Skip to content

Commit 99e7cf0

Browse files
authored
random: Clean up seeding API (#13540)
* random: Expose xoshiro256**'s seeding functions * random: Expose pcgoneseq128xslrr64's seeding functions * random: Expose Mt19937's seeding functions * random: Expose CombinedLCG's seeding functions * random: Call php_random_mt19937_seed32 to seed the global Mt19937 This avoids the function pointer indirection and improves type safety. * random: NULL the generic seeding function Different engines work quite differently, it is not useful to attempt to seed them in a generic way using a 64 bit integer. As an example Mt19937 completely ignores the upper 32 bits. * random: Remove the `seed` member from `php_random_algo` See the explanation in the previous commit for the reasoning. This member is unused since the previous commit and was not consistently available even before that (specifically for the Secure engine). * UPGRADING.INTERNALS * random: Remove useless cast in `php_mt_srand()`
1 parent a31edaa commit 99e7cf0

9 files changed

+34
-49
lines changed

UPGRADING.INTERNALS

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,11 @@ PHP 8.4 INTERNALS UPGRADE NOTES
156156
single php_random_algo_with_state struct by value, making it easier to
157157
pass around the state with its associated algorithm and thus reducing
158158
the chance for mistakes.
159+
- The seed member of a php_random_algo has been removed. As a replacement
160+
engine-specific seeding functions are now exposed. This change allows
161+
users to better take engine-specific behavior into account. As an example
162+
Mt19937 ignored the upper half of the seed parameter of the generic
163+
seeding function.
159164
- The CSPRNG API (php_random_(bytes|int)_*) is now provided by the new
160165
and much smaller php_random_csprng.h header. The new header is included
161166
in php_random.h for compatibility with existing users.

ext/random/engine_combinedlcg.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,10 @@
3232
*/
3333
#define MODMULT(a, b, c, m, s) q = s / a; s = b * (s - a * q) - c * q; if (s < 0) s += m
3434

35-
static void seed(void *state, uint64_t seed)
35+
PHPAPI void php_random_combinedlcg_seed64(php_random_status_state_combinedlcg *state, uint64_t seed)
3636
{
37-
php_random_status_state_combinedlcg *s = state;
38-
39-
s->state[0] = seed & 0xffffffffU;
40-
s->state[1] = seed >> 32;
37+
state->state[0] = seed & 0xffffffffU;
38+
state->state[1] = seed >> 32;
4139
}
4240

4341
static php_random_result generate(void *state)
@@ -100,7 +98,6 @@ static bool unserialize(void *state, HashTable *data)
10098

10199
const php_random_algo php_random_algo_combinedlcg = {
102100
sizeof(php_random_status_state_combinedlcg),
103-
seed,
104101
generate,
105102
range,
106103
serialize,

ext/random/engine_mt19937.c

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -121,15 +121,15 @@ static inline void mt19937_reload(php_random_status_state_mt19937 *state)
121121
state->count = 0;
122122
}
123123

124-
static inline void mt19937_seed_state(php_random_status_state_mt19937 *state, uint64_t seed)
124+
PHPAPI inline void php_random_mt19937_seed32(php_random_status_state_mt19937 *state, uint32_t seed)
125125
{
126126
uint32_t i, prev_state;
127127

128128
/* Initialize generator state with seed
129129
See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier.
130130
In previous versions, most significant bits (MSBs) of the seed affect
131131
only MSBs of the state array. Modified 9 Jan 2002 by Makoto Matsumoto. */
132-
state->state[0] = seed & 0xffffffffU;
132+
state->state[0] = seed;
133133
for (i = 1; i < MT_N; i++) {
134134
prev_state = state->state[i - 1];
135135
state->state[i] = (1812433253U * (prev_state ^ (prev_state >> 30)) + i) & 0xffffffffU;
@@ -139,11 +139,6 @@ static inline void mt19937_seed_state(php_random_status_state_mt19937 *state, ui
139139
mt19937_reload(state);
140140
}
141141

142-
static void seed(void *state, uint64_t seed)
143-
{
144-
mt19937_seed_state(state, seed);
145-
}
146-
147142
static php_random_result generate(void *state)
148143
{
149144
php_random_status_state_mt19937 *s = state;
@@ -231,7 +226,6 @@ static bool unserialize(void *state, HashTable *data)
231226

232227
const php_random_algo php_random_algo_mt19937 = {
233228
sizeof(php_random_status_state_mt19937),
234-
seed,
235229
generate,
236230
range,
237231
serialize,
@@ -241,13 +235,13 @@ const php_random_algo php_random_algo_mt19937 = {
241235
/* {{{ php_random_mt19937_seed_default */
242236
PHPAPI void php_random_mt19937_seed_default(php_random_status_state_mt19937 *state)
243237
{
244-
zend_long seed = 0;
238+
uint32_t seed = 0;
245239

246240
if (php_random_bytes_silent(&seed, sizeof(seed)) == FAILURE) {
247241
seed = GENERATE_SEED();
248242
}
249243

250-
mt19937_seed_state(state, (uint64_t) seed);
244+
php_random_mt19937_seed32(state, seed);
251245
}
252246
/* }}} */
253247

@@ -286,7 +280,7 @@ PHP_METHOD(Random_Engine_Mt19937, __construct)
286280
}
287281
}
288282

289-
mt19937_seed_state(state, seed);
283+
php_random_mt19937_seed32(state, seed);
290284
}
291285
/* }}} */
292286

ext/random/engine_pcgoneseq128xslrr64.c

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,14 @@ static inline void step(php_random_status_state_pcgoneseq128xslrr64 *s)
3535
);
3636
}
3737

38-
static inline void seed128(php_random_status_state_pcgoneseq128xslrr64 *s, php_random_uint128_t seed)
38+
PHPAPI inline void php_random_pcgoneseq128xslrr64_seed128(php_random_status_state_pcgoneseq128xslrr64 *s, php_random_uint128_t seed)
3939
{
4040
s->state = php_random_uint128_constant(0ULL, 0ULL);
4141
step(s);
4242
s->state = php_random_uint128_add(s->state, seed);
4343
step(s);
4444
}
4545

46-
static void seed(void *state, uint64_t seed)
47-
{
48-
seed128(state, php_random_uint128_constant(0ULL, seed));
49-
}
50-
5146
static php_random_result generate(void *state)
5247
{
5348
php_random_status_state_pcgoneseq128xslrr64 *s = state;
@@ -112,7 +107,6 @@ static bool unserialize(void *state, HashTable *data)
112107

113108
const php_random_algo php_random_algo_pcgoneseq128xslrr64 = {
114109
sizeof(php_random_status_state_pcgoneseq128xslrr64),
115-
seed,
116110
generate,
117111
range,
118112
serialize,
@@ -164,7 +158,7 @@ PHP_METHOD(Random_Engine_PcgOneseq128XslRr64, __construct)
164158
RETURN_THROWS();
165159
}
166160

167-
seed128(state, s);
161+
php_random_pcgoneseq128xslrr64_seed128(state, s);
168162
} else {
169163
if (str_seed) {
170164
/* char (byte: 8 bit) * 16 = 128 bits */
@@ -179,13 +173,13 @@ PHP_METHOD(Random_Engine_PcgOneseq128XslRr64, __construct)
179173
}
180174
}
181175

182-
seed128(state, php_random_uint128_constant(t[0], t[1]));
176+
php_random_pcgoneseq128xslrr64_seed128(state, php_random_uint128_constant(t[0], t[1]));
183177
} else {
184178
zend_argument_value_error(1, "must be a 16 byte (128 bit) string");
185179
RETURN_THROWS();
186180
}
187181
} else {
188-
seed128(state, php_random_uint128_constant(0ULL, (uint64_t) int_seed));
182+
php_random_pcgoneseq128xslrr64_seed128(state, php_random_uint128_constant(0ULL, (uint64_t) int_seed));
189183
}
190184
}
191185
}

ext/random/engine_secure.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ static zend_long range(void *state, zend_long min, zend_long max)
4848

4949
const php_random_algo php_random_algo_secure = {
5050
0,
51-
NULL,
5251
generate,
5352
range,
5453
NULL,

ext/random/engine_user.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@ static zend_long range(void *state, zend_long min, zend_long max)
7575

7676
const php_random_algo php_random_algo_user = {
7777
sizeof(php_random_status_state_user),
78-
NULL,
7978
generate,
8079
range,
8180
NULL,

ext/random/engine_xoshiro256starstar.c

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -82,15 +82,15 @@ static inline void jump(php_random_status_state_xoshiro256starstar *state, const
8282
state->state[3] = s3;
8383
}
8484

85-
static inline void seed256(php_random_status_state_xoshiro256starstar *s, uint64_t s0, uint64_t s1, uint64_t s2, uint64_t s3)
85+
PHPAPI inline void php_random_xoshiro256starstar_seed256(php_random_status_state_xoshiro256starstar *state, uint64_t s0, uint64_t s1, uint64_t s2, uint64_t s3)
8686
{
87-
s->state[0] = s0;
88-
s->state[1] = s1;
89-
s->state[2] = s2;
90-
s->state[3] = s3;
87+
state->state[0] = s0;
88+
state->state[1] = s1;
89+
state->state[2] = s2;
90+
state->state[3] = s3;
9191
}
9292

93-
static inline void seed64(php_random_status_state_xoshiro256starstar *state, uint64_t seed)
93+
PHPAPI inline void php_random_xoshiro256starstar_seed64(php_random_status_state_xoshiro256starstar *state, uint64_t seed)
9494
{
9595
uint64_t s[4];
9696

@@ -99,12 +99,7 @@ static inline void seed64(php_random_status_state_xoshiro256starstar *state, uin
9999
s[2] = splitmix64(&seed);
100100
s[3] = splitmix64(&seed);
101101

102-
seed256(state, s[0], s[1], s[2], s[3]);
103-
}
104-
105-
static void seed(void *state, uint64_t seed)
106-
{
107-
seed64(state, seed);
102+
php_random_xoshiro256starstar_seed256(state, s[0], s[1], s[2], s[3]);
108103
}
109104

110105
static php_random_result generate(void *state)
@@ -161,7 +156,6 @@ static bool unserialize(void *state, HashTable *data)
161156

162157
const php_random_algo php_random_algo_xoshiro256starstar = {
163158
sizeof(php_random_status_state_xoshiro256starstar),
164-
seed,
165159
generate,
166160
range,
167161
serialize,
@@ -228,7 +222,7 @@ PHP_METHOD(Random_Engine_Xoshiro256StarStar, __construct)
228222
}
229223
} while (UNEXPECTED(t[0] == 0 && t[1] == 0 && t[2] == 0 && t[3] == 0));
230224

231-
seed256(state, t[0], t[1], t[2], t[3]);
225+
php_random_xoshiro256starstar_seed256(state, t[0], t[1], t[2], t[3]);
232226
} else {
233227
if (str_seed) {
234228
/* char (byte: 8 bit) * 32 = 256 bits */
@@ -248,13 +242,13 @@ PHP_METHOD(Random_Engine_Xoshiro256StarStar, __construct)
248242
RETURN_THROWS();
249243
}
250244

251-
seed256(state, t[0], t[1], t[2], t[3]);
245+
php_random_xoshiro256starstar_seed256(state, t[0], t[1], t[2], t[3]);
252246
} else {
253247
zend_argument_value_error(1, "must be a 32 byte (256 bit) string");
254248
RETURN_THROWS();
255249
}
256250
} else {
257-
seed64(state, (uint64_t) int_seed);
251+
php_random_xoshiro256starstar_seed64(state, (uint64_t) int_seed);
258252
}
259253
}
260254
}

ext/random/php_random.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,6 @@ typedef struct _php_random_result {
9696

9797
typedef struct _php_random_algo {
9898
const size_t state_size;
99-
void (*seed)(void *state, uint64_t seed);
10099
php_random_result (*generate)(void *state);
101100
zend_long (*range)(void *state, zend_long min, zend_long max);
102101
bool (*serialize)(void *state, HashTable *data);
@@ -177,12 +176,17 @@ static inline php_random_algo_with_state php_random_default_engine(void)
177176
PHPAPI zend_string *php_random_bin2hex_le(const void *ptr, const size_t len);
178177
PHPAPI bool php_random_hex2bin_le(zend_string *hexstr, void *dest);
179178

179+
PHPAPI void php_random_combinedlcg_seed64(php_random_status_state_combinedlcg *state, uint64_t seed);
180180
PHPAPI void php_random_combinedlcg_seed_default(php_random_status_state_combinedlcg *state);
181181

182+
PHPAPI void php_random_mt19937_seed32(php_random_status_state_mt19937 *state, uint32_t seed);
182183
PHPAPI void php_random_mt19937_seed_default(php_random_status_state_mt19937 *state);
183184

185+
PHPAPI void php_random_pcgoneseq128xslrr64_seed128(php_random_status_state_pcgoneseq128xslrr64 *s, php_random_uint128_t seed);
184186
PHPAPI void php_random_pcgoneseq128xslrr64_advance(php_random_status_state_pcgoneseq128xslrr64 *state, uint64_t advance);
185187

188+
PHPAPI void php_random_xoshiro256starstar_seed64(php_random_status_state_xoshiro256starstar *state, uint64_t seed);
189+
PHPAPI void php_random_xoshiro256starstar_seed256(php_random_status_state_xoshiro256starstar *state, uint64_t s0, uint64_t s1, uint64_t s2, uint64_t s3);
186190
PHPAPI void php_random_xoshiro256starstar_jump(php_random_status_state_xoshiro256starstar *state);
187191
PHPAPI void php_random_xoshiro256starstar_jump_long(php_random_status_state_xoshiro256starstar *state);
188192

ext/random/random.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -404,8 +404,7 @@ PHPAPI double php_combined_lcg(void)
404404
/* {{{ php_mt_srand */
405405
PHPAPI void php_mt_srand(uint32_t seed)
406406
{
407-
/* Seed the generator with a simple uint32 */
408-
php_random_algo_mt19937.seed(php_random_default_status(), (zend_long) seed);
407+
php_random_mt19937_seed32(php_random_default_status(), seed);
409408
}
410409
/* }}} */
411410

@@ -491,7 +490,7 @@ PHP_FUNCTION(mt_srand)
491490
if (seed_is_null) {
492491
php_random_mt19937_seed_default(state);
493492
} else {
494-
php_random_algo_mt19937.seed(state, (uint64_t) seed);
493+
php_random_mt19937_seed32(state, (uint64_t) seed);
495494
}
496495
RANDOM_G(mt19937_seeded) = true;
497496
}

0 commit comments

Comments
 (0)