diff --git a/httplib.h b/httplib.h index 3548e720..040482f8 100644 --- a/httplib.h +++ b/httplib.h @@ -771,6 +771,7 @@ inline from_chars_result from_chars(const char *first, const char *last, } if (p == last) { return {first, std::errc::invalid_argument}; } + auto radix = static_cast(base); T result = 0; for (; p != last; ++p) { char c = *p; @@ -786,10 +787,11 @@ inline from_chars_result from_chars(const char *first, const char *last, } if (digit < 0 || digit >= base) { break; } - if (result > ((std::numeric_limits::max)() - digit) / base) { + auto d = static_cast(digit); + if (result > ((std::numeric_limits::max)() - d) / radix) { return {p, std::errc::result_out_of_range}; } - result = result * base + digit; + result = result * radix + d; } if (p == first || (negative && p == first + 1)) { @@ -5376,6 +5378,12 @@ inline std::string from_i_to_hex(size_t n) { return ret; } +// A round trip rather than `n <= SIZE_MAX`, which is always true on 64-bit +// builds and trips -Wtautological-type-limit-compare. +inline bool fits_in_size_t(uint64_t n) { + return static_cast(static_cast(n)) == n; +} + inline std::string compute_etag(const FileStat &fs, const std::string &suffix = std::string()) { if (!fs.is_file()) { return std::string(); } @@ -5851,7 +5859,7 @@ inline FrameRead read_websocket_frame(Stream &strm, Opcode &opcode, // A max_len of 0 means no limit, as payload_max_length does, and a length // size_t cannot hold (32-bit builds) is refused either way. if ((max_len > 0 && payload_len > max_len) || - payload_len > (std::numeric_limits::max)()) { + !detail::fits_in_size_t(payload_len)) { return FrameRead::Fail; } @@ -6515,11 +6523,7 @@ inline bool mmap::open(const char *path) { // If the following line doesn't compile due to QuadPart, update Windows SDK. // See: // https://github.com/yhirose/cpp-httplib/issues/1903#issuecomment-2316520721 - if (static_cast(size.QuadPart) > - (std::numeric_limits::max)()) { - // `size_t` might be 32-bits, on 32-bits Windows. - return false; - } + if (!fits_in_size_t(static_cast(size.QuadPart))) { return false; } size_ = static_cast(size.QuadPart); hMapping_ = @@ -6551,8 +6555,7 @@ inline bool mmap::open(const char *path) { // Only a regular file has a size to serve, unlike a directory or a device. struct stat sb; if (fstat(fd_, &sb) == -1 || !S_ISREG(sb.st_mode) || - static_cast(sb.st_size) > - (std::numeric_limits::max)()) { + !fits_in_size_t(static_cast(sb.st_size))) { close(); return false; } diff --git a/test/test.cc b/test/test.cc index cdbd4167..7cc0665a 100644 --- a/test/test.cc +++ b/test/test.cc @@ -27910,8 +27910,8 @@ static socket_t connect_raw_websocket(int port, const std::string &path) { "\r\n"; std::string res; if (::connect(sock, reinterpret_cast(&addr), sizeof(addr)) == 0 && - ::send(sock, req.data(), static_cast(req.size()), 0) == - static_cast(req.size())) { + detail::send_socket(sock, req.data(), req.size(), 0) == + static_cast(req.size())) { char c; while (res.find("\r\n\r\n") == std::string::npos && ::recv(sock, &c, 1, 0) == 1) { @@ -27963,7 +27963,7 @@ TEST(WebSocketTest, AssemblesFragmentsAroundAPing) { auto frames = masked_frame(0x02, "Hel") + // Binary, more to come masked_frame(0x89, "p") + // FIN + Ping masked_frame(0x80, "lo"); // FIN + Continuation - ::send(sock, frames.data(), static_cast(frames.size()), 0); + detail::send_socket(sock, frames.data(), frames.size(), 0); for (int i = 0; i < 500 && !done; i++) { std::this_thread::sleep_for(std::chrono::milliseconds(10)); @@ -28033,7 +28033,7 @@ TEST(WebSocketTest, AnswersAMalformedCloseWithProtocolError) { auto sock = connect_raw_websocket(port, "/ws"); ASSERT_NE(INVALID_SOCKET, sock); auto frames = prefix + masked_frame(0x88, c.first); - ::send(sock, frames.data(), static_cast(frames.size()), 0); + detail::send_socket(sock, frames.data(), frames.size(), 0); std::string reply; char buf[256];