Extracts out authority validation into a separate static method. This can then be used as a replacement for a similar function in nghttp2. PiperOrigin-RevId: 500812383
diff --git a/quiche/http2/adapter/header_validator.cc b/quiche/http2/adapter/header_validator.cc index 67d543a..e4874f2 100644 --- a/quiche/http2/adapter/header_validator.cc +++ b/quiche/http2/adapter/header_validator.cc
@@ -246,6 +246,12 @@ return false; } +/* static */ +bool HeaderValidator::IsValidAuthority(absl::string_view authority) { + static const CharMap valid_chars = BuildValidCharMap(kValidAuthorityChars); + return AllCharsInMap(authority, valid_chars); +} + HeaderValidator::ContentLengthStatus HeaderValidator::HandleContentLength( absl::string_view value) { if (value.empty()) { @@ -278,8 +284,7 @@ // Returns whether `authority` contains only characters from the `host` ABNF // from RFC 3986 section 3.2.2. bool HeaderValidator::ValidateAndSetAuthority(absl::string_view authority) { - static const CharMap valid_chars = BuildValidCharMap(kValidAuthorityChars); - if (!AllCharsInMap(authority, valid_chars)) { + if (!IsValidAuthority(authority)) { return false; } if (authority_.has_value() && authority != authority_.value()) {
diff --git a/quiche/http2/adapter/header_validator.h b/quiche/http2/adapter/header_validator.h index 096f76f..6095c7d 100644 --- a/quiche/http2/adapter/header_validator.h +++ b/quiche/http2/adapter/header_validator.h
@@ -25,6 +25,9 @@ // present for the given header type. bool FinishHeaderBlock(HeaderType type) override; + // Returns whether `authority` is valid according to RFC 3986 Section 3.2. + static bool IsValidAuthority(absl::string_view authority); + private: enum ContentLengthStatus { CONTENT_LENGTH_OK,
diff --git a/quiche/http2/adapter/header_validator_test.cc b/quiche/http2/adapter/header_validator_test.cc index 6e446f2..a329f12 100644 --- a/quiche/http2/adapter/header_validator_test.cc +++ b/quiche/http2/adapter/header_validator_test.cc
@@ -150,45 +150,59 @@ for (absl::string_view key : {":authority", "host"}) { // These characters should be allowed. (Not exhaustive.) for (const absl::string_view c : {"1", "-", "!", ":", "+", "=", ","}) { + const std::string value = absl::StrCat("ho", c, "st.example.com"); + EXPECT_TRUE(HeaderValidator::IsValidAuthority(value)); + HeaderValidator v; v.StartHeaderBlock(); - HeaderValidator::HeaderStatus status = - v.ValidateSingleHeader(key, absl::StrCat("ho", c, "st.example.com")); + HeaderValidator::HeaderStatus status = v.ValidateSingleHeader(key, value); EXPECT_EQ(HeaderValidator::HEADER_OK, status); } // These should not. for (const absl::string_view c : {"\r", "\n", "|", "\\", "`"}) { + const std::string value = absl::StrCat("ho", c, "st.example.com"); + EXPECT_FALSE(HeaderValidator::IsValidAuthority(value)); + HeaderValidator v; v.StartHeaderBlock(); - HeaderValidator::HeaderStatus status = - v.ValidateSingleHeader(key, absl::StrCat("ho", c, "st.example.com")); + HeaderValidator::HeaderStatus status = v.ValidateSingleHeader(key, value); EXPECT_EQ(HeaderValidator::HEADER_FIELD_INVALID, status); } { // IPv4 example + const std::string value = "123.45.67.89"; + EXPECT_TRUE(HeaderValidator::IsValidAuthority(value)); + HeaderValidator v; v.StartHeaderBlock(); - HeaderValidator::HeaderStatus status = - v.ValidateSingleHeader(key, "123.45.67.89"); + HeaderValidator::HeaderStatus status = v.ValidateSingleHeader(key, value); EXPECT_EQ(HeaderValidator::HEADER_OK, status); } { // IPv6 examples + const std::string value1 = "2001:0db8:85a3:0000:0000:8a2e:0370:7334"; + EXPECT_TRUE(HeaderValidator::IsValidAuthority(value1)); + HeaderValidator v; v.StartHeaderBlock(); - HeaderValidator::HeaderStatus status = v.ValidateSingleHeader( - key, "2001:0db8:85a3:0000:0000:8a2e:0370:7334"); + HeaderValidator::HeaderStatus status = + v.ValidateSingleHeader(key, value1); EXPECT_EQ(HeaderValidator::HEADER_OK, status); + + const std::string value2 = "[::1]:80"; + EXPECT_TRUE(HeaderValidator::IsValidAuthority(value2)); HeaderValidator v2; v2.StartHeaderBlock(); - status = v2.ValidateSingleHeader(key, "[::1]:80"); + status = v2.ValidateSingleHeader(key, value2); EXPECT_EQ(HeaderValidator::HEADER_OK, status); } { // Empty field + EXPECT_TRUE(HeaderValidator::IsValidAuthority("")); + HeaderValidator v; v.StartHeaderBlock(); HeaderValidator::HeaderStatus status = v.ValidateSingleHeader(key, "");