]> granicus.if.org Git - php/commitdiff
Fixed bug #70631 (Another Segfault in gc_remove_from_buffer())
authorXinchen Hui <laruence@gmail.com>
Sun, 4 Oct 2015 03:08:21 +0000 (20:08 -0700)
committerXinchen Hui <laruence@gmail.com>
Sun, 4 Oct 2015 03:08:21 +0000 (20:08 -0700)
NEWS
ext/opcache/tests/bug70631.phpt [new file with mode: 0644]
ext/reflection/php_reflection.c

diff --git a/NEWS b/NEWS
index 4adadb20835bd2ab864f56da9110e311b68345ae..79ca9877be78ee03b8fdeb50c9bf847da1988bdb 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -15,6 +15,7 @@ PHP                                                                        NEWS
   . Fixed bug #70572 segfault in mysqlnd_connect. (Andrey, Remi)
 
 - Opcache:
+  . Fixed bug #70631 (Another Segfault in gc_remove_from_buffer()). (Laruence)
   . Fixed bug #70601 (Segfault in gc_remove_from_buffer()). (Laruence)
 
 01 Oct 2015, PHP 5.6.14
diff --git a/ext/opcache/tests/bug70631.phpt b/ext/opcache/tests/bug70631.phpt
new file mode 100644 (file)
index 0000000..1089329
--- /dev/null
@@ -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
index eff8bdc65b0beaf8f4ade6f06f848e6d43dfd826..3bf49eafc7e74bfeadcecb23156c0df9a2f992ab 100644 (file)
@@ -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;