Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Fix GH-10497: Allow const obj->prop = value #20903

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
khaledalam wants to merge 1 commit into php:master
base: master
Choose a base branch
Loading
from khaledalam:fix-gh10497-allow-const-object-modification

Conversation

@khaledalam
Copy link

@khaledalam khaledalam commented Jan 11, 2026

Description

Fixes #10497 - Allows direct modification of object properties stored in constants.

Problem

Previously, this code would fail with a fatal error:

const a = new stdClass;
a->b = 42; // Fatal error: Cannot use temporary expression in write context

Solution

Modified the compiler to properly handle ZEND_AST_CONST in variable compilation contexts:

Constants now emit IS_VAR instead of IS_TMP_VAR when used in write contexts
This allows property assignment opcodes to work correctly with constant objects

Tests:

  • Added Zend/tests/gh10497.phpt - comprehensive test for the fix
  • Updated Zend/tests/gh12102_3.phpt - reflects improved constant handling

Behavior

Now supports all property operations on constant objects:

const obj = new stdClass;
obj->prop = 'value';
obj->prop = 'new value';
obj->another = 'test';
obj->counter = 0;
obj->counter++;
obj->num = 10;
obj->num += 5;
unset(obj->prop);
obj->nested = new stdClass;
obj->nested->value = 123;

The constant reference remains immutable, but the object itself is mutable as expected.

Copy link
Member

@iluuu1994 iluuu1994 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @khaledalam! Looks reasonable overall.

*result = *zend_ast_get_znode(ast);
return NULL;
case ZEND_AST_CONST:
return zend_compile_const_inner(result, ast, false);
Copy link
Member

@iluuu1994 iluuu1994 Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should pass type directly and only produce IS_VAR when in write-context (BP_VAR_W or BP_VAR_RW).

/* }}} */

static voidzend_compile_const(znode *result, const zend_ast *ast) /* {{{ */
static zend_op*zend_compile_const_inner(znode *result, const zend_ast *ast, booluse_tmp) /* {{{ */
Copy link
Member

@iluuu1994 iluuu1994 Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

zend_compile_const() is only used from one other place, no need for this BC layer. You can just pass BP_VAR_R from zend_compile_expr_inner().

resolved_name, true);
}
opline->extended_value = zend_alloc_cache_slot();
return opline;
Copy link
Member

@iluuu1994 iluuu1994 Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This return value should be unneded. It's only needed for specific opcodes, e.g. to add some extended_value flag. Just return NULL from zend_compile_var_inner().

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@iluuu1994 iluuu1994 iluuu1994 left review comments

Assignees

No one assigned

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Cannot directly modify an object stored in a constant

AltStyle によって変換されたページ (->オリジナル) /