Permalink
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...
zenovich committed Sep 15, 2012
1 parent a079457 commit 1a3af5e09ff6a867b7778d2c9652c1297eeb2ddb
View
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
}
/* }}} */
Oops, something went wrong.

0 comments on commit 1a3af5e

Please sign in to comment.