Extracts out a helper method to determine whether a chunk extension character is valid. There is a very small change in behavior, in that the `last_char_was_slash_r_` member will be updated even if `HttpValidationPolicy::disallow_lone_cr_in_chunk_extension` is not set. Protected by refactoring, no functional change intended; not protected. PiperOrigin-RevId: 704499760
diff --git a/quiche/balsa/balsa_frame.cc b/quiche/balsa/balsa_frame.cc index c93ff94..8098d36 100644 --- a/quiche/balsa/balsa_frame.cc +++ b/quiche/balsa/balsa_frame.cc
@@ -1249,22 +1249,12 @@ return current - input; } const char c = *current; - if (http_validation_policy_.disallow_lone_cr_in_chunk_extension) { - // This is a CR character and the next one is not LF. - const bool cr_followed_by_non_lf = - c == '\r' && current + 1 < end && *(current + 1) != '\n'; - // The last character processed by the last ProcessInput() call was - // CR, this is the first character of the current ProcessInput() - // call, and it is not LF. - const bool previous_cr_followed_by_non_lf = - last_char_was_slash_r_ && current == input && c != '\n'; - if (cr_followed_by_non_lf || previous_cr_followed_by_non_lf) { - HandleError(BalsaFrameEnums::INVALID_CHUNK_EXTENSION); - return current - input; - } - if (current + 1 == end) { - last_char_was_slash_r_ = c == '\r'; - } + if (!IsValidChunkExtensionCharacter(c, current, input, end)) { + HandleError(BalsaFrameEnums::INVALID_CHUNK_EXTENSION); + return current - input; + } + if (current + 1 == end) { + last_char_was_slash_r_ = c == '\r'; } if (c == '\r' || c == '\n') { extensions_length = (extensions_start == current) @@ -1501,6 +1491,25 @@ HandleError(BalsaFrameEnums::HEADERS_TOO_LONG); } +bool BalsaFrame::IsValidChunkExtensionCharacter(char c, const char* current, + const char* begin, + const char* end) { + if (http_validation_policy_.disallow_lone_cr_in_chunk_extension) { + // This is a CR character and the next one is not LF. + const bool cr_followed_by_non_lf = + c == '\r' && current + 1 < end && *(current + 1) != '\n'; + // The last character processed by the last ProcessInput() call was + // CR, this is the first character of the current ProcessInput() + // call, and it is not LF. + const bool previous_cr_followed_by_non_lf = + last_char_was_slash_r_ && current == begin && c != '\n'; + if (cr_followed_by_non_lf || previous_cr_followed_by_non_lf) { + return false; + } + } + return true; +} + const int32_t BalsaFrame::kValidTerm1; const int32_t BalsaFrame::kValidTerm1Mask; const int32_t BalsaFrame::kValidTerm2;
diff --git a/quiche/balsa/balsa_frame.h b/quiche/balsa/balsa_frame.h index 73c266d..4902ab8 100644 --- a/quiche/balsa/balsa_frame.h +++ b/quiche/balsa/balsa_frame.h
@@ -266,6 +266,10 @@ void HandleHeadersTooLongError(); + inline bool IsValidChunkExtensionCharacter(char c, const char* current, + const char* begin, + const char* end); + BalsaVisitorInterface* visitor_; BalsaHeaders* continue_headers_; // This is not reset to nullptr in Reset(). BalsaHeaders* headers_; // This is not reset to nullptr in Reset().