]> granicus.if.org Git - php/commitdiff
Fixed bug #72907 (null pointer deref, segfault in gc_remove_zval_from_buffer (zend_gc...
authorXinchen Hui <laruence@gmail.com>
Sun, 21 Aug 2016 09:10:10 +0000 (17:10 +0800)
committerXinchen Hui <laruence@gmail.com>
Sun, 21 Aug 2016 09:10:10 +0000 (17:10 +0800)
NEWS
Zend/tests/bug72907.phpt [new file with mode: 0644]
Zend/zend_execute.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

diff --git a/NEWS b/NEWS
index dca9d4f48bca641b578793ebeddfa30209835a90..608881ae6588deb10a30453b1df5f4caaf33825a 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,10 @@ PHP                                                                        NEWS
 |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
 ?? ??? 2016, PHP 5.6.26
 
+- Core:
+  . Fixed bug #72907 (null pointer deref, segfault in gc_remove_zval_from_buffer
+    (zend_gc.c:260)). (Laruence)
+
 - Streams:
   . Fixed bug #72853 (stream_set_blocking doesn't work). (Laruence)
 
diff --git a/Zend/tests/bug72907.phpt b/Zend/tests/bug72907.phpt
new file mode 100644 (file)
index 0000000..00d9f5d
--- /dev/null
@@ -0,0 +1,18 @@
+--TEST--
+Bug #72907 (null pointer deref, segfault in gc_remove_zval_from_buffer (zend_gc.c:260))
+--FILE--
+<?php
+
+$a = 0;
+
+($a->a = &$E) + ($b = $a->b->i -= 0);
+
+?>
+--EXPECTF--
+Warning: Attempt to modify property of non-object in %sbug72907.php on line %d
+
+Warning: Attempt to modify property of non-object in %sbug72907.php on line %d
+
+Warning: Creating default object from empty value in %sbug72907.php on line %d
+
+Notice: Undefined property: stdClass::$i in %sbug72907.php on line %d
index c7e4b926d8ceb8b8e14fae19f9029d2e91d91fd7..b422624bb19be424074c3aec6d1a89f2c7d655b9 100644 (file)
@@ -522,9 +522,7 @@ static void zend_assign_to_variable_reference(zval **variable_ptr_ptr, zval **va
        zval *variable_ptr = *variable_ptr_ptr;
        zval *value_ptr = *value_ptr_ptr;
 
-       if (variable_ptr == &EG(error_zval) || value_ptr == &EG(error_zval)) {
-               variable_ptr_ptr = &EG(uninitialized_zval_ptr);
-       } else if (variable_ptr != value_ptr) {
+       if (variable_ptr != value_ptr) {
                if (!PZVAL_IS_REF(value_ptr)) {
                        /* break it away */
                        Z_DELREF_P(value_ptr);
index 2e81f82e4989aa446d35cad0b5ac197d221b5b55..f79d8a3f9eb4a8bf0901f97eb74392829674525b 100644 (file)
@@ -1817,11 +1817,14 @@ ZEND_VM_HANDLER(39, ZEND_ASSIGN_REF, VAR|CV, VAR|CV)
        if ((OP2_TYPE == IS_VAR && UNEXPECTED(value_ptr_ptr == NULL)) ||
            (OP1_TYPE == IS_VAR && UNEXPECTED(variable_ptr_ptr == NULL))) {
                zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects");
-       }
-       zend_assign_to_variable_reference(variable_ptr_ptr, value_ptr_ptr TSRMLS_CC);
-
-       if (OP2_TYPE == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) {
-               Z_DELREF_PP(variable_ptr_ptr);
+       } else if ((OP2_TYPE == IS_VAR && UNEXPECTED(*value_ptr_ptr == &EG(error_zval))) ||
+               (OP1_TYPE == IS_VAR && UNEXPECTED(*variable_ptr_ptr == &EG(error_zval)))) {
+               variable_ptr_ptr = &EG(uninitialized_zval_ptr);
+       } else {
+               zend_assign_to_variable_reference(variable_ptr_ptr, value_ptr_ptr TSRMLS_CC);
+               if (OP2_TYPE == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) {
+                       Z_DELREF_PP(variable_ptr_ptr);
+               }
        }
 
        if (RETURN_VALUE_USED(opline)) {
index df47bea982f438dc3941454e346bb196ba268669..a31027ee925b8c5dd80706f7530d4e0753c123e7 100644 (file)
@@ -20408,11 +20408,14 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL
        if ((IS_VAR == IS_VAR && UNEXPECTED(value_ptr_ptr == NULL)) ||
            (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr_ptr == NULL))) {
                zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects");
-       }
-       zend_assign_to_variable_reference(variable_ptr_ptr, value_ptr_ptr TSRMLS_CC);
-
-       if (IS_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) {
-               Z_DELREF_PP(variable_ptr_ptr);
+       } else if ((IS_VAR == IS_VAR && UNEXPECTED(*value_ptr_ptr == &EG(error_zval))) ||
+               (IS_VAR == IS_VAR && UNEXPECTED(*variable_ptr_ptr == &EG(error_zval)))) {
+               variable_ptr_ptr = &EG(uninitialized_zval_ptr);
+       } else {
+               zend_assign_to_variable_reference(variable_ptr_ptr, value_ptr_ptr TSRMLS_CC);
+               if (IS_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) {
+                       Z_DELREF_PP(variable_ptr_ptr);
+               }
        }
 
        if (RETURN_VALUE_USED(opline)) {
@@ -23903,11 +23906,14 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_REF_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE
        if ((IS_CV == IS_VAR && UNEXPECTED(value_ptr_ptr == NULL)) ||
            (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr_ptr == NULL))) {
                zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects");
-       }
-       zend_assign_to_variable_reference(variable_ptr_ptr, value_ptr_ptr TSRMLS_CC);
-
-       if (IS_CV == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) {
-               Z_DELREF_PP(variable_ptr_ptr);
+       } else if ((IS_CV == IS_VAR && UNEXPECTED(*value_ptr_ptr == &EG(error_zval))) ||
+               (IS_VAR == IS_VAR && UNEXPECTED(*variable_ptr_ptr == &EG(error_zval)))) {
+               variable_ptr_ptr = &EG(uninitialized_zval_ptr);
+       } else {
+               zend_assign_to_variable_reference(variable_ptr_ptr, value_ptr_ptr TSRMLS_CC);
+               if (IS_CV == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) {
+                       Z_DELREF_PP(variable_ptr_ptr);
+               }
        }
 
        if (RETURN_VALUE_USED(opline)) {
@@ -37721,11 +37727,14 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE
        if ((IS_VAR == IS_VAR && UNEXPECTED(value_ptr_ptr == NULL)) ||
            (IS_CV == IS_VAR && UNEXPECTED(variable_ptr_ptr == NULL))) {
                zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects");
-       }
-       zend_assign_to_variable_reference(variable_ptr_ptr, value_ptr_ptr TSRMLS_CC);
-
-       if (IS_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) {
-               Z_DELREF_PP(variable_ptr_ptr);
+       } else if ((IS_VAR == IS_VAR && UNEXPECTED(*value_ptr_ptr == &EG(error_zval))) ||
+               (IS_CV == IS_VAR && UNEXPECTED(*variable_ptr_ptr == &EG(error_zval)))) {
+               variable_ptr_ptr = &EG(uninitialized_zval_ptr);
+       } else {
+               zend_assign_to_variable_reference(variable_ptr_ptr, value_ptr_ptr TSRMLS_CC);
+               if (IS_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) {
+                       Z_DELREF_PP(variable_ptr_ptr);
+               }
        }
 
        if (RETURN_VALUE_USED(opline)) {
@@ -40929,11 +40938,14 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER
        if ((IS_CV == IS_VAR && UNEXPECTED(value_ptr_ptr == NULL)) ||
            (IS_CV == IS_VAR && UNEXPECTED(variable_ptr_ptr == NULL))) {
                zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects");
-       }
-       zend_assign_to_variable_reference(variable_ptr_ptr, value_ptr_ptr TSRMLS_CC);
-
-       if (IS_CV == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) {
-               Z_DELREF_PP(variable_ptr_ptr);
+       } else if ((IS_CV == IS_VAR && UNEXPECTED(*value_ptr_ptr == &EG(error_zval))) ||
+               (IS_CV == IS_VAR && UNEXPECTED(*variable_ptr_ptr == &EG(error_zval)))) {
+               variable_ptr_ptr = &EG(uninitialized_zval_ptr);
+       } else {
+               zend_assign_to_variable_reference(variable_ptr_ptr, value_ptr_ptr TSRMLS_CC);
+               if (IS_CV == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) {
+                       Z_DELREF_PP(variable_ptr_ptr);
+               }
        }
 
        if (RETURN_VALUE_USED(opline)) {