Skip to content

Commit a85666c

Browse files
committed
ext/session: Fix GH-17541 (ext/session NULL pointer dereferencement during ID reset)
Closes GH-17541 Closes GH-17546
1 parent cf97342 commit a85666c

File tree

5 files changed

+50
-19
lines changed

5 files changed

+50
-19
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ PHP NEWS
5050

5151
- Session:
5252
. Fix type confusion with session SID constant. (nielsdos)
53+
. Fixed bug GH-17541 (ext/session NULL pointer dereferencement during
54+
ID reset). (Girgias)
5355

5456
- SimpleXML:
5557
. Fixed bug GH-17409 (Assertion failure Zend/zend_hash.c:1730). (nielsdos)

ext/session/session.c

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ zend_class_entry *php_session_update_timestamp_iface_entry;
9494
}
9595

9696
#define SESSION_FORBIDDEN_CHARS "=,;.[ \t\r\n\013\014"
97+
#define SESSION_FORBIDDEN_CHARS_FOR_ERROR_MSG "=,;.[ \\t\\r\\n\\013\\014"
9798

9899
#define APPLY_TRANS_SID (PS(use_trans_sid) && !PS(use_only_cookies))
99100

@@ -683,7 +684,12 @@ static PHP_INI_MH(OnUpdateName) /* {{{ */
683684
SESSION_CHECK_OUTPUT_STATE;
684685

685686
/* Numeric session.name won't work at all */
686-
if ((!ZSTR_LEN(new_value) || is_numeric_string(ZSTR_VAL(new_value), ZSTR_LEN(new_value), NULL, NULL, 0))) {
687+
if (
688+
ZSTR_LEN(new_value) == 0
689+
|| zend_str_has_nul_byte(new_value)
690+
|| is_numeric_str_function(new_value, NULL, NULL)
691+
|| strpbrk(ZSTR_VAL(new_value), SESSION_FORBIDDEN_CHARS) != NULL
692+
) {
687693
int err_type;
688694

689695
if (stage == ZEND_INI_STAGE_RUNTIME || stage == ZEND_INI_STAGE_ACTIVATE || stage == ZEND_INI_STAGE_STARTUP) {
@@ -694,7 +700,7 @@ static PHP_INI_MH(OnUpdateName) /* {{{ */
694700

695701
/* Do not output error when restoring ini options. */
696702
if (stage != ZEND_INI_STAGE_DEACTIVATE) {
697-
php_error_docref(NULL, err_type, "session.name \"%s\" cannot be numeric or empty", ZSTR_VAL(new_value));
703+
php_error_docref(NULL, err_type, "session.name \"%s\" must not be numeric, empty, contain null bytes or any of the following characters \"" SESSION_FORBIDDEN_CHARS_FOR_ERROR_MSG "\"", ZSTR_VAL(new_value));
698704
}
699705
return FAILURE;
700706
}
@@ -1338,11 +1344,7 @@ static zend_result php_session_send_cookie(void) /* {{{ */
13381344
return FAILURE;
13391345
}
13401346

1341-
/* Prevent broken Set-Cookie header, because the session_name might be user supplied */
1342-
if (strpbrk(PS(session_name), SESSION_FORBIDDEN_CHARS) != NULL) { /* man isspace for \013 and \014 */
1343-
php_error_docref(NULL, E_WARNING, "session.name cannot contain any of the following '=,;.[ \\t\\r\\n\\013\\014'");
1344-
return FAILURE;
1345-
}
1347+
ZEND_ASSERT(strpbrk(PS(session_name), SESSION_FORBIDDEN_CHARS) == NULL);
13461348

13471349
/* URL encode id because it might be user supplied */
13481350
e_id = php_url_encode(ZSTR_VAL(PS(id)), ZSTR_LEN(PS(id)));
@@ -1462,7 +1464,10 @@ PHPAPI zend_result php_session_reset_id(void) /* {{{ */
14621464
}
14631465

14641466
if (PS(use_cookies) && PS(send_cookie)) {
1465-
php_session_send_cookie();
1467+
zend_result cookies_sent = php_session_send_cookie();
1468+
if (UNEXPECTED(cookies_sent == FAILURE)) {
1469+
return FAILURE;
1470+
}
14661471
PS(send_cookie) = 0;
14671472
}
14681473

ext/session/tests/bug66481.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@ var_dump(session_name("foo"));
1515
var_dump(session_name("bar"));
1616
?>
1717
--EXPECT--
18-
Warning: PHP Startup: session.name "" cannot be numeric or empty in Unknown on line 0
18+
Warning: PHP Startup: session.name "" must not be numeric, empty, contain null bytes or any of the following characters "=,;.[ \t\r\n\013\014" in Unknown on line 0
1919
string(9) "PHPSESSID"
2020
string(3) "foo"

ext/session/tests/gh17541.phpt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
--TEST--
2+
GH-17541 (ext/session NULL pointer dereferencement during ID reset)
3+
--EXTENSIONS--
4+
session
5+
--SKIPIF--
6+
<?php include('skipif.inc'); ?>
7+
--FILE--
8+
<?php
9+
function errorHandler($errorNumber, $errorMessage, $fileName, $lineNumber) {
10+
// Destroy session while emitting warning from the bogus session name in session_start
11+
session_destroy();
12+
}
13+
14+
set_error_handler('errorHandler');
15+
16+
ob_start();
17+
var_dump(session_name("\t"));
18+
var_dump(session_start());
19+
20+
?>
21+
--EXPECTF--
22+
Warning: session_destroy(): Trying to destroy uninitialized session in %s on line %d
23+
string(9) "PHPSESSID"
24+
bool(true)

ext/session/tests/session_name_variation1.phpt

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,25 +38,25 @@ ob_end_flush();
3838
?>
3939
--EXPECTF--
4040
*** Testing session_name() : variation ***
41+
42+
Warning: session_name(): session.name "" must not be numeric, empty, contain null bytes or any of the following characters "=,;.[ \t\r\n\013\014" in %s on line %d
4143
string(9) "PHPSESSID"
4244
bool(true)
4345
string(9) "PHPSESSID"
4446
bool(true)
4547
string(9) "PHPSESSID"
46-
string(9) "PHPSESSID"
4748

48-
Warning: session_start(): session.name cannot contain any of the following '=,;.[ \t\r\n\013\014' in %s on line %d
49+
Warning: session_name(): session.name " " must not be numeric, empty, contain null bytes or any of the following characters "=,;.[ \t\r\n\013\014" in %s on line %d
50+
string(9) "PHPSESSID"
4951
bool(true)
50-
string(1) " "
52+
string(9) "PHPSESSID"
5153
bool(true)
52-
string(1) " "
53-
54-
Warning: session_name(): session.name "" cannot be numeric or empty in %s on line %d
55-
string(1) " "
54+
string(9) "PHPSESSID"
5655

57-
Warning: session_start(): session.name cannot contain any of the following '=,;.[ \t\r\n\013\014' in %s on line %d
56+
Warning: session_name(): session.name "" must not be numeric, empty, contain null bytes or any of the following characters "=,;.[ \t\r\n\013\014" in %s on line %d
57+
string(9) "PHPSESSID"
5858
bool(true)
59-
string(1) " "
59+
string(9) "PHPSESSID"
6060
bool(true)
61-
string(1) " "
61+
string(9) "PHPSESSID"
6262
Done

0 commit comments

Comments
 (0)