diff --git a/ext/session/php_session.h b/ext/session/php_session.h index 341aac5716ac2..c9611e6159709 100644 --- a/ext/session/php_session.h +++ b/ext/session/php_session.h @@ -19,6 +19,7 @@ #include "ext/standard/php_var.h" #include "ext/hash/php_hash.h" +#include "ext/random/php_random.h" #define PHP_SESSION_API 20161017 @@ -132,10 +133,10 @@ typedef struct _php_session_rfc1867_progress { size_t content_length; zval data; /* the array exported to session data */ - zval *post_bytes_processed; /* data["bytes_processed"] */ zval files; /* data["files"] array */ - zval current_file; /* array of currently uploading file */ + zval *post_bytes_processed; /* data["bytes_processed"] */ zval *current_file_bytes_processed; + zval current_file; /* array of currently uploading file */ } php_session_rfc1867_progress; typedef struct _php_ps_globals { @@ -147,19 +148,21 @@ typedef struct _php_ps_globals { zend_long cookie_lifetime; char *cookie_path; char *cookie_domain; + char *cookie_samesite; bool cookie_secure; bool cookie_httponly; - char *cookie_samesite; const ps_module *mod; const ps_module *default_mod; void *mod_data; php_session_status session_status; zend_string *session_started_filename; uint32_t session_started_lineno; + int module_number; + php_random_status_state_pcgoneseq128xslrr64 random_state; + php_random_algo_with_state random; zend_long gc_probability; zend_long gc_divisor; zend_long gc_maxlifetime; - int module_number; zend_long cache_expire; struct { zval ps_open; @@ -172,28 +175,29 @@ typedef struct _php_ps_globals { zval ps_validate_sid; zval ps_update_timestamp; } mod_user_names; + zend_string *mod_user_class_name; bool mod_user_implemented; bool mod_user_is_open; - zend_string *mod_user_class_name; - const struct ps_serializer_struct *serializer; - zval http_session_vars; bool auto_start; bool use_cookies; bool use_only_cookies; bool use_trans_sid; /* contains the INI value of whether to use trans-sid */ + bool send_cookie; + bool define_sid; + + const struct ps_serializer_struct *serializer; + zval http_session_vars; zend_long sid_length; zend_long sid_bits_per_character; - bool send_cookie; - bool define_sid; php_session_rfc1867_progress *rfc1867_progress; - bool rfc1867_enabled; /* session.upload_progress.enabled */ - bool rfc1867_cleanup; /* session.upload_progress.cleanup */ char *rfc1867_prefix; /* session.upload_progress.prefix */ char *rfc1867_name; /* session.upload_progress.name */ zend_long rfc1867_freq; /* session.upload_progress.freq */ double rfc1867_min_freq; /* session.upload_progress.min_freq */ + bool rfc1867_enabled; /* session.upload_progress.enabled */ + bool rfc1867_cleanup; /* session.upload_progress.cleanup */ bool use_strict_mode; /* whether or not PHP accepts unknown session ids */ bool lazy_write; /* omit session write when it is possible */ diff --git a/ext/session/session.c b/ext/session/session.c index 61d91b77eaac1..ba4bb6619766c 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -387,17 +387,16 @@ PHPAPI zend_result php_session_valid_key(const char *key) /* {{{ */ static zend_long php_session_gc(bool immediate) /* {{{ */ { - int nrand; zend_long num = -1; + bool collect = immediate; /* GC must be done before reading session data. */ if ((PS(mod_data) || PS(mod_user_implemented))) { - if (immediate) { - PS(mod)->s_gc(&PS(mod_data), PS(gc_maxlifetime), &num); - return num; + if (!collect && PS(gc_probability) > 0) { + collect = php_random_range(PS(random), 0, PS(gc_divisor) - 1) < PS(gc_probability); } - nrand = (zend_long) ((float) PS(gc_divisor) * php_combined_lcg()); - if (PS(gc_probability) > 0 && nrand < PS(gc_probability)) { + + if (collect) { PS(mod)->s_gc(&PS(mod_data), PS(gc_maxlifetime), &num); } } @@ -2872,6 +2871,16 @@ static PHP_GINIT_FUNCTION(ps) /* {{{ */ ZVAL_UNDEF(&ps_globals->mod_user_names.ps_validate_sid); ZVAL_UNDEF(&ps_globals->mod_user_names.ps_update_timestamp); ZVAL_UNDEF(&ps_globals->http_session_vars); + + ps_globals->random = (php_random_algo_with_state){ + .algo = &php_random_algo_pcgoneseq128xslrr64, + .state = &ps_globals->random_state, + }; + php_random_uint128_t seed; + if (php_random_bytes_silent(&seed, sizeof(seed)) == FAILURE) { + seed = php_random_uint128_constant(GENERATE_SEED(), GENERATE_SEED()); + } + php_random_pcgoneseq128xslrr64_seed128(ps_globals->random.state, seed); } /* }}} */