Просмотр исходного кода

Fix the warnings clang gives when building the tests

from_chars() mixed its int digit and base into the arithmetic of an
unsigned T, a sign conversion since Content-Length is parsed as size_t.
Convert both to T first.

Comparing a uint64_t with SIZE_MAX is always false on 64-bit builds,
so the WebSocket frame length and mmap size checks tripped
-Wtautological-type-limit-compare. fits_in_size_t() checks with a
round trip instead, and the Windows branch of mmap::open() uses it too.

The raw ::send() calls in the WebSocket tests passed an int length,
which POSIX takes as size_t. Use detail::send_socket(), which handles
both.
yhirose 2 дней назад
Родитель
Сommit
062666f3a1
2 измененных файлов с 17 добавлено и 14 удалено
  1. 13 10
      httplib.h
  2. 4 4
      test/test.cc

+ 13 - 10
httplib.h

@@ -771,6 +771,7 @@ inline from_chars_result<T> from_chars(const char *first, const char *last,
   }
   }
   if (p == last) { return {first, std::errc::invalid_argument}; }
   if (p == last) { return {first, std::errc::invalid_argument}; }
 
 
+  auto radix = static_cast<T>(base);
   T result = 0;
   T result = 0;
   for (; p != last; ++p) {
   for (; p != last; ++p) {
     char c = *p;
     char c = *p;
@@ -786,10 +787,11 @@ inline from_chars_result<T> from_chars(const char *first, const char *last,
     }
     }
 
 
     if (digit < 0 || digit >= base) { break; }
     if (digit < 0 || digit >= base) { break; }
-    if (result > ((std::numeric_limits<T>::max)() - digit) / base) {
+    auto d = static_cast<T>(digit);
+    if (result > ((std::numeric_limits<T>::max)() - d) / radix) {
       return {p, std::errc::result_out_of_range};
       return {p, std::errc::result_out_of_range};
     }
     }
-    result = result * base + digit;
+    result = result * radix + d;
   }
   }
 
 
   if (p == first || (negative && p == first + 1)) {
   if (p == first || (negative && p == first + 1)) {
@@ -5376,6 +5378,12 @@ inline std::string from_i_to_hex(size_t n) {
   return ret;
   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<uint64_t>(static_cast<size_t>(n)) == n;
+}
+
 inline std::string compute_etag(const FileStat &fs,
 inline std::string compute_etag(const FileStat &fs,
                                 const std::string &suffix = std::string()) {
                                 const std::string &suffix = std::string()) {
   if (!fs.is_file()) { return 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
   // 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.
   // size_t cannot hold (32-bit builds) is refused either way.
   if ((max_len > 0 && payload_len > max_len) ||
   if ((max_len > 0 && payload_len > max_len) ||
-      payload_len > (std::numeric_limits<size_t>::max)()) {
+      !detail::fits_in_size_t(payload_len)) {
     return FrameRead::Fail;
     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.
   // If the following line doesn't compile due to QuadPart, update Windows SDK.
   // See:
   // See:
   // https://github.com/yhirose/cpp-httplib/issues/1903#issuecomment-2316520721
   // https://github.com/yhirose/cpp-httplib/issues/1903#issuecomment-2316520721
-  if (static_cast<ULONGLONG>(size.QuadPart) >
-      (std::numeric_limits<decltype(size_)>::max)()) {
-    // `size_t` might be 32-bits, on 32-bits Windows.
-    return false;
-  }
+  if (!fits_in_size_t(static_cast<uint64_t>(size.QuadPart))) { return false; }
   size_ = static_cast<size_t>(size.QuadPart);
   size_ = static_cast<size_t>(size.QuadPart);
 
 
   hMapping_ =
   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.
   // Only a regular file has a size to serve, unlike a directory or a device.
   struct stat sb;
   struct stat sb;
   if (fstat(fd_, &sb) == -1 || !S_ISREG(sb.st_mode) ||
   if (fstat(fd_, &sb) == -1 || !S_ISREG(sb.st_mode) ||
-      static_cast<uint64_t>(sb.st_size) >
-          (std::numeric_limits<size_t>::max)()) {
+      !fits_in_size_t(static_cast<uint64_t>(sb.st_size))) {
     close();
     close();
     return false;
     return false;
   }
   }

+ 4 - 4
test/test.cc

@@ -27910,8 +27910,8 @@ static socket_t connect_raw_websocket(int port, const std::string &path) {
                     "\r\n";
                     "\r\n";
   std::string res;
   std::string res;
   if (::connect(sock, reinterpret_cast<sockaddr *>(&addr), sizeof(addr)) == 0 &&
   if (::connect(sock, reinterpret_cast<sockaddr *>(&addr), sizeof(addr)) == 0 &&
-      ::send(sock, req.data(), static_cast<int>(req.size()), 0) ==
-          static_cast<int>(req.size())) {
+      detail::send_socket(sock, req.data(), req.size(), 0) ==
+          static_cast<ssize_t>(req.size())) {
     char c;
     char c;
     while (res.find("\r\n\r\n") == std::string::npos &&
     while (res.find("\r\n\r\n") == std::string::npos &&
            ::recv(sock, &c, 1, 0) == 1) {
            ::recv(sock, &c, 1, 0) == 1) {
@@ -27963,7 +27963,7 @@ TEST(WebSocketTest, AssemblesFragmentsAroundAPing) {
   auto frames = masked_frame(0x02, "Hel") + // Binary, more to come
   auto frames = masked_frame(0x02, "Hel") + // Binary, more to come
                 masked_frame(0x89, "p") +   // FIN + Ping
                 masked_frame(0x89, "p") +   // FIN + Ping
                 masked_frame(0x80, "lo");   // FIN + Continuation
                 masked_frame(0x80, "lo");   // FIN + Continuation
-  ::send(sock, frames.data(), static_cast<int>(frames.size()), 0);
+  detail::send_socket(sock, frames.data(), frames.size(), 0);
 
 
   for (int i = 0; i < 500 && !done; i++) {
   for (int i = 0; i < 500 && !done; i++) {
     std::this_thread::sleep_for(std::chrono::milliseconds(10));
     std::this_thread::sleep_for(std::chrono::milliseconds(10));
@@ -28033,7 +28033,7 @@ TEST(WebSocketTest, AnswersAMalformedCloseWithProtocolError) {
       auto sock = connect_raw_websocket(port, "/ws");
       auto sock = connect_raw_websocket(port, "/ws");
       ASSERT_NE(INVALID_SOCKET, sock);
       ASSERT_NE(INVALID_SOCKET, sock);
       auto frames = prefix + masked_frame(0x88, c.first);
       auto frames = prefix + masked_frame(0x88, c.first);
-      ::send(sock, frames.data(), static_cast<int>(frames.size()), 0);
+      detail::send_socket(sock, frames.data(), frames.size(), 0);
 
 
       std::string reply;
       std::string reply;
       char buf[256];
       char buf[256];