Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Bug 57649 (https://bugs.php.net/bug.php?id=57649) has been fixed with…

…out apathy ;)

New tests from github.com/php/pecl-php-runkit have been added (thanks to sgolemon).
Some memory allocation problems have been resolved.
  • Loading branch information...
commit c5926993a839b1ac917d4dcc6857d226ad216d65 1 parent 07179d7
@zenovich authored
View
14 package.xml
@@ -68,6 +68,8 @@ Execute code in restricted environment (sandboxing).
* A test for correctness of runkit.superglobals feature was added
* Tests for correctness of inheritance of properties were added
* Tests for correctness of adding static properties were added
+ * Bug 57649 (https://bugs.php.net/bug.php?id=57649) has been fixed without apathy ;)
+ Thanks to Sara Golemon for tests.
Build system improvements:
* Declarations after statement were restricted during compiling
@@ -228,6 +230,7 @@ Execute code in restricted environment (sandboxing).
<file name="runkit_static_property_add.phpt" role="test" />
<file name="runkit_static_property_add_existing.phpt" role="test" />
<file name="runkit_static_property_add_to_subclasses.phpt" role="test" />
+ <file name="runkit_static_vars.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" />
@@ -246,6 +249,17 @@ Execute code in restricted environment (sandboxing).
<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" />
+ <file name="bug56662.phpt" role="test" />
+ <file name="bug56976.phpt" role="test" />
+ <file name="bug57249.inc" role="test" />
+ <file name="bug57249.phpt" role="test" />
+ <file name="bug57649.inc" role="test" />
+ <file name="bug57649.phpt" role="test" />
+ <file name="bug57658.phpt" role="test" />
+ <file name="runkit_import_methods1.inc" role="test" />
+ <file name="runkit_import_methods2.inc" role="test" />
+ <file name="runkit_import_methods.phpt" role="test" />
+ <file name="runkit_method_rename_002.phpt" role="test" />
</dir> <!-- //tests -->
<file name="config.m4" role="src" />
<file name="config.w32" role="src" />
View
3  php_runkit.h
@@ -270,6 +270,9 @@ zend_class_entry *_php_runkit_locate_scope(zend_class_entry *ce, zend_function *
/* runkit_constants.c */
int php_runkit_update_children_consts(RUNKIT_53_TSRMLS_ARG(void *pDest), int num_args, va_list args, zend_hash_key *hash_key);
+/* runkit_classes.c */
+int php_runkit_class_copy(zend_class_entry *src, const char *classname, int classname_len TSRMLS_DC);
+
/* 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, int override_in_objects TSRMLS_DC);
View
63 runkit_classes.c
@@ -144,6 +144,69 @@ static int php_runkit_inherit_methods(zend_function *fe, zend_class_entry *ce TS
}
/* }}} */
+/* {{{ php_runkit_class_copy
+ Copy class into class table */
+int php_runkit_class_copy(zend_class_entry *src, const char *classname, int classname_len TSRMLS_DC)
+{
+ zend_class_entry *new_class_entry;
+
+#ifndef ZEND_ENGINE_2
+ new_class_entry = emalloc(sizeof(zend_class_entry));
+
+ new_class_entry->type = ZEND_USER_CLASS;
+ new_class_entry->name = estrdup(classname);
+ new_class_entry->name_length = classname_len;
+ new_class_entry->refcount = (int *) emalloc(sizeof(int));
+ *(new_class_entry->refcount) = 1;
+ new_class_entry->constants_updated = 0;
+
+ zend_hash_init(&new_class_entry->function_table, 10, NULL, ZEND_FUNCTION_DTOR, 0);
+ zend_hash_init(&new_class_entry->default_properties, 10, NULL, ZVAL_PTR_DTOR, 0);
+
+ new_class_entry->handle_function_call = src->handle_function_call;
+ new_class_entry->handle_property_set = src->handle_property_set;
+ new_class_entry->handle_property_get = src->handle_property_get;
+
+ new_class_entry->parent = src->parent;
+
+ zend_hash_update(CG(class_table), new_class_entry->name, classname_len, new_class_entry, sizeof(zend_class_entry), (void **) &new_class_entry);
+#else
+ char *lcname;
+
+ new_class_entry = emalloc(sizeof(zend_class_entry));
+ new_class_entry->type = ZEND_USER_CLASS;
+ new_class_entry->name = estrndup(classname, classname_len);
+ new_class_entry->name_length = classname_len;
+
+ zend_initialize_class_data(new_class_entry, 1 TSRMLS_CC);
+#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
+ new_class_entry->info.user.filename = src->info.user.filename;
+ new_class_entry->info.user.line_start = src->info.user.line_start;
+ new_class_entry->info.user.doc_comment = src->info.user.doc_comment;
+ new_class_entry->info.user.doc_comment_len = src->info.user.doc_comment_len;
+ new_class_entry->info.user.line_end = src->info.user.line_end;
+ new_class_entry->num_traits = src->num_traits;
+ new_class_entry->traits = src->traits;
+#else
+ new_class_entry->filename = src->filename;
+ new_class_entry->line_start = src->line_start;
+ new_class_entry->doc_comment = src->doc_comment;
+ new_class_entry->doc_comment_len = src->doc_comment_len;
+ new_class_entry->line_end = src->line_end;
+#endif
+ new_class_entry->ce_flags = src->ce_flags;
+
+ lcname = zend_str_tolower_dup(classname, classname_len);
+ zend_hash_update(EG(class_table), lcname, classname_len + 1, &new_class_entry, sizeof(zend_class_entry *), NULL);
+ efree(lcname);
+
+
+ new_class_entry->num_interfaces = src->num_interfaces;
+#endif
+ return SUCCESS;
+}
+/* }}} */
+
/* {{{ proto bool runkit_class_adopt(string classname, string parentname)
Convert a base class to an inherited class, add ancestral methods when appropriate */
PHP_FUNCTION(runkit_class_adopt)
View
91 runkit_import.c
@@ -427,6 +427,8 @@ static int php_runkit_import_classes(HashTable *class_table, long flags
uint key_len;
int type;
ulong idx;
+ char *lcname;
+ zend_class_entry *dce;
zend_hash_get_current_data_ex(class_table, (void*)&ce, &pos);
#ifdef ZEND_ENGINE_2
@@ -440,57 +442,68 @@ static int php_runkit_import_classes(HashTable *class_table, long flags
return FAILURE;
}
- if (((type = zend_hash_get_current_key_ex(EG(class_table), &key, &key_len, &idx, 0, &pos)) != HASH_KEY_NON_EXISTANT) &&
- ce && ce->type == ZEND_USER_CLASS) {
- zend_class_entry *dce;
+ if (ce->type != ZEND_USER_CLASS) {
+ php_error_docref(NULL TSRMLS_CC, E_ERROR, "Cannot import internal class!");
+ return FAILURE;
+ }
- if (php_runkit_fetch_class(ce->name, ce->name_length, &dce TSRMLS_CC) == FAILURE) {
- /* Oddly non-existant target class or error retreiving it... Or it's an internal class... */
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot redeclare class %s", ce->name);
- continue;
- }
+ type = zend_hash_get_current_key_ex(class_table, &key, &key_len, &idx, 0, &pos);
+
+ lcname = estrndup(ce->name, ce->name_length);
+ if (lcname == NULL) {
+ php_error_docref(NULL TSRMLS_CC, E_ERROR, "Not enough memory");
+ return FAILURE;
+ }
+ php_strtolower(lcname, ce->name_length);
+
+ if (!zend_hash_exists(EG(class_table), lcname, ce->name_length + 1)) {
+ php_runkit_class_copy(ce, ce->name, ce->name_length TSRMLS_CC);
+ }
+ efree(lcname);
+
+ if (php_runkit_fetch_class(ce->name, ce->name_length, &dce TSRMLS_CC) == FAILURE) {
+ /* Oddly non-existant target class or error retreiving it... Or it's an internal class... */
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot redeclare class %s", ce->name);
+ continue;
+ }
#ifdef ZEND_ENGINE_2
- if (flags & PHP_RUNKIT_IMPORT_CLASS_CONSTS) {
- 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) != 0,
- (flags & PHP_RUNKIT_OVERRIDE_OBJECTS) != 0
- TSRMLS_CC);
- }
+ if (flags & PHP_RUNKIT_IMPORT_CLASS_CONSTS) {
+ 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) != 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) != 0,
- (flags & PHP_RUNKIT_OVERRIDE_OBJECTS) != 0
- TSRMLS_CC);
- }
+ if (flags & PHP_RUNKIT_IMPORT_CLASS_PROPS) {
+ 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) {
- php_runkit_import_class_methods(dce, ce, (flags & PHP_RUNKIT_IMPORT_OVERRIDE)
+ if (flags & PHP_RUNKIT_IMPORT_CLASS_METHODS) {
+ 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
+ , clear_cache
#endif
- TSRMLS_CC);
- }
+ TSRMLS_CC);
+ }
- zend_hash_move_forward_ex(class_table, &pos);
+ zend_hash_move_forward_ex(class_table, &pos);
- if (type == HASH_KEY_IS_STRING) {
- if (zend_hash_del(class_table, key, key_len) == FAILURE) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to remove temporary version of class %s", ce->name);
- continue;
- }
- } else {
- if (zend_hash_index_del(class_table, idx) == FAILURE) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to remove temporary version of class %s", ce->name);
- continue;
- }
+ if (type == HASH_KEY_IS_STRING) {
+ if (zend_hash_del(class_table, key, key_len) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to remove temporary version of class %s", ce->name);
+ continue;
}
} else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can not find class definition in class table");
- return FAILURE;
+ if (zend_hash_index_del(class_table, idx) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to remove temporary version of class %s", ce->name);
+ continue;
+ }
}
}
View
4 runkit_methods.c
@@ -697,9 +697,7 @@ PHP_FUNCTION(runkit_method_rename)
#endif
func = *fe;
- PHP_RUNKIT_FUNCTION_ADD_REF(&func);
- efree((void*) func.common.function_name);
- func.common.function_name = estrndup(newname, newname_len + 1);
+ php_runkit_function_copy_ctor(&func, newname, newname_len TSRMLS_CC);
if (zend_hash_add(&ce->function_table, newname_lower, newname_len + 1, &func, sizeof(zend_function), NULL) == FAILURE) {
efree(newname_lower);
View
30 tests/bug56662.phpt
@@ -0,0 +1,30 @@
+--TEST--
+Bug#56662 - Wrong access level with RUNKIT_ACC_PUBLIC
+--SKIPIF--
+<?php if(!extension_loaded("runkit")) print "skip";
+ if(version_compare(PHP_VERSION, '5.0.0', '<')) print "skip";
+?>
+--FILE--
+<?php
+class A {}
+runkit_method_add ('A', 'x', '', '', RUNKIT_ACC_PUBLIC);
+Reflection::export(new ReflectionMethod('A', 'x'));
+
+class B extends A { public function x() {} }
+Reflection::export(new ReflectionMethod('B', 'x'));
+
+eval("class C extends A { public function x() {} }");
+Reflection::export(new ReflectionMethod('C', 'x'));
+
+--EXPECTF--
+Method [ <user%S> public method x ] {
+ @@ %s/tests/bug56662.php(3) : runkit runtime-created function 1 - 1
+}
+
+Method [ <user, overwrites A%S> public method x ] {
+ @@ %s/tests/bug56662.php 6 - 6
+}
+
+Method [ <user, overwrites A, prototype A> public method x ] {
+ @@ %s/tests/bug56662.php(9) : eval()'d code 1 - 1
+}
View
32 tests/bug56976.phpt
@@ -0,0 +1,32 @@
+--TEST--
+Bug#56976 - Failure adding __call method
+--SKIPIF--
+<?php if(!extension_loaded("runkit")) print "skip";
+ if(version_compare(PHP_VERSION, '5.0.0', '<')) print "skip";
+?>
+--FILE--
+<?php
+class ParentClass
+{
+ public function foo()
+ {
+ echo "ParentClass::foo\n";
+ }
+}
+
+class ChildClass extends ParentClass { }
+
+var_dump(runkit_method_add('ParentClass', '__call', '$method, $args',
+ 'echo "In ParentClass::__call()\n";' .
+ 'call_user_func_array(array($this, "prefix_{$method}"), $args);'));
+
+var_dump(runkit_method_rename('ChildClass', 'foo', 'prefix_foo'));
+
+$o = new ChildClass;
+$o->foo();
+
+--EXPECT--
+bool(true)
+bool(true)
+In ParentClass::__call()
+ParentClass::foo
View
7 tests/bug57249.inc
@@ -0,0 +1,7 @@
+<?php
+class cBuggyClass {
+ public function mBuggyMethod() {
+ static $ls_a_iCache;
+ echo 'mBuggyMethod();'.PHP_EOL;
+ }
+}
View
16 tests/bug57249.phpt
@@ -0,0 +1,16 @@
+--TEST--
+Bug#57249 - Sutdown bug with runkit_import on a function-static variable
+--SKIPIF--
+<?php if(!extension_loaded("runkit")) print "skip";
+ if(version_compare(PHP_VERSION, '5.0.0', '<')) print "skip";
+?>
+--FILE--
+<?php
+runkit_import('bug57249.inc', RUNKIT_IMPORT_CLASS_METHODS);
+$g_oBuggyObject = new cBuggyClass();
+$g_oBuggyObject->mBuggyMethod();
+
+class cBuggyClass { }
+
+--EXPECT--
+mBuggyMethod();
View
8 tests/bug57649.inc
@@ -0,0 +1,8 @@
+<?php
+class a {
+ public function foo() {
+ echo "foo()\n";
+ }
+}
+
+class c { }
View
26 tests/bug57649.phpt
@@ -0,0 +1,26 @@
+--TEST--
+Bug#57649 - runkit_import() - methods not added - multiple classes in one file
+--SKIPIF--
+<?php if(!extension_loaded("runkit")) print "skip";
+ if(version_compare(PHP_VERSION, '5.0.0', '<')) print "skip";
+?>
+--FILE--
+<?php
+class b {
+ public function foobar() {
+ echo "foobar()\n";
+ }
+}
+
+class a extends b { }
+
+runkit_import( dirname(__FILE__) . "/bug57649.inc" );
+
+$a = new a();
+$a->foobar();
+$a->foo();
+var_dump(class_exists('c'));
+--EXPECT--
+foobar()
+foo()
+bool(true)
View
16 tests/bug57658.phpt
@@ -0,0 +1,16 @@
+--TEST--
+Bug#57658 - runkit_class_adopt fails on method names with capitals
+--SKIPIF--
+<?php if(!extension_loaded("runkit")) print "skip"; ?>
+--FILE--
+<?php
+if (version_compare(phpversion(), "5.0.0") >= 0) {
+ error_reporting(E_ALL & ~E_STRICT);
+}
+
+class A { function aB() { print "a";} function aC() { echo "d"; } }
+class B { function aB() { print "b";} }
+runkit_class_adopt("B", "A");
+B::aC();
+--EXPECT--
+d
View
35 tests/runkit_import_methods.phpt
@@ -0,0 +1,35 @@
+--TEST--
+runkit_import() Importing and overriding class methods
+--SKIPIF--
+<?php if(!extension_loaded("runkit")) print "skip"; ?>
+--FILE--
+<?php
+
+if (version_compare(phpversion(), "5.0.0") >= 0) {
+ error_reporting(E_ALL & ~E_STRICT);
+}
+
+class ParentClass {
+ function foo() {
+ echo "Parent::foo\n";
+ }
+}
+
+include dirname(__FILE__) . '/runkit_import_methods1.inc';
+
+ParentClass::foo();
+Child::foo();
+
+runkit_import(dirname(__FILE__) . '/runkit_import_methods2.inc', RUNKIT_IMPORT_CLASS_METHODS);
+Child::foo();
+
+runkit_import(dirname(__FILE__) . '/runkit_import_methods2.inc', RUNKIT_IMPORT_CLASS_METHODS | RUNKIT_IMPORT_OVERRIDE);
+Child::foo();
+
+--EXPECTF--
+Parent::foo
+Child1::foo
+
+Notice: runkit_import(): %child::foo() already exists, not importing in %s/runkit_import_methods.php on line %d
+Child1::foo
+Child2::foo
View
7 tests/runkit_import_methods1.inc
@@ -0,0 +1,7 @@
+<?php
+
+class Child extends ParentClass {
+ function foo() {
+ echo "Child1::foo\n";
+ }
+}
View
7 tests/runkit_import_methods2.inc
@@ -0,0 +1,7 @@
+<?php
+
+class Child extends ParentClass {
+ function foo() {
+ echo "Child2::foo\n";
+ }
+}
View
47 tests/runkit_method_rename_002.phpt
@@ -0,0 +1,47 @@
+--TEST--
+Rename children of ancestor methods
+--SKIPIF--
+<?php if(!extension_loaded("runkit")) print "skip";
+ if(version_compare(PHP_VERSION, '5.0.0', '<')) print "skip";
+?>
+--FILE--
+<?php
+function getClassMethods($class)
+{
+ $methods = array();
+ $class = new ReflectionClass($class);
+ foreach ($class->getMethods() as $method) {
+ array_push($methods, $method->getName());
+ }
+ return $methods;
+}
+
+class Ancestor
+{
+ public function __construct(){}
+}
+
+class Descendant extends Ancestor
+{
+ public function someMethod(){}
+}
+
+class AnotherDescendant extends Ancestor
+{
+ public function anotherMethod(){}
+}
+
+runkit_method_rename('Ancestor', '__construct', 'abcdefghmnoprst');
+print_r(getClassMethods('Descendant'));
+print_r(getClassMethods('AnotherDescendant'));
+--EXPECT--
+Array
+(
+ [0] => someMethod
+ [1] => abcdefghmnoprst
+)
+Array
+(
+ [0] => anotherMethod
+ [1] => abcdefghmnoprst
+)
View
43 tests/runkit_static_vars.phpt
@@ -0,0 +1,43 @@
+--TEST--
+Static Variables in runkit modified functions
+--SKIPIF--
+<?php if(!extension_loaded("runkit") || !RUNKIT_FEATURE_MANIPULATION) print "skip";
+ if(version_compare(PHP_VERSION, '5.0.0', '<')) print "skip";
+?>
+--FILE--
+<?php
+function orig() {
+ static $x = 0;
+ var_dump(++$x);
+}
+
+orig();
+runkit_function_copy('orig', 'funccopy');
+funccopy();
+runkit_function_remove('orig');
+funccopy();
+
+echo "====\n";
+
+class C {
+ public function orig() {
+ static $x = 0;
+ var_dump(++$x);
+ }
+}
+$c = new C;
+
+$c->orig();
+runkit_method_copy('C', 'copy', 'C', 'orig');
+$c->copy();
+runkit_method_remove('C', 'orig');
+$c->copy();
+
+--EXPECT--
+int(1)
+int(2)
+int(3)
+====
+int(1)
+int(2)
+int(3)
Please sign in to comment.
Something went wrong with that request. Please try again.