diff --git a/httplib.h b/httplib.h index 36b77ed0..ab8fc07f 100644 --- a/httplib.h +++ b/httplib.h @@ -2957,7 +2957,18 @@ inline size_t get_header_value_u64(const Headers &headers, std::advance(it, static_cast(id)); if (it != rng.second) { if (is_numeric(it->second)) { - return static_cast(std::strtoull(it->second.data(), nullptr, 10)); + errno = 0; + auto val = std::strtoull(it->second.data(), nullptr, 10); + auto result = static_cast(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(result) != val) { + is_invalid_value = true; + return (std::numeric_limits::max)(); + } + return result; } else { is_invalid_value = true; } diff --git a/test/test.cc b/test/test.cc index e0f0d0f8..44794c4a 100644 --- a/test/test.cc +++ b/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}})};