Răsfoiți Sursa

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.
yhirose 5 luni în urmă
părinte
comite
92aecf85d8

+ 10 - 1
httplib.h

@@ -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
test/fuzzing/corpus/clusterfuzz-testcase-minimized-header_parser_fuzzer-4645558454386688


+ 7 - 0
test/test.cc

@@ -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;