Skip to content

Commit 536260f

Browse files
committed
Fix bug #65821: By-ref foreach on property access of string offset segfaults
This removes the now unnecessary ZEND_FETCH_ADD_LOCK on the container of a property fetch of a by-reference foreach.
1 parent 2e2bda3 commit 536260f

File tree

4 files changed

+4
-96
lines changed

4 files changed

+4
-96
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ PHP NEWS
55
- Core:
66
. Fixed bug #64979 (Wrong behavior of static variables in closure generators).
77
(Nikita)
8+
. Fixed bug #65821 (By-ref foreach on property access of string offset
9+
segfaults). (Nikita)
810

911
- CLI server:
1012
. Fixed bug #65633 (built-in server treat some http headers as

Zend/zend_compile.c

Lines changed: 2 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1749,7 +1749,6 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
17491749
zend_op dummy_opline;
17501750

17511751
dummy_opline.result_type = IS_UNUSED;
1752-
dummy_opline.op1_type = IS_UNUSED;
17531752

17541753
zend_stack_push(&CG(foreach_copy_stack), (void *) &dummy_opline, sizeof(zend_op));
17551754
}
@@ -2662,7 +2661,7 @@ static int generate_free_switch_expr(const zend_switch_entry *switch_entry TSRML
26622661
opline->opcode = (switch_entry->cond.op_type == IS_TMP_VAR) ? ZEND_FREE : ZEND_SWITCH_FREE;
26632662
SET_NODE(opline->op1, &switch_entry->cond);
26642663
SET_UNUSED(opline->op2);
2665-
opline->extended_value = 0;
2664+
26662665
return 0;
26672666
}
26682667
/* }}} */
@@ -2672,7 +2671,7 @@ static int generate_free_foreach_copy(const zend_op *foreach_copy TSRMLS_DC) /*
26722671
zend_op *opline;
26732672

26742673
/* If we reach the separator then stop applying the stack */
2675-
if (foreach_copy->result_type == IS_UNUSED && foreach_copy->op1_type == IS_UNUSED) {
2674+
if (foreach_copy->result_type == IS_UNUSED) {
26762675
return 1;
26772676
}
26782677

@@ -2681,16 +2680,6 @@ static int generate_free_foreach_copy(const zend_op *foreach_copy TSRMLS_DC) /*
26812680
opline->opcode = (foreach_copy->result_type == IS_TMP_VAR) ? ZEND_FREE : ZEND_SWITCH_FREE;
26822681
COPY_NODE(opline->op1, foreach_copy->result);
26832682
SET_UNUSED(opline->op2);
2684-
opline->extended_value = 1;
2685-
2686-
if (foreach_copy->op1_type != IS_UNUSED) {
2687-
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2688-
2689-
opline->opcode = (foreach_copy->op1_type == IS_TMP_VAR) ? ZEND_FREE : ZEND_SWITCH_FREE;
2690-
COPY_NODE(opline->op1, foreach_copy->op1);
2691-
SET_UNUSED(opline->op2);
2692-
opline->extended_value = 0;
2693-
}
26942683

26952684
return 0;
26962685
}
@@ -6227,7 +6216,6 @@ void zend_do_foreach_begin(znode *foreach_token, znode *open_brackets_token, zno
62276216
{
62286217
zend_op *opline;
62296218
zend_bool is_variable;
6230-
zend_bool push_container = 0;
62316219
zend_op dummy_opline;
62326220

62336221
if (variable) {
@@ -6239,14 +6227,6 @@ void zend_do_foreach_begin(znode *foreach_token, znode *open_brackets_token, zno
62396227
/* save the location of FETCH_W instruction(s) */
62406228
open_brackets_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
62416229
zend_do_end_variable_parse(array, BP_VAR_W, 0 TSRMLS_CC);
6242-
if (CG(active_op_array)->last > 0 &&
6243-
CG(active_op_array)->opcodes[CG(active_op_array)->last-1].opcode == ZEND_FETCH_OBJ_W) {
6244-
/* Only lock the container if we are fetching from a real container and not $this */
6245-
if (CG(active_op_array)->opcodes[CG(active_op_array)->last-1].op1_type == IS_VAR) {
6246-
CG(active_op_array)->opcodes[CG(active_op_array)->last-1].extended_value |= ZEND_FETCH_ADD_LOCK;
6247-
push_container = 1;
6248-
}
6249-
}
62506230
} else {
62516231
is_variable = 0;
62526232
open_brackets_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
@@ -6266,11 +6246,6 @@ void zend_do_foreach_begin(znode *foreach_token, znode *open_brackets_token, zno
62666246
opline->extended_value = is_variable ? ZEND_FE_RESET_VARIABLE : 0;
62676247

62686248
COPY_NODE(dummy_opline.result, opline->result);
6269-
if (push_container) {
6270-
COPY_NODE(dummy_opline.op1, CG(active_op_array)->opcodes[CG(active_op_array)->last-2].op1);
6271-
} else {
6272-
dummy_opline.op1_type = IS_UNUSED;
6273-
}
62746249
zend_stack_push(&CG(foreach_copy_stack), (void *) &dummy_opline, sizeof(zend_op));
62756250

62766251
/* save the location of FE_FETCH */
@@ -6327,7 +6302,6 @@ void zend_do_foreach_cont(znode *foreach_token, const znode *open_brackets_token
63276302
opline->extended_value |= ZEND_FE_FETCH_BYREF;
63286303
CG(active_op_array)->opcodes[foreach_token->u.op.opline_num].extended_value |= ZEND_FE_RESET_REFERENCE;
63296304
} else {
6330-
zend_op *foreach_copy;
63316305
zend_op *fetch = &CG(active_op_array)->opcodes[foreach_token->u.op.opline_num];
63326306
zend_op *end = &CG(active_op_array)->opcodes[open_brackets_token->u.op.opline_num];
63336307

@@ -6344,9 +6318,6 @@ void zend_do_foreach_cont(znode *foreach_token, const znode *open_brackets_token
63446318
fetch->opcode -= 3; /* FETCH_W -> FETCH_R */
63456319
}
63466320
}
6347-
/* prevent double SWITCH_FREE */
6348-
zend_stack_top(&CG(foreach_copy_stack), (void **) &foreach_copy);
6349-
foreach_copy->op1_type = IS_UNUSED;
63506321
}
63516322

63526323
GET_NODE(&value_node, opline->result);

Zend/zend_vm_def.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1392,11 +1392,6 @@ ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
13921392
SAVE_OPLINE();
13931393
property = GET_OP2_ZVAL_PTR(BP_VAR_R);
13941394

1395-
if (OP1_TYPE == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) {
1396-
PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
1397-
EX_T(opline->op1.var).var.ptr = *EX_T(opline->op1.var).var.ptr_ptr;
1398-
}
1399-
14001395
if (IS_OP2_TMP_FREE()) {
14011396
MAKE_REAL_ZVAL_PTR(property);
14021397
}

Zend/zend_vm_execute.h

Lines changed: 0 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -14997,11 +14997,6 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HA
1499714997
SAVE_OPLINE();
1499814998
property = opline->op2.zv;
1499914999

15000-
if (IS_VAR == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) {
15001-
PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
15002-
EX_T(opline->op1.var).var.ptr = *EX_T(opline->op1.var).var.ptr_ptr;
15003-
}
15004-
1500515000
if (0) {
1500615001
MAKE_REAL_ZVAL_PTR(property);
1500715002
}
@@ -17353,11 +17348,6 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAND
1735317348
SAVE_OPLINE();
1735417349
property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
1735517350

17356-
if (IS_VAR == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) {
17357-
PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
17358-
EX_T(opline->op1.var).var.ptr = *EX_T(opline->op1.var).var.ptr_ptr;
17359-
}
17360-
1736117351
if (1) {
1736217352
MAKE_REAL_ZVAL_PTR(property);
1736317353
}
@@ -19616,11 +19606,6 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAND
1961619606
SAVE_OPLINE();
1961719607
property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
1961819608

19619-
if (IS_VAR == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) {
19620-
PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
19621-
EX_T(opline->op1.var).var.ptr = *EX_T(opline->op1.var).var.ptr_ptr;
19622-
}
19623-
1962419609
if (0) {
1962519610
MAKE_REAL_ZVAL_PTR(property);
1962619611
}
@@ -23081,11 +23066,6 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDL
2308123066
SAVE_OPLINE();
2308223067
property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
2308323068

23084-
if (IS_VAR == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) {
23085-
PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
23086-
EX_T(opline->op1.var).var.ptr = *EX_T(opline->op1.var).var.ptr_ptr;
23087-
}
23088-
2308923069
if (0) {
2309023070
MAKE_REAL_ZVAL_PTR(property);
2309123071
}
@@ -24867,11 +24847,6 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE
2486724847
SAVE_OPLINE();
2486824848
property = opline->op2.zv;
2486924849

24870-
if (IS_UNUSED == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) {
24871-
PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
24872-
EX_T(opline->op1.var).var.ptr = *EX_T(opline->op1.var).var.ptr_ptr;
24873-
}
24874-
2487524850
if (0) {
2487624851
MAKE_REAL_ZVAL_PTR(property);
2487724852
}
@@ -26285,11 +26260,6 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_H
2628526260
SAVE_OPLINE();
2628626261
property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
2628726262

26288-
if (IS_UNUSED == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) {
26289-
PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
26290-
EX_T(opline->op1.var).var.ptr = *EX_T(opline->op1.var).var.ptr_ptr;
26291-
}
26292-
2629326263
if (1) {
2629426264
MAKE_REAL_ZVAL_PTR(property);
2629526265
}
@@ -27606,11 +27576,6 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_H
2760627576
SAVE_OPLINE();
2760727577
property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
2760827578

27609-
if (IS_UNUSED == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) {
27610-
PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
27611-
EX_T(opline->op1.var).var.ptr = *EX_T(opline->op1.var).var.ptr_ptr;
27612-
}
27613-
2761427579
if (0) {
2761527580
MAKE_REAL_ZVAL_PTR(property);
2761627581
}
@@ -29349,11 +29314,6 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HA
2934929314
SAVE_OPLINE();
2935029315
property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
2935129316

29352-
if (IS_UNUSED == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) {
29353-
PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
29354-
EX_T(opline->op1.var).var.ptr = *EX_T(opline->op1.var).var.ptr_ptr;
29355-
}
29356-
2935729317
if (0) {
2935829318
MAKE_REAL_ZVAL_PTR(property);
2935929319
}
@@ -32493,11 +32453,6 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAN
3249332453
SAVE_OPLINE();
3249432454
property = opline->op2.zv;
3249532455

32496-
if (IS_CV == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) {
32497-
PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
32498-
EX_T(opline->op1.var).var.ptr = *EX_T(opline->op1.var).var.ptr_ptr;
32499-
}
32500-
3250132456
if (0) {
3250232457
MAKE_REAL_ZVAL_PTR(property);
3250332458
}
@@ -34614,11 +34569,6 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDL
3461434569
SAVE_OPLINE();
3461534570
property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
3461634571

34617-
if (IS_CV == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) {
34618-
PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
34619-
EX_T(opline->op1.var).var.ptr = *EX_T(opline->op1.var).var.ptr_ptr;
34620-
}
34621-
3462234572
if (1) {
3462334573
MAKE_REAL_ZVAL_PTR(property);
3462434574
}
@@ -36739,11 +36689,6 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDL
3673936689
SAVE_OPLINE();
3674036690
property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
3674136691

36742-
if (IS_CV == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) {
36743-
PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
36744-
EX_T(opline->op1.var).var.ptr = *EX_T(opline->op1.var).var.ptr_ptr;
36745-
}
36746-
3674736692
if (0) {
3674836693
MAKE_REAL_ZVAL_PTR(property);
3674936694
}
@@ -39917,11 +39862,6 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLE
3991739862
SAVE_OPLINE();
3991839863
property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
3991939864

39920-
if (IS_CV == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) {
39921-
PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
39922-
EX_T(opline->op1.var).var.ptr = *EX_T(opline->op1.var).var.ptr_ptr;
39923-
}
39924-
3992539865
if (0) {
3992639866
MAKE_REAL_ZVAL_PTR(property);
3992739867
}

0 commit comments

Comments
 (0)