Skip to content

Commit

Permalink
Fixes of issues with importing constant arrays into properties and co…
Browse files Browse the repository at this point in the history
…nstants.

Fixes of issues with importing functions or methods having static variables inside them.
Some new tests were added.
  • Loading branch information
zenovich committed Sep 24, 2010
1 parent 6804778 commit c74fcca
Show file tree
Hide file tree
Showing 9 changed files with 227 additions and 28 deletions.
79 changes: 51 additions & 28 deletions runkit_import.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,36 +45,34 @@ static int php_runkit_import_functions(HashTable *function_table, long flags TSR
if (((type = zend_hash_get_current_key_ex(function_table, &key, &key_len, &idx, 0, &pos)) != HASH_KEY_NON_EXISTANT) &&
fe && fe->type == ZEND_USER_FUNCTION) {

if (type == HASH_KEY_IS_STRING) {
new_key = key;
new_key_len = key_len;
exists = zend_hash_exists(EG(function_table), new_key, new_key_len);
} else {
exists = zend_hash_index_exists(EG(function_table), idx);
}

if (exists) {
if (flags & PHP_RUNKIT_IMPORT_OVERRIDE) {
if (type == HASH_KEY_IS_STRING) {
if (zend_hash_del(EG(function_table), new_key, new_key_len) == FAILURE) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Inconsistency cleaning up import environment");
return FAILURE;
}
} else {
if (zend_hash_index_del(EG(function_table), idx) == FAILURE) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Inconsistency cleaning up import environment");
return FAILURE;
}
}
if (type == HASH_KEY_IS_STRING) {
new_key = key;
new_key_len = key_len;
exists = zend_hash_exists(EG(function_table), new_key, new_key_len);
} else {
add_function = 0;
exists = zend_hash_index_exists(EG(function_table), idx);
}

if (exists) {
if (flags & PHP_RUNKIT_IMPORT_OVERRIDE) {
if (type == HASH_KEY_IS_STRING) {
if (zend_hash_del(EG(function_table), new_key, new_key_len) == FAILURE) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Inconsistency cleaning up import environment");
return FAILURE;
}
} else {
if (zend_hash_index_del(EG(function_table), idx) == FAILURE) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Inconsistency cleaning up import environment");
return FAILURE;
}
}
} else {
add_function = 0;
}
}
}
}

if (add_function) {
PHP_RUNKIT_FUNCTION_ADD_REF(fe);

if (zend_hash_add(EG(function_table), new_key, new_key_len, fe, sizeof(zend_function), NULL) == FAILURE) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failure importing %s()", fe->common.function_name);
#ifdef ZEND_ENGINE_2
Expand All @@ -83,6 +81,9 @@ static int php_runkit_import_functions(HashTable *function_table, long flags TSR
destroy_end_function(fe);
#endif
return FAILURE;
} else {
fe->op_array.static_variables = NULL;
(*fe->op_array.refcount)++;
}
}
zend_hash_move_forward_ex(function_table, &pos);
Expand Down Expand Up @@ -147,18 +148,20 @@ static int php_runkit_import_class_methods(zend_class_entry *dce, zend_class_ent
}
}

PHP_RUNKIT_FUNCTION_ADD_REF(fe);
#ifdef ZEND_ENGINE_2
fe->common.scope = dce;
#endif
zend_hash_apply_with_arguments(RUNKIT_53_TSRMLS_PARAM(EG(class_table)), (apply_func_args_t)php_runkit_update_children_methods, 5, dce, dce, fe, fn, fn_len);

if (zend_hash_add(&dce->function_table, fn, fn_len + 1, fe, sizeof(zend_function), NULL) == FAILURE) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failure importing %s::%s()", ce->name, fe->common.function_name);
zend_hash_move_forward_ex(&ce->function_table, &pos);
continue;
} else {
fe->op_array.static_variables = NULL;
(*fe->op_array.refcount)++;
}

zend_hash_apply_with_arguments(RUNKIT_53_TSRMLS_PARAM(EG(class_table)), (apply_func_args_t)php_runkit_update_children_methods, 5, dce, dce, fe, fn, fn_len);

zend_hash_move_forward_ex(&ce->function_table, &pos);
}

Expand Down Expand Up @@ -234,6 +237,16 @@ static int php_runkit_import_class_static_props(zend_class_entry *dce, zend_clas
goto import_st_prop_skip;
}
}

if (
Z_TYPE_PP(c) == IS_CONSTANT_ARRAY
#if RUNKIT_ABOVE53
|| (Z_TYPE_PP(c) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT
#endif
) {
zval_update_constant_ex(c, (void*) 1, dce TSRMLS_CC);
}

Z_ADDREF_P(*c);
if (zend_hash_add_or_update(CE_STATIC_MEMBERS(dce), key, key_len, (void*)c, sizeof(zval*), NULL, action) == FAILURE) {
zval_ptr_dtor(c);
Expand Down Expand Up @@ -282,6 +295,16 @@ static int php_runkit_import_class_props(zend_class_entry *dce, zend_class_entry
goto import_prop_skip;
}
}

if (
Z_TYPE_PP(p) == IS_CONSTANT_ARRAY
#if RUNKIT_ABOVE53
|| (Z_TYPE_PP(p) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT
#endif
) {
zval_update_constant_ex(p, (void*) 1, dce TSRMLS_CC);
}

Z_ADDREF_P(*p);
if (zend_hash_add_or_update(&dce->default_properties, key, key_len, (void*)p, sizeof(zval*), NULL, action) == FAILURE) {
zval_ptr_dtor(p);
Expand Down
8 changes: 8 additions & 0 deletions tests/runkit_import_constant_properties.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php
return new Test;

class Test {
const C = 4;
public $v = array(Test::C,5,6);
}

47 changes: 47 additions & 0 deletions tests/runkit_import_constant_properties.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
--TEST--
runkit_import() Importing and overriding property with constant array as the value
--SKIPIF--
<?php
if(!extension_loaded("runkit")) print "skip";
?>
--FILE--
<?php
class Test {
const C = 1;
public $v = array(Test::C,2,3);
}

$t = new Test;
var_dump($t->v);
runkit_import(dirname(__FILE__) . '/runkit_import_constant_properties.inc', RUNKIT_IMPORT_CLASS_PROPS | RUNKIT_IMPORT_OVERRIDE);
$t = new Test;
var_dump($t->v);
runkit_import(dirname(__FILE__) . '/runkit_import_constant_properties.inc', RUNKIT_IMPORT_CLASSES | RUNKIT_IMPORT_OVERRIDE);
$t = new Test;
var_dump($t->v);
?>
--EXPECT--
array(3) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
}
array(3) {
[0]=>
int(1)
[1]=>
int(5)
[2]=>
int(6)
}
array(3) {
[0]=>
int(4)
[1]=>
int(5)
[2]=>
int(6)
}
8 changes: 8 additions & 0 deletions tests/runkit_import_constant_static_properties.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php
return new Test;

class Test {
const C = 4;
public static $v = array(Test::C,5,6);
}

44 changes: 44 additions & 0 deletions tests/runkit_import_constant_static_properties.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
--TEST--
runkit_import() Importing and overriding static property with constant array as the value
--SKIPIF--
<?php
if(!extension_loaded("runkit")) print "skip";
?>
--FILE--
<?php
class Test {
const C = 1;
public static $v = array(Test::C,2,3);
}

var_dump(Test::$v);
runkit_import(dirname(__FILE__) . '/runkit_import_constant_static_properties.inc', RUNKIT_IMPORT_CLASS_STATIC_PROPS | RUNKIT_IMPORT_OVERRIDE);
var_dump(Test::$v);
runkit_import(dirname(__FILE__) . '/runkit_import_constant_static_properties.inc', RUNKIT_IMPORT_CLASSES | RUNKIT_IMPORT_OVERRIDE);
var_dump(Test::$v);
?>
--EXPECT--
array(3) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
}
array(3) {
[0]=>
int(1)
[1]=>
int(5)
[2]=>
int(6)
}
array(3) {
[0]=>
int(4)
[1]=>
int(5)
[2]=>
int(6)
}
6 changes: 6 additions & 0 deletions tests/runkit_import_function_with_static_var.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?php
function f() {
static $v = 1;
$v++;
echo $v, "\n";
}
25 changes: 25 additions & 0 deletions tests/runkit_import_function_with_static_var.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
--TEST--
runkit_import() Importing and overriding function with a static variable
--SKIPIF--
<?php
if(!extension_loaded("runkit")) print "skip";
?>
--FILE--
<?php
function f() {
static $v = 0;
$v++;
echo $v, "\n";
}

f();
runkit_import(dirname(__FILE__) . '/runkit_import_function_with_static_var.inc', RUNKIT_IMPORT_FUNCTIONS | RUNKIT_IMPORT_OVERRIDE);
f();
runkit_import(dirname(__FILE__) . '/runkit_import_function_with_static_var.inc', RUNKIT_IMPORT_FUNCTIONS | RUNKIT_IMPORT_OVERRIDE);
f();
?>
--EXPECT--
1
2
2

10 changes: 10 additions & 0 deletions tests/runkit_import_method_with_static_var.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php
return new Test;

class Test {
public function f() {
static $v = 1;
$v++;
echo $v, "\n";
}
}
28 changes: 28 additions & 0 deletions tests/runkit_import_method_with_static_var.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
--TEST--
runkit_import() Importing and overriding method with a static variable
--SKIPIF--
<?php
if(!extension_loaded("runkit")) print "skip";
?>
--FILE--
<?php
class Test {
public function f() {
static $v = 0;
$v++;
echo $v, "\n";
}
}

$t = new Test;
$t->f();
runkit_import(dirname(__FILE__) . '/runkit_import_method_with_static_var.inc', RUNKIT_IMPORT_CLASSES | RUNKIT_IMPORT_OVERRIDE);
$t->f();
runkit_import(dirname(__FILE__) . '/runkit_import_method_with_static_var.inc', RUNKIT_IMPORT_CLASSES | RUNKIT_IMPORT_OVERRIDE);
$t->f();
?>
--EXPECT--
1
2
2

0 comments on commit c74fcca

Please sign in to comment.