Skip to content

Commit 383ff8c

Browse files
authored
ext/session: improve parsing of session.cookie_lifetime (#21704)
When session.cookie_lifetime was set to a value larger than maxcookie, OnUpdateCookieLifetime returned SUCCESS without updating the internal long value, causing ini_get() string and PS(cookie_lifetime) to go out of sync. We now properly parse the string value of the ini setting and fail when it is not an integer string or is not within the expected range.
1 parent 3afd6d3 commit 383ff8c

7 files changed

+79
-13
lines changed

ext/session/session.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -704,12 +704,20 @@ static PHP_INI_MH(OnUpdateCookieLifetime)
704704
#else
705705
const zend_long maxcookie = ZEND_LONG_MAX / 2 - 1;
706706
#endif
707-
zend_long v = (zend_long)atol(ZSTR_VAL(new_value));
708-
if (v < 0) {
709-
php_error_docref(NULL, E_WARNING, "CookieLifetime cannot be negative");
707+
zend_long lval = 0;
708+
int oflow = 0;
709+
uint8_t type = is_numeric_string_ex(ZSTR_VAL(new_value), ZSTR_LEN(new_value), &lval, NULL, false, &oflow, NULL);
710+
if (UNEXPECTED(type != IS_LONG)) {
711+
if (oflow != 0) {
712+
php_error_docref(NULL, E_WARNING, "session.cookie_lifetime must be between 0 and " ZEND_LONG_FMT, maxcookie);
713+
} else {
714+
php_error_docref(NULL, E_WARNING, "session.cookie_lifetime must be of type int");
715+
}
716+
return FAILURE;
717+
}
718+
if (lval < 0 || lval > maxcookie) {
719+
php_error_docref(NULL, E_WARNING, "session.cookie_lifetime must be between 0 and " ZEND_LONG_FMT, maxcookie);
710720
return FAILURE;
711-
} else if (v > maxcookie) {
712-
return SUCCESS;
713721
}
714722

715723
return OnUpdateLongGEZero(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);

ext/session/tests/gh16290.phpt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@ session
66
<?php include('skipif.inc'); ?>
77
--FILE--
88
<?php
9+
ob_start();
910
session_set_cookie_params(PHP_INT_MAX, '/', null, false, true);
1011
echo "DONE";
12+
ob_end_flush();
1113
?>
12-
--EXPECT--
14+
--EXPECTF--
15+
Warning: session_set_cookie_params(): session.cookie_lifetime must be between 0 and %d in %s on line %d
1316
DONE
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
--TEST--
2+
session.cookie_lifetime rejects invalid values
3+
--EXTENSIONS--
4+
session
5+
--SKIPIF--
6+
<?php include('skipif.inc'); ?>
7+
--FILE--
8+
<?php
9+
10+
ob_start();
11+
12+
ini_set("session.cookie_lifetime", 100);
13+
14+
// Float strings are rejected
15+
ini_set("session.cookie_lifetime", "1.5");
16+
var_dump(ini_get("session.cookie_lifetime"));
17+
18+
// Non-numeric strings are rejected
19+
ini_set("session.cookie_lifetime", "abc");
20+
var_dump(ini_get("session.cookie_lifetime"));
21+
22+
// Negative values are rejected
23+
ini_set("session.cookie_lifetime", -1);
24+
var_dump(ini_get("session.cookie_lifetime"));
25+
26+
// Negative overflow strings are rejected
27+
ini_set("session.cookie_lifetime", "-99999999999999999999");
28+
var_dump(ini_get("session.cookie_lifetime"));
29+
30+
// Overflow values are rejected
31+
ini_set("session.cookie_lifetime", PHP_INT_MAX);
32+
var_dump(ini_get("session.cookie_lifetime"));
33+
34+
// Valid values still work after rejection
35+
ini_set("session.cookie_lifetime", 200);
36+
var_dump(ini_get("session.cookie_lifetime"));
37+
38+
ob_end_flush();
39+
?>
40+
--EXPECTF--
41+
Warning: ini_set(): session.cookie_lifetime must be of type int in %s on line %d
42+
string(3) "100"
43+
44+
Warning: ini_set(): session.cookie_lifetime must be of type int in %s on line %d
45+
string(3) "100"
46+
47+
Warning: ini_set(): session.cookie_lifetime must be between 0 and %d in %s on line %d
48+
string(3) "100"
49+
50+
Warning: ini_set(): session.cookie_lifetime must be between 0 and %d in %s on line %d
51+
string(3) "100"
52+
53+
Warning: ini_set(): session.cookie_lifetime must be between 0 and %d in %s on line %d
54+
string(3) "100"
55+
string(3) "200"

ext/session/tests/session_get_cookie_params_basic.phpt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ echo "*** Testing session_get_cookie_params() : basic functionality ***\n";
2222
var_dump(session_get_cookie_params());
2323
var_dump(session_set_cookie_params(3600, "/path", "blah", FALSE, FALSE));
2424
var_dump(session_get_cookie_params());
25-
var_dump(session_set_cookie_params(1234567890, "/guff", "foo", TRUE, TRUE));
25+
var_dump(session_set_cookie_params(1000000000, "/guff", "foo", TRUE, TRUE));
2626
var_dump(session_get_cookie_params());
2727
var_dump(session_set_cookie_params([
2828
"lifetime" => 123,
@@ -40,7 +40,7 @@ var_dump(session_get_cookie_params());
4040
echo "Done";
4141
ob_end_flush();
4242
?>
43-
--EXPECTF--
43+
--EXPECT--
4444
*** Testing session_get_cookie_params() : basic functionality ***
4545
array(7) {
4646
["lifetime"]=>
@@ -78,7 +78,7 @@ array(7) {
7878
bool(true)
7979
array(7) {
8080
["lifetime"]=>
81-
int(%d)
81+
int(1000000000)
8282
["path"]=>
8383
string(5) "/guff"
8484
["domain"]=>

ext/session/tests/session_set_cookie_params_basic.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ var_dump(session_set_cookie_params(3600));
1515
var_dump(session_start());
1616
var_dump(session_set_cookie_params(1800));
1717
var_dump(session_destroy());
18-
var_dump(session_set_cookie_params(1234567890));
18+
var_dump(session_set_cookie_params(1000000000));
1919

2020
echo "Done";
2121
ob_end_flush();

ext/session/tests/session_set_cookie_params_variation1.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ var_dump(ini_get("session.cookie_lifetime"));
2424
var_dump(session_destroy());
2525

2626
var_dump(ini_get("session.cookie_lifetime"));
27-
var_dump(session_set_cookie_params(1234567890));
27+
var_dump(session_set_cookie_params(1000000000));
2828
var_dump(ini_get("session.cookie_lifetime"));
2929

3030
echo "Done";
@@ -44,5 +44,5 @@ string(4) "3600"
4444
bool(true)
4545
string(4) "3600"
4646
bool(true)
47-
string(10) "1234567890"
47+
string(10) "1000000000"
4848
Done

ext/session/tests/session_set_cookie_params_variation8.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ bool(true)
2525
string(1) "0"
2626
string(1) "0"
2727

28-
Warning: session_set_cookie_params(): CookieLifetime cannot be negative in %s on line %d
28+
Warning: session_set_cookie_params(): session.cookie_lifetime must be between 0 and %d in %s on line %d
2929
bool(false)
3030
string(1) "0"
3131
Done

0 commit comments

Comments
 (0)