]> granicus.if.org Git - php/commitdiff
Improved fix for bug #70262
authorXinchen Hui <laruence@php.net>
Tue, 18 Aug 2015 10:07:31 +0000 (18:07 +0800)
committerXinchen Hui <laruence@php.net>
Tue, 18 Aug 2015 10:07:31 +0000 (18:07 +0800)
Zend/tests/bug70262.phpt
Zend/zend_execute.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

index 42e7fe0c1655ac2a089bea40ec86f640069eb214..7e285e8002f8d1a0b2d3bfd8574fb25b91418dd8 100644 (file)
@@ -2,33 +2,29 @@
 Bug #70262 (Accessing array crashes)
 --FILE--
 <?php
-class C {
-    public $arguments;
-    public function __construct($arg) {
-        $this->arguments = $arg;
-    }
-}
 
-function & a(&$arg) {
-    $c = new C($arg);
-    $arg[] = $c;
-    return $c;
-}
+$array = array();
+$array[] = 1; // make this not immutable
 
-function c($arr) {
-    a($arr)->arguments[0] = "bad";
+$extra = $array; // make the refcount == 2
+
+class A {
+    public function getObj($array) {
+        $obj = new Stdclass;
+        $obj->arr = $array; // make the refcount == 3;
+        return $obj;
+    }
 }
 
-$arr = array();
-$arr[] = "foo";
-$arr[] = "bar";
-c($arr);
-var_dump($arr);
+$a = new A;
+$a->getObj($array) //use function call to get a refcount == 1 IS_VAR object
+    ->arr // FETCH_OBJ_W will EXTRACT_ZVAL_PTR because getObj() result a refcount == 1 object (READY_TO_DESTROY)
+        [0] = "test"; //We will get a refcount == 3 array (not a IS_INDIRCT) in ZEND_ASSIGN_DIM_SPEC_VAR_CONST_HANDLER
+
+var_dump($array);
 ?>
 --EXPECT--
-array(2) {
+array(1) {
   [0]=>
-  string(3) "foo"
-  [1]=>
-  string(3) "bar"
+  int(1)
 }
index c3d8990940c0b0885b0c0650ea3c0ba105371870..dbf5c5086d5b142f2eb740e146da00d085716f82 100644 (file)
@@ -480,13 +480,8 @@ static zend_always_inline zval *_get_zval_ptr_ptr_var(uint32_t var, const zend_e
        if (EXPECTED(Z_TYPE_P(ret) == IS_INDIRECT)) {
                *should_free = NULL;
                ret = Z_INDIRECT_P(ret);
-       } else if (!Z_REFCOUNTED_P(ret)) {
-               *should_free = ret; /* immutable array may be converted to regular */
-       } else if (Z_REFCOUNT_P(ret) == 1) {
-               *should_free = ret;
        } else {
-               *should_free = NULL;
-               Z_DELREF_P(ret);
+               *should_free = ret; /* immutable array may be converted to regular */
        }
        return ret;
 }
index 9ee27d84d07cc5e030bcdb29a634defed239e43a..eceed13bae5b5a735b6af7b277c19d2e24a80c65 100644 (file)
@@ -7250,11 +7250,11 @@ ZEND_VM_HANDLER(156, ZEND_SEPARATE, VAR, UNUSED)
        zval *var_ptr;
 
        var_ptr = EX_VAR(opline->op1.var);
-       if (UNEXPECTED(Z_ISREF_P(var_ptr))) {
-               if (UNEXPECTED(Z_REFCOUNT_P(var_ptr) == 1)) {
-                       ZVAL_UNREF(var_ptr);
-               }
-       } else if (Z_COPYABLE_P(var_ptr) && Z_REFCOUNT_P(var_ptr) > 1) {
+       if (Z_TYPE_P(var_ptr) != IS_OBJECT &&
+           !Z_ISREF_P(var_ptr) &&
+           Z_REFCOUNTED_P(var_ptr) &&
+           Z_REFCOUNT_P(var_ptr) > 1) {
+
                Z_DELREF_P(var_ptr);
                ZVAL_DUP(EX_VAR(opline->op1.var), var_ptr);
        }
index 8dd8881299eae845717e81cbfa2354fdc6c5c1da..cf1c7a1e8fb90aa32fb226e5b58077184bba6897 100644 (file)
@@ -19444,11 +19444,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEPARATE_SPEC_VAR_UNUSED_HANDL
        zval *var_ptr;
 
        var_ptr = EX_VAR(opline->op1.var);
-       if (UNEXPECTED(Z_ISREF_P(var_ptr))) {
-               if (UNEXPECTED(Z_REFCOUNT_P(var_ptr) == 1)) {
-                       ZVAL_UNREF(var_ptr);
-               }
-       } else if (Z_COPYABLE_P(var_ptr) && Z_REFCOUNT_P(var_ptr) > 1) {
+       if (Z_TYPE_P(var_ptr) != IS_OBJECT &&
+           !Z_ISREF_P(var_ptr) &&
+           Z_REFCOUNTED_P(var_ptr) &&
+           Z_REFCOUNT_P(var_ptr) > 1) {
+
                Z_DELREF_P(var_ptr);
                ZVAL_DUP(EX_VAR(opline->op1.var), var_ptr);
        }