mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
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()`
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user