Skip to content

Commit 623bf39

Browse files
committed
Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4: Fixed bug #80186
2 parents e4e2541 + 15443f8 commit 623bf39

File tree

3 files changed

+121
-50
lines changed

3 files changed

+121
-50
lines changed

Zend/zend_vm_def.h

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6484,14 +6484,7 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET_R, CONST|TMP|VAR|CV, JMP_ADDR)
64846484
} else if (OP1_TYPE != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) {
64856485
zend_object *zobj = Z_OBJ_P(array_ptr);
64866486
if (!zobj->ce->get_iterator) {
6487-
HashTable *properties;
6488-
6489-
result = EX_VAR(opline->result.var);
6490-
ZVAL_OBJ(result, zobj);
6491-
if (OP1_TYPE != IS_TMP_VAR) {
6492-
GC_ADDREF(zobj);
6493-
}
6494-
properties = zobj->properties;
6487+
HashTable *properties = zobj->properties;
64956488
if (properties) {
64966489
if (UNEXPECTED(GC_REFCOUNT(properties) > 1)) {
64976490
if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) {
@@ -6502,8 +6495,17 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET_R, CONST|TMP|VAR|CV, JMP_ADDR)
65026495
} else {
65036496
properties = zobj->handlers->get_properties(zobj);
65046497
}
6505-
Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(properties, 0);
65066498

6499+
if (zend_hash_num_elements(properties) == 0) {
6500+
ZEND_VM_C_GOTO(fe_reset_r_empty);
6501+
}
6502+
6503+
result = EX_VAR(opline->result.var);
6504+
ZVAL_COPY_VALUE(result, array_ptr);
6505+
if (OP1_TYPE != IS_TMP_VAR) {
6506+
Z_ADDREF_P(array_ptr);
6507+
}
6508+
Z_FE_ITER_P(result) = zend_hash_iterator_add(properties, 0);
65076509
FREE_OP1_IF_VAR();
65086510
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
65096511
} else {
@@ -6520,6 +6522,7 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET_R, CONST|TMP|VAR|CV, JMP_ADDR)
65206522
}
65216523
} else {
65226524
zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_type_name(array_ptr));
6525+
ZEND_VM_C_LABEL(fe_reset_r_empty):
65236526
ZVAL_UNDEF(EX_VAR(opline->result.var));
65246527
Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1;
65256528
FREE_OP1();
@@ -6569,6 +6572,7 @@ ZEND_VM_COLD_CONST_HANDLER(125, ZEND_FE_RESET_RW, CONST|TMP|VAR|CV, JMP_ADDR)
65696572
ZEND_VM_NEXT_OPCODE();
65706573
} else if (OP1_TYPE != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) {
65716574
if (!Z_OBJCE_P(array_ptr)->get_iterator) {
6575+
HashTable *properties;
65726576
if (OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) {
65736577
if (array_ptr == array_ref) {
65746578
ZVAL_NEW_REF(array_ref, array_ref);
@@ -6587,8 +6591,14 @@ ZEND_VM_COLD_CONST_HANDLER(125, ZEND_FE_RESET_RW, CONST|TMP|VAR|CV, JMP_ADDR)
65876591
}
65886592
Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties);
65896593
}
6590-
Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(Z_OBJPROP_P(array_ptr), 0);
65916594

6595+
properties = Z_OBJPROP_P(array_ptr);
6596+
if (zend_hash_num_elements(properties) == 0) {
6597+
Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t) -1;
6598+
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
6599+
}
6600+
6601+
Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(properties, 0);
65926602
FREE_OP1_VAR_PTR();
65936603
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
65946604
} else {

Zend/zend_vm_execute.h

Lines changed: 86 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -4793,14 +4793,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CONST_HANDLER(
47934793
} else if (IS_CONST != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) {
47944794
zend_object *zobj = Z_OBJ_P(array_ptr);
47954795
if (!zobj->ce->get_iterator) {
4796-
HashTable *properties;
4797-
4798-
result = EX_VAR(opline->result.var);
4799-
ZVAL_OBJ(result, zobj);
4800-
if (IS_CONST != IS_TMP_VAR) {
4801-
GC_ADDREF(zobj);
4802-
}
4803-
properties = zobj->properties;
4796+
HashTable *properties = zobj->properties;
48044797
if (properties) {
48054798
if (UNEXPECTED(GC_REFCOUNT(properties) > 1)) {
48064799
if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) {
@@ -4811,7 +4804,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CONST_HANDLER(
48114804
} else {
48124805
properties = zobj->handlers->get_properties(zobj);
48134806
}
4814-
Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(properties, 0);
4807+
4808+
if (zend_hash_num_elements(properties) == 0) {
4809+
goto fe_reset_r_empty;
4810+
}
4811+
4812+
result = EX_VAR(opline->result.var);
4813+
ZVAL_COPY_VALUE(result, array_ptr);
4814+
if (IS_CONST != IS_TMP_VAR) {
4815+
Z_ADDREF_P(array_ptr);
4816+
}
4817+
Z_FE_ITER_P(result) = zend_hash_iterator_add(properties, 0);
48154818

48164819
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
48174820
} else {
@@ -4827,6 +4830,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CONST_HANDLER(
48274830
}
48284831
} else {
48294832
zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_type_name(array_ptr));
4833+
fe_reset_r_empty:
48304834
ZVAL_UNDEF(EX_VAR(opline->result.var));
48314835
Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1;
48324836

@@ -4876,6 +4880,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_
48764880
ZEND_VM_NEXT_OPCODE();
48774881
} else if (IS_CONST != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) {
48784882
if (!Z_OBJCE_P(array_ptr)->get_iterator) {
4883+
HashTable *properties;
48794884
if (IS_CONST == IS_VAR || IS_CONST == IS_CV) {
48804885
if (array_ptr == array_ref) {
48814886
ZVAL_NEW_REF(array_ref, array_ref);
@@ -4894,7 +4899,14 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_
48944899
}
48954900
Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties);
48964901
}
4897-
Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(Z_OBJPROP_P(array_ptr), 0);
4902+
4903+
properties = Z_OBJPROP_P(array_ptr);
4904+
if (zend_hash_num_elements(properties) == 0) {
4905+
Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t) -1;
4906+
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
4907+
}
4908+
4909+
Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(properties, 0);
48984910

48994911
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
49004912
} else {
@@ -18788,14 +18800,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_TMP_HANDLER(ZE
1878818800
} else if (IS_TMP_VAR != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) {
1878918801
zend_object *zobj = Z_OBJ_P(array_ptr);
1879018802
if (!zobj->ce->get_iterator) {
18791-
HashTable *properties;
18792-
18793-
result = EX_VAR(opline->result.var);
18794-
ZVAL_OBJ(result, zobj);
18795-
if (IS_TMP_VAR != IS_TMP_VAR) {
18796-
GC_ADDREF(zobj);
18797-
}
18798-
properties = zobj->properties;
18803+
HashTable *properties = zobj->properties;
1879918804
if (properties) {
1880018805
if (UNEXPECTED(GC_REFCOUNT(properties) > 1)) {
1880118806
if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) {
@@ -18806,7 +18811,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_TMP_HANDLER(ZE
1880618811
} else {
1880718812
properties = zobj->handlers->get_properties(zobj);
1880818813
}
18809-
Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(properties, 0);
18814+
18815+
if (zend_hash_num_elements(properties) == 0) {
18816+
goto fe_reset_r_empty;
18817+
}
18818+
18819+
result = EX_VAR(opline->result.var);
18820+
ZVAL_COPY_VALUE(result, array_ptr);
18821+
if (IS_TMP_VAR != IS_TMP_VAR) {
18822+
Z_ADDREF_P(array_ptr);
18823+
}
18824+
Z_FE_ITER_P(result) = zend_hash_iterator_add(properties, 0);
1881018825

1881118826
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
1881218827
} else {
@@ -18823,6 +18838,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_TMP_HANDLER(ZE
1882318838
}
1882418839
} else {
1882518840
zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_type_name(array_ptr));
18841+
fe_reset_r_empty:
1882618842
ZVAL_UNDEF(EX_VAR(opline->result.var));
1882718843
Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1;
1882818844
zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));
@@ -18872,6 +18888,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(Z
1887218888
ZEND_VM_NEXT_OPCODE();
1887318889
} else if (IS_TMP_VAR != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) {
1887418890
if (!Z_OBJCE_P(array_ptr)->get_iterator) {
18891+
HashTable *properties;
1887518892
if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) {
1887618893
if (array_ptr == array_ref) {
1887718894
ZVAL_NEW_REF(array_ref, array_ref);
@@ -18890,7 +18907,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(Z
1889018907
}
1889118908
Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties);
1889218909
}
18893-
Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(Z_OBJPROP_P(array_ptr), 0);
18910+
18911+
properties = Z_OBJPROP_P(array_ptr);
18912+
if (zend_hash_num_elements(properties) == 0) {
18913+
Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t) -1;
18914+
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
18915+
}
18916+
18917+
Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(properties, 0);
1889418918

1889518919
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
1889618920
} else {
@@ -21338,14 +21362,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_VAR_HANDLER(ZE
2133821362
} else if (IS_VAR != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) {
2133921363
zend_object *zobj = Z_OBJ_P(array_ptr);
2134021364
if (!zobj->ce->get_iterator) {
21341-
HashTable *properties;
21342-
21343-
result = EX_VAR(opline->result.var);
21344-
ZVAL_OBJ(result, zobj);
21345-
if (IS_VAR != IS_TMP_VAR) {
21346-
GC_ADDREF(zobj);
21347-
}
21348-
properties = zobj->properties;
21365+
HashTable *properties = zobj->properties;
2134921366
if (properties) {
2135021367
if (UNEXPECTED(GC_REFCOUNT(properties) > 1)) {
2135121368
if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) {
@@ -21356,8 +21373,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_VAR_HANDLER(ZE
2135621373
} else {
2135721374
properties = zobj->handlers->get_properties(zobj);
2135821375
}
21359-
Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(properties, 0);
2136021376

21377+
if (zend_hash_num_elements(properties) == 0) {
21378+
goto fe_reset_r_empty;
21379+
}
21380+
21381+
result = EX_VAR(opline->result.var);
21382+
ZVAL_COPY_VALUE(result, array_ptr);
21383+
if (IS_VAR != IS_TMP_VAR) {
21384+
Z_ADDREF_P(array_ptr);
21385+
}
21386+
Z_FE_ITER_P(result) = zend_hash_iterator_add(properties, 0);
2136121387
zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));
2136221388
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
2136321389
} else {
@@ -21374,6 +21400,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_VAR_HANDLER(ZE
2137421400
}
2137521401
} else {
2137621402
zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_type_name(array_ptr));
21403+
fe_reset_r_empty:
2137721404
ZVAL_UNDEF(EX_VAR(opline->result.var));
2137821405
Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1;
2137921406
zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));
@@ -21423,6 +21450,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(Z
2142321450
ZEND_VM_NEXT_OPCODE();
2142421451
} else if (IS_VAR != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) {
2142521452
if (!Z_OBJCE_P(array_ptr)->get_iterator) {
21453+
HashTable *properties;
2142621454
if (IS_VAR == IS_VAR || IS_VAR == IS_CV) {
2142721455
if (array_ptr == array_ref) {
2142821456
ZVAL_NEW_REF(array_ref, array_ref);
@@ -21441,8 +21469,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(Z
2144121469
}
2144221470
Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties);
2144321471
}
21444-
Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(Z_OBJPROP_P(array_ptr), 0);
2144521472

21473+
properties = Z_OBJPROP_P(array_ptr);
21474+
if (zend_hash_num_elements(properties) == 0) {
21475+
Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t) -1;
21476+
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
21477+
}
21478+
21479+
Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(properties, 0);
2144621480
zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));
2144721481
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
2144821482
} else {
@@ -38040,14 +38074,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CV_HANDLER(ZEN
3804038074
} else if (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) {
3804138075
zend_object *zobj = Z_OBJ_P(array_ptr);
3804238076
if (!zobj->ce->get_iterator) {
38043-
HashTable *properties;
38044-
38045-
result = EX_VAR(opline->result.var);
38046-
ZVAL_OBJ(result, zobj);
38047-
if (IS_CV != IS_TMP_VAR) {
38048-
GC_ADDREF(zobj);
38049-
}
38050-
properties = zobj->properties;
38077+
HashTable *properties = zobj->properties;
3805138078
if (properties) {
3805238079
if (UNEXPECTED(GC_REFCOUNT(properties) > 1)) {
3805338080
if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) {
@@ -38058,7 +38085,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CV_HANDLER(ZEN
3805838085
} else {
3805938086
properties = zobj->handlers->get_properties(zobj);
3806038087
}
38061-
Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(properties, 0);
38088+
38089+
if (zend_hash_num_elements(properties) == 0) {
38090+
goto fe_reset_r_empty;
38091+
}
38092+
38093+
result = EX_VAR(opline->result.var);
38094+
ZVAL_COPY_VALUE(result, array_ptr);
38095+
if (IS_CV != IS_TMP_VAR) {
38096+
Z_ADDREF_P(array_ptr);
38097+
}
38098+
Z_FE_ITER_P(result) = zend_hash_iterator_add(properties, 0);
3806238099

3806338100
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
3806438101
} else {
@@ -38074,6 +38111,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CV_HANDLER(ZEN
3807438111
}
3807538112
} else {
3807638113
zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_type_name(array_ptr));
38114+
fe_reset_r_empty:
3807738115
ZVAL_UNDEF(EX_VAR(opline->result.var));
3807838116
Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1;
3807938117

@@ -38123,6 +38161,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CV_HANDLER(ZE
3812338161
ZEND_VM_NEXT_OPCODE();
3812438162
} else if (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) {
3812538163
if (!Z_OBJCE_P(array_ptr)->get_iterator) {
38164+
HashTable *properties;
3812638165
if (IS_CV == IS_VAR || IS_CV == IS_CV) {
3812738166
if (array_ptr == array_ref) {
3812838167
ZVAL_NEW_REF(array_ref, array_ref);
@@ -38141,7 +38180,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CV_HANDLER(ZE
3814138180
}
3814238181
Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties);
3814338182
}
38144-
Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(Z_OBJPROP_P(array_ptr), 0);
38183+
38184+
properties = Z_OBJPROP_P(array_ptr);
38185+
if (zend_hash_num_elements(properties) == 0) {
38186+
Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t) -1;
38187+
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
38188+
}
38189+
38190+
Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(properties, 0);
3814538191

3814638192
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
3814738193
} else {

ext/ffi/tests/bug80186.phpt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
--TEST--
2+
Bug #80186 (Segfault when iterating over FFI object)
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded('ffi')) die('skip ffi extension not available');
6+
?>
7+
--FILE--
8+
<?php
9+
$ffi = FFI::cdef('typedef int dummy;');
10+
foreach ($ffi as $_) { }
11+
foreach ($ffi as &$_) { }
12+
?>
13+
===DONE===
14+
--EXPECT--
15+
===DONE===

0 commit comments

Comments
 (0)