]> granicus.if.org Git - php/commitdiff
Fixed bug #73288 (Segfault in __clone > Exception.toString > __get)
authorXinchen Hui <laruence@gmail.com>
Wed, 12 Oct 2016 08:07:56 +0000 (16:07 +0800)
committerAnatol Belski <ab@php.net>
Thu, 13 Oct 2016 23:35:39 +0000 (01:35 +0200)
Actually this is caused by optimization(opcache)

(cherry picked from commit d19898b2981c839f0758571c1b83052111634154)

Zend/tests/bug73288.phpt [new file with mode: 0644]
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

diff --git a/Zend/tests/bug73288.phpt b/Zend/tests/bug73288.phpt
new file mode 100644 (file)
index 0000000..fefcf3b
--- /dev/null
@@ -0,0 +1,34 @@
+--TEST--
+Bug #73288 (Segfault in __clone > Exception.toString > __get)
+--INI--
+opcache.enable=1
+opcache.enable_cli=1
+--FILE--
+<?php
+
+class NoClone {
+       public function __clone() {
+               throw new Exception("No Cloneable");
+       }
+}
+
+class C {
+       public function __get($name) {
+               return new NoClone;
+       }
+}
+
+function test_clone() {
+       $c = new C;
+       $b = clone $c->x;
+}
+
+test_clone();
+?>
+--EXPECTF--
+Fatal error: Uncaught Exception: No Cloneable in %sbug73288.php:%d
+Stack trace:
+#0 %s(%d): NoClone->__clone()
+#1 %s(%d): test_clone()
+#2 {main}
+  thrown in %sbug73288.php on line %d
index fb7010e40a6da7dc05193629840fc2a93ebee165..253443003e393c8bdfe3074d9506ab5717c250f8 100644 (file)
@@ -5000,6 +5000,7 @@ ZEND_VM_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|THIS|CV, ANY)
        USE_OPLINE
        zend_free_op free_op1;
        zval *obj;
+       zend_object *clone_obj;
        zend_class_entry *ce, *scope;
        zend_function *clone;
        zend_object_clone_obj_t clone_call;
@@ -5064,9 +5065,11 @@ ZEND_VM_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|THIS|CV, ANY)
                }
        }
 
-       ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj));
-       if (UNEXPECTED(EG(exception) != NULL)) {
-               OBJ_RELEASE(Z_OBJ_P(EX_VAR(opline->result.var)));
+       clone_obj = clone_call(obj);
+       if (EXPECTED(EG(exception) == NULL)) {
+               ZVAL_OBJ(EX_VAR(opline->result.var), clone_obj);
+       } else {
+               OBJ_RELEASE(clone_obj);
        }
 
        FREE_OP1();
index f0b03d91c46c79cfee1e4f0afacbe5b30236778e..4c0907254570fff3a490e12ccba139957308c923 100644 (file)
@@ -3231,6 +3231,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_HANDLER(ZEND_
        USE_OPLINE
 
        zval *obj;
+       zend_object *clone_obj;
        zend_class_entry *ce, *scope;
        zend_function *clone;
        zend_object_clone_obj_t clone_call;
@@ -3295,9 +3296,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_HANDLER(ZEND_
                }
        }
 
-       ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj));
-       if (UNEXPECTED(EG(exception) != NULL)) {
-               OBJ_RELEASE(Z_OBJ_P(EX_VAR(opline->result.var)));
+       clone_obj = clone_call(obj);
+       if (EXPECTED(EG(exception) == NULL)) {
+               ZVAL_OBJ(EX_VAR(opline->result.var), clone_obj);
+       } else {
+               OBJ_RELEASE(clone_obj);
        }
 
        ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
@@ -27847,6 +27850,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND
        USE_OPLINE
 
        zval *obj;
+       zend_object *clone_obj;
        zend_class_entry *ce, *scope;
        zend_function *clone;
        zend_object_clone_obj_t clone_call;
@@ -27911,9 +27915,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND
                }
        }
 
-       ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj));
-       if (UNEXPECTED(EG(exception) != NULL)) {
-               OBJ_RELEASE(Z_OBJ_P(EX_VAR(opline->result.var)));
+       clone_obj = clone_call(obj);
+       if (EXPECTED(EG(exception) == NULL)) {
+               ZVAL_OBJ(EX_VAR(opline->result.var), clone_obj);
+       } else {
+               OBJ_RELEASE(clone_obj);
        }
 
        ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
@@ -35170,6 +35176,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPC
        USE_OPLINE
 
        zval *obj;
+       zend_object *clone_obj;
        zend_class_entry *ce, *scope;
        zend_function *clone;
        zend_object_clone_obj_t clone_call;
@@ -35234,9 +35241,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPC
                }
        }
 
-       ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj));
-       if (UNEXPECTED(EG(exception) != NULL)) {
-               OBJ_RELEASE(Z_OBJ_P(EX_VAR(opline->result.var)));
+       clone_obj = clone_call(obj);
+       if (EXPECTED(EG(exception) == NULL)) {
+               ZVAL_OBJ(EX_VAR(opline->result.var), clone_obj);
+       } else {
+               OBJ_RELEASE(clone_obj);
        }
 
        ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
@@ -51389,6 +51398,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_TMPVAR_HANDLER(ZEND
        USE_OPLINE
        zend_free_op free_op1;
        zval *obj;
+       zend_object *clone_obj;
        zend_class_entry *ce, *scope;
        zend_function *clone;
        zend_object_clone_obj_t clone_call;
@@ -51453,9 +51463,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_TMPVAR_HANDLER(ZEND
                }
        }
 
-       ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj));
-       if (UNEXPECTED(EG(exception) != NULL)) {
-               OBJ_RELEASE(Z_OBJ_P(EX_VAR(opline->result.var)));
+       clone_obj = clone_call(obj);
+       if (EXPECTED(EG(exception) == NULL)) {
+               ZVAL_OBJ(EX_VAR(opline->result.var), clone_obj);
+       } else {
+               OBJ_RELEASE(clone_obj);
        }
 
        zval_ptr_dtor_nogc(free_op1);