@@ -642,6 +642,41 @@ static PHP_INI_MH(OnUpdateSaveDir) /* {{{ */
642
642
}
643
643
/* }}} */
644
644
645
+ /* If diagnostic_type is 0 then no diagnostic will be emitted */
646
+ static bool is_session_name_valid (const zend_string * name , int diagnostic_type )
647
+ {
648
+ if (ZSTR_LEN (name ) == 0 ) {
649
+ if (diagnostic_type ) {
650
+ php_error_docref (NULL , diagnostic_type , "session.name \"%s\" cannot be empty" , ZSTR_VAL (name ));
651
+ }
652
+ return false;
653
+ }
654
+ /* NUL bytes are not allowed */
655
+ if (ZSTR_LEN (name ) != strlen (ZSTR_VAL (name ))) {
656
+ if (diagnostic_type ) {
657
+ php_error_docref (NULL , diagnostic_type , "session.name \"%s\" cannot contain NUL bytes" , ZSTR_VAL (name ));
658
+ }
659
+ return false;
660
+ }
661
+ /* Numeric session.name won't work at all
662
+ * See https://bugs.php.net/bug.php?id=35703
663
+ (TL;DR: name is stored in HashTable so numeric string is converted to int key, but lookup looks for string key). */
664
+ if (is_numeric_str_function (name , NULL , NULL )) {
665
+ if (diagnostic_type ) {
666
+ php_error_docref (NULL , diagnostic_type , "session.name \"%s\" cannot be numeric" , ZSTR_VAL (name ));
667
+ }
668
+ return false;
669
+ }
670
+ /* Prevent broken Set-Cookie header, because the session_name might be user supplied */
671
+ if (strpbrk (ZSTR_VAL (name ), "=,; \t\r\n\013\014" ) != NULL ) { /* man isspace for \013 and \014 */
672
+ if (diagnostic_type ) {
673
+ php_error_docref (NULL , diagnostic_type , "session.name \"%s\" cannot contain any of the following "
674
+ "'=,; \\t\\r\\n\\013\\014'" , ZSTR_VAL (name ));
675
+ }
676
+ return false;
677
+ }
678
+ return true;
679
+ }
645
680
646
681
static PHP_INI_MH (OnUpdateName ) /* {{{ */
647
682
{
@@ -652,33 +687,14 @@ static PHP_INI_MH(OnUpdateName) /* {{{ */
652
687
653
688
if (stage == ZEND_INI_STAGE_RUNTIME || stage == ZEND_INI_STAGE_ACTIVATE || stage == ZEND_INI_STAGE_STARTUP ) {
654
689
err_type = E_WARNING ;
690
+ } else if (stage == ZEND_INI_STAGE_DEACTIVATE ) {
691
+ /* Do not output error when restoring ini options. */
692
+ err_type = 0 ;
655
693
} else {
656
694
err_type = E_ERROR ;
657
695
}
658
696
659
- if (ZSTR_LEN (new_value ) == 0 ) {
660
- /* Do not output error when restoring ini options. */
661
- if (stage != ZEND_INI_STAGE_DEACTIVATE ) {
662
- php_error_docref (NULL , err_type , "session.name \"%s\" cannot be empty" , ZSTR_VAL (new_value ));
663
- }
664
- return FAILURE ;
665
- }
666
- /* NUL bytes are not allowed */
667
- if (ZSTR_LEN (new_value ) != strlen (ZSTR_VAL (new_value ))) {
668
- /* Do not output error when restoring ini options. */
669
- if (stage != ZEND_INI_STAGE_DEACTIVATE ) {
670
- php_error_docref (NULL , err_type , "session.name \"%s\" cannot contain NUL bytes" , ZSTR_VAL (new_value ));
671
- }
672
- return FAILURE ;
673
- }
674
- /* Numeric session.name won't work at all
675
- * See https://bugs.php.net/bug.php?id=35703
676
- (TL;DR: name is stored in HashTable so numeric string is converted to int key, but lookup looks for string key). */
677
- if (is_numeric_str_function (new_value , NULL , NULL )) {
678
- /* Do not output error when restoring ini options. */
679
- if (stage != ZEND_INI_STAGE_DEACTIVATE ) {
680
- php_error_docref (NULL , err_type , "session.name \"%s\" cannot be numeric" , ZSTR_VAL (new_value ));
681
- }
697
+ if (!is_session_name_valid (new_value , err_type )) {
682
698
return FAILURE ;
683
699
}
684
700
@@ -1270,7 +1286,7 @@ static void php_session_remove_cookie(void) {
1270
1286
size_t session_cookie_len ;
1271
1287
size_t len = sizeof ("Set-Cookie" )- 1 ;
1272
1288
1273
- ZEND_ASSERT (strpbrk ( ZSTR_VAL ( PS (session_name )), "=,; \t\r\n\013\014" ) == NULL );
1289
+ ZEND_ASSERT (is_session_name_valid ( PS (session_name ), 0 ) );
1274
1290
spprintf (& session_cookie , 0 , "Set-Cookie: %s=" , ZSTR_VAL (PS (session_name )));
1275
1291
1276
1292
// TODO Manually compute from known information?
@@ -1318,10 +1334,8 @@ static zend_result php_session_send_cookie(void) /* {{{ */
1318
1334
return FAILURE ;
1319
1335
}
1320
1336
1321
- // TODO need to Check for nul byte?
1322
1337
/* Prevent broken Set-Cookie header, because the session_name might be user supplied */
1323
- if (strpbrk (ZSTR_VAL (PS (session_name )), "=,; \t\r\n\013\014" ) != NULL ) { /* man isspace for \013 and \014 */
1324
- php_error_docref (NULL , E_WARNING , "session.name cannot contain any of the following '=,; \\t\\r\\n\\013\\014'" );
1338
+ if (!is_session_name_valid (PS (session_name ), E_WARNING )) {
1325
1339
return FAILURE ;
1326
1340
}
1327
1341
0 commit comments