Skip to content

Commit 05ae5ed

Browse files
committed
Test new API and fix issues encountered in testing
1 parent 3878414 commit 05ae5ed

File tree

5 files changed

+138
-6
lines changed

5 files changed

+138
-6
lines changed

Zend/zend_API.c

+10-5
Original file line numberDiff line numberDiff line change
@@ -1852,22 +1852,27 @@ ZEND_API zend_result object_init_with_constructor(zval *arg, zend_class_entry *c
18521852
if (UNEXPECTED(status == FAILURE)) {
18531853
return FAILURE;
18541854
}
1855-
/* A constructor does not return a value, however if an exception is thrown
1855+
zend_object * obj = Z_OBJ_P(arg);
1856+
zend_function *constructor = obj->handlers->get_constructor(obj);
1857+
if (UNEXPECTED(constructor == NULL)) {
1858+
return FAILURE;
1859+
}
1860+
/* A constructor should not return a value, however if an exception is thrown
18561861
* zend_call_known_function() will set the retval to IS_UNDEF */
18571862
zval retval;
1858-
ZVAL_UNDEF(&retval);
18591863
zend_call_known_function(
1860-
class_type->constructor,
1861-
Z_OBJ_P(arg),
1864+
constructor,
1865+
obj,
18621866
class_type,
1863-
/* retval */ NULL,
1867+
/* retval */ &retval,
18641868
param_count,
18651869
params,
18661870
named_params
18671871
);
18681872
if (Z_TYPE(retval) == IS_UNDEF) {
18691873
return FAILURE;
18701874
} else {
1875+
/* Unlikely, but user constructors may return any value they want */
18711876
zval_ptr_dtor(&retval);
18721877
return SUCCESS;
18731878
}

ext/zend_test/test.c

+20
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,26 @@ static ZEND_FUNCTION(zend_call_method)
460460
zend_call_method(obj, ce, NULL, ZSTR_VAL(method_name), ZSTR_LEN(method_name), return_value, argc - 2, arg1, arg2);
461461
}
462462

463+
/* Instantiate a class and run the constructor via object_init_with_constructor */
464+
static ZEND_FUNCTION(zend_object_init_with_constructor)
465+
{
466+
zend_class_entry *ce = NULL;
467+
zval *args;
468+
uint32_t num_args;
469+
HashTable *named_args;
470+
471+
ZEND_PARSE_PARAMETERS_START(1, -1)
472+
Z_PARAM_CLASS(ce)
473+
Z_PARAM_VARIADIC_WITH_NAMED(args, num_args, named_args)
474+
ZEND_PARSE_PARAMETERS_END();
475+
476+
zend_result status = object_init_with_constructor(return_value, ce, num_args, args, named_args);
477+
if (status == FAILURE) {
478+
RETURN_THROWS();
479+
}
480+
ZEND_ASSERT(!EG(exception));
481+
}
482+
463483
static ZEND_FUNCTION(zend_get_unit_enum)
464484
{
465485
ZEND_PARSE_PARAMETERS_NONE();

ext/zend_test/test.stub.php

+2
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,8 @@ function zend_get_current_func_name(): string {}
247247

248248
function zend_call_method(object|string $obj_or_class, string $method, mixed $arg1 = UNKNOWN, mixed $arg2 = UNKNOWN): mixed {}
249249

250+
function zend_object_init_with_constructor(string $class, mixed ...$args): mixed {}
251+
250252
function zend_test_zend_ini_parse_quantity(string $str): int {}
251253
function zend_test_zend_ini_parse_uquantity(string $str): int {}
252254

ext/zend_test/test_arginfo.h

+8-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
--TEST--
2+
Zend: Test zend_forbid_dynamic_call() for methods
3+
--EXTENSIONS--
4+
zend_test
5+
sysvmsg
6+
--FILE--
7+
<?php
8+
9+
class PrivateUser {
10+
private function __construct() {
11+
return new stdClass();
12+
}
13+
}
14+
15+
class ThrowingUser {
16+
public function __construct() {
17+
throw new Exception("Don't construct");
18+
}
19+
}
20+
21+
class TestUser {
22+
public function __construct(int $int_param, string $string_param) {
23+
return new stdClass();
24+
}
25+
}
26+
27+
echo "Testing impossible initializations\n";
28+
try {
29+
$o = zend_object_init_with_constructor("_ZendTestInterface");
30+
var_dump($o);
31+
} catch (\Throwable $e) {
32+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
33+
}
34+
try {
35+
$o = zend_object_init_with_constructor("_ZendTestTrait");
36+
var_dump($o);
37+
} catch (\Throwable $e) {
38+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
39+
}
40+
try {
41+
$o = zend_object_init_with_constructor("ZendTestUnitEnum");
42+
var_dump($o);
43+
} catch (\Throwable $e) {
44+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
45+
}
46+
try {
47+
$o = zend_object_init_with_constructor("SysvMessageQueue");
48+
var_dump($o);
49+
} catch (\Throwable $e) {
50+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
51+
}
52+
try {
53+
$o = zend_object_init_with_constructor("PrivateUser");
54+
var_dump($o);
55+
} catch (\Throwable $e) {
56+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
57+
}
58+
try {
59+
$o = zend_object_init_with_constructor("ThrowingUser");
60+
var_dump($o);
61+
} catch (\Throwable $e) {
62+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
63+
}
64+
65+
echo "Testing param passing\n";
66+
try {
67+
$o = zend_object_init_with_constructor("TestUser");
68+
var_dump($o);
69+
} catch (\Throwable $e) {
70+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
71+
}
72+
try {
73+
$o = zend_object_init_with_constructor("TestUser", "str", 5);
74+
var_dump($o);
75+
} catch (\Throwable $e) {
76+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
77+
}
78+
try {
79+
$o = zend_object_init_with_constructor("TestUser", 5, string_param: "str");
80+
var_dump($o);
81+
} catch (\Throwable $e) {
82+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
83+
}
84+
85+
?>
86+
--EXPECT--
87+
Testing impossible initializations
88+
Error: Cannot instantiate interface _ZendTestInterface
89+
Error: Cannot instantiate trait _ZendTestTrait
90+
Error: Cannot instantiate enum ZendTestUnitEnum
91+
Error: Cannot directly construct SysvMessageQueue, use msg_get_queue() instead
92+
Error: Call to private PrivateUser::__construct() from global scope
93+
Exception: Don't construct
94+
Testing param passing
95+
ArgumentCountError: Too few arguments to function TestUser::__construct(), 0 passed and exactly 2 expected
96+
TypeError: TestUser::__construct(): Argument #1 ($int_param) must be of type int, string given
97+
object(TestUser)#3 (0) {
98+
}

0 commit comments

Comments
 (0)