@@ -675,6 +675,41 @@ static PHP_INI_MH(OnUpdateSaveDir) /* {{{ */
675
675
}
676
676
/* }}} */
677
677
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
+ }
678
713
679
714
static PHP_INI_MH (OnUpdateName ) /* {{{ */
680
715
{
@@ -685,33 +720,14 @@ static PHP_INI_MH(OnUpdateName) /* {{{ */
685
720
686
721
if (stage == ZEND_INI_STAGE_RUNTIME || stage == ZEND_INI_STAGE_ACTIVATE || stage == ZEND_INI_STAGE_STARTUP ) {
687
722
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 ;
688
726
} else {
689
727
err_type = E_ERROR ;
690
728
}
691
729
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 )) {
715
731
return FAILURE ;
716
732
}
717
733
@@ -1391,7 +1407,7 @@ static void php_session_remove_cookie(void) {
1391
1407
size_t session_cookie_len ;
1392
1408
size_t len = sizeof ("Set-Cookie" )- 1 ;
1393
1409
1394
- ZEND_ASSERT (strpbrk ( ZSTR_VAL ( PS (session_name )), SESSION_FORBIDDEN_CHARS ) == NULL );
1410
+ ZEND_ASSERT (is_session_name_valid ( PS (session_name ), 0 ) );
1395
1411
spprintf (& session_cookie , 0 , "Set-Cookie: %s=" , ZSTR_VAL (PS (session_name )));
1396
1412
1397
1413
// TODO Manually compute from known information?
@@ -1439,10 +1455,8 @@ static zend_result php_session_send_cookie(void) /* {{{ */
1439
1455
return FAILURE ;
1440
1456
}
1441
1457
1442
- // TODO need to Check for nul byte?
1443
1458
/* 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 )) {
1446
1460
return FAILURE ;
1447
1461
}
1448
1462
0 commit comments