diff --git a/Zend/tests/partial_application/attributes_004.phpt b/Zend/tests/partial_application/attributes_004.phpt new file mode 100644 index 000000000000..15e62b96df67 --- /dev/null +++ b/Zend/tests/partial_application/attributes_004.phpt @@ -0,0 +1,60 @@ +--TEST-- +PFA attribute UAF +--CREDITS-- +Ryan @ Calif.io +--FILE-- +getAttributes(NoDiscard::class)[0]->getArguments(); +} + +$original = new ReflectionFunction('userTarget'); +var_dump(arguments($original)); + +$partial = userTarget(?); +echo "partial-created\n"; +var_dump(arguments($original)); +var_dump(arguments(new ReflectionFunction($partial))); + +unset($partial); +gc_collect_cycles(); +echo "partial-destroyed\n"; +var_dump(arguments($original)); + +userTarget('discarded'); + +?> +--EXPECTF-- +array(1) { + [0]=> + string(266) "message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-%d" +} +partial-created +array(1) { + [0]=> + string(266) "message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-%d" +} +array(1) { + [0]=> + string(266) "message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-%d" +} +partial-destroyed +array(1) { + [0]=> + string(266) "message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-%d" +} + +Warning: The return value of function userTarget() should either be used or intentionally ignored by casting it as (void), message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-message-%d in %s on line %d diff --git a/Zend/zend_partial.c b/Zend/zend_partial.c index ec60383a2bc8..3952208765ee 100644 --- a/Zend/zend_partial.c +++ b/Zend/zend_partial.c @@ -472,7 +472,9 @@ static zend_ast *zp_attribute_to_ast(zend_attribute *attribute) if (attribute->argc) { args_ast = zend_ast_create_arg_list(0, ZEND_AST_ARG_LIST); for (uint32_t i = 0; i < attribute->argc; i++) { - zend_ast *arg_ast = zend_ast_create_zval(&attribute->args[i].value); + zval *zv = &attribute->args[i].value; + Z_TRY_ADDREF_P(zv); + zend_ast *arg_ast = zend_ast_create_zval(zv); if (attribute->args[i].name) { arg_ast = zend_ast_create(ZEND_AST_NAMED_ARG, zend_ast_create_zval_from_str( @@ -561,6 +563,7 @@ static zend_ast *zp_compile_forwarding_call( args_ast = zend_ast_list_add(args_ast, default_value_ast); } else if (zp_is_const_arg(const_args, offset)) { ZEND_ASSERT(Z_TYPE(argv[offset]) < IS_OBJECT); + ZEND_ASSERT(!Z_REFCOUNTED(argv[offset])); args_ast = zend_ast_list_add(args_ast, zend_ast_create_zval(&argv[offset])); } else { args_ast = zend_ast_list_add(args_ast, zend_ast_create(ZEND_AST_VAR,