Skip to content

Commit af53d9e

Browse files
Fix named parameters and opcache protection
1 parent e46f32f commit af53d9e

File tree

3 files changed

+60
-8
lines changed

3 files changed

+60
-8
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
--TEST--
2+
Verify that named parameters can be passed to attributes on constants
3+
--FILE--
4+
<?php
5+
6+
#[MyAttribute(foo: "bar")]
7+
const EXAMPLE = 'Foo';
8+
9+
$ref = new ReflectionConstant('EXAMPLE');
10+
$attribs = $ref->getAttributes();
11+
var_dump( $attribs );
12+
var_dump( $attribs[0]->getArguments() );
13+
14+
?>
15+
--EXPECTF--
16+
array(1) {
17+
[0]=>
18+
object(ReflectionAttribute)#2 (1) {
19+
["name"]=>
20+
string(11) "MyAttribute"
21+
}
22+
}
23+
array(1) {
24+
["foo"]=>
25+
string(3) "bar"
26+
}

Zend/zend_attributes.c

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -251,11 +251,24 @@ ZEND_API zend_result zend_get_attribute_value(zval *ret, zend_attribute *attr, u
251251

252252
ZVAL_COPY_OR_DUP(ret, &attr->args[i].value);
253253

254-
if (Z_TYPE_P(ret) == IS_CONSTANT_AST) {
255-
if (SUCCESS != zval_update_constant_ex(ret, scope)) {
256-
zval_ptr_dtor(ret);
257-
return FAILURE;
258-
}
254+
if (Z_TYPE_P(ret) != IS_CONSTANT_AST) {
255+
return SUCCESS;
256+
}
257+
zend_ast *arg_ast = Z_ASTVAL_P(ret);
258+
zend_result result;
259+
if (arg_ast->kind == ZEND_AST_NAMED_ARG) {
260+
attr->args[i].name = zend_string_copy(zend_ast_get_str(arg_ast->child[0]));
261+
zend_ast *value = arg_ast->child[1];
262+
zend_ast_ref *ast_ref = zend_ast_copy(value);
263+
zval_ptr_dtor(ret);
264+
ZVAL_AST(ret, ast_ref);
265+
result = zval_update_constant_ex(ret, scope);
266+
} else {
267+
result = zval_update_constant_ex(ret, scope);
268+
}
269+
if (result != SUCCESS) {
270+
zval_ptr_dtor(ret);
271+
return FAILURE;
259272
}
260273

261274
return SUCCESS;

Zend/zend_compile.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7425,8 +7425,20 @@ void zend_compile_attributes(
74257425
"Cannot use positional argument after named argument");
74267426
}
74277427

7428-
zend_const_expr_to_zval(
7429-
&attr->args[j].value, arg_ast_ptr, /* allow_dynamic */ true);
7428+
if (target == ZEND_ATTRIBUTE_TARGET_CONST) {
7429+
// Make sure that deprecated constants are not updated
7430+
// into protected memory from opcache
7431+
zend_ast_ref *ast_copy_ref = zend_ast_copy(args->child[j]);
7432+
zend_ast *copied_ast = GC_AST(ast_copy_ref);
7433+
zend_ast **extra_ptr = &copied_ast;
7434+
zend_const_expr_to_zval(
7435+
&attr->args[j].value, extra_ptr, /* allow_dynamic */ true);
7436+
zend_ast_destroy(*extra_ptr);
7437+
zend_ast_ref_destroy(ast_copy_ref);
7438+
} else {
7439+
zend_const_expr_to_zval(
7440+
&attr->args[j].value, arg_ast_ptr, /* allow_dynamic */ true);
7441+
}
74307442
}
74317443
}
74327444
}
@@ -11336,7 +11348,8 @@ void zend_const_expr_to_zval(zval *result, zend_ast **ast_ptr, bool allow_dynami
1133611348
if ((*ast_ptr)->kind != ZEND_AST_ZVAL) {
1133711349
/* Replace with compiled AST zval representation. */
1133811350
zval ast_zv;
11339-
ZVAL_AST(&ast_zv, zend_ast_copy(*ast_ptr));
11351+
zend_ast_ref *copy_ref = zend_ast_copy(*ast_ptr);
11352+
ZVAL_AST(&ast_zv, copy_ref);
1134011353
zend_ast_destroy(*ast_ptr);
1134111354
*ast_ptr = zend_ast_create_zval(&ast_zv);
1134211355
}

0 commit comments

Comments
 (0)