Skip to content

Commit ff69f33

Browse files
authored
ext/session: Warn when providing invalid values for session.gc_probability and session.gc_divisor
1 parent 6b809c8 commit ff69f33

File tree

3 files changed

+109
-2
lines changed

3 files changed

+109
-2
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ PHP NEWS
2323
. Fixed bug GH-15432 (Heap corruption when querying a vector). (cmb,
2424
Kamil Tekiela)
2525

26+
- Session:
27+
. Emit warnings for non-positive values of session.gc_divisor and negative values
28+
of session.gc_probability. (Jorg Sowa)
29+
2630
- Standard:
2731
. The "allowed_classes" option for unserialize() now throws TypeErrors and
2832
ValueErrors if it is not an array of class names. (Girgias)

ext/session/session.c

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,44 @@ static PHP_INI_MH(OnUpdateSidBits) /* {{{ */
789789
}
790790
/* }}} */
791791

792+
static PHP_INI_MH(OnUpdateSessionGcProbability) /* {{{ */
793+
{
794+
SESSION_CHECK_ACTIVE_STATE;
795+
SESSION_CHECK_OUTPUT_STATE;
796+
797+
zend_long tmp = zend_ini_parse_quantity_warn(new_value, entry->name);
798+
799+
if (tmp < 0) {
800+
php_error_docref("session.gc_probability", E_WARNING, "session.gc_probability must be greater than or equal to 0");
801+
return FAILURE;
802+
}
803+
804+
zend_long *p = (zend_long *) ZEND_INI_GET_ADDR();
805+
*p = tmp;
806+
807+
return SUCCESS;
808+
}
809+
/* }}} */
810+
811+
static PHP_INI_MH(OnUpdateSessionDivisor) /* {{{ */
812+
{
813+
SESSION_CHECK_ACTIVE_STATE;
814+
SESSION_CHECK_OUTPUT_STATE;
815+
816+
zend_long tmp = zend_ini_parse_quantity_warn(new_value, entry->name);
817+
818+
if (tmp <= 0) {
819+
php_error_docref("session.gc_divisor", E_WARNING, "session.gc_divisor must be greater than 0");
820+
return FAILURE;
821+
}
822+
823+
zend_long *p = (zend_long *) ZEND_INI_GET_ADDR();
824+
*p = tmp;
825+
826+
return SUCCESS;
827+
}
828+
/* }}} */
829+
792830
static PHP_INI_MH(OnUpdateRfc1867Freq) /* {{{ */
793831
{
794832
int tmp = ZEND_ATOL(ZSTR_VAL(new_value));
@@ -814,8 +852,8 @@ PHP_INI_BEGIN()
814852
STD_PHP_INI_ENTRY("session.name", "PHPSESSID", PHP_INI_ALL, OnUpdateName, session_name, php_ps_globals, ps_globals)
815853
PHP_INI_ENTRY("session.save_handler", "files", PHP_INI_ALL, OnUpdateSaveHandler)
816854
STD_PHP_INI_BOOLEAN("session.auto_start", "0", PHP_INI_PERDIR, OnUpdateBool, auto_start, php_ps_globals, ps_globals)
817-
STD_PHP_INI_ENTRY("session.gc_probability", "1", PHP_INI_ALL, OnUpdateSessionLong, gc_probability, php_ps_globals, ps_globals)
818-
STD_PHP_INI_ENTRY("session.gc_divisor", "100", PHP_INI_ALL, OnUpdateSessionLong, gc_divisor, php_ps_globals, ps_globals)
855+
STD_PHP_INI_ENTRY("session.gc_probability", "1", PHP_INI_ALL, OnUpdateSessionGcProbability, gc_probability, php_ps_globals, ps_globals)
856+
STD_PHP_INI_ENTRY("session.gc_divisor", "100", PHP_INI_ALL, OnUpdateSessionDivisor,gc_divisor, php_ps_globals, ps_globals)
819857
STD_PHP_INI_ENTRY("session.gc_maxlifetime", "1440", PHP_INI_ALL, OnUpdateSessionLong, gc_maxlifetime, php_ps_globals, ps_globals)
820858
PHP_INI_ENTRY("session.serialize_handler", "php", PHP_INI_ALL, OnUpdateSerializer)
821859
STD_PHP_INI_ENTRY("session.cookie_lifetime", "0", PHP_INI_ALL, OnUpdateCookieLifetime,cookie_lifetime, php_ps_globals, ps_globals)
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
--TEST--
2+
Test session.gc_probability and session.gc_divisor settings for invalid values
3+
--INI--
4+
session.gc_maxlifetime=1
5+
--EXTENSIONS--
6+
session
7+
--SKIPIF--
8+
<?php
9+
include('skipif.inc');
10+
?>
11+
--FILE--
12+
<?php
13+
14+
$gc_settings = [
15+
[
16+
'gc_probability' => -1,
17+
'gc_divisor' => -1
18+
],
19+
[
20+
'gc_probability' => -1,
21+
'gc_divisor' => 1
22+
],
23+
[
24+
'gc_probability' => 1,
25+
'gc_divisor' => -1
26+
],
27+
[
28+
'gc_probability' => 1,
29+
'gc_divisor' => 0
30+
],
31+
];
32+
33+
ob_start();
34+
foreach($gc_settings as $gc_setting) {
35+
try {
36+
session_start($gc_setting);
37+
session_write_close();
38+
} catch (Throwable $e) {
39+
echo $e::class, ': '. $e->getMessage(), "\n";
40+
}
41+
}
42+
ob_end_flush();
43+
?>
44+
Done
45+
--EXPECTF--
46+
Warning: session_start(): session.gc_probability must be greater than or equal to 0 in %s on line %d
47+
48+
Warning: session_start(): Setting option "gc_probability" failed in %s on line %d
49+
50+
Warning: session_start(): session.gc_divisor must be greater than 0 in %s on line %d
51+
52+
Warning: session_start(): Setting option "gc_divisor" failed in %s on line %d
53+
54+
Warning: session_start(): session.gc_probability must be greater than or equal to 0 in %s on line %d
55+
56+
Warning: session_start(): Setting option "gc_probability" failed in %s on line %d
57+
58+
Warning: session_start(): session.gc_divisor must be greater than 0 in %s on line %d
59+
60+
Warning: session_start(): Setting option "gc_divisor" failed in %s on line %d
61+
62+
Warning: session_start(): session.gc_divisor must be greater than 0 in %s on line %d
63+
64+
Warning: session_start(): Setting option "gc_divisor" failed in %s on line %d
65+
Done

0 commit comments

Comments
 (0)