@@ -392,9 +392,15 @@ static zend_long php_session_gc(bool immediate)
392392
393393 /* GC must be done before reading session data. */
394394 if ((PS (mod_data ) || PS (mod_user_implemented ))) {
395- /* Use probability-based GC if not forced and probability is configured */
396395 if (!collect && PS (gc_probability ) > 0 ) {
397- collect = php_random_range (PS (random ), 0 , PS (gc_divisor ) - 1 ) < PS (gc_probability );
396+ /* Draw fresh entropy per request instead of using the per-process
397+ * PS(random) state. The latter is seeded once in GINIT, which runs
398+ * before SAPIs such as PHP-FPM fork their workers, so every worker
399+ * would inherit and replay the same GC-decision sequence. */
400+ uint32_t rand_val ;
401+ if (php_random_bytes_silent (& rand_val , sizeof (rand_val )) == SUCCESS ) {
402+ collect = (rand_val % (uint32_t ) PS (gc_divisor )) < (uint32_t ) PS (gc_probability );
403+ }
398404 }
399405
400406 if (collect ) {
@@ -2886,19 +2892,6 @@ static PHP_GINIT_FUNCTION(ps)
28862892 ZVAL_UNDEF (& ps_globals -> mod_user_names .ps_validate_sid );
28872893 ZVAL_UNDEF (& ps_globals -> mod_user_names .ps_update_timestamp );
28882894 ZVAL_UNDEF (& ps_globals -> http_session_vars );
2889-
2890- ps_globals -> random = (php_random_algo_with_state ){
2891- .algo = & php_random_algo_pcgoneseq128xslrr64 ,
2892- .state = & ps_globals -> random_state ,
2893- };
2894- php_random_uint128_t seed ;
2895- if (php_random_bytes_silent (& seed , sizeof (seed )) == FAILURE ) {
2896- seed = php_random_uint128_constant (
2897- php_random_generate_fallback_seed (),
2898- php_random_generate_fallback_seed ()
2899- );
2900- }
2901- php_random_pcgoneseq128xslrr64_seed128 (ps_globals -> random .state , seed );
29022895}
29032896
29042897static PHP_MINIT_FUNCTION (session )
0 commit comments