From b740bb3987ba4f181dfda91ce3bd9fe663155574 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sun, 21 Aug 2016 17:10:10 +0800 Subject: [PATCH] Fixed bug #72907 (null pointer deref, segfault in gc_remove_zval_from_buffer (zend_gc.c:260)) --- NEWS | 4 ++++ Zend/tests/bug72907.phpt | 18 ++++++++++++++ Zend/zend_execute.c | 4 +--- Zend/zend_vm_def.h | 13 ++++++---- Zend/zend_vm_execute.h | 52 ++++++++++++++++++++++++---------------- 5 files changed, 63 insertions(+), 28 deletions(-) create mode 100644 Zend/tests/bug72907.phpt diff --git a/NEWS b/NEWS index dca9d4f48b..608881ae65 100644 --- 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 index 0000000000..00d9f5d183 --- /dev/null +++ b/Zend/tests/bug72907.phpt @@ -0,0 +1,18 @@ +--TEST-- +Bug #72907 (null pointer deref, segfault in gc_remove_zval_from_buffer (zend_gc.c:260)) +--FILE-- +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 diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index c7e4b926d8..b422624bb1 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -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); diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 2e81f82e49..f79d8a3f9e 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -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)) { diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index df47bea982..a31027ee92 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -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)) { -- 2.50.0