From 6827e8d5ce400a99bee0ae7963cc6fe6d76c99b9 Mon Sep 17 00:00:00 2001 From: Jorg Sowa Date: Fri, 30 Oct 2026 20:58:06 +0100 Subject: [PATCH] Fix AST export of by-reference property hooks ZEND_ACC_RETURN_REFERENCE shares a bit with ZEND_ACC_PRIVATE_SET, so &get was exported as private(set) get. --- NEWS | 1 + .../property_hooks/ast_printing_by_ref.phpt | 34 +++++++++++++++++++ Zend/zend_ast.c | 4 ++- 3 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 Zend/tests/property_hooks/ast_printing_by_ref.phpt diff --git a/NEWS b/NEWS index 18ec48a2acfe..5ff350cd25d6 100644 --- a/NEWS +++ b/NEWS @@ -144,6 +144,7 @@ PHP NEWS . Fixed bug GH-24480 (Finally block running a second time when a VM interrupt throws as the finally block returns to a "return" in its try block). (C. Scott Ananian) + . Fixed AST export of by-reference property hooks. (Jorg Sowa) - CLI: . Fixed bug GH-24697 (PHP_HTTP_PARSER_STRICT build option doesn't work). diff --git a/Zend/tests/property_hooks/ast_printing_by_ref.phpt b/Zend/tests/property_hooks/ast_printing_by_ref.phpt new file mode 100644 index 000000000000..a3b0bd405f74 --- /dev/null +++ b/Zend/tests/property_hooks/ast_printing_by_ref.phpt @@ -0,0 +1,34 @@ +--TEST-- +By-reference hook AST printing +--FILE-- + $this->prop1; } + public $prop2 { + final &get { + return $this->prop2; + } + } + public private(set) int $prop3 { &get => $this->prop3; } + }); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +assert(false && new class { + public $prop1 { + &get => $this->prop1; + } + public $prop2 { + final &get { + return $this->prop2; + } + } + public private(set) int $prop3 { + &get => $this->prop3; + } +}) diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index 0f20becf0454..062983769a65 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -1788,10 +1788,12 @@ static ZEND_COLD void zend_ast_export_hook_list(smart_str *str, zend_ast_list *h for (uint32_t i = 0; i < hook_list->children; i++) { zend_ast_decl *hook = (zend_ast_decl *)hook_list->child[i]; - zend_ast_export_visibility(str, hook->flags, ZEND_MODIFIER_TARGET_PROPERTY); if (hook->flags & ZEND_ACC_FINAL) { smart_str_appends(str, "final "); } + if (hook->flags & ZEND_ACC_RETURN_REFERENCE) { + smart_str_appendc(str, '&'); + } smart_str_append(str, hook->name); zend_ast *body = hook->child[2]; if (body == NULL) {