Hash case-insensitive keys in a loop

case_ignore::hash recursed once per character of the key, and trailer
field names from the wire reach it, so a long one could overflow the
stack of a build that keeps the recursion (-O0). Hash in a loop instead,
which gives the same values.
This commit is contained in:
yhirose committed 2026-10-16 16:39:00 -04:00
1 parent 6acdc6255d
commit 82e28aa4f3
2 files changed
+16 -11

No files matched your search

+7 -11
View File
@@ -676,17 +676,13 @@ struct equal_to {
struct hash { struct hash {
size_t operator()(const std::string &key) const { size_t operator()(const std::string &key) const {
return hash_core(key.data(), key.size(), 0); size_t h = 0;
} for (auto c : key) {
// Unsets the 6 high bits of h, therefore no overflow happens
size_t hash_core(const char *s, size_t l, size_t h) const { h = (((std::numeric_limits<size_t>::max)() >> 6) & h * 33) ^
return (l == 0) ? h static_cast<unsigned char>(to_lower(c));
: hash_core(s + 1, l - 1, }
// Unsets the 6 high bits of h, therefore no return h;
// overflow happens
(((std::numeric_limits<size_t>::max)() >> 6) &
h * 33) ^
static_cast<unsigned char>(to_lower(*s)));
} }
}; };
+9
View File
@@ -643,6 +643,15 @@ TEST(FileExtensionTest, TakesTheAlphanumericSuffix) {
EXPECT_EQ(long_ext, detail::file_extension("a." + long_ext)); EXPECT_EQ(long_ext, detail::file_extension("a." + long_ext));
} }
TEST(CaseIgnoreHashTest, IgnoresCaseAndTakesLongKeys) {
detail::case_ignore::hash hash;
EXPECT_EQ(hash("Content-Type"), hash("content-TYPE"));
EXPECT_NE(hash("Content-Type"), hash("Content-Length"));
// Long enough to overflow the stack if hashed one call per character.
EXPECT_EQ(hash(std::string(1 << 20, 'A')), hash(std::string(1 << 20, 'a')));
}
TEST(FindContentTypeTest, ComparesWholeExtensions) { TEST(FindContentTypeTest, ComparesWholeExtensions) {
EXPECT_EQ("text/html", detail::find_content_type("/a.html", {}, "")); EXPECT_EQ("text/html", detail::find_content_type("/a.html", {}, ""));
EXPECT_EQ("image/svg+xml", detail::find_content_type("/a.svg", {}, "")); EXPECT_EQ("image/svg+xml", detail::find_content_type("/a.svg", {}, ""));