Skip to content

Commit 0847552

Browse files
Girgiasjorgsowa
authored andcommitted
Check for session name criterias consistently
1 parent 5d010c6 commit 0847552

File tree

2 files changed

+52
-35
lines changed

2 files changed

+52
-35
lines changed

ext/session/session.c

Lines changed: 41 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,41 @@ static PHP_INI_MH(OnUpdateSaveDir) /* {{{ */
675675
}
676676
/* }}} */
677677

678+
/* If diagnostic_type is 0 then no diagnostic will be emitted */
679+
static bool is_session_name_valid(const zend_string *name, int diagnostic_type)
680+
{
681+
if (ZSTR_LEN(name) == 0) {
682+
if (diagnostic_type) {
683+
php_error_docref(NULL, diagnostic_type, "session.name \"%s\" cannot be empty", ZSTR_VAL(name));
684+
}
685+
return false;
686+
}
687+
/* NUL bytes are not allowed */
688+
if (ZSTR_LEN(name) != strlen(ZSTR_VAL(name))) {
689+
if (diagnostic_type) {
690+
php_error_docref(NULL, diagnostic_type, "session.name \"%s\" cannot contain NUL bytes", ZSTR_VAL(name));
691+
}
692+
return false;
693+
}
694+
/* Numeric session.name won't work at all
695+
* See https://bugs.php.net/bug.php?id=35703
696+
(TL;DR: name is stored in HashTable so numeric string is converted to int key, but lookup looks for string key). */
697+
if (is_numeric_str_function(name, NULL, NULL)) {
698+
if (diagnostic_type) {
699+
php_error_docref(NULL, diagnostic_type, "session.name \"%s\" cannot be numeric", ZSTR_VAL(name));
700+
}
701+
return false;
702+
}
703+
/* Prevent broken Set-Cookie header, because the session_name might be user supplied */
704+
if (strpbrk(ZSTR_VAL(name), "=,; \t\r\n\013\014") != NULL) { /* man isspace for \013 and \014 */
705+
if (diagnostic_type) {
706+
php_error_docref(NULL, diagnostic_type, "session.name \"%s\" cannot contain any of the following "
707+
"'=,; \\t\\r\\n\\013\\014'", ZSTR_VAL(name));
708+
}
709+
return false;
710+
}
711+
return true;
712+
}
678713

679714
static PHP_INI_MH(OnUpdateName) /* {{{ */
680715
{
@@ -685,33 +720,14 @@ static PHP_INI_MH(OnUpdateName) /* {{{ */
685720

686721
if (stage == ZEND_INI_STAGE_RUNTIME || stage == ZEND_INI_STAGE_ACTIVATE || stage == ZEND_INI_STAGE_STARTUP) {
687722
err_type = E_WARNING;
723+
} else if (stage == ZEND_INI_STAGE_DEACTIVATE) {
724+
/* Do not output error when restoring ini options. */
725+
err_type = 0;
688726
} else {
689727
err_type = E_ERROR;
690728
}
691729

692-
if (ZSTR_LEN(new_value) == 0) {
693-
/* Do not output error when restoring ini options. */
694-
if (stage != ZEND_INI_STAGE_DEACTIVATE) {
695-
php_error_docref(NULL, err_type, "session.name \"%s\" cannot be empty", ZSTR_VAL(new_value));
696-
}
697-
return FAILURE;
698-
}
699-
/* NUL bytes are not allowed */
700-
if (ZSTR_LEN(new_value) != strlen(ZSTR_VAL(new_value))) {
701-
/* Do not output error when restoring ini options. */
702-
if (stage != ZEND_INI_STAGE_DEACTIVATE) {
703-
php_error_docref(NULL, err_type, "session.name \"%s\" cannot contain NUL bytes", ZSTR_VAL(new_value));
704-
}
705-
return FAILURE;
706-
}
707-
/* Numeric session.name won't work at all
708-
* See https://bugs.php.net/bug.php?id=35703
709-
(TL;DR: name is stored in HashTable so numeric string is converted to int key, but lookup looks for string key). */
710-
if (is_numeric_str_function(new_value, NULL, NULL)) {
711-
/* Do not output error when restoring ini options. */
712-
if (stage != ZEND_INI_STAGE_DEACTIVATE) {
713-
php_error_docref(NULL, err_type, "session.name \"%s\" cannot be numeric", ZSTR_VAL(new_value));
714-
}
730+
if (!is_session_name_valid(new_value, err_type)) {
715731
return FAILURE;
716732
}
717733

@@ -1391,7 +1407,7 @@ static void php_session_remove_cookie(void) {
13911407
size_t session_cookie_len;
13921408
size_t len = sizeof("Set-Cookie")-1;
13931409

1394-
ZEND_ASSERT(strpbrk(ZSTR_VAL(PS(session_name)), SESSION_FORBIDDEN_CHARS) == NULL);
1410+
ZEND_ASSERT(is_session_name_valid(PS(session_name), 0));
13951411
spprintf(&session_cookie, 0, "Set-Cookie: %s=", ZSTR_VAL(PS(session_name)));
13961412

13971413
// TODO Manually compute from known information?
@@ -1439,10 +1455,8 @@ static zend_result php_session_send_cookie(void) /* {{{ */
14391455
return FAILURE;
14401456
}
14411457

1442-
// TODO need to Check for nul byte?
14431458
/* Prevent broken Set-Cookie header, because the session_name might be user supplied */
1444-
if (strpbrk(ZSTR_VAL(PS(session_name)), SESSION_FORBIDDEN_CHARS) != NULL) { /* man isspace for \013 and \014 */
1445-
php_error_docref(NULL, E_WARNING, "session.name cannot contain any of the following '=,; \\t\\r\\n\\013\\014'");
1459+
if (!is_session_name_valid(PS(session_name), E_WARNING)) {
14461460
return FAILURE;
14471461
}
14481462

ext/session/tests/session_name_variation1.phpt

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -67,19 +67,22 @@ string(9) "PHPSESSID"
6767

6868
Warning: session_name(): session.name "10.25" cannot be numeric in %s on line %d
6969
string(9) "PHPSESSID"
70+
bool(true)
71+
string(9) "PHPSESSID"
72+
bool(true)
73+
string(9) "PHPSESSID"
7074

71-
Warning: session_start(): session.name cannot contain any of the following '=,;.[ \t\r\n\013\014' in %s on line %d
75+
Warning: session_name(): session.name " " cannot contain any of the following '=,; \t\r\n\013\014' in %s on line %d
76+
string(9) "PHPSESSID"
7277
bool(true)
73-
string(1) " "
78+
string(9) "PHPSESSID"
7479
bool(true)
75-
string(1) " "
80+
string(9) "PHPSESSID"
7681

7782
Warning: session_name(): session.name "" cannot be empty in %s on line %d
78-
string(1) " "
79-
80-
Warning: session_start(): session.name cannot contain any of the following '=,;.[ \t\r\n\013\014' in %s on line %d
83+
string(9) "PHPSESSID"
8184
bool(true)
82-
string(1) " "
85+
string(9) "PHPSESSID"
8386
bool(true)
84-
string(1) " "
87+
string(9) "PHPSESSID"
8588
Done

0 commit comments

Comments
 (0)