@@ -647,6 +647,41 @@ static PHP_INI_MH(OnUpdateSaveDir) /* {{{ */
647
647
}
648
648
/* }}} */
649
649
650
+ /* If diagnostic_type is 0 then no diagnostic will be emitted */
651
+ static bool is_session_name_valid (const zend_string * name , int diagnostic_type )
652
+ {
653
+ if (ZSTR_LEN (name ) == 0 ) {
654
+ if (diagnostic_type ) {
655
+ php_error_docref (NULL , diagnostic_type , "session.name \"%s\" cannot be empty" , ZSTR_VAL (name ));
656
+ }
657
+ return false;
658
+ }
659
+ /* NUL bytes are not allowed */
660
+ if (ZSTR_LEN (name ) != strlen (ZSTR_VAL (name ))) {
661
+ if (diagnostic_type ) {
662
+ php_error_docref (NULL , diagnostic_type , "session.name \"%s\" cannot contain NUL bytes" , ZSTR_VAL (name ));
663
+ }
664
+ return false;
665
+ }
666
+ /* Numeric session.name won't work at all
667
+ * See https://bugs.php.net/bug.php?id=35703
668
+ (TL;DR: name is stored in HashTable so numeric string is converted to int key, but lookup looks for string key). */
669
+ if (is_numeric_str_function (name , NULL , NULL )) {
670
+ if (diagnostic_type ) {
671
+ php_error_docref (NULL , diagnostic_type , "session.name \"%s\" cannot be numeric" , ZSTR_VAL (name ));
672
+ }
673
+ return false;
674
+ }
675
+ /* Prevent broken Set-Cookie header, because the session_name might be user supplied */
676
+ if (strpbrk (ZSTR_VAL (name ), "=,; \t\r\n\013\014" ) != NULL ) { /* man isspace for \013 and \014 */
677
+ if (diagnostic_type ) {
678
+ php_error_docref (NULL , diagnostic_type , "session.name \"%s\" cannot contain any of the following "
679
+ "'=,; \\t\\r\\n\\013\\014'" , ZSTR_VAL (name ));
680
+ }
681
+ return false;
682
+ }
683
+ return true;
684
+ }
650
685
651
686
static PHP_INI_MH (OnUpdateName ) /* {{{ */
652
687
{
@@ -657,33 +692,14 @@ static PHP_INI_MH(OnUpdateName) /* {{{ */
657
692
658
693
if (stage == ZEND_INI_STAGE_RUNTIME || stage == ZEND_INI_STAGE_ACTIVATE || stage == ZEND_INI_STAGE_STARTUP ) {
659
694
err_type = E_WARNING ;
695
+ } else if (stage == ZEND_INI_STAGE_DEACTIVATE ) {
696
+ /* Do not output error when restoring ini options. */
697
+ err_type = 0 ;
660
698
} else {
661
699
err_type = E_ERROR ;
662
700
}
663
701
664
- if (ZSTR_LEN (new_value ) == 0 ) {
665
- /* Do not output error when restoring ini options. */
666
- if (stage != ZEND_INI_STAGE_DEACTIVATE ) {
667
- php_error_docref (NULL , err_type , "session.name \"%s\" cannot be empty" , ZSTR_VAL (new_value ));
668
- }
669
- return FAILURE ;
670
- }
671
- /* NUL bytes are not allowed */
672
- if (ZSTR_LEN (new_value ) != strlen (ZSTR_VAL (new_value ))) {
673
- /* Do not output error when restoring ini options. */
674
- if (stage != ZEND_INI_STAGE_DEACTIVATE ) {
675
- php_error_docref (NULL , err_type , "session.name \"%s\" cannot contain NUL bytes" , ZSTR_VAL (new_value ));
676
- }
677
- return FAILURE ;
678
- }
679
- /* Numeric session.name won't work at all
680
- * See https://bugs.php.net/bug.php?id=35703
681
- (TL;DR: name is stored in HashTable so numeric string is converted to int key, but lookup looks for string key). */
682
- if (is_numeric_str_function (new_value , NULL , NULL )) {
683
- /* Do not output error when restoring ini options. */
684
- if (stage != ZEND_INI_STAGE_DEACTIVATE ) {
685
- php_error_docref (NULL , err_type , "session.name \"%s\" cannot be numeric" , ZSTR_VAL (new_value ));
686
- }
702
+ if (!is_session_name_valid (new_value , err_type )) {
687
703
return FAILURE ;
688
704
}
689
705
@@ -1277,7 +1293,7 @@ static void php_session_remove_cookie(void) {
1277
1293
size_t session_cookie_len ;
1278
1294
size_t len = sizeof ("Set-Cookie" )- 1 ;
1279
1295
1280
- ZEND_ASSERT (strpbrk ( ZSTR_VAL ( PS (session_name )), "=,; \t\r\n\013\014" ) == NULL );
1296
+ ZEND_ASSERT (is_session_name_valid ( PS (session_name ), 0 ) );
1281
1297
spprintf (& session_cookie , 0 , "Set-Cookie: %s=" , ZSTR_VAL (PS (session_name )));
1282
1298
1283
1299
// TODO Manually compute from known information?
@@ -1325,10 +1341,8 @@ static zend_result php_session_send_cookie(void) /* {{{ */
1325
1341
return FAILURE ;
1326
1342
}
1327
1343
1328
- // TODO need to Check for nul byte?
1329
1344
/* Prevent broken Set-Cookie header, because the session_name might be user supplied */
1330
- if (strpbrk (ZSTR_VAL (PS (session_name )), "=,; \t\r\n\013\014" ) != NULL ) { /* man isspace for \013 and \014 */
1331
- php_error_docref (NULL , E_WARNING , "session.name cannot contain any of the following '=,; \\t\\r\\n\\013\\014'" );
1345
+ if (!is_session_name_valid (PS (session_name ), E_WARNING )) {
1332
1346
return FAILURE ;
1333
1347
}
1334
1348
0 commit comments