@@ -658,6 +658,41 @@ static PHP_INI_MH(OnUpdateSaveDir) /* {{{ */
658
658
}
659
659
/* }}} */
660
660
661
+ /* If diagnostic_type is 0 then no diagnostic will be emitted */
662
+ static bool is_session_name_valid (const zend_string * name , int diagnostic_type )
663
+ {
664
+ if (ZSTR_LEN (name ) == 0 ) {
665
+ if (diagnostic_type ) {
666
+ php_error_docref (NULL , diagnostic_type , "session.name \"%s\" cannot be empty" , ZSTR_VAL (name ));
667
+ }
668
+ return false;
669
+ }
670
+ /* NUL bytes are not allowed */
671
+ if (ZSTR_LEN (name ) != strlen (ZSTR_VAL (name ))) {
672
+ if (diagnostic_type ) {
673
+ php_error_docref (NULL , diagnostic_type , "session.name \"%s\" cannot contain NUL bytes" , ZSTR_VAL (name ));
674
+ }
675
+ return false;
676
+ }
677
+ /* Numeric session.name won't work at all
678
+ * See https://bugs.php.net/bug.php?id=35703
679
+ (TL;DR: name is stored in HashTable so numeric string is converted to int key, but lookup looks for string key). */
680
+ if (is_numeric_str_function (name , NULL , NULL )) {
681
+ if (diagnostic_type ) {
682
+ php_error_docref (NULL , diagnostic_type , "session.name \"%s\" cannot be numeric" , ZSTR_VAL (name ));
683
+ }
684
+ return false;
685
+ }
686
+ /* Prevent broken Set-Cookie header, because the session_name might be user supplied */
687
+ if (strpbrk (ZSTR_VAL (name ), "=,; \t\r\n\013\014" ) != NULL ) { /* man isspace for \013 and \014 */
688
+ if (diagnostic_type ) {
689
+ php_error_docref (NULL , diagnostic_type , "session.name \"%s\" cannot contain any of the following "
690
+ "'=,; \\t\\r\\n\\013\\014'" , ZSTR_VAL (name ));
691
+ }
692
+ return false;
693
+ }
694
+ return true;
695
+ }
661
696
662
697
static PHP_INI_MH (OnUpdateName ) /* {{{ */
663
698
{
@@ -668,33 +703,14 @@ static PHP_INI_MH(OnUpdateName) /* {{{ */
668
703
669
704
if (stage == ZEND_INI_STAGE_RUNTIME || stage == ZEND_INI_STAGE_ACTIVATE || stage == ZEND_INI_STAGE_STARTUP ) {
670
705
err_type = E_WARNING ;
706
+ } else if (stage == ZEND_INI_STAGE_DEACTIVATE ) {
707
+ /* Do not output error when restoring ini options. */
708
+ err_type = 0 ;
671
709
} else {
672
710
err_type = E_ERROR ;
673
711
}
674
712
675
- if (ZSTR_LEN (new_value ) == 0 ) {
676
- /* Do not output error when restoring ini options. */
677
- if (stage != ZEND_INI_STAGE_DEACTIVATE ) {
678
- php_error_docref (NULL , err_type , "session.name \"%s\" cannot be empty" , ZSTR_VAL (new_value ));
679
- }
680
- return FAILURE ;
681
- }
682
- /* NUL bytes are not allowed */
683
- if (ZSTR_LEN (new_value ) != strlen (ZSTR_VAL (new_value ))) {
684
- /* Do not output error when restoring ini options. */
685
- if (stage != ZEND_INI_STAGE_DEACTIVATE ) {
686
- php_error_docref (NULL , err_type , "session.name \"%s\" cannot contain NUL bytes" , ZSTR_VAL (new_value ));
687
- }
688
- return FAILURE ;
689
- }
690
- /* Numeric session.name won't work at all
691
- * See https://bugs.php.net/bug.php?id=35703
692
- (TL;DR: name is stored in HashTable so numeric string is converted to int key, but lookup looks for string key). */
693
- if (is_numeric_str_function (new_value , NULL , NULL )) {
694
- /* Do not output error when restoring ini options. */
695
- if (stage != ZEND_INI_STAGE_DEACTIVATE ) {
696
- php_error_docref (NULL , err_type , "session.name \"%s\" cannot be numeric" , ZSTR_VAL (new_value ));
697
- }
713
+ if (!is_session_name_valid (new_value , err_type )) {
698
714
return FAILURE ;
699
715
}
700
716
@@ -1297,7 +1313,7 @@ static void php_session_remove_cookie(void) {
1297
1313
size_t session_cookie_len ;
1298
1314
size_t len = sizeof ("Set-Cookie" )- 1 ;
1299
1315
1300
- ZEND_ASSERT (strpbrk ( ZSTR_VAL ( PS (session_name )), "=,; \t\r\n\013\014" ) == NULL );
1316
+ ZEND_ASSERT (is_session_name_valid ( PS (session_name ), 0 ) );
1301
1317
spprintf (& session_cookie , 0 , "Set-Cookie: %s=" , ZSTR_VAL (PS (session_name )));
1302
1318
1303
1319
// TODO Manually compute from known information?
@@ -1345,10 +1361,8 @@ static zend_result php_session_send_cookie(void) /* {{{ */
1345
1361
return FAILURE ;
1346
1362
}
1347
1363
1348
- // TODO need to Check for nul byte?
1349
1364
/* Prevent broken Set-Cookie header, because the session_name might be user supplied */
1350
- if (strpbrk (ZSTR_VAL (PS (session_name )), "=,; \t\r\n\013\014" ) != NULL ) { /* man isspace for \013 and \014 */
1351
- php_error_docref (NULL , E_WARNING , "session.name cannot contain any of the following '=,; \\t\\r\\n\\013\\014'" );
1365
+ if (!is_session_name_valid (PS (session_name ), E_WARNING )) {
1352
1366
return FAILURE ;
1353
1367
}
1354
1368
0 commit comments