]> granicus.if.org Git - php/commitdiff
Fixed bug #73792 (invalid foreach loop hangs script)
authorDmitry Stogov <dmitry@zend.com>
Tue, 20 Dec 2016 13:48:57 +0000 (16:48 +0300)
committerDmitry Stogov <dmitry@zend.com>
Tue, 20 Dec 2016 13:48:57 +0000 (16:48 +0300)
NEWS
Zend/tests/bug73792.phpt [new file with mode: 0644]
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

diff --git a/NEWS b/NEWS
index e242961fd183dfdf3840f63ba400f22f94301ebe..98b88cc3f7601fb255803c247ee4e6d85594f2a1 100644 (file)
--- 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 (file)
index 0000000..ac4f265
--- /dev/null
@@ -0,0 +1,20 @@
+--TEST--
+Bug #73792 (invalid foreach loop hangs script)
+--FILE--
+<?php
+$a = 'aaa';
+
+foreach ($a['bbb'] as &$value) {
+       echo 'loop';
+}
+
+unset($value);
+echo 'done';
+?>
+--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
index 3fe2f1dc5a6ff7674d711637031dbe67271429d6..89725bd02d2d2694b092065e066d8d3d0ede7af9 100644 (file)
@@ -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);
                }
index 3e38c71436eaf62234fe3aac152e900e5b9872bb..5784ead38d2b6d72b2d00183a8d0a1f488c18c70 100644 (file)
@@ -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);
                }