From cd7de3e390225f3de84ca61cc3a449ca44afd30e Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Sat, 11 Apr 2026 21:27:57 -0400 Subject: [PATCH] Fix GH-21731: Random\Engine\Xoshiro256StarStar::__unserialize() accepts all-zero state The constructor rejects a seed that would leave the internal state all zero, because xoshiro256** with zero state produces 0 on every call forever. The unserialize callback didn't check the same invariant. A caller feeding a crafted serialized payload through __unserialize() ended up with a live engine that returned 0 from every operation. Match the constructor: reject the all-zero state from the unserialize callback too. The Mt19937-aliased __unserialize() wrapper turns the false return into the standard "Invalid serialization data" exception. Closes GH-21731 --- NEWS | 4 ++++ ext/random/engine_xoshiro256starstar.c | 6 ++++++ ...iro256starstar_unserialize_zero_state.phpt | 21 +++++++++++++++++++ 3 files changed, 31 insertions(+) create mode 100644 ext/random/tests/02_engine/xoshiro256starstar_unserialize_zero_state.phpt diff --git a/NEWS b/NEWS index 07653ef6a37f..24846881de96 100644 --- a/NEWS +++ b/NEWS @@ -31,6 +31,10 @@ PHP NEWS - OpenSSL: . Fix a bunch of memory leaks and crashes on edge cases. (ndossche) +- Random: + . Fixed bug GH-21731 (Random\Engine\Xoshiro256StarStar::__unserialize() + accepts all-zero state). (iliaal) + - SPL: . Fixed bug GH-21499 (RecursiveArrayIterator getChildren UAF after parent free). (Girgias) diff --git a/ext/random/engine_xoshiro256starstar.c b/ext/random/engine_xoshiro256starstar.c index 1a054362f065..b6ffd085c187 100644 --- a/ext/random/engine_xoshiro256starstar.c +++ b/ext/random/engine_xoshiro256starstar.c @@ -151,6 +151,12 @@ static bool unserialize(void *state, HashTable *data) } } + /* An all-zero state generates zero forever. The constructor rejects + * such a seed; reject it here for symmetry. */ + if (UNEXPECTED(s->state[0] == 0 && s->state[1] == 0 && s->state[2] == 0 && s->state[3] == 0)) { + return false; + } + return true; } diff --git a/ext/random/tests/02_engine/xoshiro256starstar_unserialize_zero_state.phpt b/ext/random/tests/02_engine/xoshiro256starstar_unserialize_zero_state.phpt new file mode 100644 index 000000000000..4a4d56cc210b --- /dev/null +++ b/ext/random/tests/02_engine/xoshiro256starstar_unserialize_zero_state.phpt @@ -0,0 +1,21 @@ +--TEST-- +GH-21731: Xoshiro256StarStar::__unserialize() must reject the all-zero state +--FILE-- +__unserialize([ + [], + ['0000000000000000', '0000000000000000', '0000000000000000', '0000000000000000'], + ]); + echo "FAIL: __unserialize() accepted zero state\n"; +} catch (\Exception $e) { + echo $e::class, ': ', $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +Exception: Invalid serialization data for Random\Engine\Xoshiro256StarStar object