Skip to content

Commit a73fc46

Browse files
committed
Fix GH-10497: Allow direct modification of object properties in constants
1 parent b7c855f commit a73fc46

3 files changed

Lines changed: 64 additions & 10 deletions

File tree

Zend/tests/gh10497.phpt

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
--TEST--
2+
GH-10497: Allow direct modification of object stored in a constant
3+
--FILE--
4+
<?php
5+
const a = new stdClass;
6+
a->b = 42;
7+
var_dump(a->b);
8+
9+
const obj = new stdClass;
10+
obj->foo = 'bar';
11+
obj->baz = 123;
12+
var_dump(obj->foo, obj->baz);
13+
14+
const nested = new stdClass;
15+
nested->inner = new stdClass;
16+
nested->inner->value = 999;
17+
var_dump(nested->inner->value);
18+
19+
const readTest = new stdClass;
20+
readTest->prop = 'test';
21+
echo readTest->prop . "\n";
22+
23+
var_dump(isset(readTest->prop));
24+
var_dump(empty(readTest->missing));
25+
26+
const modTest = new stdClass;
27+
modTest->val = 1;
28+
modTest->val = 2;
29+
var_dump(modTest->val);
30+
?>
31+
--EXPECT--
32+
int(42)
33+
string(3) "bar"
34+
int(123)
35+
int(999)
36+
test
37+
bool(true)
38+
bool(true)
39+
int(2)

Zend/tests/gh12102_3.phpt

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,8 @@ GH-12102: Incorrect "Cannot use temporary expression in write context" error for
55

66
function test() {
77
byVal(C[0]);
8-
try {
9-
byRef(C[0]);
10-
} catch (Error $e) {
11-
echo $e->getMessage(), "\n";
12-
}
8+
byRef(C[0]);
9+
var_dump(C);
1310
}
1411

1512
/* Intentionally declared after test() to avoid compile-time checking of ref args. */
@@ -21,6 +18,7 @@ function byVal($arg) {
2118
}
2219

2320
function byRef(&$arg) {
21+
$arg = 'modified';
2422
var_dump($arg);
2523
}
2624

@@ -29,4 +27,8 @@ test('y');
2927
?>
3028
--EXPECT--
3129
string(3) "foo"
32-
Cannot use temporary expression in write context
30+
string(8) "modified"
31+
array(1) {
32+
[0]=>
33+
string(3) "foo"
34+
}

Zend/zend_compile.c

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11309,7 +11309,7 @@ static void zend_compile_array(znode *result, zend_ast *ast) /* {{{ */
1130911309
}
1131011310
/* }}} */
1131111311

11312-
static void zend_compile_const(znode *result, const zend_ast *ast) /* {{{ */
11312+
static zend_op *zend_compile_const_inner(znode *result, const zend_ast *ast, bool use_tmp) /* {{{ */
1131311313
{
1131411314
zend_ast *name_ast = ast->child[0];
1131511315

@@ -11333,17 +11333,21 @@ static void zend_compile_const(znode *result, const zend_ast *ast) /* {{{ */
1133311333
result->op_type = IS_CONST;
1133411334
ZVAL_LONG(&result->u.constant, Z_LVAL_P(zend_ast_get_zval(last->child[0])));
1133511335
zend_string_release_ex(resolved_name, 0);
11336-
return;
11336+
return NULL;
1133711337
}
1133811338
}
1133911339

1134011340
if (zend_try_ct_eval_const(&result->u.constant, resolved_name, is_fully_qualified)) {
1134111341
result->op_type = IS_CONST;
1134211342
zend_string_release_ex(resolved_name, 0);
11343-
return;
11343+
return NULL;
1134411344
}
1134511345

11346-
opline = zend_emit_op_tmp(result, ZEND_FETCH_CONSTANT, NULL, NULL);
11346+
if (use_tmp) {
11347+
opline = zend_emit_op_tmp(result, ZEND_FETCH_CONSTANT, NULL, NULL);
11348+
} else {
11349+
opline = zend_emit_op(result, ZEND_FETCH_CONSTANT, NULL, NULL);
11350+
}
1134711351
opline->op2_type = IS_CONST;
1134811352

1134911353
if (is_fully_qualified || !FC(current_namespace)) {
@@ -11356,6 +11360,13 @@ static void zend_compile_const(znode *result, const zend_ast *ast) /* {{{ */
1135611360
resolved_name, true);
1135711361
}
1135811362
opline->extended_value = zend_alloc_cache_slot();
11363+
return opline;
11364+
}
11365+
/* }}} */
11366+
11367+
static void zend_compile_const(znode *result, const zend_ast *ast) /* {{{ */
11368+
{
11369+
zend_compile_const_inner(result, ast, true);
1135911370
}
1136011371
/* }}} */
1136111372

@@ -12314,6 +12325,8 @@ static zend_op *zend_compile_var_inner(znode *result, zend_ast *ast, uint32_t ty
1231412325
case ZEND_AST_ASSIGN:
1231512326
zend_compile_assign(result, ast, false, type);
1231612327
return NULL;
12328+
case ZEND_AST_CONST:
12329+
return zend_compile_const_inner(result, ast, false);
1231712330
default:
1231812331
if (type == BP_VAR_W || type == BP_VAR_RW || type == BP_VAR_UNSET) {
1231912332
zend_error_noreturn(E_COMPILE_ERROR,

0 commit comments

Comments
 (0)