1
0
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:
Tim Düsterhus
2024-02-29 08:03:35 +01:00
committed by GitHub
parent a31edaa99b
commit 99e7cf074b
9 changed files with 34 additions and 49 deletions

View File

@@ -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.

View File

@@ -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,

View File

@@ -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);
}
/* }}} */

View File

@@ -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));
}
}
}

View File

@@ -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,

View File

@@ -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,

View File

@@ -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);
}
}
}

View File

@@ -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);

View File

@@ -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;
}