diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index fb22b733c365..217d86809ad4 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -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. diff --git a/ext/random/engine_combinedlcg.c b/ext/random/engine_combinedlcg.c index a37882689114..8874998f3323 100644 --- a/ext/random/engine_combinedlcg.c +++ b/ext/random/engine_combinedlcg.c @@ -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) @@ -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, diff --git a/ext/random/engine_mt19937.c b/ext/random/engine_mt19937.c index ceb81e24a997..1034fdf39a4c 100644 --- a/ext/random/engine_mt19937.c +++ b/ext/random/engine_mt19937.c @@ -121,7 +121,7 @@ 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; @@ -129,7 +129,7 @@ static inline void mt19937_seed_state(php_random_status_state_mt19937 *state, ui 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; @@ -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; @@ -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, @@ -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); } /* }}} */ @@ -286,7 +280,7 @@ PHP_METHOD(Random_Engine_Mt19937, __construct) } } - mt19937_seed_state(state, seed); + php_random_mt19937_seed32(state, seed); } /* }}} */ diff --git a/ext/random/engine_pcgoneseq128xslrr64.c b/ext/random/engine_pcgoneseq128xslrr64.c index b95dd9f55c21..4d288f5793eb 100644 --- a/ext/random/engine_pcgoneseq128xslrr64.c +++ b/ext/random/engine_pcgoneseq128xslrr64.c @@ -35,7 +35,7 @@ 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); @@ -43,11 +43,6 @@ static inline void seed128(php_random_status_state_pcgoneseq128xslrr64 *s, php_r 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; @@ -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, @@ -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 */ @@ -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)); } } } diff --git a/ext/random/engine_secure.c b/ext/random/engine_secure.c index 8d99cd07818b..e55b98469399 100644 --- a/ext/random/engine_secure.c +++ b/ext/random/engine_secure.c @@ -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, diff --git a/ext/random/engine_user.c b/ext/random/engine_user.c index 25bd86bfb0c4..d8c6909d1db8 100644 --- a/ext/random/engine_user.c +++ b/ext/random/engine_user.c @@ -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, diff --git a/ext/random/engine_xoshiro256starstar.c b/ext/random/engine_xoshiro256starstar.c index f581471e4ece..fba834ebcd5e 100644 --- a/ext/random/engine_xoshiro256starstar.c +++ b/ext/random/engine_xoshiro256starstar.c @@ -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]; @@ -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) @@ -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, @@ -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 */ @@ -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); } } } diff --git a/ext/random/php_random.h b/ext/random/php_random.h index 34dc7eb89dd7..c62761029ddc 100644 --- a/ext/random/php_random.h +++ b/ext/random/php_random.h @@ -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); @@ -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); diff --git a/ext/random/random.c b/ext/random/random.c index 706be3b1551d..afd4cc1a77bb 100644 --- a/ext/random/random.c +++ b/ext/random/random.c @@ -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); } /* }}} */ @@ -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; }