Skip to content

Commit 193d385

Browse files
authored
Leverage object_init_with_constructor() in zend_get_attribute_object() (#14532)
1 parent 10a6f0b commit 193d385

File tree

4 files changed

+35
-95
lines changed

4 files changed

+35
-95
lines changed

Zend/tests/attributes/005_objects.phpt

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -72,19 +72,6 @@ try {
7272

7373
echo "\n";
7474

75-
#[Attribute]
76-
class A4 { }
77-
78-
$ref = new \ReflectionFunction(#[A4(1)] function () { });
79-
80-
try {
81-
$ref->getAttributes()[0]->newInstance();
82-
} catch (\Error $e) {
83-
var_dump('ERROR 5', $e->getMessage());
84-
}
85-
86-
echo "\n";
87-
8875
class A5 { }
8976

9077
$ref = new \ReflectionFunction(#[A5] function () { });
@@ -111,10 +98,7 @@ string(7) "ERROR 3"
11198
string(30) "Attribute class "A2" not found"
11299

113100
string(7) "ERROR 4"
114-
string(48) "Attribute constructor of class A3 must be public"
115-
116-
string(7) "ERROR 5"
117-
string(69) "Attribute class A4 does not have a constructor, cannot pass arguments"
101+
string(51) "Call to private A3::__construct() from global scope"
118102

119103
string(7) "ERROR 6"
120104
string(55) "Attempting to use non-attribute class "A5" as attribute"

Zend/tests/prop_const_expr/attributes.phpt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,20 @@ foreach ((new ReflectionClass(C::class))->getAttributes() as $reflectionAttribut
2525
}
2626

2727
?>
28-
--EXPECT--
29-
object(Attr)#1 (1) {
28+
--EXPECTF--
29+
object(Attr)#%d (1) {
3030
["value"]=>
3131
string(1) "B"
3232
}
33-
object(Attr)#1 (1) {
33+
object(Attr)#%d (1) {
3434
["value"]=>
3535
string(1) "C"
3636
}
37-
object(Attr)#1 (1) {
37+
object(Attr)#%d (1) {
3838
["value"]=>
3939
string(1) "B"
4040
}
41-
object(Attr)#1 (1) {
41+
object(Attr)#%d (1) {
4242
["value"]=>
4343
string(1) "C"
4444
}

Zend/zend_attributes.c

Lines changed: 22 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -214,18 +214,9 @@ ZEND_API zend_result zend_get_attribute_value(zval *ret, zend_attribute *attr, u
214214
return SUCCESS;
215215
}
216216

217-
static zend_result call_attribute_constructor(
218-
zend_attribute *attr, zend_class_entry *ce, zend_object *obj,
219-
zval *args, uint32_t argc, HashTable *named_params, zend_string *filename)
217+
ZEND_API zend_result zend_get_attribute_object(zval *obj, zend_class_entry *attribute_ce, zend_attribute *attribute_data, zend_class_entry *scope, zend_string *filename)
220218
{
221-
zend_function *ctor = ce->constructor;
222219
zend_execute_data *call = NULL;
223-
ZEND_ASSERT(ctor != NULL);
224-
225-
if (!(ctor->common.fn_flags & ZEND_ACC_PUBLIC)) {
226-
zend_throw_error(NULL, "Attribute constructor of class %s must be public", ZSTR_VAL(ce->name));
227-
return FAILURE;
228-
}
229220

230221
if (filename) {
231222
/* Set up dummy call frame that makes it look like the attribute was invoked
@@ -244,7 +235,7 @@ static zend_result call_attribute_constructor(
244235
opline = (zend_op*)(call + 1);
245236
memset(opline, 0, sizeof(zend_op));
246237
opline->opcode = ZEND_DO_FCALL;
247-
opline->lineno = attr->lineno;
238+
opline->lineno = attribute_data->lineno;
248239

249240
call->opline = opline;
250241
call->call = NULL;
@@ -255,57 +246,17 @@ static zend_result call_attribute_constructor(
255246
memset(call->func, 0, sizeof(zend_function));
256247
call->func->type = ZEND_USER_FUNCTION;
257248
call->func->op_array.fn_flags =
258-
attr->flags & ZEND_ATTRIBUTE_STRICT_TYPES ? ZEND_ACC_STRICT_TYPES : 0;
249+
attribute_data->flags & ZEND_ATTRIBUTE_STRICT_TYPES ? ZEND_ACC_STRICT_TYPES : 0;
259250
call->func->op_array.fn_flags |= ZEND_ACC_CALL_VIA_TRAMPOLINE;
260251
call->func->op_array.filename = filename;
261252

262253
EG(current_execute_data) = call;
263254
}
264255

265-
zend_call_known_function(ctor, obj, obj->ce, NULL, argc, args, named_params);
266-
267-
if (filename) {
268-
EG(current_execute_data) = call->prev_execute_data;
269-
zend_vm_stack_free_call_frame(call);
270-
}
271-
272-
if (EG(exception)) {
273-
zend_object_store_ctor_failed(obj);
274-
return FAILURE;
275-
}
276-
277-
return SUCCESS;
278-
}
279-
280-
static void attribute_ctor_cleanup(zval *obj, zval *args, uint32_t argc, HashTable *named_params)
281-
{
282-
if (obj) {
283-
zval_ptr_dtor(obj);
284-
}
285-
286-
if (args) {
287-
uint32_t i;
288-
289-
for (i = 0; i < argc; i++) {
290-
zval_ptr_dtor(&args[i]);
291-
}
292-
293-
efree(args);
294-
}
295-
296-
if (named_params) {
297-
zend_array_destroy(named_params);
298-
}
299-
}
300-
301-
ZEND_API zend_result zend_get_attribute_object(zval *obj, zend_class_entry *attribute_ce, zend_attribute *attribute_data, zend_class_entry *scope, zend_string *filename)
302-
{
303256
zval *args = NULL;
304257
HashTable *named_params = NULL;
305258

306-
if (SUCCESS != object_init_ex(obj, attribute_ce)) {
307-
return FAILURE;
308-
}
259+
zend_result result = FAILURE;
309260

310261
uint32_t argc = 0;
311262
if (attribute_data->argc) {
@@ -314,8 +265,8 @@ ZEND_API zend_result zend_get_attribute_object(zval *obj, zend_class_entry *attr
314265
for (uint32_t i = 0; i < attribute_data->argc; i++) {
315266
zval val;
316267
if (FAILURE == zend_get_attribute_value(&val, attribute_data, i, scope)) {
317-
attribute_ctor_cleanup(obj, args, argc, named_params);
318-
return FAILURE;
268+
result = FAILURE;
269+
goto out;
319270
}
320271
if (attribute_data->args[i].name) {
321272
if (!named_params) {
@@ -329,20 +280,25 @@ ZEND_API zend_result zend_get_attribute_object(zval *obj, zend_class_entry *attr
329280
}
330281
}
331282

332-
if (attribute_ce->constructor) {
333-
if (FAILURE == call_attribute_constructor(attribute_data, attribute_ce, Z_OBJ_P(obj), args, argc, named_params, filename)) {
334-
attribute_ctor_cleanup(obj, args, argc, named_params);
335-
return FAILURE;
336-
}
337-
} else if (argc || named_params) {
338-
attribute_ctor_cleanup(obj, args, argc, named_params);
339-
zend_throw_error(NULL, "Attribute class %s does not have a constructor, cannot pass arguments", ZSTR_VAL(attribute_ce->name));
340-
return FAILURE;
283+
result = object_init_with_constructor(obj, attribute_ce, argc, args, named_params);
284+
285+
out:
286+
for (uint32_t i = 0; i < argc; i++) {
287+
zval_ptr_dtor(&args[i]);
341288
}
342289

343-
attribute_ctor_cleanup(NULL, args, argc, named_params);
290+
efree(args);
344291

345-
return SUCCESS;
292+
if (named_params) {
293+
zend_array_destroy(named_params);
294+
}
295+
296+
if (filename) {
297+
EG(current_execute_data) = call->prev_execute_data;
298+
zend_vm_stack_free_call_frame(call);
299+
}
300+
301+
return result;
346302
}
347303

348304
static const char *target_names[] = {

ext/reflection/tests/new_in_attributes.phpt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,34 +36,34 @@ $obj = $ra->newInstance();
3636
var_dump($args, $obj);
3737

3838
?>
39-
--EXPECT--
39+
--EXPECTF--
4040
array(2) {
4141
[0]=>
4242
NULL
4343
[1]=>
44-
object(stdClass)#3 (0) {
44+
object(stdClass)#%d (0) {
4545
}
4646
}
47-
object(MyAttribute)#4 (2) {
47+
object(MyAttribute)#%d (2) {
4848
["x"]=>
4949
NULL
5050
["y"]=>
51-
object(stdClass)#5 (0) {
51+
object(stdClass)#%d (0) {
5252
}
5353
}
5454
bool(true)
5555
bool(true)
5656
array(2) {
5757
["y"]=>
58-
object(stdClass)#2 (0) {
58+
object(stdClass)#%d (0) {
5959
}
6060
["x"]=>
6161
NULL
6262
}
63-
object(MyAttribute)#10 (2) {
63+
object(MyAttribute)#%d (2) {
6464
["x"]=>
6565
NULL
6666
["y"]=>
67-
object(stdClass)#11 (0) {
67+
object(stdClass)#%d (0) {
6868
}
6969
}

0 commit comments

Comments
 (0)