@@ -1072,178 +1072,173 @@ fn parse_headers_iter_uninit<'a>(
10721072 }
10731073
10741074 ' headers: loop {
1075- // Return the error `$err` if `ignore_invalid_headers_in_responses`
1076- // is false, otherwise find the end of the current line and resume
1077- // parsing on the next one.
1078- macro_rules! handle_invalid_char {
1079- ( $bytes: ident, $b: ident, $err: ident) => {
1080- if !config. ignore_invalid_headers {
1081- return Err ( Error :: $err) ;
1082- }
1083-
1084- let mut b = $b;
1075+ let mut b;
10851076
1086- loop {
1087- if b == b'\r' {
1088- expect!( bytes. next( ) == b'\n' => Err ( Error :: $err) ) ;
1089- break ;
1090- }
1091- if b == b'\n' {
1092- break ;
1093- }
1094- if b == b'\0' {
1095- return Err ( Error :: $err) ;
1077+ #[ allow( clippy:: never_loop) ]
1078+ let invalid_header_err = ' header: loop {
1079+ // a newline here means the head is over!
1080+ b = next ! ( bytes) ;
1081+ if b == b'\r' {
1082+ expect ! ( bytes. next( ) == b'\n' => Err ( Error :: NewLine ) ) ;
1083+ let end = bytes. as_ref ( ) . as_ptr ( ) as usize ;
1084+ result = Ok ( Status :: Complete ( end - start) ) ;
1085+ break ' headers;
1086+ }
1087+ if b == b'\n' {
1088+ let end = bytes. as_ref ( ) . as_ptr ( ) as usize ;
1089+ result = Ok ( Status :: Complete ( end - start) ) ;
1090+ break ' headers;
1091+ }
1092+ if !is_header_name_token ( b) {
1093+ if config. allow_space_before_first_header_name
1094+ && autoshrink. num_headers == 0
1095+ && ( b == b' ' || b == b'\t' )
1096+ {
1097+ //advance past white space and then try parsing header again
1098+ while let Some ( peek) = bytes. peek ( ) {
1099+ if peek == b' ' || peek == b'\t' {
1100+ next ! ( bytes) ;
1101+ } else {
1102+ break ;
1103+ }
10961104 }
1097- b = next!( $bytes) ;
1105+ bytes. slice ( ) ;
1106+ continue ' headers;
1107+ } else {
1108+ break ' header Error :: HeaderName ;
10981109 }
1110+ }
10991111
1100- $bytes. slice( ) ;
1112+ #[ allow( clippy:: never_loop) ]
1113+ // parse header name until colon
1114+ let header_name: & str = ' name: loop {
1115+ simd:: match_header_name_vectored ( bytes) ;
1116+ b = next ! ( bytes) ;
11011117
1102- continue ' headers;
1103- } ;
1104- }
1118+ // SAFETY: previously bumped by 1 with next! -> always safe.
1119+ let bslice = unsafe { bytes. slice_skip ( 1 ) } ;
1120+ // SAFETY: previous call to match_header_name_vectored ensured all bytes are valid
1121+ // header name chars, and as such also valid utf-8.
1122+ let name = unsafe { str:: from_utf8_unchecked ( bslice) } ;
11051123
1106- // a newline here means the head is over!
1107- let b = next ! ( bytes) ;
1108- if b == b'\r' {
1109- expect ! ( bytes. next( ) == b'\n' => Err ( Error :: NewLine ) ) ;
1110- let end = bytes. as_ref ( ) . as_ptr ( ) as usize ;
1111- result = Ok ( Status :: Complete ( end - start) ) ;
1112- break ;
1113- }
1114- if b == b'\n' {
1115- let end = bytes. as_ref ( ) . as_ptr ( ) as usize ;
1116- result = Ok ( Status :: Complete ( end - start) ) ;
1117- break ;
1118- }
1119- if !is_header_name_token ( b) {
1120- if config. allow_space_before_first_header_name
1121- && autoshrink. num_headers == 0
1122- && ( b == b' ' || b == b'\t' )
1123- {
1124- //advance past white space and then try parsing header again
1125- while let Some ( peek) = bytes. peek ( ) {
1126- if peek == b' ' || peek == b'\t' {
1127- next ! ( bytes) ;
1128- } else {
1129- break ;
1124+ if b == b':' {
1125+ break ' name name;
1126+ }
1127+
1128+ if config. allow_spaces_after_header_name {
1129+ while b == b' ' || b == b'\t' {
1130+ b = next ! ( bytes) ;
1131+
1132+ if b == b':' {
1133+ bytes. slice ( ) ;
1134+ break ' name name;
1135+ }
11301136 }
11311137 }
1132- bytes. slice ( ) ;
1133- continue ' headers;
1134- } else {
1135- handle_invalid_char ! ( bytes, b, HeaderName ) ;
1136- }
1137- }
11381138
1139- #[ allow( clippy:: never_loop) ]
1140- // parse header name until colon
1141- let header_name: & str = ' name: loop {
1142- simd:: match_header_name_vectored ( bytes) ;
1143- let mut b = next ! ( bytes) ;
1144-
1145- // SAFETY: previously bumped by 1 with next! -> always safe.
1146- let bslice = unsafe { bytes. slice_skip ( 1 ) } ;
1147- // SAFETY: previous call to match_header_name_vectored ensured all bytes are valid
1148- // header name chars, and as such also valid utf-8.
1149- let name = unsafe { str:: from_utf8_unchecked ( bslice) } ;
1150-
1151- if b == b':' {
1152- break ' name name;
1153- }
1139+ break ' header Error :: HeaderName ;
1140+ } ;
11541141
1155- if config. allow_spaces_after_header_name {
1156- while b == b' ' || b == b'\t' {
1142+ #[ allow( clippy:: never_loop) ]
1143+ let value_slice = ' value: loop {
1144+ // eat white space between colon and value
1145+ ' whitespace_after_colon: loop {
11571146 b = next ! ( bytes) ;
1158-
1159- if b == b':' {
1147+ if b == b' ' || b == b'\t' {
11601148 bytes. slice ( ) ;
1161- break ' name name;
1149+ continue ' whitespace_after_colon;
1150+ }
1151+ if is_header_value_token ( b) {
1152+ break ' whitespace_after_colon;
11621153 }
1163- }
1164- }
11651154
1166- handle_invalid_char ! ( bytes, b, HeaderName ) ;
1167- } ;
1155+ if b == b'\r' {
1156+ expect ! ( bytes. next( ) == b'\n' => Err ( Error :: HeaderValue ) ) ;
1157+ } else if b != b'\n' {
1158+ break ' header Error :: HeaderValue ;
1159+ }
11681160
1169- let mut b ;
1161+ maybe_continue_after_obsolete_line_folding ! ( bytes , ' whitespace_after_colon ) ;
11701162
1171- #[ allow( clippy:: never_loop) ]
1172- let value_slice = ' value: loop {
1173- // eat white space between colon and value
1174- ' whitespace_after_colon: loop {
1175- b = next ! ( bytes) ;
1176- if b == b' ' || b == b'\t' {
1177- bytes. slice ( ) ;
1178- continue ' whitespace_after_colon;
1179- }
1180- if is_header_value_token ( b) {
1181- break ' whitespace_after_colon;
1182- }
1163+ let whitespace_slice = bytes. slice ( ) ;
11831164
1184- if b == b'\r' {
1185- expect ! ( bytes. next( ) == b'\n' => Err ( Error :: HeaderValue ) ) ;
1186- } else if b != b'\n' {
1187- handle_invalid_char ! ( bytes, b, HeaderValue ) ;
1165+ // This produces an empty slice that points to the beginning
1166+ // of the whitespace.
1167+ break ' value & whitespace_slice[ 0 ..0 ] ;
11881168 }
11891169
1190- maybe_continue_after_obsolete_line_folding ! ( bytes, ' whitespace_after_colon) ;
1191-
1192- let whitespace_slice = bytes. slice ( ) ;
1170+ ' value_lines: loop {
1171+ // parse value till EOL
11931172
1194- // This produces an empty slice that points to the beginning
1195- // of the whitespace.
1196- break ' value & whitespace_slice[ 0 ..0 ] ;
1197- }
1173+ simd:: match_header_value_vectored ( bytes) ;
1174+ b = next ! ( bytes) ;
11981175
1199- ' value_lines: loop {
1200- // parse value till EOL
1176+ //found_ctl
1177+ let skip = if b == b'\r' {
1178+ expect ! ( bytes. next( ) == b'\n' => Err ( Error :: HeaderValue ) ) ;
1179+ 2
1180+ } else if b == b'\n' {
1181+ 1
1182+ } else {
1183+ break ' header Error :: HeaderValue ;
1184+ } ;
12011185
1202- simd:: match_header_value_vectored ( bytes) ;
1203- let b = next ! ( bytes) ;
1186+ maybe_continue_after_obsolete_line_folding ! ( bytes, ' value_lines) ;
12041187
1205- //found_ctl
1206- let skip = if b == b'\r' {
1207- expect ! ( bytes. next( ) == b'\n' => Err ( Error :: HeaderValue ) ) ;
1208- 2
1209- } else if b == b'\n' {
1210- 1
1211- } else {
1212- handle_invalid_char ! ( bytes, b, HeaderValue ) ;
1213- } ;
1188+ // SAFETY: having just checked that a newline exists, it's safe to skip it.
1189+ unsafe {
1190+ break ' value bytes. slice_skip ( skip) ;
1191+ }
1192+ }
1193+ } ;
12141194
1215- maybe_continue_after_obsolete_line_folding ! ( bytes, ' value_lines) ;
1195+ let uninit_header = match iter. next ( ) {
1196+ Some ( header) => header,
1197+ None => break ' headers
1198+ } ;
12161199
1217- // SAFETY: having just checked that a newline exists, it's safe to skip it.
1218- unsafe {
1219- break ' value bytes. slice_skip ( skip) ;
1220- }
1221- }
1222- } ;
1200+ // trim trailing whitespace in the header
1201+ let header_value = if let Some ( last_visible) = value_slice
1202+ . iter ( )
1203+ . rposition ( |b| * b != b' ' && * b != b'\t' && * b != b'\r' && * b != b'\n' )
1204+ {
1205+ // There is at least one non-whitespace character.
1206+ & value_slice[ 0 ..last_visible+1 ]
1207+ } else {
1208+ // There is no non-whitespace character. This can only happen when value_slice is
1209+ // empty.
1210+ value_slice
1211+ } ;
12231212
1224- let uninit_header = match iter. next ( ) {
1225- Some ( header) => header,
1226- None => break ' headers
1213+ * uninit_header = MaybeUninit :: new ( Header {
1214+ name : header_name,
1215+ value : header_value,
1216+ } ) ;
1217+ autoshrink. num_headers += 1 ;
1218+ continue ' headers;
12271219 } ;
12281220
1229- // trim trailing whitespace in the header
1230- let header_value = if let Some ( last_visible) = value_slice
1231- . iter ( )
1232- . rposition ( |b| * b != b' ' && * b != b'\t' && * b != b'\r' && * b != b'\n' )
1233- {
1234- // There is at least one non-whitespace character.
1235- & value_slice[ 0 ..last_visible+1 ]
1236- } else {
1237- // There is no non-whitespace character. This can only happen when value_slice is
1238- // empty.
1239- value_slice
1240- } ;
1221+ // The header contains an invalid character. Reject the header if
1222+ // `ignore_invalid_headers_in_responses` is false; otherwise find the
1223+ // end of the current line and resume parsing on the next one.
1224+ if !config. ignore_invalid_headers {
1225+ return Err ( invalid_header_err) ;
1226+ }
12411227
1242- * uninit_header = MaybeUninit :: new ( Header {
1243- name : header_name,
1244- value : header_value,
1245- } ) ;
1246- autoshrink. num_headers += 1 ;
1228+ loop {
1229+ if b == b'\r' {
1230+ expect ! ( bytes. next( ) == b'\n' => Err ( invalid_header_err) ) ;
1231+ break ;
1232+ }
1233+ if b == b'\n' {
1234+ break ;
1235+ }
1236+ if b == b'\0' {
1237+ return Err ( invalid_header_err) ;
1238+ }
1239+ b = next ! ( bytes) ;
1240+ }
1241+ bytes. slice ( ) ;
12471242 }
12481243
12491244 result
0 commit comments