Skip to content

Commit ae6c172

Browse files
committed
allow null
1 parent be00c05 commit ae6c172

File tree

5 files changed

+98
-56
lines changed

5 files changed

+98
-56
lines changed

ext/random/random.c

Lines changed: 85 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1285,13 +1285,29 @@ PHP_FUNCTION(random_int)
12851285
PHP_METHOD(Random_Engine_CombinedLCG, __construct)
12861286
{
12871287
php_random_engine *engine = Z_RANDOM_ENGINE_P(ZEND_THIS);
1288+
php_random_engine_state_combinedlcg *state = engine->state;
12881289
zend_long seed;
1290+
bool seed_is_null = true;
12891291

1290-
ZEND_PARSE_PARAMETERS_START(1, 1)
1291-
Z_PARAM_LONG(seed)
1292+
ZEND_PARSE_PARAMETERS_START(0, 1)
1293+
Z_PARAM_OPTIONAL;
1294+
Z_PARAM_LONG_OR_NULL(seed, seed_is_null);
12921295
ZEND_PARSE_PARAMETERS_END();
12931296

1294-
engine->algo->seed(engine->state, seed);
1297+
if (seed_is_null) {
1298+
int i;
1299+
1300+
for (i = 0; i < 2; i++) {
1301+
if (php_random_bytes_silent(&state->s[i], sizeof(int32_t)) == FAILURE) {
1302+
zend_throw_exception(spl_ce_RuntimeException, "Random number generate failed", 0);
1303+
RETURN_THROWS();
1304+
}
1305+
}
1306+
1307+
state->seeded = true;
1308+
} else {
1309+
engine->algo->seed(engine->state, seed);
1310+
}
12951311
}
12961312
/* }}} */
12971313

@@ -1412,11 +1428,12 @@ PHP_METHOD(Random_Engine_MersenneTwister, __construct)
14121428
php_random_engine *engine = Z_RANDOM_ENGINE_P(ZEND_THIS);
14131429
php_random_engine_state_mersennetwister *state = engine->state;
14141430
zend_long seed, mode = MT_RAND_MT19937;
1431+
bool seed_is_null = true;
14151432

1416-
ZEND_PARSE_PARAMETERS_START(1, 2)
1417-
Z_PARAM_LONG(seed);
1433+
ZEND_PARSE_PARAMETERS_START(0, 2)
14181434
Z_PARAM_OPTIONAL;
1419-
Z_PARAM_LONG(mode)
1435+
Z_PARAM_LONG_OR_NULL(seed, seed_is_null);
1436+
Z_PARAM_LONG(mode);
14201437
ZEND_PARSE_PARAMETERS_END();
14211438

14221439
switch (mode) {
@@ -1427,6 +1444,14 @@ PHP_METHOD(Random_Engine_MersenneTwister, __construct)
14271444
state->mode = MT_RAND_MT19937;
14281445
}
14291446

1447+
if (seed_is_null) {
1448+
/* MT19937 has a very large state, uses CSPRNG for seeding only */
1449+
if (php_random_bytes_silent(&seed, sizeof(zend_long)) == FAILURE) {
1450+
zend_throw_exception(spl_ce_RuntimeException, "Random number generate failed", 0);
1451+
RETURN_THROWS();
1452+
}
1453+
}
1454+
14301455
engine->algo->seed(engine->state, seed);
14311456
}
14321457
/* }}} */
@@ -1438,28 +1463,39 @@ PHP_METHOD(Random_Engine_XorShift128Plus, __construct)
14381463
php_random_engine_state_xorshift128plus *state = engine->state;
14391464
zend_string *str_seed = NULL;
14401465
zend_long int_seed = 0;
1466+
bool seed_is_null = true;
14411467
int i, j;
14421468

1443-
ZEND_PARSE_PARAMETERS_START(1, 1)
1444-
Z_PARAM_STR_OR_LONG(str_seed, int_seed)
1469+
ZEND_PARSE_PARAMETERS_START(0, 1)
1470+
Z_PARAM_OPTIONAL;
1471+
Z_PARAM_STR_OR_LONG_OR_NULL(str_seed, int_seed, seed_is_null);
14451472
ZEND_PARSE_PARAMETERS_END();
1446-
1447-
if (str_seed) {
1448-
/* char (8 bit) * 16 = 128 bits */
1449-
if (str_seed->len == 16) {
1450-
/* Endianness safe copy */
1451-
for (i = 0; i < 2; i++) {
1452-
state->s[i] = 0;
1453-
for (j = 0; j < 8; j++) {
1454-
state->s[i] += ((uint64_t) (unsigned char) ZSTR_VAL(str_seed)[(i * 8) + j]) << (j * 8);
1455-
}
1473+
1474+
if (seed_is_null) {
1475+
for (i = 0; i < 2; i++) {
1476+
if (php_random_bytes_silent(&state->s[i], sizeof(uint64_t)) == FAILURE) {
1477+
zend_throw_exception(spl_ce_RuntimeException, "Random number generate failed", 0);
1478+
RETURN_THROWS();
14561479
}
1457-
} else {
1458-
zend_argument_value_error(1, "state strings must be 16 bytes");
1459-
RETURN_THROWS();
14601480
}
14611481
} else {
1462-
engine->algo->seed(state, int_seed);
1482+
if (str_seed) {
1483+
/* char (8 bit) * 16 = 128 bits */
1484+
if (str_seed->len == 16) {
1485+
/* Endianness safe copy */
1486+
for (i = 0; i < 2; i++) {
1487+
state->s[i] = 0;
1488+
for (j = 0; j < 8; j++) {
1489+
state->s[i] += ((uint64_t) (unsigned char) ZSTR_VAL(str_seed)[(i * 8) + j]) << (j * 8);
1490+
}
1491+
}
1492+
} else {
1493+
zend_argument_value_error(1, "state strings must be 16 bytes");
1494+
RETURN_THROWS();
1495+
}
1496+
} else {
1497+
engine->algo->seed(state, int_seed);
1498+
}
14631499
}
14641500
}
14651501
/* }}} */
@@ -1497,28 +1533,39 @@ PHP_METHOD(Random_Engine_Xoshiro256StarStar, __construct)
14971533
php_random_engine_state_xoshiro256starstar *state = engine->state;
14981534
zend_string *str_seed = NULL;
14991535
zend_long int_seed = 0;
1536+
bool seed_is_null = true;
15001537
int i, j;
15011538

1502-
ZEND_PARSE_PARAMETERS_START(1, 1)
1503-
Z_PARAM_STR_OR_LONG(str_seed, int_seed)
1539+
ZEND_PARSE_PARAMETERS_START(0, 1)
1540+
Z_PARAM_OPTIONAL;
1541+
Z_PARAM_STR_OR_LONG_OR_NULL(str_seed, int_seed, seed_is_null);
15041542
ZEND_PARSE_PARAMETERS_END();
15051543

1506-
if (str_seed) {
1507-
/* char (8 bit) * 32 = 256 bits */
1508-
if (str_seed->len == 32) {
1509-
/* Endianness safe copy */
1510-
for (i = 0; i < 4; i++) {
1511-
state->s[i] = 0;
1512-
for (j = 0; j < 8; j++) {
1513-
state->s[i] += ((uint64_t) (unsigned char) ZSTR_VAL(str_seed)[(i * 8) + j]) << (j * 8);
1514-
}
1544+
if (seed_is_null) {
1545+
for (i = 0; i < 4; i++) {
1546+
if (php_random_bytes_silent(&state->s[i], sizeof(uint64_t)) == FAILURE) {
1547+
zend_throw_exception(spl_ce_RuntimeException, "Random number generate failed", 0);
1548+
RETURN_THROWS();
15151549
}
1516-
} else {
1517-
zend_argument_value_error(1, "state strings must be 32 bytes");
1518-
RETURN_THROWS();
15191550
}
15201551
} else {
1521-
engine->algo->seed(state, int_seed);
1552+
if (str_seed) {
1553+
/* char (8 bit) * 32 = 256 bits */
1554+
if (str_seed->len == 32) {
1555+
/* Endianness safe copy */
1556+
for (i = 0; i < 4; i++) {
1557+
state->s[i] = 0;
1558+
for (j = 0; j < 8; j++) {
1559+
state->s[i] += ((uint64_t) (unsigned char) ZSTR_VAL(str_seed)[(i * 8) + j]) << (j * 8);
1560+
}
1561+
}
1562+
} else {
1563+
zend_argument_value_error(1, "state strings must be 32 bytes");
1564+
RETURN_THROWS();
1565+
}
1566+
} else {
1567+
engine->algo->seed(state, int_seed);
1568+
}
15221569
}
15231570
}
15241571
/* }}} */
@@ -1536,7 +1583,7 @@ PHP_METHOD(Random_Engine_Xoshiro256StarStar, jump)
15361583

15371584
for (i = 0; i < sizeof(jmp) / sizeof(*jmp); i++) {
15381585
for (j = 0; j < 64; j++) {
1539-
if (jmp[i] & UINT64_C(1) << j) {
1586+
if (jmp[i] & 1ULL << j) {
15401587
s0 ^= s->s[0];
15411588
s1 ^= s->s[1];
15421589
s2 ^= s->s[2];
@@ -1599,11 +1646,6 @@ PHP_METHOD(Random_Randomizer, __construct)
15991646
/* Create default RNG instance */
16001647
if (!engine_object) {
16011648
engine_object = php_random_engine_secure_new(random_ce_Random_Engine_Secure);
1602-
zend_call_known_instance_method_with_0_params(
1603-
random_ce_Random_Engine_Secure->constructor,
1604-
engine_object,
1605-
NULL
1606-
);
16071649

16081650
/* No need self-refcount */
16091651
GC_DELREF(engine_object);

ext/random/random.stub.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ function random_int(int $min, int $max): int {}
2929
{
3030
class CombinedLCG implements Random\SeedableEngine, Random\SerializableEngine
3131
{
32-
public function __construct(int $seed) {}
32+
public function __construct(int|null $seed = null) {}
3333

3434
public function generate(): string {}
3535

@@ -42,7 +42,7 @@ public function __debugInfo(): array {}
4242

4343
class MersenneTwister implements Random\SeedableEngine, Random\SerializableEngine
4444
{
45-
public function __construct(int $seed, int $mode = MT_RAND_MT19937) {}
45+
public function __construct(int|null $seed = null, int $mode = MT_RAND_MT19937) {}
4646

4747
/** @implementation-alias Random\Engine\CombinedLCG::generate */
4848
public function generate(): string {}
@@ -66,7 +66,7 @@ public function generate(): string {}
6666

6767
class XorShift128Plus implements Random\SeedableEngine, Random\SerializableEngine
6868
{
69-
public function __construct(string|int $seed) {}
69+
public function __construct(string|int|null $seed = null) {}
7070

7171
/** @implementation-alias Random\Engine\CombinedLCG::generate */
7272
public function generate(): string {}
@@ -85,7 +85,7 @@ public function __debugInfo(): array {}
8585

8686
class Xoshiro256StarStar implements Random\SeedableEngine, Random\SerializableEngine
8787
{
88-
public function __construct(string|int $seed) {}
88+
public function __construct(string|int|null $seed = null) {}
8989

9090
/** @implementation-alias Random\Engine\CombinedLCG::generate */
9191
public function generate(): string {}

ext/random/random_arginfo.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* This is a generated file, edit the .stub.php file instead.
2-
* Stub hash: 5a7e5078af5896788f35d9c33fe10ef2079648e2 */
2+
* Stub hash: d4414e9eb5d3fd2bc7c8c2c41ae169e823711341 */
33

44
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_lcg_value, 0, 0, IS_DOUBLE, 0)
55
ZEND_END_ARG_INFO()
@@ -32,8 +32,8 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_random_int, 0, 2, IS_LONG, 0)
3232
ZEND_ARG_TYPE_INFO(0, max, IS_LONG, 0)
3333
ZEND_END_ARG_INFO()
3434

35-
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Random_Engine_CombinedLCG___construct, 0, 0, 1)
36-
ZEND_ARG_TYPE_INFO(0, seed, IS_LONG, 0)
35+
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Random_Engine_CombinedLCG___construct, 0, 0, 0)
36+
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, seed, IS_LONG, 1, "null")
3737
ZEND_END_ARG_INFO()
3838

3939
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Random_Engine_CombinedLCG_generate, 0, 0, IS_STRING, 0)
@@ -48,8 +48,8 @@ ZEND_END_ARG_INFO()
4848

4949
#define arginfo_class_Random_Engine_CombinedLCG___debugInfo arginfo_class_Random_Engine_CombinedLCG___serialize
5050

51-
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Random_Engine_MersenneTwister___construct, 0, 0, 1)
52-
ZEND_ARG_TYPE_INFO(0, seed, IS_LONG, 0)
51+
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Random_Engine_MersenneTwister___construct, 0, 0, 0)
52+
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, seed, IS_LONG, 1, "null")
5353
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, mode, IS_LONG, 0, "MT_RAND_MT19937")
5454
ZEND_END_ARG_INFO()
5555

@@ -63,8 +63,8 @@ ZEND_END_ARG_INFO()
6363

6464
#define arginfo_class_Random_Engine_Secure_generate arginfo_class_Random_Engine_CombinedLCG_generate
6565

66-
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Random_Engine_XorShift128Plus___construct, 0, 0, 1)
67-
ZEND_ARG_TYPE_MASK(0, seed, MAY_BE_STRING|MAY_BE_LONG, NULL)
66+
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Random_Engine_XorShift128Plus___construct, 0, 0, 0)
67+
ZEND_ARG_TYPE_MASK(0, seed, MAY_BE_STRING|MAY_BE_LONG|MAY_BE_NULL, "null")
6868
ZEND_END_ARG_INFO()
6969

7070
#define arginfo_class_Random_Engine_XorShift128Plus_generate arginfo_class_Random_Engine_CombinedLCG_generate

ext/random/tests/02_engine/xorshift128plus_seed.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ for ($i = 0; $i < 1000; $i++) {
2929

3030
?>
3131
--EXPECTF--
32-
Random\Engine\XorShift128Plus::__construct(): Argument #1 ($seed) must be of type string|int, float given
32+
Random\Engine\XorShift128Plus::__construct(): Argument #1 ($seed) must be of type string|int|null, float given
3333
Random\Engine\XorShift128Plus::__construct(): Argument #1 ($seed) state strings must be 16 bytes
3434
object(Random\Engine\XorShift128Plus)#%d (%d) {
3535
["__states"]=>

ext/random/tests/02_engine/xoshiro256starstar_seed.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ for ($i = 0; $i < 1000; $i++) {
2929

3030
?>
3131
--EXPECTF--
32-
Random\Engine\Xoshiro256StarStar::__construct(): Argument #1 ($seed) must be of type string|int, float given
32+
Random\Engine\Xoshiro256StarStar::__construct(): Argument #1 ($seed) must be of type string|int|null, float given
3333
Random\Engine\Xoshiro256StarStar::__construct(): Argument #1 ($seed) state strings must be 32 bytes
3434
object(Random\Engine\Xoshiro256StarStar)#%d (%d) {
3535
["__states"]=>

0 commit comments

Comments
 (0)