From 8aa81168b57330ff8b86d7064728e5f89530fd16 Mon Sep 17 00:00:00 2001 From: Anthony Ryan Date: Thu, 5 Mar 2026 21:47:08 -0500 Subject: [PATCH] ext/pcntl: Children should not inherit random seeds Fix GH-21351 --- .../tests/pcntl_fork_reseed_mt_rand.phpt | 51 +++++++++++++++++++ main/main.c | 7 +++ 2 files changed, 58 insertions(+) create mode 100644 ext/pcntl/tests/pcntl_fork_reseed_mt_rand.phpt diff --git a/ext/pcntl/tests/pcntl_fork_reseed_mt_rand.phpt b/ext/pcntl/tests/pcntl_fork_reseed_mt_rand.phpt new file mode 100644 index 000000000000..437e9d6693dd --- /dev/null +++ b/ext/pcntl/tests/pcntl_fork_reseed_mt_rand.phpt @@ -0,0 +1,51 @@ +--TEST-- +pcntl_fork() reseeds MT rand in child processes (GH-21351) +--EXTENSIONS-- +pcntl +posix +--FILE-- + 0); + +$lines = array_filter(array_map('trim', file($tmpfile))); +$unique = array_unique($lines); + +// With 5 children and a 31-bit range, getting all identical values +// from truly independent seeds is astronomically unlikely. +if (count($unique) > 1) { + echo "PASS: children produced different mt_rand values after fork\n"; +} else { + echo "FAIL: all children produced the same mt_rand value: " . $lines[0] . "\n"; +} + +@unlink($tmpfile); +?> +--EXPECT-- +PASS: children produced different mt_rand values after fork diff --git a/main/main.c b/main/main.c index bbd2d18ba187..e11b65145187 100644 --- a/main/main.c +++ b/main/main.c @@ -51,6 +51,7 @@ #include "fopen_wrappers.h" #include "ext/standard/php_standard.h" #include "ext/date/php_date.h" +#include "ext/random/php_random.h" #include "ext/random/php_random_csprng.h" #include "ext/random/php_random_zend_utils.h" #include "ext/opcache/ZendAccelerator.h" @@ -1870,6 +1871,12 @@ PHPAPI void php_child_init(void) { refresh_memory_manager(); zend_max_execution_timer_init(); + + /* Force re-seeding of random engines in child process after fork(), + * otherwise the child inherits the parent's MT state and produces + * identical sequences. See GH-21351. */ + RANDOM_G(mt19937_seeded) = false; + RANDOM_G(combined_lcg_seeded) = false; } /* {{{ php_request_startup */