From 3c6a2fb08cb8c0dddc16a62a816249c68132773d Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 20 Dec 2016 16:48:57 +0300 Subject: [PATCH] Fixed bug #73792 (invalid foreach loop hangs script) --- NEWS | 1 + Zend/tests/bug73792.phpt | 20 ++++++++++++++++++++ Zend/zend_vm_def.h | 6 ++++++ Zend/zend_vm_execute.h | 24 ++++++++++++++++++++++++ 4 files changed, 51 insertions(+) create mode 100644 Zend/tests/bug73792.phpt diff --git a/NEWS b/NEWS index e242961fd1..98b88cc3f7 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,7 @@ PHP NEWS ?? ??? 2016 PHP 7.0.15 - Core: + . Fixed bug #73792 (invalid foreach loop hangs script). (Dmitry) . Fixed bug #73663 ("Invalid opcode 65/16/8" occurs with a variable created with list()). (Laruence) . Fixed bug #73585 (Logging of "Internal Zend error - Missing class diff --git a/Zend/tests/bug73792.phpt b/Zend/tests/bug73792.phpt new file mode 100644 index 0000000000..ac4f265aaf --- /dev/null +++ b/Zend/tests/bug73792.phpt @@ -0,0 +1,20 @@ +--TEST-- +Bug #73792 (invalid foreach loop hangs script) +--FILE-- + +--EXPECTF-- +Warning: Illegal string offset 'bbb' in %sbug73792.php on line 4 + +Fatal error: Uncaught Error: Cannot iterate on string offsets by reference in %sbug73792.php:4 +Stack trace: +#0 {main} + thrown in %sbug73792.php on line 4 diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 3fe2f1dc5a..89725bd02d 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -5878,6 +5878,12 @@ ZEND_VM_HANDLER(125, ZEND_FE_RESET_RW, CONST|TMP|VAR|CV, ANY) if (OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) { array_ref = array_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_R); + if (OP1_TYPE == IS_VAR && UNEXPECTED(array_ref == NULL)) { + zend_throw_error(NULL, "Cannot iterate on string offsets by reference"); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; + HANDLE_EXCEPTION(); + } if (Z_ISREF_P(array_ref)) { array_ptr = Z_REFVAL_P(array_ref); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 3e38c71436..5784ead38d 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -3836,6 +3836,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CONST_HANDLER if (IS_CONST == IS_VAR || IS_CONST == IS_CV) { array_ref = array_ptr = NULL; + if (IS_CONST == IS_VAR && UNEXPECTED(array_ref == NULL)) { + zend_throw_error(NULL, "Cannot iterate on string offsets by reference"); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; + HANDLE_EXCEPTION(); + } if (Z_ISREF_P(array_ref)) { array_ptr = Z_REFVAL_P(array_ref); } @@ -12331,6 +12337,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(Z if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) { array_ref = array_ptr = NULL; + if (IS_TMP_VAR == IS_VAR && UNEXPECTED(array_ref == NULL)) { + zend_throw_error(NULL, "Cannot iterate on string offsets by reference"); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; + HANDLE_EXCEPTION(); + } if (Z_ISREF_P(array_ref)) { array_ptr = Z_REFVAL_P(array_ref); } @@ -15799,6 +15811,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(Z if (IS_VAR == IS_VAR || IS_VAR == IS_CV) { array_ref = array_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + if (IS_VAR == IS_VAR && UNEXPECTED(array_ref == NULL)) { + zend_throw_error(NULL, "Cannot iterate on string offsets by reference"); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; + HANDLE_EXCEPTION(); + } if (Z_ISREF_P(array_ref)) { array_ptr = Z_REFVAL_P(array_ref); } @@ -29641,6 +29659,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CV_HANDLER(ZE if (IS_CV == IS_VAR || IS_CV == IS_CV) { array_ref = array_ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); + if (IS_CV == IS_VAR && UNEXPECTED(array_ref == NULL)) { + zend_throw_error(NULL, "Cannot iterate on string offsets by reference"); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; + HANDLE_EXCEPTION(); + } if (Z_ISREF_P(array_ref)) { array_ptr = Z_REFVAL_P(array_ref); } -- 2.40.0