Move IsInvalidHeaderKeyChar() from balsa_frame.cc anonymous namespace to header_properties.
This is for consistency with IsInvalidHeaderChar().
Also, add tests for IsInvalidHeaderKeyChar(), and extend tests for IsInvalidHeaderChar().
PiperOrigin-RevId: 446704033
diff --git a/quiche/common/balsa/balsa_frame.cc b/quiche/common/balsa/balsa_frame.cc
index b148a42..cb7db65 100644
--- a/quiche/common/balsa/balsa_frame.cc
+++ b/quiche/common/balsa/balsa_frame.cc
@@ -34,22 +34,6 @@
constexpr absl::string_view kIdentity = "identity";
constexpr absl::string_view kTransferEncoding = "transfer-encoding";
-std::array<bool, 256> buildInvalidHeaderKeyCharLookupTable() {
- std::array<bool, 256> invalidCharTable;
- invalidCharTable.fill(false);
- for (uint8_t c : BalsaFrame::kInvalidHeaderKeyCharList) {
- invalidCharTable[c] = true;
- }
- return invalidCharTable;
-}
-
-inline bool IsInvalidHeaderKeyChar(uint8_t c) {
- static const std::array<bool, 256> invalidHeaderKeyCharTable =
- buildInvalidHeaderKeyCharLookupTable();
-
- return invalidHeaderKeyCharTable[c];
-}
-
} // namespace
void BalsaFrame::Reset() {
@@ -408,7 +392,7 @@
break;
}
- if (IsInvalidHeaderKeyChar(*current)) {
+ if (header_properties::IsInvalidHeaderKeyChar(*current)) {
// Generally invalid characters were found earlier.
HandleError(is_trailer
? BalsaFrameEnums::INVALID_TRAILER_NAME_CHARACTER
diff --git a/quiche/common/balsa/balsa_frame.h b/quiche/common/balsa/balsa_frame.h
index 5b54272..2711ac0 100644
--- a/quiche/common/balsa/balsa_frame.h
+++ b/quiche/common/balsa/balsa_frame.h
@@ -34,17 +34,6 @@
typedef BalsaHeaders::HeaderLines HeaderLines;
typedef BalsaHeaders::HeaderTokenList HeaderTokenList;
- // Only applied in strict mode.
- // Control characters, including \t, \n, \r, as well as space and
- // (),/;<=>?@[\]{} and \x7f (see
- // https://tools.ietf.org/html/rfc7230#section-3.2.6).
- static constexpr char kInvalidHeaderKeyCharList[] = {
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
- 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13,
- 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D,
- 0x1E, 0x1F, ' ', '(', ')', ',', '/', ';', '<', '=',
- '>', '?', '@', '[', '\\', ']', '{', '}', 0x7f};
-
enum class InvalidCharsLevel { kOff, kWarning, kError };
// TODO(fenix): get rid of the 'kValidTerm*' stuff by using the 'since last
diff --git a/quiche/common/balsa/header_properties.cc b/quiche/common/balsa/header_properties.cc
index 6722239..561fe7a 100644
--- a/quiche/common/balsa/header_properties.cc
+++ b/quiche/common/balsa/header_properties.cc
@@ -59,6 +59,15 @@
});
}
+std::array<bool, 256> buildInvalidHeaderKeyCharLookupTable() {
+ std::array<bool, 256> invalidCharTable;
+ invalidCharTable.fill(false);
+ for (uint8_t c : kInvalidHeaderKeyCharList) {
+ invalidCharTable[c] = true;
+ }
+ return invalidCharTable;
+}
+
std::array<bool, 256> buildInvalidCharLookupTable() {
std::array<bool, 256> invalidCharTable;
invalidCharTable.fill(false);
@@ -76,6 +85,13 @@
return multivalued_headers->contains(header);
}
+bool IsInvalidHeaderKeyChar(uint8_t c) {
+ static const std::array<bool, 256> invalidHeaderKeyCharTable =
+ buildInvalidHeaderKeyCharLookupTable();
+
+ return invalidHeaderKeyCharTable[c];
+}
+
bool IsInvalidHeaderChar(uint8_t c) {
static const std::array<bool, 256> invalidCharTable =
buildInvalidCharLookupTable();
diff --git a/quiche/common/balsa/header_properties.h b/quiche/common/balsa/header_properties.h
index 6b43763..2539a90 100644
--- a/quiche/common/balsa/header_properties.h
+++ b/quiche/common/balsa/header_properties.h
@@ -18,6 +18,17 @@
// be perfectly reliable in practice.
QUICHE_EXPORT_PRIVATE bool IsMultivaluedHeader(absl::string_view header);
+// An array of characters that are invalid in HTTP header field names.
+// These are control characters, including \t, \n, \r, as well as space and
+// (),/;<=>?@[\]{} and \x7f (see
+// https://tools.ietf.org/html/rfc7230#section-3.2.6).
+inline constexpr char kInvalidHeaderKeyCharList[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
+ 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13,
+ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D,
+ 0x1E, 0x1F, ' ', '(', ')', ',', '/', ';', '<', '=',
+ '>', '?', '@', '[', '\\', ']', '{', '}', 0x7f};
+
// An array of characters that are invalid in HTTP header field values,
// according to RFC 7230 Section 3.2. Valid low characters not in this array
// are \t (0x09), \n (0x0A), and \r (0x0D).
@@ -27,6 +38,8 @@
0x0C, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x7F};
+// Returns true if the given `c` is invalid in a header field name.
+QUICHE_EXPORT_PRIVATE bool IsInvalidHeaderKeyChar(uint8_t c);
// Returns true if the given `c` is invalid in a header field or the `value` has
// invalid characters.
QUICHE_EXPORT_PRIVATE bool IsInvalidHeaderChar(uint8_t c);
diff --git a/quiche/common/balsa/header_properties_test.cc b/quiche/common/balsa/header_properties_test.cc
index ffb6b83..c9dfc6d 100644
--- a/quiche/common/balsa/header_properties_test.cc
+++ b/quiche/common/balsa/header_properties_test.cc
@@ -18,17 +18,48 @@
EXPECT_FALSE(IsMultivaluedHeader("Content-Length"));
}
+TEST(HeaderPropertiesTest, IsInvalidHeaderKeyChar) {
+ EXPECT_TRUE(IsInvalidHeaderKeyChar(0x00));
+ EXPECT_TRUE(IsInvalidHeaderKeyChar(0x06));
+ EXPECT_TRUE(IsInvalidHeaderKeyChar(0x09));
+ EXPECT_TRUE(IsInvalidHeaderKeyChar(0x1F));
+ EXPECT_TRUE(IsInvalidHeaderKeyChar(0x7F));
+ EXPECT_TRUE(IsInvalidHeaderKeyChar(' '));
+ EXPECT_TRUE(IsInvalidHeaderKeyChar('\t'));
+ EXPECT_TRUE(IsInvalidHeaderKeyChar('\r'));
+ EXPECT_TRUE(IsInvalidHeaderKeyChar('\n'));
+
+ EXPECT_FALSE(IsInvalidHeaderKeyChar('a'));
+ EXPECT_FALSE(IsInvalidHeaderKeyChar('B'));
+ EXPECT_FALSE(IsInvalidHeaderKeyChar('7'));
+ EXPECT_FALSE(IsInvalidHeaderKeyChar(0x42));
+ EXPECT_FALSE(IsInvalidHeaderChar(0x7D));
+}
+
TEST(HeaderPropertiesTest, IsInvalidHeaderChar) {
EXPECT_TRUE(IsInvalidHeaderChar(0x00));
EXPECT_TRUE(IsInvalidHeaderChar(0x06));
EXPECT_TRUE(IsInvalidHeaderChar(0x1F));
EXPECT_TRUE(IsInvalidHeaderChar(0x7F));
+ EXPECT_FALSE(IsInvalidHeaderChar(0x09));
EXPECT_FALSE(IsInvalidHeaderChar(' '));
EXPECT_FALSE(IsInvalidHeaderChar('\t'));
EXPECT_FALSE(IsInvalidHeaderChar('\r'));
EXPECT_FALSE(IsInvalidHeaderChar('\n'));
+ EXPECT_FALSE(IsInvalidHeaderChar('a'));
+ EXPECT_FALSE(IsInvalidHeaderChar('B'));
+ EXPECT_FALSE(IsInvalidHeaderChar('7'));
EXPECT_FALSE(IsInvalidHeaderChar(0x42));
+ EXPECT_FALSE(IsInvalidHeaderChar(0x7D));
+}
+
+TEST(HeaderPropertiesTest, KeyMoreRestrictiveThanValue) {
+ for (int c = 0; c < 255; ++c) {
+ if (IsInvalidHeaderChar(c)) {
+ EXPECT_TRUE(IsInvalidHeaderKeyChar(c)) << c;
+ }
+ }
}
TEST(HeaderPropertiesTest, HasInvalidHeaderChars) {