mirror of
https://github.com/yhirose/cpp-httplib
synced 2026-06-08 18:30:49 +00:00
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:
@@ -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 {
|
||||
|
||||
BIN
Binary file not shown.
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user