Fix OSS-Fuzz #508087118: avoid stack overflow in str2tag

str2tag_core is recursive (one frame per character), so a long runtime
input such as a fuzzer-supplied Content-Type would overflow the stack.
Rewrite the runtime entry point str2tag() iteratively while keeping the
recursive constexpr str2tag_core for compile-time UDL evaluation. The
hash output is unchanged for all inputs.
This commit is contained in:
yhirose
2026-05-01 21:39:46 +09:00
parent b223e29778
commit 92aecf85d8
3 changed files with 17 additions and 1 deletions
+10 -1
View File
@@ -6374,7 +6374,16 @@ inline constexpr unsigned int str2tag_core(const char *s, size_t l,
}
inline unsigned int str2tag(const std::string &s) {
return str2tag_core(s.data(), s.size(), 0);
// Iterative form of str2tag_core: the recursive constexpr version is kept
// for compile-time UDL evaluation of short string literals, but at runtime
// we may receive arbitrarily long inputs (e.g. fuzzed Content-Type) that
// would blow the stack with one frame per character.
unsigned int h = 0;
for (auto c : s) {
h = (((std::numeric_limits<unsigned int>::max)() >> 6) & h * 33) ^
static_cast<unsigned char>(c);
}
return h;
}
namespace udl {
+7
View File
@@ -767,6 +767,13 @@ TEST(ParseAcceptHeaderTest, InvalidCases) {
EXPECT_EQ(result[0], "text/*");
}
// Regression test for OSS-Fuzz #508087118: a long Content-Type ran str2tag
// recursively (one stack frame per character) and overflowed the stack.
TEST(Str2tagTest, LongInputDoesNotOverflowStack) {
std::string long_content_type(60000, 'x');
EXPECT_NO_THROW(detail::can_compress_content_type(long_content_type));
}
TEST(ParseAcceptHeaderTest, ContentTypesPopulatedAndInvalidHeaderHandling) {
Server svr;