diff options
author | Xinchen Hui <laruence@gmail.com> | 2015-10-03 20:08:21 -0700 |
---|---|---|
committer | Xinchen Hui <laruence@gmail.com> | 2015-10-03 20:08:21 -0700 |
commit | 4744eec753786e18b28887463bdcb3f1e91efb60 (patch) | |
tree | c3273c287f1f8c841797648e4fe48f6bd13e7ce7 /ext | |
parent | 925412ee1c123c55e2b5badf6daf193e6c1bdd5b (diff) | |
download | php-git-4744eec753786e18b28887463bdcb3f1e91efb60.tar.gz |
Fixed bug #70631 (Another Segfault in gc_remove_from_buffer())
Diffstat (limited to 'ext')
-rw-r--r-- | ext/opcache/tests/bug70631.phpt | 20 | ||||
-rw-r--r-- | ext/reflection/php_reflection.c | 30 |
2 files changed, 49 insertions, 1 deletions
diff --git a/ext/opcache/tests/bug70631.phpt b/ext/opcache/tests/bug70631.phpt new file mode 100644 index 0000000000..1089329fe2 --- /dev/null +++ b/ext/opcache/tests/bug70631.phpt @@ -0,0 +1,20 @@ +--TEST-- +Bug #70631 (Another Segfault in gc_remove_from_buffer()) +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.protect_memory=1 +--SKIPIF-- +<?php if (!extension_loaded('Zend OPcache') || !extension_loaded("Reflection")) die("skip"); ?> +--FILE-- +<?php + +function x($x = array("Okay")) {} + +$func = new ReflectionFunction('x'); +$params = $func->getParameters(); +$value = $params[0]->getDefaultValue(); +echo $value[0]; +?> +--EXPECT-- +Okay diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index eff8bdc65b..3bf49eafc7 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -242,6 +242,25 @@ static void _default_lookup_entry(zval *object, char *name, int name_len, zval * /* }}} */ #endif +static void reflection_zval_deep_copy(zval **p) +{ + zval *value; + + ALLOC_ZVAL(value); + *value = **p; + if (Z_TYPE_P(value) == IS_ARRAY) { + HashTable *ht; + + ALLOC_HASHTABLE(ht); + zend_hash_init(ht, zend_hash_num_elements(Z_ARRVAL_P(value)), NULL, ZVAL_PTR_DTOR, 0); + zend_hash_copy(ht, Z_ARRVAL_P(value), (copy_ctor_func_t) reflection_zval_deep_copy, NULL, sizeof(zval *)); + Z_ARRVAL_P(value) = ht; + } else { + zval_copy_ctor(value); + } + INIT_PZVAL(value); + *p = value; +} static void reflection_register_implement(zend_class_entry *class_entry, zend_class_entry *interface_entry TSRMLS_DC) /* {{{ */ { zend_uint num_interfaces = ++class_entry->num_interfaces; @@ -2606,7 +2625,16 @@ ZEND_METHOD(reflection_parameter, getDefaultValue) *return_value = *precv->op2.zv; INIT_PZVAL(return_value); if (!IS_CONSTANT_TYPE(Z_TYPE_P(return_value))) { - zval_copy_ctor(return_value); + if (Z_TYPE_P(return_value) != IS_ARRAY) { + zval_copy_ctor(return_value); + } else { + HashTable *ht; + + ALLOC_HASHTABLE(ht); + zend_hash_init(ht, zend_hash_num_elements(Z_ARRVAL_P(return_value)), NULL, ZVAL_PTR_DTOR, 0); + zend_hash_copy(ht, Z_ARRVAL_P(return_value), (copy_ctor_func_t) reflection_zval_deep_copy, NULL, sizeof(zval *)); + Z_ARRVAL_P(return_value) = ht; + } } old_scope = EG(scope); EG(scope) = param->fptr->common.scope; |