Skip to content

Commit df79277

Browse files
committed
Revert "Fetch for read in nested property assignments"
This reverts commit bb43a38. After thinking about this a bit more, this is now going to be a complete solution for the "readonly properties" case, for example: unset($foo->readOnly->bar); should also be legal and $foo->readOnly['bar'] = 42; should also be legal if $foo->readOnly is not an array but an ArrayAccess object. I think it may be better to distinguish better on the BP_VAR flag level. Reverting for now.
1 parent a5f136b commit df79277

15 files changed

+9267
-9283
lines changed

UPGRADING

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ PHP 8.0 UPGRADE NOTES
4444
. Removed ability to use array_key_exists() with objects. Use one of isset()
4545
or property_exists() instead.
4646
. Made the behavior of array_key_exists() regarding the type of the key
47-
parameter consistent with isset() and normal array access. All key types
48-
now use the usual coercions and array/object keys throw a TypeError.
47+
parameter consistent with isset() and normal array access. All key types now use
48+
the usual coercions and array/object keys throw a TypeError.
4949
. Any array that has a number n as its first numeric key will use n+1 for
5050
its next implicit key. Even if n is negative.
5151
RFC: https://wiki.php.net/rfc/negative_array_index
@@ -305,19 +305,6 @@ PHP 8.0 UPGRADE NOTES
305305
of the return value is not stable and may change between PHP versions.
306306
. Reflection export() methods have been removed.
307307

308-
- SimpleXML:
309-
. It is no longer possible to perform deep initialization of SimpleXMLElement
310-
objects:
311-
312-
$x = simplexml_load_string("<root></root>");
313-
$x->a->b->c = 'Test';
314-
// Error: Attempt to assign property 'c' of non-object
315-
316-
The addChild() and addAttribute() APIs should be used instead. It is still
317-
possible to modify already existing nodes by direct property assignment,
318-
only the creation of multiple levels of nodes in one assignment is no longer
319-
supported.
320-
321308
- Socket:
322309
. The deprecated AI_IDN_ALLOW_UNASSIGNED and AI_IDN_USE_STD3_ASCII_RULES
323310
flags for socket_addrinfo_lookup() have been removed.

Zend/tests/033.phpt

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,14 @@ try {
1515
echo $e->getMessage(), "\n";
1616
}
1717

18+
$arr[][] = 2;
19+
20+
try {
21+
$arr[][]->bar = 2;
22+
} catch (Error $e) {
23+
echo $e->getMessage(), "\n";
24+
}
25+
1826
?>
1927
--EXPECTF--
2028
Warning: Undefined variable: arr in %s on line %d
@@ -54,16 +62,5 @@ Warning: Trying to access array offset on value of type null in %s on line %d
5462
Warning: Trying to access array offset on value of type null in %s on line %d
5563

5664
Warning: Trying to get property 'foo' of non-object in %s on line %d
57-
58-
Warning: Undefined variable: arr in %s on line %d
59-
60-
Warning: Trying to access array offset on value of type null in %s on line %d
61-
62-
Warning: Trying to access array offset on value of type null in %s on line %d
63-
64-
Warning: Trying to access array offset on value of type null in %s on line %d
65-
66-
Warning: Trying to access array offset on value of type null in %s on line %d
67-
68-
Warning: Trying to access array offset on value of type null in %s on line %d
6965
Attempt to assign property 'foo' of non-object
66+
Attempt to assign property 'bar' of non-object

Zend/tests/bug41813.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ $foo[0]->bar = "xyz";
99
echo "Done\n";
1010
?>
1111
--EXPECTF--
12-
Fatal error: Uncaught Error: Attempt to assign property 'bar' of non-object in %s:%d
12+
Fatal error: Uncaught Error: Cannot use string offset as an object in %s:%d
1313
Stack trace:
1414
#0 {main}
1515
thrown in %s on line %d

Zend/tests/bug41919.phpt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,7 @@ $foo[3]->bar[1] = "bang";
88
echo "ok\n";
99
?>
1010
--EXPECTF--
11-
Warning: Uninitialized string offset: 3 in %s on line %d
12-
13-
Fatal error: Uncaught Error: Attempt to modify property 'bar' of non-object in %s:%d
11+
Fatal error: Uncaught Error: Cannot use string offset as an object in %sbug41919.php:%d
1412
Stack trace:
1513
#0 {main}
1614
thrown in %sbug41919.php on line %d

Zend/tests/bug47704.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ $s = "abd";
66
$s[0]->a += 1;
77
?>
88
--EXPECTF--
9-
Fatal error: Uncaught Error: Attempt to assign property 'a' of non-object in %s:%d
9+
Fatal error: Uncaught Error: Cannot use string offset as an object in %sbug47704.php:%d
1010
Stack trace:
1111
#0 {main}
1212
thrown in %sbug47704.php on line %d

Zend/tests/bug52041.phpt

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -51,25 +51,19 @@ Warning: Undefined variable: x in %s on line %d
5151
Attempt to assign property 'a' of non-object
5252

5353
Warning: Undefined variable: x in %s on line %d
54-
55-
Warning: Trying to get property 'a' of non-object in %s on line %d
56-
Attempt to assign property 'b' of non-object
54+
Attempt to modify property 'a' of non-object
5755

5856
Warning: Undefined variable: x in %s on line %d
5957
Attempt to increment/decrement property 'a' of non-object
6058

6159
Warning: Undefined variable: x in %s on line %d
62-
63-
Warning: Trying to get property 'a' of non-object in %s on line %d
64-
Attempt to increment/decrement property 'b' of non-object
60+
Attempt to modify property 'a' of non-object
6561

6662
Warning: Undefined variable: x in %s on line %d
6763
Attempt to assign property 'a' of non-object
6864

6965
Warning: Undefined variable: x in %s on line %d
70-
71-
Warning: Trying to get property 'a' of non-object in %s on line %d
72-
Attempt to assign property 'b' of non-object
66+
Attempt to modify property 'a' of non-object
7367

7468
Warning: Undefined variable: x in %s on line %d
7569

Zend/tests/bug75921.phpt

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -53,29 +53,15 @@ Attempt to modify property 'a' of non-object
5353

5454
Warning: Undefined variable: null in %s on line %d
5555
NULL
56-
57-
Warning: Undefined variable: null in %s on line %d
58-
59-
Warning: Trying to get property 'a' of non-object in %s on line %d
60-
Attempt to assign property 'b' of non-object
56+
Attempt to modify property 'a' of non-object
6157

6258
Warning: Undefined variable: null in %s on line %d
6359
NULL
64-
65-
Warning: Undefined variable: null in %s on line %d
66-
67-
Warning: Trying to get property 'a' of non-object in %s on line %d
68-
69-
Warning: Trying to access array offset on value of type null in %s on line %d
70-
Attempt to assign property 'b' of non-object
60+
Attempt to modify property 'a' of non-object
7161

7262
Warning: Undefined variable: null in %s on line %d
7363
NULL
74-
75-
Warning: Undefined variable: null in %s on line %d
76-
77-
Warning: Trying to get property 'a' of non-object in %s on line %d
78-
Attempt to modify property 'b' of non-object
64+
Attempt to modify property 'a' of non-object
7965

8066
Warning: Undefined variable: null in %s on line %d
8167
NULL

Zend/tests/bug78531.phpt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,4 @@ Warning: Undefined variable: u3 in %s on line %d
3434
Attempt to increment/decrement property 'a' of non-object
3535

3636
Warning: Undefined variable: u4 in %s on line %d
37-
38-
Warning: Trying to get property 'a' of non-object in %s on line %d
39-
Attempt to assign property 'a' of non-object
37+
Attempt to modify property 'a' of non-object

Zend/zend_compile.c

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2703,13 +2703,7 @@ static zend_op *zend_delayed_compile_prop(znode *result, zend_ast *ast, uint32_t
27032703
}
27042704
CG(active_op_array)->fn_flags |= ZEND_ACC_USES_THIS;
27052705
} else {
2706-
/* In $a->b->c = $d, fetch $a->b for read and only ->c for write.
2707-
* We will never modify $a->b itself, only the object it holds. */
2708-
if (type == BP_VAR_W || type == BP_VAR_RW || type == BP_VAR_FUNC_ARG) {
2709-
opline = zend_delayed_compile_var(&obj_node, obj_ast, BP_VAR_R, 0);
2710-
} else {
2711-
opline = zend_delayed_compile_var(&obj_node, obj_ast, type, 0);
2712-
}
2706+
opline = zend_delayed_compile_var(&obj_node, obj_ast, type, 0);
27132707
zend_separate_if_call_and_write(&obj_node, obj_ast, type);
27142708
}
27152709
zend_compile_expr(&prop_node, prop_ast);

Zend/zend_vm_def.h

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -989,7 +989,7 @@ ZEND_VM_COLD_HELPER(zend_undefined_function_helper, ANY, ANY)
989989
HANDLE_EXCEPTION();
990990
}
991991

992-
ZEND_VM_HANDLER(28, ZEND_ASSIGN_OBJ_OP, TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, OP)
992+
ZEND_VM_HANDLER(28, ZEND_ASSIGN_OBJ_OP, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, OP)
993993
{
994994
USE_OPLINE
995995
zval *object;
@@ -1002,7 +1002,7 @@ ZEND_VM_HANDLER(28, ZEND_ASSIGN_OBJ_OP, TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV,
10021002
zend_string *name, *tmp_name;
10031003

10041004
SAVE_OPLINE();
1005-
object = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R);
1005+
object = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
10061006
property = GET_OP2_ZVAL_PTR(BP_VAR_R);
10071007

10081008
do {
@@ -1080,7 +1080,7 @@ ZEND_VM_C_LABEL(assign_op_object):
10801080

10811081
FREE_OP_DATA();
10821082
FREE_OP2();
1083-
FREE_OP1();
1083+
FREE_OP1_VAR_PTR();
10841084
/* assign_obj has two opcodes! */
10851085
ZEND_VM_NEXT_OPCODE_EX(1, 2);
10861086
}
@@ -1248,7 +1248,7 @@ ZEND_VM_HANDLER(26, ZEND_ASSIGN_OP, VAR|CV, CONST|TMPVAR|CV, OP)
12481248
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
12491249
}
12501250

1251-
ZEND_VM_HANDLER(132, ZEND_PRE_INC_OBJ, TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT)
1251+
ZEND_VM_HANDLER(132, ZEND_PRE_INC_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT)
12521252
{
12531253
USE_OPLINE
12541254
zval *object;
@@ -1260,7 +1260,7 @@ ZEND_VM_HANDLER(132, ZEND_PRE_INC_OBJ, TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, C
12601260
zend_string *name, *tmp_name;
12611261

12621262
SAVE_OPLINE();
1263-
object = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R);
1263+
object = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
12641264
property = GET_OP2_ZVAL_PTR(BP_VAR_R);
12651265

12661266
do {
@@ -1312,7 +1312,7 @@ ZEND_VM_C_LABEL(pre_incdec_object):
13121312
} while (0);
13131313

13141314
FREE_OP2();
1315-
FREE_OP1();
1315+
FREE_OP1_VAR_PTR();
13161316
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
13171317
}
13181318

@@ -1333,7 +1333,7 @@ ZEND_VM_HANDLER(134, ZEND_POST_INC_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CAC
13331333
zend_string *name, *tmp_name;
13341334

13351335
SAVE_OPLINE();
1336-
object = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R);
1336+
object = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
13371337
property = GET_OP2_ZVAL_PTR(BP_VAR_R);
13381338

13391339
do {
@@ -1384,7 +1384,7 @@ ZEND_VM_C_LABEL(post_incdec_object):
13841384
} while (0);
13851385

13861386
FREE_OP2();
1387-
FREE_OP1();
1387+
FREE_OP1_VAR_PTR();
13881388
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
13891389
}
13901390

@@ -2113,39 +2113,39 @@ ZEND_VM_C_LABEL(fetch_obj_r_finish):
21132113
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
21142114
}
21152115

2116-
ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, FETCH_REF|DIM_WRITE|CACHE_SLOT)
2116+
ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, FETCH_REF|DIM_WRITE|CACHE_SLOT)
21172117
{
21182118
USE_OPLINE
21192119
zval *property, *container, *result;
21202120

21212121
SAVE_OPLINE();
21222122

2123-
container = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R);
2123+
container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
21242124
property = GET_OP2_ZVAL_PTR(BP_VAR_R);
21252125
result = EX_VAR(opline->result.var);
21262126
zend_fetch_property_address(
21272127
result, container, OP1_TYPE, property, OP2_TYPE,
21282128
((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) : NULL),
21292129
BP_VAR_W, opline->extended_value & ZEND_FETCH_OBJ_FLAGS, 1 OPLINE_CC EXECUTE_DATA_CC);
21302130
FREE_OP2();
2131-
if (OP1_TYPE & (IS_VAR|IS_TMP_VAR)) {
2131+
if (OP1_TYPE == IS_VAR) {
21322132
FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var);
21332133
}
21342134
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
21352135
}
21362136

2137-
ZEND_VM_HANDLER(88, ZEND_FETCH_OBJ_RW, TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT)
2137+
ZEND_VM_HANDLER(88, ZEND_FETCH_OBJ_RW, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT)
21382138
{
21392139
USE_OPLINE
21402140
zval *property, *container, *result;
21412141

21422142
SAVE_OPLINE();
2143-
container = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R);
2143+
container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
21442144
property = GET_OP2_ZVAL_PTR(BP_VAR_R);
21452145
result = EX_VAR(opline->result.var);
21462146
zend_fetch_property_address(result, container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, 1 OPLINE_CC EXECUTE_DATA_CC);
21472147
FREE_OP2();
2148-
if (OP1_TYPE & (IS_VAR|IS_TMP_VAR)) {
2148+
if (OP1_TYPE == IS_VAR) {
21492149
FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var);
21502150
}
21512151
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
@@ -2262,15 +2262,15 @@ ZEND_VM_C_LABEL(fetch_obj_is_finish):
22622262
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
22632263
}
22642264

2265-
ZEND_VM_COLD_CONST_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, CONST|TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, FETCH_REF|CACHE_SLOT)
2265+
ZEND_VM_COLD_CONST_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, CONST|TMP|VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, FETCH_REF|CACHE_SLOT)
22662266
{
22672267
#if !ZEND_VM_SPEC
22682268
USE_OPLINE
22692269
#endif
22702270

22712271
if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
22722272
/* Behave like FETCH_OBJ_W */
2273-
if (OP1_TYPE == IS_CONST) {
2273+
if ((OP1_TYPE & (IS_CONST|IS_TMP_VAR))) {
22742274
ZEND_VM_DISPATCH_TO_HELPER(zend_use_tmp_in_write_context_helper);
22752275
}
22762276
ZEND_VM_DISPATCH_TO_HANDLER(ZEND_FETCH_OBJ_W);
@@ -2331,15 +2331,15 @@ ZEND_VM_HANDLER(155, ZEND_FETCH_LIST_W, VAR, CONST|TMPVAR|CV)
23312331
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
23322332
}
23332333

2334-
ZEND_VM_HANDLER(24, ZEND_ASSIGN_OBJ, TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT, SPEC(OP_DATA=CONST|TMP|VAR|CV))
2334+
ZEND_VM_HANDLER(24, ZEND_ASSIGN_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT, SPEC(OP_DATA=CONST|TMP|VAR|CV))
23352335
{
23362336
USE_OPLINE
23372337
zval *object, *property, *value, tmp;
23382338
zend_object *zobj;
23392339
zend_string *name, *tmp_name;
23402340

23412341
SAVE_OPLINE();
2342-
object = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R);
2342+
object = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
23432343
property = GET_OP2_ZVAL_PTR(BP_VAR_R);
23442344
value = GET_OP_DATA_ZVAL_PTR(BP_VAR_R);
23452345

@@ -2470,7 +2470,7 @@ ZEND_VM_C_LABEL(free_and_exit_assign_obj):
24702470
FREE_OP_DATA();
24712471
ZEND_VM_C_LABEL(exit_assign_obj):
24722472
FREE_OP2();
2473-
FREE_OP1();
2473+
FREE_OP1_VAR_PTR();
24742474
/* assign_obj has two opcodes! */
24752475
ZEND_VM_NEXT_OPCODE_EX(1, 2);
24762476
}
@@ -2676,14 +2676,14 @@ ZEND_VM_HANDLER(30, ZEND_ASSIGN_REF, VAR|CV, VAR|CV, SRC)
26762676
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
26772677
}
26782678

2679-
ZEND_VM_HANDLER(32, ZEND_ASSIGN_OBJ_REF, TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT|SRC, SPEC(OP_DATA=VAR|CV))
2679+
ZEND_VM_HANDLER(32, ZEND_ASSIGN_OBJ_REF, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT|SRC, SPEC(OP_DATA=VAR|CV))
26802680
{
26812681
USE_OPLINE
26822682
zval *property, *container, *value_ptr;
26832683

26842684
SAVE_OPLINE();
26852685

2686-
container = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R);
2686+
container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
26872687
property = GET_OP2_ZVAL_PTR(BP_VAR_R);
26882688

26892689
value_ptr = GET_OP_DATA_ZVAL_PTR_PTR(BP_VAR_W);
@@ -2706,7 +2706,7 @@ ZEND_VM_HANDLER(32, ZEND_ASSIGN_OBJ_REF, TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV,
27062706
zend_assign_to_property_reference(container, OP1_TYPE, property, OP2_TYPE, value_ptr OPLINE_CC EXECUTE_DATA_CC);
27072707
}
27082708

2709-
FREE_OP1();
2709+
FREE_OP1_VAR_PTR();
27102710
FREE_OP2();
27112711
FREE_OP_DATA_VAR_PTR();
27122712
ZEND_VM_NEXT_OPCODE_EX(1, 2);

0 commit comments

Comments
 (0)