Skip to content
Browse files

functions and methods redefining in PHP 5.4 was corrected in all plac…

…es, new tests were added (#36, #32)
  • Loading branch information...
1 parent a079457 commit 1a3af5e09ff6a867b7778d2c9652c1297eeb2ddb @zenovich committed Sep 15, 2012
View
5 package.xml
@@ -72,10 +72,13 @@ Execute code in restricted environment (sandboxing).
<file name="runkit_function_add.phpt" role="test" />
<file name="runkit_function_copy.phpt" role="test" />
<file name="runkit_function_redefine.phpt" role="test" />
+ <file name="runkit_function_redefine_from_anonymous.phpt" role="test" />
<file name="runkit_function_remove.phpt" role="test" />
<file name="runkit_function_rename.phpt" role="test" />
<file name="runkit_function_rename_internal.phpt" role="test" />
<file name="runkit_function_rename_redefine_add_remove.phpt" role="test" />
+ <file name="runkit_functions_redefining_and_cache.inc" role="test" />
+ <file name="runkit_functions_redefining_and_cache.phpt" role="test" />
<file name="runkit_import_class.inc" role="test" />
<file name="runkit_import_class.phpt" role="test" />
<file name="runkit_import_constant_properties.inc" role="test" />
@@ -99,6 +102,8 @@ Execute code in restricted environment (sandboxing).
<file name="runkit_method_remove.phpt" role="test" />
<file name="runkit_method_rename.phpt" role="test" />
<file name="runkit_method_rename_inheritance.phpt" role="test" />
+ <file name="runkit_methods_redefining_and_cache.inc" role="test" />
+ <file name="runkit_methods_redefining_and_cache.phpt" role="test" />
<file name="runkit_return_value_used.phpt" role="test" />
<file name="runkit_zval_inspect.phpt" role="test" />
<file name="Runkit_Sandbox_.active.phpt" role="test" />
View
3 php_runkit.h
@@ -181,6 +181,9 @@ extern ZEND_DECLARE_MODULE_GLOBALS(runkit);
/* runkit_functions.c */
#define RUNKIT_TEMP_FUNCNAME "__runkit_temporary_function__"
int php_runkit_check_call_stack(zend_op_array *op_array TSRMLS_DC);
+#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
+void php_runkit_clear_all_functions_runtime_cache(TSRMLS_D);
+#endif
void php_runkit_function_copy_ctor(zend_function *fe, const char *newname, int newname_len TSRMLS_DC);
int php_runkit_generate_lambda_method(const char *arguments, int arguments_len, const char *phpcode, int phpcode_len, zend_function **pfe TSRMLS_DC);
int php_runkit_destroy_misplaced_functions(void *pDest TSRMLS_DC);
View
73 runkit_functions.c
@@ -289,6 +289,67 @@ void php_runkit_function_copy_ctor(zend_function *fe, const char *newname, int n
}
/* }}}} */
+#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
+/* {{{ php_runkit_clear_function_runtime_cache */
+static int php_runkit_clear_function_runtime_cache(void *pDest TSRMLS_DC)
+{
+ zend_function *f = (zend_function *) pDest;
+
+ if (pDest == NULL || f->type != ZEND_USER_FUNCTION ||
+ f->op_array.last_cache_slot == 0 || f->op_array.run_time_cache == NULL) {
+ return ZEND_HASH_APPLY_KEEP;
+ }
+
+ memset(f->op_array.run_time_cache, 0, (f->op_array.last_cache_slot) * sizeof(void *));
+
+ return ZEND_HASH_APPLY_KEEP;
+}
+/* }}} */
+
+/* {{{ php_runkit_clear_all_functions_runtime_cache */
+void php_runkit_clear_all_functions_runtime_cache(TSRMLS_D)
+{
+ int i, count;
+ zend_execute_data *ptr;
+ HashPosition pos;
+
+ zend_hash_apply(EG(function_table), php_runkit_clear_function_runtime_cache TSRMLS_CC);
+
+ zend_hash_internal_pointer_reset_ex(EG(class_table), &pos);
+ count = zend_hash_num_elements(EG(class_table));
+ for (i = 0; i < count; ++i) {
+ zend_class_entry **curce;
+ zend_hash_get_current_data_ex(EG(class_table), (void**)&curce, &pos);
+ zend_hash_apply(&(*curce)->function_table, php_runkit_clear_function_runtime_cache TSRMLS_CC);
+ zend_hash_move_forward_ex(EG(class_table), &pos);
+ }
+
+ for (ptr = EG(current_execute_data); ptr != NULL; ptr = ptr->prev_execute_data) {
+ if (ptr->op_array == NULL || ptr->op_array->last_cache_slot == 0 || ptr->op_array->run_time_cache == NULL) {
+ continue;
+ }
+ memset(ptr->op_array->run_time_cache, 0, (ptr->op_array->last_cache_slot) * sizeof(void*));
+ }
+
+ if (!EG(objects_store).object_buckets) {
+ return;
+ }
+
+ for (i = 1; i < EG(objects_store).top ; i++) {
+ if (EG(objects_store).object_buckets[i].valid && (!EG(objects_store).object_buckets[i].destructor_called) &&
+ EG(objects_store).object_buckets[i].bucket.obj.object) {
+ zend_object *object;
+ object = (zend_object *) EG(objects_store).object_buckets[i].bucket.obj.object;
+ if (object->ce == zend_ce_closure) {
+ zend_closure *cl = (zend_closure *) object;
+ php_runkit_clear_function_runtime_cache((void*) &cl->func TSRMLS_CC);
+ }
+ }
+ }
+}
+/* }}} */
+#endif
+
/* {{{ php_runkit_generate_lambda_method
Heavily borrowed from ZEND_FUNCTION(create_function) */
int php_runkit_generate_lambda_method(const char *arguments, int arguments_len, const char *phpcode, int phpcode_len, zend_function **pfe TSRMLS_DC)
@@ -451,6 +512,10 @@ PHP_FUNCTION(runkit_function_remove)
result = (zend_hash_del(EG(function_table), funcname_lower, funcname_len + 1) == SUCCESS);
efree(funcname_lower);
+#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
+ php_runkit_clear_all_functions_runtime_cache(TSRMLS_C);
+#endif
+
RETURN_BOOL(result);
}
/* }}} */
@@ -524,6 +589,10 @@ PHP_FUNCTION(runkit_function_rename)
}
efree(dfunc_lower);
+#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
+ php_runkit_clear_all_functions_runtime_cache(TSRMLS_C);
+#endif
+
RETURN_TRUE;
}
/* }}} */
@@ -578,6 +647,10 @@ PHP_FUNCTION(runkit_function_redefine)
efree(delta_desc);
efree(delta);
+#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
+ php_runkit_clear_all_functions_runtime_cache(TSRMLS_C);
+#endif
+
RETURN_BOOL(retval == SUCCESS);
}
/* }}} */
View
52 runkit_import.c
@@ -24,7 +24,11 @@
#ifdef PHP_RUNKIT_MANIPULATION
/* {{{ php_runkit_import_functions
*/
-static int php_runkit_import_functions(HashTable *function_table, long flags TSRMLS_DC)
+static int php_runkit_import_functions(HashTable *function_table, long flags
+#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
+ , zend_bool *clear_cache
+#endif
+ TSRMLS_DC)
{
HashPosition pos;
int i, func_count = zend_hash_num_elements(function_table);
@@ -69,6 +73,9 @@ static int php_runkit_import_functions(HashTable *function_table, long flags TSR
return FAILURE;
}
}
+#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
+ *clear_cache = 1;
+#endif
} else {
add_function = 0;
}
@@ -93,7 +100,11 @@ static int php_runkit_import_functions(HashTable *function_table, long flags TSR
/* {{{ php_runkit_import_class_methods
*/
-static int php_runkit_import_class_methods(zend_class_entry *dce, zend_class_entry *ce, int override TSRMLS_DC)
+static int php_runkit_import_class_methods(zend_class_entry *dce, zend_class_entry *ce, int override
+#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
+ , zend_bool *clear_cache
+#endif
+ TSRMLS_DC)
{
HashPosition pos;
zend_function *fe;
@@ -139,6 +150,10 @@ static int php_runkit_import_class_methods(zend_class_entry *dce, zend_class_ent
continue;
}
+#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
+ *clear_cache = 1;
+#endif
+
zend_hash_apply_with_arguments(RUNKIT_53_TSRMLS_PARAM(EG(class_table)), (apply_func_args_t)php_runkit_clean_children_methods, 4, scope, dce, fn, fn_len);
if (zend_hash_del(&dce->function_table, fn, fn_len + 1) == FAILURE) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error removing old method in destination class %s::%s", dce->name, fe->common.function_name);
@@ -409,7 +424,11 @@ static int php_runkit_import_class_props(zend_class_entry *dce, zend_class_entry
/* {{{ php_runkit_import_classes
*/
-static int php_runkit_import_classes(HashTable *class_table, long flags TSRMLS_DC)
+static int php_runkit_import_classes(HashTable *class_table, long flags
+#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
+ , zend_bool *clear_cache
+#endif
+ TSRMLS_DC)
{
HashPosition pos;
int i, class_count;
@@ -459,7 +478,11 @@ static int php_runkit_import_classes(HashTable *class_table, long flags TSRMLS_D
}
if (flags & PHP_RUNKIT_IMPORT_CLASS_METHODS) {
- php_runkit_import_class_methods(dce, ce, (flags & PHP_RUNKIT_IMPORT_OVERRIDE) TSRMLS_CC);
+ php_runkit_import_class_methods(dce, ce, (flags & PHP_RUNKIT_IMPORT_OVERRIDE)
+#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
+ , clear_cache
+#endif
+ TSRMLS_CC);
}
zend_hash_move_forward_ex(class_table, &pos);
@@ -572,6 +595,9 @@ PHP_FUNCTION(runkit_import)
zend_op_array *new_op_array;
zval *filename;
long flags = PHP_RUNKIT_IMPORT_CLASS_METHODS;
+#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
+ zend_bool clear_cache = 0;
+#endif
zend_op_array *(*local_compile_filename)(int type, zval *filename TSRMLS_DC) = compile_filename;
@@ -630,11 +656,19 @@ PHP_FUNCTION(runkit_import)
efree(new_op_array);
if (flags & PHP_RUNKIT_IMPORT_FUNCTIONS) {
- php_runkit_import_functions(tmp_function_table, flags TSRMLS_CC);
+ php_runkit_import_functions(tmp_function_table, flags
+#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
+ , &clear_cache
+#endif
+ TSRMLS_CC);
}
if (flags & PHP_RUNKIT_IMPORT_CLASSES) {
- php_runkit_import_classes(tmp_class_table, flags TSRMLS_CC);
+ php_runkit_import_classes(tmp_class_table, flags
+#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
+ , &clear_cache
+#endif
+ TSRMLS_CC);
}
zend_hash_destroy(tmp_class_table);
@@ -644,6 +678,12 @@ PHP_FUNCTION(runkit_import)
zend_hash_destroy(tmp_function_table);
efree(tmp_function_table);
+#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
+ if (clear_cache) {
+ php_runkit_clear_all_functions_runtime_cache(TSRMLS_C);
+ }
+#endif
+
RETURN_TRUE;
}
/* }}} */
View
87 runkit_methods.c
@@ -379,67 +379,6 @@ int php_runkit_clean_children_methods(RUNKIT_53_TSRMLS_ARG(zend_class_entry *ce)
}
/* }}} */
-#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
-/* {{{ php_runkit_clear_function_runtime_cache */
-int php_runkit_clear_function_runtime_cache(void *pDest TSRMLS_DC)
-{
- zend_function *f = (zend_function *) pDest;
-
- if (pDest == NULL || f->type == ZEND_INTERNAL_FUNCTION ||
- f->op_array.last_cache_slot == 0 || f->op_array.run_time_cache == NULL) {
- return ZEND_HASH_APPLY_KEEP;
- }
-
- memset(f->op_array.run_time_cache, 0, (f->op_array.last_cache_slot) * sizeof(void *));
-
- return ZEND_HASH_APPLY_KEEP;
-}
-/* }}} */
-
-/* {{{ php_runkit_clear_all_functions_runtime_cache */
-void php_runkit_clear_all_functions_runtime_cache(TSRMLS_D)
-{
- int i, count;
- zend_execute_data *ptr;
- HashPosition pos;
-
- zend_hash_apply(EG(function_table), php_runkit_clear_function_runtime_cache TSRMLS_CC);
-
- zend_hash_internal_pointer_reset_ex(EG(class_table), &pos);
- count = zend_hash_num_elements(EG(class_table));
- for (i = 0; i < count; ++i) {
- zend_class_entry **curce;
- zend_hash_get_current_data_ex(EG(class_table), (void**)&curce, &pos);
- zend_hash_apply(&(*curce)->function_table, php_runkit_clear_function_runtime_cache TSRMLS_CC);
- zend_hash_move_forward_ex(EG(class_table), &pos);
- }
-
- for (ptr = EG(current_execute_data); ptr != NULL; ptr = ptr->prev_execute_data) {
- if (ptr->op_array == NULL || ptr->op_array->last_cache_slot == 0 || ptr->op_array->run_time_cache == NULL) {
- continue;
- }
- memset(ptr->op_array->run_time_cache, 0, (ptr->op_array->last_cache_slot) * sizeof(void*));
- }
-
- if (!EG(objects_store).object_buckets) {
- return;
- }
-
- for (i = 1; i < EG(objects_store).top ; i++) {
- if (EG(objects_store).object_buckets[i].valid && (!EG(objects_store).object_buckets[i].destructor_called) &&
- EG(objects_store).object_buckets[i].bucket.obj.object) {
- zend_object *object;
- object = (zend_object *) EG(objects_store).object_buckets[i].bucket.obj.object;
- if (object->ce == zend_ce_closure) {
- zend_closure *cl = (zend_closure *) object;
- php_runkit_clear_function_runtime_cache((void*) &cl->func TSRMLS_CC);
- }
- }
- }
-}
-/* }}} */
-#endif
-
/* {{{ php_runkit_method_add_or_update
*/
static void php_runkit_method_add_or_update(INTERNAL_FUNCTION_PARAMETERS, int add_or_update)
@@ -534,6 +473,10 @@ static void php_runkit_method_add_or_update(INTERNAL_FUNCTION_PARAMETERS, int ad
}
#endif
+#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
+ php_runkit_clear_all_functions_runtime_cache(TSRMLS_C);
+#endif
+
zend_hash_apply_with_arguments(RUNKIT_53_TSRMLS_PARAM(EG(class_table)), (apply_func_args_t)php_runkit_update_children_methods, 5,
ancestor_class, ce, &func, methodname, methodname_len);
@@ -559,9 +502,6 @@ static void php_runkit_method_add_or_update(INTERNAL_FUNCTION_PARAMETERS, int ad
PHP_RUNKIT_ADD_MAGIC_METHOD(ce, methodname, fe);
efree(methodname_lower);
-#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
- php_runkit_clear_all_functions_runtime_cache(TSRMLS_C);
-#endif
RETURN_TRUE;
}
@@ -616,9 +556,6 @@ static int php_runkit_method_copy(const char *dclass, int dclass_len, const char
zend_hash_apply_with_arguments(RUNKIT_53_TSRMLS_PARAM(EG(class_table)), (apply_func_args_t)php_runkit_update_children_methods, 5, dce, dce, &dfe, dfunc_lower, dfunc_len);
efree(dfunc_lower);
-#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
- php_runkit_clear_all_functions_runtime_cache(TSRMLS_C);
-#endif
return SUCCESS;
}
/* }}} */
@@ -680,6 +617,10 @@ PHP_FUNCTION(runkit_method_remove)
zend_hash_apply_with_arguments(RUNKIT_53_TSRMLS_PARAM(EG(class_table)), (apply_func_args_t)php_runkit_clean_children_methods, 4, ancestor_class, ce, methodname, methodname_len);
+#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
+ php_runkit_clear_all_functions_runtime_cache(TSRMLS_C);
+#endif
+
if (zend_hash_del(&ce->function_table, methodname_lower, methodname_len + 1) == FAILURE) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to remove method from class");
efree(methodname_lower);
@@ -688,9 +629,7 @@ PHP_FUNCTION(runkit_method_remove)
efree(methodname_lower);
PHP_RUNKIT_DEL_MAGIC_METHOD(ce, fe);
-#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
- php_runkit_clear_all_functions_runtime_cache(TSRMLS_C);
-#endif
+
RETURN_TRUE;
}
/* }}} */
@@ -746,6 +685,10 @@ PHP_FUNCTION(runkit_method_rename)
zend_hash_apply_with_arguments(RUNKIT_53_TSRMLS_PARAM(EG(class_table)), (apply_func_args_t)php_runkit_clean_children_methods, 4,
ancestor_class, ce, methodname_lower, methodname_len);
+#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
+ php_runkit_clear_all_functions_runtime_cache(TSRMLS_C);
+#endif
+
func = *fe;
PHP_RUNKIT_FUNCTION_ADD_REF(&func);
efree((void *) func.common.function_name);
@@ -781,10 +724,6 @@ PHP_FUNCTION(runkit_method_rename)
zend_hash_apply_with_arguments(RUNKIT_53_TSRMLS_PARAM(EG(class_table)), (apply_func_args_t)php_runkit_update_children_methods, 5, ce, ce, fe, newname, newname_len);
-#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
- php_runkit_clear_all_functions_runtime_cache(TSRMLS_C);
-#endif
-
RETURN_TRUE;
}
/* }}} */
View
36 tests/runkit_function_redefine_from_anonymous.phpt
@@ -0,0 +1,36 @@
+--TEST--
+runkit_function_redefine() and call from anonymous function
+--SKIPIF--
+<?php
+ if(!extension_loaded("runkit") || !RUNKIT_FEATURE_MANIPULATION) print "skip";
+ if(version_compare(PHP_VERSION, '5.3.0', '<')) print "skip";
+?>
+--INI--
+error_reporting=E_ALL
+display_errors=on
+runkit.internal_override=On
+--FILE--
+<?php
+function greet(){
+ echo "hey\n";
+}
+greet();
+runkit_function_redefine("greet",'$name',"echo \"hey \$name\n\";");
+greet("you");
+function parent() {
+ $localvar = "john";
+ $af = function() use ($localvar){
+ greet($localvar);
+ };
+ return $af;
+}
+$greet1 = parent();
+$greet1();
+runkit_function_redefine("greet",'$name',"echo \"hello \$name\n\";");
+$greet1();
+--EXPECT--
+hey
+hey you
+hey john
+hello john
+
View
6 tests/runkit_functions_redefining_and_cache.inc
@@ -0,0 +1,6 @@
+<?php
+
+function sprintf($a) {
+ echo '';
+ return $a+1;
+}
View
92 tests/runkit_functions_redefining_and_cache.phpt
@@ -0,0 +1,92 @@
+--TEST--
+Test for caching issues on redefining functions
+--SKIPIF--
+<?php
+if(!extension_loaded("runkit") || !RUNKIT_FEATURE_MANIPULATION) print "skip";
+?>
+--INI--
+error_reporting=E_ALL
+display_errors=on
+runkit.internal_override=On
+--FILE--
+<?php
+function a($result) {
+ for ($i = 0; $i < 10; $i++) {
+ runkit_function_redefine('sprintf', '$v', "echo ''; return $result + 1;");
+ $result = sprintf('a');
+ }
+ return $result;
+}
+
+$result = 0;
+for ($i = 0; $i < 10; $i++) {
+ $result = a($result);
+}
+
+echo $result, "\n";
+
+function b($result) {
+ for ($i = 0; $i < 10; $i++) {
+ runkit_function_remove('sprintf');
+ runkit_function_add('sprintf', '$v', "echo ''; return $result + 1;");
+ $result = sprintf('a');
+ }
+ return $result;
+}
+
+for ($i=0; $i<10; $i++) {
+ $result = b($result);
+}
+echo $result, "\n";
+
+class A {
+ function run() {
+ echo '';
+ return mail('a');
+ }
+
+ function c($result) {
+ for ($i = 0; $i < 10; $i++) {
+ runkit_function_redefine('mail', '$v', "echo ''; return $result + 1;");
+ $result = $this->run();
+ }
+ return $result;
+ }
+
+ function d($result) {
+ for ($i = 0; $i < 10; $i++) {
+ runkit_function_remove('mail');
+ runkit_function_add('mail', '$v', "echo ''; return $result + 1;");
+ $result = $this->run();
+ }
+ return $result;
+ }
+}
+$a = new A();
+for ($i = 0; $i < 10; $i++) {
+ $result = $a->c($result);
+}
+echo $result, "\n";
+for ($i = 0; $i < 10; $i++) {
+ $result = $a->d($result);
+}
+echo $result, "\n";
+
+function e($result) {
+ for ($i = 0; $i < 10; $i++) {
+ runkit_import('runkit_functions_redefining_and_cache.inc', RUNKIT_IMPORT_FUNCTIONS | RUNKIT_IMPORT_OVERRIDE);
+ $result = sprintf($result);
+ }
+ return $result;
+}
+
+for ($i = 0; $i < 10; $i++) {
+ $result = e($result);
+}
+echo $result;
+--EXPECT--
+100
+200
+300
+400
+500
View
7 tests/runkit_methods_redefining_and_cache.inc
@@ -0,0 +1,7 @@
+<?php
+class RunkitClass {
+ function a($a) {
+ echo '';
+ return $a+1;
+ }
+}
View
98 tests/runkit_methods_redefining_and_cache.phpt
@@ -0,0 +1,98 @@
+--TEST--
+Test for caching issues on redefining class methods
+--SKIPIF--
+<?php
+if(!extension_loaded("runkit") || !RUNKIT_FEATURE_MANIPULATION) print "skip";
+?>
+--INI--
+error_reporting=E_ALL
+display_errors=on
+--FILE--
+<?php
+class RunkitClass {
+ function a() {
+ }
+}
+
+class Test {
+ var $obj;
+
+ function a($result) {
+ for ($i = 0; $i < 10; $i++) {
+ runkit_method_redefine('RunkitClass', 'a', '', "echo ''; return $result + 1;");
+ $result = $this->obj->a($result);
+ }
+ return $result;
+ }
+
+ function b($result) {
+ for ($i = 0; $i < 10; $i++) {
+ runkit_method_remove('RunkitClass', 'a');
+ runkit_method_add('RunkitClass', 'a', '', "echo ''; return $result + 1;");
+ $result = $this->obj->a();
+ }
+ return $result;
+ }
+
+ function c($result) {
+ for ($i = 0; $i < 10; $i++) {
+ runkit_import('runkit_methods_redefining_and_cache.inc', RUNKIT_IMPORT_CLASSES | RUNKIT_IMPORT_OVERRIDE);
+ $result = $this->obj->a($result);
+ }
+ return $result;
+ }
+
+ function t() {
+ $this->obj = new RunkitClass();
+ $result = 0;
+ for ($i = 0; $i < 10; $i++) {
+ $result = $this->a($result);
+ }
+ echo $result, "\n";
+
+ for ($i=0; $i<10; $i++) {
+ $result = $this->b($result);
+ }
+ echo $result, "\n";
+
+ for ($i=0; $i<10; $i++) {
+ $result = $this->c($result);
+ }
+ echo $result, "\n";
+ }
+}
+
+$t = new Test();
+$t->t();
+
+$obj = new RunkitClass();
+function a($result, $obj) {
+ for ($i = 0; $i < 10; $i++) {
+ runkit_method_redefine('RunkitClass', 'a', '', "echo ''; return $result + 1;");
+ $result = $obj->a();
+ }
+ return $result;
+}
+$result = 300;
+for ($i = 0; $i < 10; $i++) {
+ $result = a($result, $obj);
+}
+echo $result, "\n";
+
+function b($result, $obj) {
+ for ($i = 0; $i < 10; $i++) {
+ runkit_method_redefine('RunkitClass', 'a', '', "echo ''; return $result + 1;");
+ $result = $obj->a();
+ }
+ return $result;
+}
+for ($i = 0; $i < 10; $i++) {
+ $result = b($result, $obj);
+}
+echo $result, "\n";
+--EXPECT--
+100
+200
+300
+400
+500

0 comments on commit 1a3af5e

Please sign in to comment.
Something went wrong with that request. Please try again.