Skip to content

Commit 3c6a2fb

Browse files
committed
Fixed bug #73792 (invalid foreach loop hangs script)
1 parent 9fb8ea5 commit 3c6a2fb

File tree

4 files changed

+51
-0
lines changed

4 files changed

+51
-0
lines changed

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ PHP NEWS
33
?? ??? 2016 PHP 7.0.15
44

55
- Core:
6+
. Fixed bug #73792 (invalid foreach loop hangs script). (Dmitry)
67
. Fixed bug #73663 ("Invalid opcode 65/16/8" occurs with a variable created
78
with list()). (Laruence)
89
. Fixed bug #73585 (Logging of "Internal Zend error - Missing class

Zend/tests/bug73792.phpt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
Bug #73792 (invalid foreach loop hangs script)
3+
--FILE--
4+
<?php
5+
$a = 'aaa';
6+
7+
foreach ($a['bbb'] as &$value) {
8+
echo 'loop';
9+
}
10+
11+
unset($value);
12+
echo 'done';
13+
?>
14+
--EXPECTF--
15+
Warning: Illegal string offset 'bbb' in %sbug73792.php on line 4
16+
17+
Fatal error: Uncaught Error: Cannot iterate on string offsets by reference in %sbug73792.php:4
18+
Stack trace:
19+
#0 {main}
20+
thrown in %sbug73792.php on line 4

Zend/zend_vm_def.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5878,6 +5878,12 @@ ZEND_VM_HANDLER(125, ZEND_FE_RESET_RW, CONST|TMP|VAR|CV, ANY)
58785878

58795879
if (OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) {
58805880
array_ref = array_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_R);
5881+
if (OP1_TYPE == IS_VAR && UNEXPECTED(array_ref == NULL)) {
5882+
zend_throw_error(NULL, "Cannot iterate on string offsets by reference");
5883+
ZVAL_UNDEF(EX_VAR(opline->result.var));
5884+
Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1;
5885+
HANDLE_EXCEPTION();
5886+
}
58815887
if (Z_ISREF_P(array_ref)) {
58825888
array_ptr = Z_REFVAL_P(array_ref);
58835889
}

Zend/zend_vm_execute.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3836,6 +3836,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CONST_HANDLER
38363836

38373837
if (IS_CONST == IS_VAR || IS_CONST == IS_CV) {
38383838
array_ref = array_ptr = NULL;
3839+
if (IS_CONST == IS_VAR && UNEXPECTED(array_ref == NULL)) {
3840+
zend_throw_error(NULL, "Cannot iterate on string offsets by reference");
3841+
ZVAL_UNDEF(EX_VAR(opline->result.var));
3842+
Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1;
3843+
HANDLE_EXCEPTION();
3844+
}
38393845
if (Z_ISREF_P(array_ref)) {
38403846
array_ptr = Z_REFVAL_P(array_ref);
38413847
}
@@ -12331,6 +12337,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(Z
1233112337

1233212338
if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) {
1233312339
array_ref = array_ptr = NULL;
12340+
if (IS_TMP_VAR == IS_VAR && UNEXPECTED(array_ref == NULL)) {
12341+
zend_throw_error(NULL, "Cannot iterate on string offsets by reference");
12342+
ZVAL_UNDEF(EX_VAR(opline->result.var));
12343+
Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1;
12344+
HANDLE_EXCEPTION();
12345+
}
1233412346
if (Z_ISREF_P(array_ref)) {
1233512347
array_ptr = Z_REFVAL_P(array_ref);
1233612348
}
@@ -15799,6 +15811,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(Z
1579915811

1580015812
if (IS_VAR == IS_VAR || IS_VAR == IS_CV) {
1580115813
array_ref = array_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
15814+
if (IS_VAR == IS_VAR && UNEXPECTED(array_ref == NULL)) {
15815+
zend_throw_error(NULL, "Cannot iterate on string offsets by reference");
15816+
ZVAL_UNDEF(EX_VAR(opline->result.var));
15817+
Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1;
15818+
HANDLE_EXCEPTION();
15819+
}
1580215820
if (Z_ISREF_P(array_ref)) {
1580315821
array_ptr = Z_REFVAL_P(array_ref);
1580415822
}
@@ -29641,6 +29659,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CV_HANDLER(ZE
2964129659

2964229660
if (IS_CV == IS_VAR || IS_CV == IS_CV) {
2964329661
array_ref = array_ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
29662+
if (IS_CV == IS_VAR && UNEXPECTED(array_ref == NULL)) {
29663+
zend_throw_error(NULL, "Cannot iterate on string offsets by reference");
29664+
ZVAL_UNDEF(EX_VAR(opline->result.var));
29665+
Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1;
29666+
HANDLE_EXCEPTION();
29667+
}
2964429668
if (Z_ISREF_P(array_ref)) {
2964529669
array_ptr = Z_REFVAL_P(array_ref);
2964629670
}

0 commit comments

Comments
 (0)