Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

runkit_method_redefine() must update prototypes #38

Merged
merged 3 commits into from Sep 19, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
22 changes: 14 additions & 8 deletions runkit_methods.c
Expand Up @@ -298,6 +298,10 @@ int php_runkit_update_children_methods(RUNKIT_53_TSRMLS_ARG(zend_class_entry *ce
scope = php_runkit_locate_scope(ce, cfe, fname, fname_len);
if (scope != ancestor_class) {
/* This method was defined below our current level, leave it be */
#ifdef ZEND_ENGINE_2
cfe->common.prototype = _php_runkit_get_method_prototype(scope->parent, fname, fname_len TSRMLS_CC);
zend_hash_apply_with_arguments(RUNKIT_53_TSRMLS_PARAM(EG(class_table)), (apply_func_args_t)php_runkit_update_children_methods, 7, ancestor_class, ce, fe, fname, fname_len, orig_fe, 0);
#endif
efree(fname_lower);
return ZEND_HASH_APPLY_KEEP;
}
Expand Down Expand Up @@ -464,9 +468,6 @@ static void php_runkit_method_add_or_update(INTERNAL_FUNCTION_PARAMETERS, int ad
efree((void *)func.common.function_name);
func.common.function_name = estrndup(methodname, methodname_len);
#ifdef ZEND_ENGINE_2
func.common.scope = ce;
func.common.prototype = _php_runkit_get_method_prototype(ce, methodname, methodname_len TSRMLS_CC);

if (flags & ZEND_ACC_PRIVATE) {
func.common.fn_flags &= ~ZEND_ACC_PPP_MASK;
func.common.fn_flags |= ZEND_ACC_PRIVATE;
Expand Down Expand Up @@ -514,6 +515,11 @@ static void php_runkit_method_add_or_update(INTERNAL_FUNCTION_PARAMETERS, int ad
RETURN_FALSE;
}

#ifdef ZEND_ENGINE_2
fe->common.scope = ce;
fe->common.prototype = _php_runkit_get_method_prototype(ce, methodname, methodname_len TSRMLS_CC);
#endif

PHP_RUNKIT_ADD_MAGIC_METHOD(ce, methodname_lower, methodname_len, fe, orig_fe);
#if PHP_MAJOR_VERSION >= 5
zend_hash_apply_with_arguments(RUNKIT_53_TSRMLS_PARAM(EG(class_table)), (apply_func_args_t)php_runkit_update_children_methods, 7,
Expand Down Expand Up @@ -559,17 +565,17 @@ static int php_runkit_method_copy(const char *dclass, int dclass_len, const char
dfe = *sfe;
php_runkit_function_copy_ctor(&dfe, dfunc, dfunc_len TSRMLS_CC);

#ifdef ZEND_ENGINE_2
dfe.common.scope = dce;
dfe.common.prototype = _php_runkit_get_method_prototype(dce, dfunc, dfunc_len TSRMLS_CC);
#endif

if (zend_hash_add(&dce->function_table, dfunc_lower, dfunc_len + 1, &dfe, sizeof(zend_function), (void **) &dfeInHashTable) == FAILURE) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error adding method to class %s::%s()", dclass, dfunc);
efree(dfunc_lower);
return FAILURE;
}

#ifdef ZEND_ENGINE_2
dfeInHashTable->common.scope = dce;
dfeInHashTable->common.prototype = _php_runkit_get_method_prototype(dce, dfunc, dfunc_len TSRMLS_CC);
#endif

PHP_RUNKIT_ADD_MAGIC_METHOD(dce, dfunc_lower, dfunc_len, dfeInHashTable, NULL);

zend_hash_apply_with_arguments(RUNKIT_53_TSRMLS_PARAM(EG(class_table)), (apply_func_args_t)php_runkit_update_children_methods, 7,
Expand Down
40 changes: 40 additions & 0 deletions tests/runkit_method_redefine_update_proto.phpt
@@ -0,0 +1,40 @@
--TEST--
runkit_method_redefine() must also update children methods' prototypes
--FILE--
<?php
class a
{
protected function foo()
{
}

public function test()
{
$this->foo();
}
}

class b extends a {

protected function foo()
{
}
}

class c extends b {
function bar()
{
$this->test();
}
}

runkit_method_redefine('a', 'foo', '', 'var_dump("new foo()");');

$c = new c;
$c->bar();

echo "==DONE==\n";

?>
--EXPECT--
==DONE==
23 changes: 23 additions & 0 deletions tests/runkit_method_redefine_update_proto2.phpt
@@ -0,0 +1,23 @@
--TEST--
runkit_method_redefine() must also update method's prototype
--FILE--
<?php

class a {
function foo() {
}
}

runkit_method_redefine("a", "foo", "", "return false;");

eval("
class b extends a {
function foo() {
}
}");

echo "==DONE==\n";

?>
--EXPECT--
==DONE==