Adds `quiche::header_properties::HasInvalidPathChar()`.
Returns true if any character is not in the set allowed by RFC 3986 Sections 3.3 or 3.4.
Protected by new code, not yet used; not protected.
PiperOrigin-RevId: 662548538
diff --git a/quiche/balsa/header_properties.cc b/quiche/balsa/header_properties.cc
index 53978df..8d24172 100644
--- a/quiche/balsa/header_properties.cc
+++ b/quiche/balsa/header_properties.cc
@@ -86,6 +86,15 @@
return invalidCharTable;
}
+std::array<bool, 256> buildInvalidPathCharLookupTable() {
+ std::array<bool, 256> invalidCharTable;
+ invalidCharTable.fill(true);
+ for (uint8_t c : kValidPathCharList) {
+ invalidCharTable[c] = false;
+ }
+ return invalidCharTable;
+}
+
} // anonymous namespace
bool IsMultivaluedHeader(absl::string_view header) {
@@ -124,4 +133,15 @@
return false;
}
+bool HasInvalidPathChar(absl::string_view value) {
+ static const std::array<bool, 256> invalidCharTable =
+ buildInvalidPathCharLookupTable();
+ for (const char c : value) {
+ if (invalidCharTable[c]) {
+ return true;
+ }
+ }
+ return false;
+}
+
} // namespace quiche::header_properties
diff --git a/quiche/balsa/header_properties.h b/quiche/balsa/header_properties.h
index 5a8cc24..7bee5f7 100644
--- a/quiche/balsa/header_properties.h
+++ b/quiche/balsa/header_properties.h
@@ -48,6 +48,12 @@
0x0C, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x7F};
+// The set of characters allowed in the Path and Query components of a URI, as
+// described in RFC 3986 Sections 3.3 and 3.4.
+inline constexpr char kValidPathCharList[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~%!$&'()*"
+ "+,;=:@/?";
+
// Returns true if the given `c` is invalid in a header field name. The first
// version is spec compliant, the second one incorrectly allows '"'.
QUICHE_EXPORT bool IsInvalidHeaderKeyChar(uint8_t c);
@@ -57,6 +63,10 @@
QUICHE_EXPORT bool IsInvalidHeaderChar(uint8_t c);
QUICHE_EXPORT bool HasInvalidHeaderChars(absl::string_view value);
+// Returns true if `value` contains a character not allowed in a path or query
+// component of a URI.
+QUICHE_EXPORT bool HasInvalidPathChar(absl::string_view value);
+
} // namespace quiche::header_properties
#endif // QUICHE_BALSA_HEADER_PROPERTIES_H_
diff --git a/quiche/balsa/header_properties_test.cc b/quiche/balsa/header_properties_test.cc
index 1930354..253c97c 100644
--- a/quiche/balsa/header_properties_test.cc
+++ b/quiche/balsa/header_properties_test.cc
@@ -100,5 +100,19 @@
EXPECT_FALSE(HasInvalidHeaderChars("\x42 is a nice character"));
}
+TEST(HeaderPropertiesTest, HasInvalidPathChar) {
+ EXPECT_FALSE(HasInvalidPathChar(""));
+ EXPECT_FALSE(HasInvalidPathChar("/"));
+ EXPECT_FALSE(HasInvalidPathChar("invalid_path/but/valid/chars"));
+ EXPECT_FALSE(HasInvalidPathChar("/path/with?query;fragment"));
+ EXPECT_FALSE(HasInvalidPathChar("/path2.fun/my_site-root/!&$=,+*()/wow"));
+
+ EXPECT_TRUE(HasInvalidPathChar("/path with spaces"));
+ EXPECT_TRUE(HasInvalidPathChar("/path\rwith\tother\nwhitespace"));
+ EXPECT_TRUE(HasInvalidPathChar("/square[brackets]not/allowed"));
+ EXPECT_TRUE(HasInvalidPathChar("/backtick`"));
+ EXPECT_TRUE(HasInvalidPathChar("/angle<brackets>also/bad"));
+}
+
} // namespace
} // namespace quiche::header_properties::test