Permalink
Browse files

A new constant RUNKIT_OVERRIDE_OBJECTS was introduced. Use it by bitw…

…ise adding to the flags parameter of functions runkit_default_property_add and runkit_import to add (and remove) properties of existing objects. This feature works in PHP 5.x and above and it is switched off by default.

New (the third one) parameter remove_from_objects of boolean type was introduced in runkit_default_property_remove function. Pass the TRUE value to remove property from existing objects. This feature works in PHP 5.x and above. The default value for this parameter is FALSE.
  • Loading branch information...
1 parent d069e23 commit 07179d72a2165a8bee60ddab5f0b79d96b39a387 @zenovich committed May 12, 2013
Showing with 1,597 additions and 206 deletions.
  1. +25 −2 package.xml
  2. +15 −10 php_runkit.h
  3. +1 −0 runkit.c
  4. +30 −51 runkit_import.c
  5. +423 −119 runkit_props.c
  6. +1 −1 tests/runkit_default_property_add.phpt
  7. +14 −4 tests/runkit_default_property_add_and_remove_for_class_with_dynamic_properties.phpt
  8. +72 −0 ...nkit_default_property_add_and_remove_for_class_with_dynamic_properties_overriding_in_objects.phpt
  9. +49 −0 tests/runkit_default_property_add_overriding_objects.phpt
  10. +27 −0 tests/runkit_default_property_add_overriding_objects4.phpt
  11. +0 −4 tests/runkit_default_property_add_to_subclasses.phpt
  12. +85 −0 tests/runkit_default_property_add_to_subclasses_overriding_objects.phpt
  13. +4 −2 tests/runkit_default_property_remove.phpt
  14. +11 −8 tests/runkit_default_property_remove_and_add_for_class_with_dynamic_properties.phpt
  15. +81 −0 .../runkit_default_property_remove_and_add_for_class_with_dynamic_properties_overriding_objects.phpt
  16. +1 −1 tests/runkit_default_property_remove_and_reflection.phpt
  17. +5 −1 tests/runkit_default_property_remove_from_subclasses.phpt
  18. +52 −0 tests/runkit_default_property_remove_from_subclasses_overriding_objects.phpt
  19. +15 −2 tests/runkit_default_property_remove_inheritance.phpt
  20. +61 −0 tests/runkit_default_property_remove_inheritance_overriding_objects.phpt
  21. +46 −0 tests/runkit_default_property_remove_overriding_objects.phpt
  22. +30 −0 tests/runkit_default_property_remove_overriding_objects4.phpt
  23. +94 −0 tests/runkit_default_property_remove_private_and_inheritance.phpt
  24. +69 −0 tests/runkit_default_property_remove_private_and_inheritance_overriding_objects.phpt
  25. +92 −0 tests/runkit_default_property_remove_private_shadow_and_inheritance.phpt
  26. +95 −0 tests/runkit_default_property_remove_private_shadow_and_inheritance54.phpt
  27. +90 −0 tests/runkit_default_property_remove_private_shadow_and_inheritance_overriding_objects.phpt
  28. +8 −0 tests/runkit_import_class_property.phpt
  29. +6 −1 tests/runkit_import_class_property_and_inheritance.phpt
  30. +59 −0 tests/runkit_import_class_property_and_inheritance_overriding_objects.phpt
  31. +8 −0 tests/runkit_import_class_property_not_overriding_subclasses.phpt
  32. +7 −0 tests/runkit_import_function_overriding_objects4.inc
  33. +19 −0 tests/runkit_import_function_overriding_objects4.phpt
  34. +2 −0 tests/runkit_import_static_properties_override.phpt
View
@@ -17,7 +17,7 @@ Execute code in restricted environment (sandboxing).
<active>yes</active>
</lead>
- <date>2012-01-02</date>
+ <date>2013-05-12</date>
<version>
<release>1.0.4</release>
<api>1.0.4</api>
@@ -38,7 +38,13 @@ Execute code in restricted environment (sandboxing).
New optional argument 'return_ref' of functions runkit_function_add and runkit_function_redefine was introduced
New constant RUNKIT_ACC_RETURN_REFERENCE was introduced for use with functions runkit_method_add and runkit_method_redefine
+ Properties adding, removing, and importing were reworked for proper inheritance (including objects in PHP5+)
- + Namespaces are fully supported by constants manipulation functions (Thanks to Anthony Dovgal)
+ + A new constant RUNKIT_OVERRIDE_OBJECTS was introduced. Use it by bitwise adding to the flags parameter
+ of functions runkit_default_property_add and runkit_import to add (and remove) properties of existing objects.
+ This feature works in PHP 5.x and above and it is switched off by default.
+ + New (the third one) parameter remove_from_objects of boolean type was introduced
+ in runkit_default_property_remove function. Pass the TRUE value to remove property from existing objects.
+ This feature works in PHP 5.x and above. The default value for this parameter is FALSE.
+ + Namespaces are fully supported by constants manipulation functions (Thanks to Antony Dovgal)
Critical fixes:
* Highly probable crashes on using Reflection objects after modifying removing or renaming of functions, methods, and properties,
@@ -223,6 +229,23 @@ Execute code in restricted environment (sandboxing).
<file name="runkit_static_property_add_existing.phpt" role="test" />
<file name="runkit_static_property_add_to_subclasses.phpt" role="test" />
<file name="runkit_superglobals.phpt" role="test" />
+ <file name="runkit_default_property_add_and_remove_for_class_with_dynamic_properties_overriding_in_objects.phpt" role="test" />
+ <file name="runkit_default_property_add_overriding_objects.phpt" role="test" />
+ <file name="runkit_default_property_add_overriding_objects4.phpt" role="test" />
+ <file name="runkit_default_property_add_to_subclasses_overriding_objects.phpt" role="test" />
+ <file name="runkit_default_property_remove_and_add_for_class_with_dynamic_properties_overriding_objects.phpt" role="test" />
+ <file name="runkit_default_property_remove_from_subclasses_overriding_objects.phpt" role="test" />
+ <file name="runkit_default_property_remove_inheritance_overriding_objects.phpt" role="test" />
+ <file name="runkit_default_property_remove_overriding_objects.phpt" role="test" />
+ <file name="runkit_default_property_remove_overriding_objects4.phpt" role="test" />
+ <file name="runkit_default_property_remove_private_and_inheritance.phpt" role="test" />
+ <file name="runkit_default_property_remove_private_and_inheritance_overriding_objects.phpt" role="test" />
+ <file name="runkit_default_property_remove_private_shadow_and_inheritance.phpt" role="test" />
+ <file name="runkit_default_property_remove_private_shadow_and_inheritance54.phpt" role="test" />
+ <file name="runkit_default_property_remove_private_shadow_and_inheritance_overriding_objects.phpt" role="test" />
+ <file name="runkit_import_class_property_and_inheritance_overriding_objects.phpt" role="test" />
+ <file name="runkit_import_function_overriding_objects4.inc" role="test" />
+ <file name="runkit_import_function_overriding_objects4.phpt" role="test" />
</dir> <!-- //tests -->
<file name="config.m4" role="src" />
<file name="config.w32" role="src" />
View
@@ -39,13 +39,15 @@
#define PHP_RUNKIT_SANDBOX_CLASSNAME "Runkit_Sandbox"
#define PHP_RUNKIT_SANDBOX_PARENT_CLASSNAME "Runkit_Sandbox_Parent"
-#define PHP_RUNKIT_IMPORT_FUNCTIONS 0x0001
-#define PHP_RUNKIT_IMPORT_CLASS_METHODS 0x0002
-#define PHP_RUNKIT_IMPORT_CLASS_CONSTS 0x0004
-#define PHP_RUNKIT_IMPORT_CLASS_PROPS 0x0008
-#define PHP_RUNKIT_IMPORT_CLASS_STATIC_PROPS 0x0010
-#define PHP_RUNKIT_IMPORT_CLASSES (PHP_RUNKIT_IMPORT_CLASS_METHODS|PHP_RUNKIT_IMPORT_CLASS_CONSTS|PHP_RUNKIT_IMPORT_CLASS_PROPS|PHP_RUNKIT_IMPORT_CLASS_STATIC_PROPS)
-#define PHP_RUNKIT_IMPORT_OVERRIDE 0x0020
+#define PHP_RUNKIT_IMPORT_FUNCTIONS 0x0001
+#define PHP_RUNKIT_IMPORT_CLASS_METHODS 0x0002
+#define PHP_RUNKIT_IMPORT_CLASS_CONSTS 0x0004
+#define PHP_RUNKIT_IMPORT_CLASS_PROPS 0x0008
+#define PHP_RUNKIT_IMPORT_CLASS_STATIC_PROPS 0x0010
+#define PHP_RUNKIT_IMPORT_CLASSES (PHP_RUNKIT_IMPORT_CLASS_METHODS|PHP_RUNKIT_IMPORT_CLASS_CONSTS|\
+ PHP_RUNKIT_IMPORT_CLASS_PROPS|PHP_RUNKIT_IMPORT_CLASS_STATIC_PROPS)
+#define PHP_RUNKIT_IMPORT_OVERRIDE 0x0020
+#define PHP_RUNKIT_OVERRIDE_OBJECTS 0x8000
#if ZEND_MODULE_API_NO > 20050922
#define ZEND_ENGINE_2_2
@@ -270,11 +272,14 @@ int php_runkit_update_children_consts(RUNKIT_53_TSRMLS_ARG(void *pDest), int num
/* runkit_props.c */
int php_runkit_update_children_def_props(RUNKIT_53_TSRMLS_ARG(zend_class_entry *ce), int num_args, va_list args, zend_hash_key *hash_key);
-int php_runkit_def_prop_add_int(zend_class_entry *ce, const char *propname, int propname_len, zval *copyval, long visibility, const char *doc_comment, int doc_comment_len, zend_class_entry *definer_class, int override TSRMLS_DC);
-int php_runkit_def_prop_remove_int(zend_class_entry *ce, const char *propname, int propname_len, zend_class_entry *definer_class,
- int parent_offset, zend_bool was_static TSRMLS_DC);
+int php_runkit_def_prop_add_int(zend_class_entry *ce, const char *propname, int propname_len, zval *copyval, long visibility, const char *doc_comment, int doc_comment_len, zend_class_entry *definer_class, int override, int override_in_objects TSRMLS_DC);
#ifdef ZEND_ENGINE_2
+int php_runkit_def_prop_remove_int(zend_class_entry *ce, const char *propname, int propname_len, zend_class_entry *definer_class,
+ zend_bool was_static, zend_bool remove_from_objects, zend_property_info *parent_property TSRMLS_DC);
void php_runkit_remove_property_from_reflection_objects(zend_class_entry *ce, const char *prop_name, int prop_name_len TSRMLS_DC);
+#else
+int php_runkit_def_prop_remove_int(zend_class_entry *ce, const char *propname, int propname_len, zend_class_entry *definer_class,
+ zend_bool was_static, zend_bool remove_from_objects, void *parent_property TSRMLS_DC);
#endif
#ifdef ZEND_ENGINE_2
View
@@ -271,6 +271,7 @@ PHP_MINIT_FUNCTION(runkit)
REGISTER_LONG_CONSTANT("RUNKIT_ACC_PRIVATE", 0x400, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("RUNKIT_ACC_STATIC", 0x001, CONST_CS | CONST_PERSISTENT);
#endif
+ REGISTER_LONG_CONSTANT("RUNKIT_OVERRIDE_OBJECTS", PHP_RUNKIT_OVERRIDE_OBJECTS, CONST_CS | CONST_PERSISTENT);
#ifdef PHP_RUNKIT_CLASSKIT_COMPAT
#ifdef ZEND_ENGINE_2
View
@@ -259,7 +259,7 @@ static int php_runkit_import_class_consts(zend_class_entry *dce, zend_class_entr
#ifdef ZEND_ENGINE_2
/* {{{ php_runkit_import_class_static_props
*/
-static int php_runkit_import_class_static_props(zend_class_entry *dce, zend_class_entry *ce, int override TSRMLS_DC)
+static int php_runkit_import_class_static_props(zend_class_entry *dce, zend_class_entry *ce, int override, int remove_from_objects TSRMLS_DC)
{
HashPosition pos;
char *key;
@@ -290,43 +290,19 @@ static int php_runkit_import_class_static_props(zend_class_entry *dce, zend_clas
#endif // (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
if (zend_hash_find(&dce->properties_info, key, key_len, (void*) &ex_property_info_ptr) == SUCCESS && ex_property_info_ptr) {
if (override) {
- if (!(ex_property_info_ptr->flags & ZEND_ACC_STATIC)) {
- if (php_runkit_def_prop_remove_int(dce, key, key_len - 1, NULL, -1, 0 TSRMLS_CC) != SUCCESS) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to import %s::$%s (cannot remove old member)", dce->name, key);
- goto import_st_prop_skip;
- }
- if (php_runkit_def_prop_add_int(dce, key, key_len - 1, *pp, property_info_ptr->flags,
- property_info_ptr->doc_comment,
- property_info_ptr->doc_comment_len, dce,
- override TSRMLS_CC) != SUCCESS) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to import %s::$%s (cannot add new member)", dce->name, key);
- goto import_st_prop_skip;
- }
+ if (php_runkit_def_prop_remove_int(dce, key, key_len - 1, NULL, 0, 0, NULL TSRMLS_CC) != SUCCESS) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to import %s::$%s (cannot remove old member)", dce->name, key);
goto import_st_prop_skip;
- } else {
- zval *pcopy;
-#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
- zval_ptr_dtor(&dce->default_static_members_table[ex_property_info_ptr->offset]);
- dce->default_static_members_table[ex_property_info_ptr->offset] = ce->default_static_members_table[property_info_ptr->offset];
- ce->default_static_members_table[property_info_ptr->offset] = NULL;
- zval_update_constant(&dce->default_static_members_table[ex_property_info_ptr->offset], dce TSRMLS_CC);
- pcopy = dce->default_static_members_table[ex_property_info_ptr->offset];
-#else
- pcopy = *pp;
-#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION <= 2)
- SEPARATE_ARG_IF_REF(pcopy);
-#else
- Z_ADDREF_P(pcopy);
-#endif
- if (zend_hash_update(CE_STATIC_MEMBERS(dce), ex_property_info_ptr->name, ex_property_info_ptr->name_length + 1, (void*)pp, sizeof(zval*), NULL) == FAILURE) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to import %s::$%s", dce->name, key);
- }
-#endif
- zend_hash_apply_with_arguments(RUNKIT_53_TSRMLS_PARAM(EG(class_table)),
- (apply_func_args_t)php_runkit_update_children_def_props,
- 7, dce, pcopy, key, key_len - 1,
- property_info_ptr->flags, dce, override);
}
+ zval_update_constant(pp, dce TSRMLS_CC);
+ if (php_runkit_def_prop_add_int(dce, key, key_len - 1, *pp, property_info_ptr->flags,
+ property_info_ptr->doc_comment,
+ property_info_ptr->doc_comment_len, dce,
+ override, remove_from_objects TSRMLS_CC) != SUCCESS) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to import %s::$%s (cannot add new member)", dce->name, key);
+ goto import_st_prop_skip;
+ }
+ goto import_st_prop_skip;
} else {
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "%s::$%s already exists, not importing", dce->name, key);
goto import_st_prop_skip;
@@ -335,7 +311,7 @@ static int php_runkit_import_class_static_props(zend_class_entry *dce, zend_clas
if (php_runkit_def_prop_add_int(dce, key, key_len - 1, *pp, property_info_ptr->flags,
property_info_ptr->doc_comment,
property_info_ptr->doc_comment_len, dce,
- override TSRMLS_CC) != SUCCESS) {
+ override, remove_from_objects TSRMLS_CC) != SUCCESS) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to import %s::$%s (cannot add new member)", dce->name, key);
goto import_st_prop_skip;
}
@@ -353,7 +329,7 @@ static int php_runkit_import_class_static_props(zend_class_entry *dce, zend_clas
/* {{{ php_runkit_import_class_props
*/
-static int php_runkit_import_class_props(zend_class_entry *dce, zend_class_entry *ce, int override TSRMLS_DC)
+static int php_runkit_import_class_props(zend_class_entry *dce, zend_class_entry *ce, int override, int remove_from_objects TSRMLS_DC)
{
HashPosition pos;
char *key;
@@ -372,15 +348,7 @@ static int php_runkit_import_class_props(zend_class_entry *dce, zend_class_entry
goto import_st54_prop_skip;
}
if (zend_hash_exists(&dce->properties_info, key, key_len)) {
- if (override) {
- if (php_runkit_def_prop_remove_int(dce, key, key_len - 1, NULL, -1, 0 TSRMLS_CC) != SUCCESS) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING,
- "Unable to remove old property %s%s%s, not importing",
- dce->name, (property_info_ptr->flags & ZEND_ACC_STATIC) ? "::$" : "->",
- property_info_ptr->name);
- goto import_st54_prop_skip;
- }
- } else {
+ if (!override) {
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "%s%s%s already exists, not importing",
dce->name, (property_info_ptr->flags & ZEND_ACC_STATIC) ? "::$" : "->", key);
goto import_st54_prop_skip;
@@ -406,7 +374,7 @@ static int php_runkit_import_class_props(zend_class_entry *dce, zend_class_entry
php_runkit_def_prop_add_int(dce, key, key_len - 1, *p,
property_info_ptr->flags, property_info_ptr->doc_comment,
- property_info_ptr->doc_comment_len, dce, override TSRMLS_CC);
+ property_info_ptr->doc_comment_len, dce, override, remove_from_objects TSRMLS_CC);
}
#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 4) || (PHP_MAJOR_VERSION < 5)
else {
@@ -427,7 +395,7 @@ static int php_runkit_import_class_props(zend_class_entry *dce, zend_class_entry
}
}
- php_runkit_def_prop_add_int(dce, key, key_len - 1, *p, 0, NULL, 0, dce, override TSRMLS_CC);
+ php_runkit_def_prop_add_int(dce, key, key_len - 1, *p, 0, NULL, 0, dce, override, remove_from_objects TSRMLS_CC);
} else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Property has invalid key name");
}
@@ -487,12 +455,16 @@ static int php_runkit_import_classes(HashTable *class_table, long flags
php_runkit_import_class_consts(dce, ce, (flags & PHP_RUNKIT_IMPORT_OVERRIDE) TSRMLS_CC);
}
if (flags & PHP_RUNKIT_IMPORT_CLASS_STATIC_PROPS) {
- php_runkit_import_class_static_props(dce, ce, (flags & PHP_RUNKIT_IMPORT_OVERRIDE) TSRMLS_CC);
+ php_runkit_import_class_static_props(dce, ce, (flags & PHP_RUNKIT_IMPORT_OVERRIDE) != 0,
+ (flags & PHP_RUNKIT_OVERRIDE_OBJECTS) != 0
+ TSRMLS_CC);
}
#endif
if (flags & PHP_RUNKIT_IMPORT_CLASS_PROPS) {
- php_runkit_import_class_props(dce, ce, (flags & PHP_RUNKIT_IMPORT_OVERRIDE) TSRMLS_CC);
+ php_runkit_import_class_props(dce, ce, (flags & PHP_RUNKIT_IMPORT_OVERRIDE) != 0,
+ (flags & PHP_RUNKIT_OVERRIDE_OBJECTS) != 0
+ TSRMLS_CC);
}
if (flags & PHP_RUNKIT_IMPORT_CLASS_METHODS) {
@@ -618,6 +590,13 @@ PHP_FUNCTION(runkit_import)
}
convert_to_string(filename);
+#ifndef ZEND_ENGINE_2
+ if (flags & PHP_RUNKIT_OVERRIDE_OBJECTS) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Overriding in objects is not supported for PHP versions below 5.0");
+ flags &= ~PHP_RUNKIT_OVERRIDE_OBJECTS;
+ }
+#endif
+
if (compile_file != zend_compile_file) {
/* An accellerator or other dark force is at work
* Use the wrapper method to force the builtin compiler
Oops, something went wrong.

0 comments on commit 07179d7

Please sign in to comment.