@@ -698,6 +698,41 @@ static PHP_INI_MH(OnUpdateSaveDir) /* {{{ */
698
698
}
699
699
/* }}} */
700
700
701
+ /* If diagnostic_type is 0 then no diagnostic will be emitted */
702
+ static bool is_session_name_valid (const zend_string * name , int diagnostic_type )
703
+ {
704
+ if (ZSTR_LEN (name ) == 0 ) {
705
+ if (diagnostic_type ) {
706
+ php_error_docref (NULL , diagnostic_type , "session.name \"%s\" cannot be empty" , ZSTR_VAL (name ));
707
+ }
708
+ return false;
709
+ }
710
+ /* NUL bytes are not allowed */
711
+ if (ZSTR_LEN (name ) != strlen (ZSTR_VAL (name ))) {
712
+ if (diagnostic_type ) {
713
+ php_error_docref (NULL , diagnostic_type , "session.name \"%s\" cannot contain NUL bytes" , ZSTR_VAL (name ));
714
+ }
715
+ return false;
716
+ }
717
+ /* Numeric session.name won't work at all
718
+ * See https://bugs.php.net/bug.php?id=35703
719
+ (TL;DR: name is stored in HashTable so numeric string is converted to int key, but lookup looks for string key). */
720
+ if (is_numeric_str_function (name , NULL , NULL )) {
721
+ if (diagnostic_type ) {
722
+ php_error_docref (NULL , diagnostic_type , "session.name \"%s\" cannot be numeric" , ZSTR_VAL (name ));
723
+ }
724
+ return false;
725
+ }
726
+ /* Prevent broken Set-Cookie header, because the session_name might be user supplied */
727
+ if (strpbrk (ZSTR_VAL (name ), "=,; \t\r\n\013\014" ) != NULL ) { /* man isspace for \013 and \014 */
728
+ if (diagnostic_type ) {
729
+ php_error_docref (NULL , diagnostic_type , "session.name \"%s\" cannot contain any of the following "
730
+ "'=,; \\t\\r\\n\\013\\014'" , ZSTR_VAL (name ));
731
+ }
732
+ return false;
733
+ }
734
+ return true;
735
+ }
701
736
702
737
static PHP_INI_MH (OnUpdateName ) /* {{{ */
703
738
{
@@ -708,33 +743,14 @@ static PHP_INI_MH(OnUpdateName) /* {{{ */
708
743
709
744
if (stage == ZEND_INI_STAGE_RUNTIME || stage == ZEND_INI_STAGE_ACTIVATE || stage == ZEND_INI_STAGE_STARTUP ) {
710
745
err_type = E_WARNING ;
746
+ } else if (stage == ZEND_INI_STAGE_DEACTIVATE ) {
747
+ /* Do not output error when restoring ini options. */
748
+ err_type = 0 ;
711
749
} else {
712
750
err_type = E_ERROR ;
713
751
}
714
752
715
- if (ZSTR_LEN (new_value ) == 0 ) {
716
- /* Do not output error when restoring ini options. */
717
- if (stage != ZEND_INI_STAGE_DEACTIVATE ) {
718
- php_error_docref (NULL , err_type , "session.name \"%s\" cannot be empty" , ZSTR_VAL (new_value ));
719
- }
720
- return FAILURE ;
721
- }
722
- /* NUL bytes are not allowed */
723
- if (ZSTR_LEN (new_value ) != strlen (ZSTR_VAL (new_value ))) {
724
- /* Do not output error when restoring ini options. */
725
- if (stage != ZEND_INI_STAGE_DEACTIVATE ) {
726
- php_error_docref (NULL , err_type , "session.name \"%s\" cannot contain NUL bytes" , ZSTR_VAL (new_value ));
727
- }
728
- return FAILURE ;
729
- }
730
- /* Numeric session.name won't work at all
731
- * See https://bugs.php.net/bug.php?id=35703
732
- (TL;DR: name is stored in HashTable so numeric string is converted to int key, but lookup looks for string key). */
733
- if (is_numeric_str_function (new_value , NULL , NULL )) {
734
- /* Do not output error when restoring ini options. */
735
- if (stage != ZEND_INI_STAGE_DEACTIVATE ) {
736
- php_error_docref (NULL , err_type , "session.name \"%s\" cannot be numeric" , ZSTR_VAL (new_value ));
737
- }
753
+ if (!is_session_name_valid (new_value , err_type )) {
738
754
return FAILURE ;
739
755
}
740
756
@@ -1413,7 +1429,7 @@ static void php_session_remove_cookie(void) {
1413
1429
size_t session_cookie_len ;
1414
1430
size_t len = sizeof ("Set-Cookie" )- 1 ;
1415
1431
1416
- ZEND_ASSERT (strpbrk ( ZSTR_VAL ( PS (session_name )), SESSION_FORBIDDEN_CHARS ) == NULL );
1432
+ ZEND_ASSERT (is_session_name_valid ( PS (session_name ), 0 ) );
1417
1433
spprintf (& session_cookie , 0 , "Set-Cookie: %s=" , ZSTR_VAL (PS (session_name )));
1418
1434
1419
1435
// TODO Manually compute from known information?
@@ -1454,10 +1470,8 @@ static zend_result php_session_send_cookie(void) /* {{{ */
1454
1470
return FAILURE ;
1455
1471
}
1456
1472
1457
- // TODO need to Check for nul byte?
1458
1473
/* Prevent broken Set-Cookie header, because the session_name might be user supplied */
1459
- if (strpbrk (ZSTR_VAL (PS (session_name )), SESSION_FORBIDDEN_CHARS ) != NULL ) { /* man isspace for \013 and \014 */
1460
- php_error_docref (NULL , E_WARNING , "session.name cannot contain any of the following '=,; \\t\\r\\n\\013\\014'" );
1474
+ if (!is_session_name_valid (PS (session_name ), E_WARNING )) {
1461
1475
return FAILURE ;
1462
1476
}
1463
1477
0 commit comments