Commit 1a428e528f9 for php.net

commit 1a428e528f9c67d67e0b6bff5b036e04f9f9203e
Author: Ilia Alshanetsky <ilia@ilia.ws>
Date:   Sun Apr 12 13:51:30 2026 -0400

    Fix GH-21731: Random\Engine\Xoshiro256StarStar::__unserialize() accepts all-zero state (#21732)

    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

diff --git a/NEWS b/NEWS
index 07653ef6a37..24846881de9 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 1a054362f06..12db8198978 100644
--- a/ext/random/engine_xoshiro256starstar.c
+++ b/ext/random/engine_xoshiro256starstar.c
@@ -151,6 +151,10 @@ static bool unserialize(void *state, HashTable *data)
 		}
 	}

+	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 00000000000..6ebcd03e857
--- /dev/null
+++ b/ext/random/tests/02_engine/xoshiro256starstar_unserialize_zero_state.phpt
@@ -0,0 +1,14 @@
+--TEST--
+GH-21731: Xoshiro256StarStar::__unserialize() must reject the all-zero state
+--FILE--
+<?php
+
+try {
+    var_dump(unserialize('O:32:"Random\Engine\Xoshiro256StarStar":2:{i:0;a:0:{}i:1;a:4:{i:0;s:16:"0000000000000000";i:1;s:16:"0000000000000000";i:2;s:16:"0000000000000000";i:3;s:16:"0000000000000000";}}'));
+} catch (\Exception $e) {
+    echo $e->getMessage(), PHP_EOL;
+}
+
+?>
+--EXPECT--
+Invalid serialization data for Random\Engine\Xoshiro256StarStar object