Skip to content

random: Clean up seeding API #13540

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Feb 29, 2024
5 changes: 5 additions & 0 deletions UPGRADING.INTERNALS
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,11 @@ PHP 8.4 INTERNALS UPGRADE NOTES
single php_random_algo_with_state struct by value, making it easier to
pass around the state with its associated algorithm and thus reducing
the chance for mistakes.
- The seed member of a php_random_algo has been removed. As a replacement
engine-specific seeding functions are now exposed. This change allows
users to better take engine-specific behavior into account. As an example
Mt19937 ignored the upper half of the seed parameter of the generic
seeding function.
- The CSPRNG API (php_random_(bytes|int)_*) is now provided by the new
and much smaller php_random_csprng.h header. The new header is included
in php_random.h for compatibility with existing users.
Expand Down
9 changes: 3 additions & 6 deletions ext/random/engine_combinedlcg.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,10 @@
*/
#define MODMULT(a, b, c, m, s) q = s / a; s = b * (s - a * q) - c * q; if (s < 0) s += m

static void seed(void *state, uint64_t seed)
PHPAPI void php_random_combinedlcg_seed64(php_random_status_state_combinedlcg *state, uint64_t seed)
{
php_random_status_state_combinedlcg *s = state;

s->state[0] = seed & 0xffffffffU;
s->state[1] = seed >> 32;
state->state[0] = seed & 0xffffffffU;
state->state[1] = seed >> 32;
}

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

const php_random_algo php_random_algo_combinedlcg = {
sizeof(php_random_status_state_combinedlcg),
seed,
generate,
range,
serialize,
Expand Down
16 changes: 5 additions & 11 deletions ext/random/engine_mt19937.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,15 +121,15 @@ static inline void mt19937_reload(php_random_status_state_mt19937 *state)
state->count = 0;
}

static inline void mt19937_seed_state(php_random_status_state_mt19937 *state, uint64_t seed)
PHPAPI inline void php_random_mt19937_seed32(php_random_status_state_mt19937 *state, uint32_t seed)
{
uint32_t i, prev_state;

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

static void seed(void *state, uint64_t seed)
{
mt19937_seed_state(state, seed);
}

static php_random_result generate(void *state)
{
php_random_status_state_mt19937 *s = state;
Expand Down Expand Up @@ -231,7 +226,6 @@ static bool unserialize(void *state, HashTable *data)

const php_random_algo php_random_algo_mt19937 = {
sizeof(php_random_status_state_mt19937),
seed,
generate,
range,
serialize,
Expand All @@ -241,13 +235,13 @@ const php_random_algo php_random_algo_mt19937 = {
/* {{{ php_random_mt19937_seed_default */
PHPAPI void php_random_mt19937_seed_default(php_random_status_state_mt19937 *state)
{
zend_long seed = 0;
uint32_t seed = 0;

if (php_random_bytes_silent(&seed, sizeof(seed)) == FAILURE) {
seed = GENERATE_SEED();
}

mt19937_seed_state(state, (uint64_t) seed);
php_random_mt19937_seed32(state, seed);
}
/* }}} */

Expand Down Expand Up @@ -286,7 +280,7 @@ PHP_METHOD(Random_Engine_Mt19937, __construct)
}
}

mt19937_seed_state(state, seed);
php_random_mt19937_seed32(state, seed);
}
/* }}} */

Expand Down
14 changes: 4 additions & 10 deletions ext/random/engine_pcgoneseq128xslrr64.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,19 +35,14 @@ static inline void step(php_random_status_state_pcgoneseq128xslrr64 *s)
);
}

static inline void seed128(php_random_status_state_pcgoneseq128xslrr64 *s, php_random_uint128_t seed)
PHPAPI inline void php_random_pcgoneseq128xslrr64_seed128(php_random_status_state_pcgoneseq128xslrr64 *s, php_random_uint128_t seed)
{
s->state = php_random_uint128_constant(0ULL, 0ULL);
step(s);
s->state = php_random_uint128_add(s->state, seed);
step(s);
}

static void seed(void *state, uint64_t seed)
{
seed128(state, php_random_uint128_constant(0ULL, seed));
}

static php_random_result generate(void *state)
{
php_random_status_state_pcgoneseq128xslrr64 *s = state;
Expand Down Expand Up @@ -112,7 +107,6 @@ static bool unserialize(void *state, HashTable *data)

const php_random_algo php_random_algo_pcgoneseq128xslrr64 = {
sizeof(php_random_status_state_pcgoneseq128xslrr64),
seed,
generate,
range,
serialize,
Expand Down Expand Up @@ -164,7 +158,7 @@ PHP_METHOD(Random_Engine_PcgOneseq128XslRr64, __construct)
RETURN_THROWS();
}

seed128(state, s);
php_random_pcgoneseq128xslrr64_seed128(state, s);
} else {
if (str_seed) {
/* char (byte: 8 bit) * 16 = 128 bits */
Expand All @@ -179,13 +173,13 @@ PHP_METHOD(Random_Engine_PcgOneseq128XslRr64, __construct)
}
}

seed128(state, php_random_uint128_constant(t[0], t[1]));
php_random_pcgoneseq128xslrr64_seed128(state, php_random_uint128_constant(t[0], t[1]));
} else {
zend_argument_value_error(1, "must be a 16 byte (128 bit) string");
RETURN_THROWS();
}
} else {
seed128(state, php_random_uint128_constant(0ULL, (uint64_t) int_seed));
php_random_pcgoneseq128xslrr64_seed128(state, php_random_uint128_constant(0ULL, (uint64_t) int_seed));
}
}
}
Expand Down
1 change: 0 additions & 1 deletion ext/random/engine_secure.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ static zend_long range(void *state, zend_long min, zend_long max)

const php_random_algo php_random_algo_secure = {
0,
NULL,
generate,
range,
NULL,
Expand Down
1 change: 0 additions & 1 deletion ext/random/engine_user.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ static zend_long range(void *state, zend_long min, zend_long max)

const php_random_algo php_random_algo_user = {
sizeof(php_random_status_state_user),
NULL,
generate,
range,
NULL,
Expand Down
26 changes: 10 additions & 16 deletions ext/random/engine_xoshiro256starstar.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,15 @@ static inline void jump(php_random_status_state_xoshiro256starstar *state, const
state->state[3] = s3;
}

static inline void seed256(php_random_status_state_xoshiro256starstar *s, uint64_t s0, uint64_t s1, uint64_t s2, uint64_t s3)
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)
{
s->state[0] = s0;
s->state[1] = s1;
s->state[2] = s2;
s->state[3] = s3;
state->state[0] = s0;
state->state[1] = s1;
state->state[2] = s2;
state->state[3] = s3;
}

static inline void seed64(php_random_status_state_xoshiro256starstar *state, uint64_t seed)
PHPAPI inline void php_random_xoshiro256starstar_seed64(php_random_status_state_xoshiro256starstar *state, uint64_t seed)
{
uint64_t s[4];

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

seed256(state, s[0], s[1], s[2], s[3]);
}

static void seed(void *state, uint64_t seed)
{
seed64(state, seed);
php_random_xoshiro256starstar_seed256(state, s[0], s[1], s[2], s[3]);
}

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

const php_random_algo php_random_algo_xoshiro256starstar = {
sizeof(php_random_status_state_xoshiro256starstar),
seed,
generate,
range,
serialize,
Expand Down Expand Up @@ -228,7 +222,7 @@ PHP_METHOD(Random_Engine_Xoshiro256StarStar, __construct)
}
} while (UNEXPECTED(t[0] == 0 && t[1] == 0 && t[2] == 0 && t[3] == 0));

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

seed256(state, t[0], t[1], t[2], t[3]);
php_random_xoshiro256starstar_seed256(state, t[0], t[1], t[2], t[3]);
} else {
zend_argument_value_error(1, "must be a 32 byte (256 bit) string");
RETURN_THROWS();
}
} else {
seed64(state, (uint64_t) int_seed);
php_random_xoshiro256starstar_seed64(state, (uint64_t) int_seed);
}
}
}
Expand Down
6 changes: 5 additions & 1 deletion ext/random/php_random.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ typedef struct _php_random_result {

typedef struct _php_random_algo {
const size_t state_size;
void (*seed)(void *state, uint64_t seed);
php_random_result (*generate)(void *state);
zend_long (*range)(void *state, zend_long min, zend_long max);
bool (*serialize)(void *state, HashTable *data);
Expand Down Expand Up @@ -177,12 +176,17 @@ static inline php_random_algo_with_state php_random_default_engine(void)
PHPAPI zend_string *php_random_bin2hex_le(const void *ptr, const size_t len);
PHPAPI bool php_random_hex2bin_le(zend_string *hexstr, void *dest);

PHPAPI void php_random_combinedlcg_seed64(php_random_status_state_combinedlcg *state, uint64_t seed);
PHPAPI void php_random_combinedlcg_seed_default(php_random_status_state_combinedlcg *state);

PHPAPI void php_random_mt19937_seed32(php_random_status_state_mt19937 *state, uint32_t seed);
PHPAPI void php_random_mt19937_seed_default(php_random_status_state_mt19937 *state);

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

PHPAPI void php_random_xoshiro256starstar_seed64(php_random_status_state_xoshiro256starstar *state, uint64_t seed);
PHPAPI void php_random_xoshiro256starstar_seed256(php_random_status_state_xoshiro256starstar *state, uint64_t s0, uint64_t s1, uint64_t s2, uint64_t s3);
PHPAPI void php_random_xoshiro256starstar_jump(php_random_status_state_xoshiro256starstar *state);
PHPAPI void php_random_xoshiro256starstar_jump_long(php_random_status_state_xoshiro256starstar *state);

Expand Down
5 changes: 2 additions & 3 deletions ext/random/random.c
Original file line number Diff line number Diff line change
Expand Up @@ -404,8 +404,7 @@ PHPAPI double php_combined_lcg(void)
/* {{{ php_mt_srand */
PHPAPI void php_mt_srand(uint32_t seed)
{
/* Seed the generator with a simple uint32 */
php_random_algo_mt19937.seed(php_random_default_status(), (zend_long) seed);
php_random_mt19937_seed32(php_random_default_status(), seed);
}
/* }}} */

Expand Down Expand Up @@ -491,7 +490,7 @@ PHP_FUNCTION(mt_srand)
if (seed_is_null) {
php_random_mt19937_seed_default(state);
} else {
php_random_algo_mt19937.seed(state, (uint64_t) seed);
php_random_mt19937_seed32(state, (uint64_t) seed);
}
RANDOM_G(mt19937_seeded) = true;
}
Expand Down