Forráskód Böngészése

flag out-of-range Content-Length in get_header_value_u64

Sayed Kaif 2 hónapja
szülő
commit
982235c0a9
2 módosított fájl, 32 hozzáadás és 1 törlés
  1. 12 1
      httplib.h
  2. 20 0
      test/test.cc

+ 12 - 1
httplib.h

@@ -2957,7 +2957,18 @@ inline size_t get_header_value_u64(const Headers &headers,
   std::advance(it, static_cast<ssize_t>(id));
   if (it != rng.second) {
     if (is_numeric(it->second)) {
-      return static_cast<size_t>(std::strtoull(it->second.data(), nullptr, 10));
+      errno = 0;
+      auto val = std::strtoull(it->second.data(), nullptr, 10);
+      auto result = static_cast<size_t>(val);
+      // strtoull saturates to ULLONG_MAX on overflow, and the size_t cast
+      // truncates a value that doesn't fit (a Content-Length above 2^32 wraps
+      // to a small length on 32-bit builds). Either way the framing length
+      // would be wrong, so flag it rather than return a bogus size.
+      if (errno == ERANGE || static_cast<unsigned long long>(result) != val) {
+        is_invalid_value = true;
+        return (std::numeric_limits<size_t>::max)();
+      }
+      return result;
     } else {
       is_invalid_value = true;
     }

+ 20 - 0
test/test.cc

@@ -1300,6 +1300,26 @@ TEST(GetHeaderValueTest, RegularInvalidValueInt) {
   EXPECT_TRUE(is_invalid_value);
 }
 
+TEST(GetHeaderValueTest, OutOfRangeValueInt) {
+  // An all-digit value that overflows size_t must be reported as invalid, not
+  // silently saturated/truncated: strtoull would otherwise return ULLONG_MAX
+  // (or, on 32-bit builds, the cast would wrap a large length to a small one),
+  // leaving the framing length wrong while is_invalid_value stayed false.
+  Headers headers = {{"Content-Length", "99999999999999999999999999"}};
+  auto is_invalid_value = false;
+  detail::get_header_value_u64(headers, "Content-Length", 0, 0,
+                               is_invalid_value);
+  EXPECT_TRUE(is_invalid_value);
+
+  // A well-formed length is unaffected.
+  Headers ok = {{"Content-Length", "1234"}};
+  is_invalid_value = false;
+  auto val = detail::get_header_value_u64(ok, "Content-Length", 0, 0,
+                                          is_invalid_value);
+  EXPECT_EQ(1234ull, val);
+  EXPECT_FALSE(is_invalid_value);
+}
+
 TEST(GetHeaderValueTest, Range) {
   {
     Headers headers = {make_range_header({{1, -1}})};