Skip to content

Commit a6922fd

Browse files
authored
Clean up the implementation of Randomizer::__construct() (#9222)
* Verify that the engine doesn't change in construct_twice.phpt * Clean up the implementation of Randomizer::__construct() Instead of manually checking whether the constructor was already called, we rely on the `readonly` modifier of the `$engine` property. Additionally use `object_init_ex()` instead of manually calling `->create_object()`.
1 parent 54e406c commit a6922fd

File tree

2 files changed

+31
-22
lines changed

2 files changed

+31
-22
lines changed

ext/random/randomizer.c

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -62,32 +62,30 @@ static inline void randomizer_common_init(php_random_randomizer *randomizer, zen
6262
PHP_METHOD(Random_Randomizer, __construct)
6363
{
6464
php_random_randomizer *randomizer = Z_RANDOM_RANDOMIZER_P(ZEND_THIS);
65-
zend_object *engine_object = NULL;
66-
zval zengine_object;
65+
zval engine;
66+
zval *param_engine = NULL;
6767

6868
ZEND_PARSE_PARAMETERS_START(0, 1)
6969
Z_PARAM_OPTIONAL
70-
Z_PARAM_OBJ_OF_CLASS_OR_NULL(engine_object, random_ce_Random_Engine);
70+
Z_PARAM_OBJECT_OF_CLASS_OR_NULL(param_engine, random_ce_Random_Engine);
7171
ZEND_PARSE_PARAMETERS_END();
7272

73-
if (randomizer->algo) {
74-
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Cannot call constructor twice");
75-
RETURN_THROWS();
73+
if (param_engine != NULL) {
74+
ZVAL_COPY(&engine, param_engine);
75+
} else {
76+
/* Create default RNG instance */
77+
object_init_ex(&engine, random_ce_Random_Engine_Secure);
7678
}
7779

78-
/* Create default RNG instance */
79-
if (!engine_object) {
80-
engine_object = random_ce_Random_Engine_Secure->create_object(random_ce_Random_Engine_Secure);
81-
82-
/* No need self-refcount */
83-
GC_DELREF(engine_object);
84-
}
80+
zend_update_property(random_ce_Random_Randomizer, Z_OBJ_P(ZEND_THIS), "engine", strlen("engine"), &engine);
8581

86-
ZVAL_OBJ(&zengine_object, engine_object);
82+
OBJ_RELEASE(Z_OBJ_P(&engine));
8783

88-
zend_update_property(random_ce_Random_Randomizer, Z_OBJ_P(ZEND_THIS), "engine", strlen("engine"), &zengine_object);
84+
if (EG(exception)) {
85+
RETURN_THROWS();
86+
}
8987

90-
randomizer_common_init(randomizer, engine_object);
88+
randomizer_common_init(randomizer, Z_OBJ_P(&engine));
9189
}
9290
/* }}} */
9391

ext/random/tests/03_randomizer/construct_twice.phpt

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,28 +13,39 @@ final class UserEngine implements \Random\Engine
1313

1414
try {
1515
(new \Random\Randomizer())->__construct();
16-
} catch (\BadMethodCallException $e) {
16+
} catch (\Error $e) {
1717
echo $e->getMessage() . PHP_EOL;
1818
}
1919

2020
try {
2121
$r = new \Random\Randomizer(new \Random\Engine\Xoshiro256StarStar());
2222
$r->__construct(new \Random\Engine\PcgOneseq128XslRr64());
23-
} catch (\BadMethodCallException $e) {
23+
} catch (\Error $e) {
2424
echo $e->getMessage() . PHP_EOL;
2525
}
2626

2727
try {
2828
$r = new \Random\Randomizer(new \UserEngine());
2929
$r->__construct(new \UserEngine());
30-
} catch (\BadMethodCallException $e) {
30+
} catch (\Error $e) {
3131
echo $e->getMessage() . PHP_EOL;
3232
}
3333

34+
try {
35+
$r = new \Random\Randomizer(new \Random\Engine\Xoshiro256StarStar());
36+
$r->__construct(new \UserEngine());
37+
} catch (\Error $e) {
38+
echo $e->getMessage(), PHP_EOL;
39+
}
40+
41+
var_dump($r->engine::class);
42+
3443
die('success');
3544
?>
3645
--EXPECT--
37-
Cannot call constructor twice
38-
Cannot call constructor twice
39-
Cannot call constructor twice
46+
Cannot modify readonly property Random\Randomizer::$engine
47+
Cannot modify readonly property Random\Randomizer::$engine
48+
Cannot modify readonly property Random\Randomizer::$engine
49+
Cannot modify readonly property Random\Randomizer::$engine
50+
string(32) "Random\Engine\Xoshiro256StarStar"
4051
success

0 commit comments

Comments
 (0)