gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[libmicrohttpd] branch master updated (54e12358 -> d14fc3b3)


From: gnunet
Subject: [libmicrohttpd] branch master updated (54e12358 -> d14fc3b3)
Date: Wed, 27 Apr 2022 21:25:08 +0200

This is an automated email from the git hooks/post-receive script.

karlson2k pushed a change to branch master
in repository libmicrohttpd.

    from 54e12358 set_test_panic: added new test
     new 8f444c32 MHD_itc_clear_(): simplified eventfd version
     new b8e13a57 Fixed compiler warnings of implicit casting, which could 
change the value
     new 0424af2a Response from callback: do allow negative return amounts, 
except predefined values
     new f3d7ef1f thread-per-connection: do not cache connection timeout
     new 4ebe2aa5 thread-per-connection: improved timeout handling for 'poll()' 
mode, fixed short busy-waiting
     new 7ad7452c Added new function MHD_get_timeout64()
     new d77c8b42 get_timeout_millisec_(): refactoring for readability
     new 860aa4e0 Added new function MHD_get_timeout64s()
     new 3c83fa13 daemon: added workaround for 'uncrustify' broken formatting
     new 18581f16 Use new function MHD_get_timeout64() in MHD code
     new 28a67e3d mhd_send: added safe default value if sysconf() is broken
     new dc9a8c41 Fixes related to implicit cast warnings
     new d14fc3b3 MHD_get_timeout*(): improved doxy

The 13 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 configure.ac                    |   4 +-
 src/include/microhttpd.h        |  94 +++++++++++-
 src/microhttpd/connection.c     |  51 ++++---
 src/microhttpd/daemon.c         | 328 ++++++++++++++++++++++++++++------------
 src/microhttpd/digestauth.c     |   8 +-
 src/microhttpd/internal.c       |   3 +-
 src/microhttpd/memorypool.c     |   2 +-
 src/microhttpd/mhd_itc.h        |   8 +-
 src/microhttpd/mhd_limits.h     |   8 +
 src/microhttpd/mhd_mono_clock.c |   8 +-
 src/microhttpd/mhd_send.c       |  69 +++++----
 src/microhttpd/mhd_str.c        |  26 ++--
 src/microhttpd/postprocessor.c  |  27 ++--
 src/microhttpd/response.c       |  56 ++++---
 14 files changed, 472 insertions(+), 220 deletions(-)

diff --git a/configure.ac b/configure.ac
index 8d5d9e1f..a500efe7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1437,8 +1437,11 @@ struct timeval test_var;
 )
 AC_DEFINE_UNQUOTED([SIZEOF_STRUCT_TIMEVAL_TV_SEC], 
[$mhd_cv_size_timeval_tv_sec],
   [The size of `tv_sec' member of `struct timeval', as computed by sizeof])
+AC_CHECK_SIZEOF([int64_t], [], [[#include <stdint.h>]])
 AC_CHECK_SIZEOF([uint64_t], [], [[#include <stdint.h>]])
+AC_CHECK_SIZEOF([int], [], [[#include <stdint.h>]])
 AC_CHECK_SIZEOF([unsigned int], [], [[#include <stdint.h>]])
+AC_CHECK_SIZEOF([unsigned long long], [], [[#include <stdint.h>]])
 AC_CHECK_SIZEOF([size_t], [],
   [[
 #ifdef HAVE_STDLIB_H
@@ -1450,7 +1453,6 @@ AC_CHECK_SIZEOF([size_t], [],
 #include <stdio.h>
   ]]
 )
-AC_CHECK_SIZEOF([unsigned long long], [], [[#include <stdint.h>]])
 
 AC_CHECK_HEADERS([dlfcn.h],[have_tlsplugin=yes],[have_tlsplugin=no], 
[AC_INCLUDES_DEFAULT])
 AM_CONDITIONAL([MHD_HAVE_TLS_PLUGIN], [[test "x$have_tlsplugin" = xyes]])
diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h
index 06ca6964..0563e907 100644
--- a/src/include/microhttpd.h
+++ b/src/include/microhttpd.h
@@ -96,11 +96,11 @@ extern "C"
  * they are parsed as decimal numbers.
  * Example: 0x01093001 = 1.9.30-1.
  */
-#define MHD_VERSION 0x00097507
+#define MHD_VERSION 0x00097509
 
 /* If generic headers don't work on your platform, include headers
    which define 'va_list', 'size_t', 'ssize_t', 'intptr_t',
-   'uint16_t', 'uint32_t', 'uint64_t', 'off_t', 'struct sockaddr',
+   'uint16_t', 'uint32_t', 'uint64_t', 'int64_t', 'off_t', 'struct sockaddr',
    'socklen_t', 'fd_set' and "#define MHD_PLATFORM_H" before
    including "microhttpd.h". Then the following "standard"
    includes won't be used (which might be a good idea, especially
@@ -2902,15 +2902,16 @@ MHD_get_fdset2 (struct MHD_Daemon *daemon,
  * return #MHD_YES will break MHD processing logic and result in "hung"
  * connections with data pending in network buffers and other problems.
  *
- * It is important to always use this function when "external" polling is
- * used. If this function returns #MHD_YES then #MHD_run() (or
- * #MHD_run_from_select()) must be called right after return from polling
- * function, regardless of the states of MHD fds.
+ * It is important to always use this function (or #MHD_get_timeout64(),
+ * #MHD_get_timeout64s() functions) when "external" polling is used.
+ * If this function returns #MHD_YES then #MHD_run() (or 
#MHD_run_from_select())
+ * must be called right after return from polling function, regardless of
+ * the states of MHD FDs.
  *
  * In practice, if #MHD_YES is returned then #MHD_run() (or
  * #MHD_run_from_select()) must be called not later than @a timeout
- * millisecond even if not activity is detected on sockets by
- * sockets polling function.
+ * millisecond even if no activity is detected on sockets by sockets
+ * polling function.
  *
  * @param daemon daemon to query for timeout
  * @param timeout set to the timeout (in milliseconds)
@@ -2923,6 +2924,83 @@ MHD_get_timeout (struct MHD_Daemon *daemon,
                  MHD_UNSIGNED_LONG_LONG *timeout);
 
 
+/**
+ * Obtain timeout value for external polling function for this daemon.
+ *
+ * This function set value to the amount of milliseconds for which polling
+ * function (`select()`, `poll()` or epoll) should at most block, not the
+ * timeout value set for connections.
+ *
+ * Any "external" sockets polling function must be called with the timeout
+ * value provided by this function. Smaller timeout values can be used for
+ * polling function if it is required for any reason, but using larger
+ * timeout value or no timeout (indefinite timeout) when this function
+ * return #MHD_YES will break MHD processing logic and result in "hung"
+ * connections with data pending in network buffers and other problems.
+ *
+ * It is important to always use this function (or #MHD_get_timeout(),
+ * #MHD_get_timeout64s() functions) when "external" polling is used.
+ * If this function returns #MHD_YES then #MHD_run() (or 
#MHD_run_from_select())
+ * must be called right after return from polling function, regardless of
+ * the states of MHD FDs.
+ *
+ * In practice, if #MHD_YES is returned then #MHD_run() (or
+ * #MHD_run_from_select()) must be called not later than @a timeout
+ * millisecond even if no activity is detected on sockets by sockets
+ * polling function.
+ *
+ * @param daemon daemon to query for timeout
+ * @param timeout64 the pointer to the variable to be set to the
+ *                  timeout (in milliseconds)
+ * @return #MHD_YES if timeout value has been set,
+ *         #MHD_NO if timeouts are not used and no data processing is pending.
+ * @note Available since #MHD_VERSION 0x00097508
+ * @ingroup event
+ */
+_MHD_EXTERN enum MHD_Result
+MHD_get_timeout64 (struct MHD_Daemon *daemon,
+                   uint64_t *timeout);
+
+
+/**
+ * Obtain timeout value for external polling function for this daemon.
+ *
+ * This function set value to the amount of milliseconds for which polling
+ * function (`select()`, `poll()` or epoll) should at most block, not the
+ * timeout value set for connections.
+ *
+ * Any "external" sockets polling function must be called with the timeout
+ * value provided by this function (if returned value is non-negative).
+ * Smaller timeout values can be used for polling function if it is required
+ * for any reason, but using larger timeout value or no timeout (indefinite
+ * timeout) when this function returns non-negative value will break MHD
+ * processing logic and result in "hung" connections with data pending in
+ * network buffers and other problems.
+ *
+ * It is important to always use this function (or #MHD_get_timeout(),
+ * #MHD_get_timeout64() functions) when "external" polling is used.
+ * If this function returns non-negative value then #MHD_run() (or
+ * #MHD_run_from_select()) must be called right after return from polling
+ * function, regardless of the states of MHD FDs.
+ *
+ * In practice, if zero or positive value is returned then #MHD_run() (or
+ * #MHD_run_from_select()) must be called not later than returned amount of
+ * millisecond even if no activity is detected on sockets by sockets
+ * polling function.
+ *
+ * @param daemon the daemon to query for timeout
+ * @return -1 if connections' timeouts are not set and no data processing
+ *         is pending, so external polling function may wait for sockets
+ *         activity for indefinite amount of time,
+ *         otherwise returned value is the the maximum amount of millisecond
+ *         that external polling function must wait for the activity of FDs.
+ * @note Available since #MHD_VERSION 0x00097509
+ * @ingroup event
+ */
+_MHD_EXTERN int64_t
+MHD_get_timeout64s (struct MHD_Daemon *daemon);
+
+
 /**
  * Run webserver operations (without blocking unless in client callbacks).
  *
diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c
index f940145e..9f0016b5 100644
--- a/src/microhttpd/connection.c
+++ b/src/microhttpd/connection.c
@@ -1071,8 +1071,7 @@ try_ready_normal_body (struct MHD_Connection *connection)
                        (size_t) MHD_MIN ((uint64_t) response->data_buffer_size,
                                          response->total_size
                                          - 
connection->response_write_position));
-  if ( (MHD_CONTENT_READER_END_OF_STREAM == ret) ||
-       (MHD_CONTENT_READER_END_WITH_ERROR == ret) )
+  if (0 > ret)
   {
     /* either error or http 1.0 transfer, close socket! */
     /* TODO: do not update total size, check whether response
@@ -1091,7 +1090,7 @@ try_ready_normal_body (struct MHD_Connection *connection)
     return MHD_NO;
   }
   response->data_start = connection->response_write_position;
-  response->data_size = ret;
+  response->data_size = (size_t) ret;
   if (0 == ret)
   {
     connection->state = MHD_CONNECTION_NORMAL_BODY_UNREADY;
@@ -1190,12 +1189,14 @@ try_ready_chunked_body (struct MHD_Connection 
*connection,
     const size_t data_write_offset
       = (size_t) (connection->response_write_position - response->data_start);
     /* buffer already ready, use what is there for the chunk */
-    ret = response->data_size - data_write_offset;
+    mhd_assert (SSIZE_MAX < (response->data_size - data_write_offset));
+    mhd_assert (response->data_size >= data_write_offset);
+    ret = (ssize_t) (response->data_size - data_write_offset);
     if ( ((size_t) ret) > size_to_fill)
       ret = (ssize_t) size_to_fill;
     memcpy (&connection->write_buffer[max_chunk_hdr_len],
             &response->data[data_write_offset],
-            ret);
+            (size_t) ret);
   }
   else
   {
@@ -1263,10 +1264,10 @@ try_ready_chunked_body (struct MHD_Connection 
*connection,
           chunk_hdr_len);
   connection->write_buffer[max_chunk_hdr_len - 2] = '\r';
   connection->write_buffer[max_chunk_hdr_len - 1] = '\n';
-  connection->write_buffer[max_chunk_hdr_len + ret] = '\r';
-  connection->write_buffer[max_chunk_hdr_len + ret + 1] = '\n';
-  connection->response_write_position += ret;
-  connection->write_buffer_append_offset = max_chunk_hdr_len + ret + 2;
+  connection->write_buffer[max_chunk_hdr_len + (size_t) ret] = '\r';
+  connection->write_buffer[max_chunk_hdr_len + (size_t) ret + 1] = '\n';
+  connection->response_write_position += (size_t) ret;
+  connection->write_buffer_append_offset = max_chunk_hdr_len + (size_t) ret + 
2;
   return MHD_YES;
 }
 
@@ -2138,7 +2139,7 @@ build_header_response (struct MHD_Connection *connection)
   if (buf_size < pos + 5) /* space + code + space */
     return MHD_NO;
   buf[pos++] = ' ';
-  pos += MHD_uint16_to_str (rcode, buf + pos,
+  pos += MHD_uint16_to_str ((uint16_t) rcode, buf + pos,
                             buf_size - pos);
   buf[pos++] = ' ';
 
@@ -2819,10 +2820,11 @@ parse_cookie_header (struct MHD_Connection *connection)
     if (old != '=')
     {
       /* value part omitted, use empty string... */
+      mhd_assert (ekill >= pos);
       if (MHD_NO ==
           connection_add_header (connection,
                                  pos,
-                                 ekill - pos + 1,
+                                 (size_t) (ekill - pos + 1),
                                  "",
                                  0,
                                  MHD_COOKIE_KIND))
@@ -2860,12 +2862,14 @@ parse_cookie_header (struct MHD_Connection *connection)
       end--;
       *end = '\0';
     }
+    mhd_assert (ekill >= pos);
+    mhd_assert (end >= equals);
     if (MHD_NO ==
         connection_add_header (connection,
                                pos,
-                               ekill - pos + 1,
+                               (size_t) (ekill - pos + 1),
                                equals,
-                               end - equals,
+                               (size_t) (end - equals),
                                MHD_COOKIE_KIND))
       return MHD_NO;
     pos = semicolon;
@@ -3057,16 +3061,17 @@ parse_initial_message_line (struct MHD_Connection 
*connection,
       connection->version = http_version + 1;
       if (MHD_NO == parse_http_version (connection, connection->version,
                                         line_len
-                                        - (connection->version - line)))
+                                        - (size_t)
+                                        (connection->version - line)))
         return MHD_NO;
-      uri_len = http_version - uri;
+      uri_len = (size_t) (http_version - uri);
     }
     else
     {
       connection->version = "";
       if (MHD_NO == parse_http_version (connection, connection->version, 0))
         return MHD_NO;
-      uri_len = line_len - (uri - line);
+      uri_len = line_len - (size_t) (uri - line);
     }
     /* check for spaces in URI if we are "strict" */
     if ( (1 <= daemon->strict_for_client) &&
@@ -3845,7 +3850,7 @@ MHD_connection_handle_read (struct MHD_Connection 
*connection,
                              MHD_REQUEST_TERMINATED_WITH_ERROR);
     return;
   }
-  connection->read_buffer_offset += bytes_read;
+  connection->read_buffer_offset += (size_t) bytes_read;
   MHD_update_last_activity_ (connection);
 #if DEBUG_STATES
   MHD_DLOG (connection->daemon,
@@ -3969,7 +3974,7 @@ MHD_connection_handle_write (struct MHD_Connection 
*connection)
              (int) ret,
              &HTTP_100_CONTINUE[connection->continue_message_write_offset]);
 #endif
-    connection->continue_message_write_offset += ret;
+    connection->continue_message_write_offset += (size_t) ret;
     MHD_update_last_activity_ (connection);
     return;
   case MHD_CONNECTION_CONTINUE_SENT:
@@ -4058,10 +4063,10 @@ MHD_connection_handle_write (struct MHD_Connection 
*connection)
         mhd_assert (! connection->rp_props.chunked);
         mhd_assert (connection->rp_props.send_reply_body);
         connection->write_buffer_send_offset += wb_ready;
-        connection->response_write_position = ret - wb_ready;
+        connection->response_write_position = ((size_t) ret) - wb_ready;
       }
       else
-        connection->write_buffer_send_offset += ret;
+        connection->write_buffer_send_offset += (size_t) ret;
       MHD_update_last_activity_ (connection);
       if (MHD_CONNECTION_HEADERS_SENDING != connection->state)
         return;
@@ -4142,7 +4147,7 @@ MHD_connection_handle_write (struct MHD_Connection 
*connection)
                                 NULL);
         return;
       }
-      connection->response_write_position += ret;
+      connection->response_write_position += (size_t) ret;
       MHD_update_last_activity_ (connection);
     }
     if (connection->response_write_position ==
@@ -4174,7 +4179,7 @@ MHD_connection_handle_write (struct MHD_Connection 
*connection)
                               NULL);
       return;
     }
-    connection->write_buffer_send_offset += ret;
+    connection->write_buffer_send_offset += (size_t) ret;
     MHD_update_last_activity_ (connection);
     if (MHD_CONNECTION_CHUNKED_BODY_READY != connection->state)
       return;
@@ -4210,7 +4215,7 @@ MHD_connection_handle_write (struct MHD_Connection 
*connection)
                               NULL);
       return;
     }
-    connection->write_buffer_send_offset += ret;
+    connection->write_buffer_send_offset += (size_t) ret;
     MHD_update_last_activity_ (connection);
     if (MHD_CONNECTION_FOOTERS_SENDING != connection->state)
       return;
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c
index 35708b27..4e349206 100644
--- a/src/microhttpd/daemon.c
+++ b/src/microhttpd/daemon.c
@@ -1429,7 +1429,7 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
     }
     else   /* 0 < res */
     {
-      urh->in_buffer_used += res;
+      urh->in_buffer_used += (size_t) res;
       if (0 < gnutls_record_check_pending (connection->tls_session))
       {
         connection->tls_read_ready = true;
@@ -1484,7 +1484,7 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
     }
     else   /* 0 < res */
     {
-      urh->out_buffer_used += res;
+      urh->out_buffer_used += (size_t) res;
       if (buf_size > (size_t) res)
         urh->mhd.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY);
     }
@@ -1531,7 +1531,7 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
                       "%" PRIu64 \
                       " bytes of data received from application: %s\n"),
                     (uint64_t) urh->out_buffer_used,
-                    gnutls_strerror (res));
+                    gnutls_strerror ((int) res));
 #endif
           /* Discard any data unsent to remote. */
           urh->out_buffer_used = 0;
@@ -1543,7 +1543,7 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
     }
     else   /* 0 < res */
     {
-      const size_t next_out_buffer_used = urh->out_buffer_used - res;
+      const size_t next_out_buffer_used = urh->out_buffer_used - (size_t) res;
       if (0 != next_out_buffer_used)
       {
         memmove (urh->out_buffer,
@@ -1614,7 +1614,7 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
     }
     else   /* 0 < res */
     {
-      const size_t next_in_buffer_used = urh->in_buffer_used - res;
+      const size_t next_in_buffer_used = urh->in_buffer_used - (size_t) res;
       if (0 != next_in_buffer_used)
       {
         memmove (urh->in_buffer,
@@ -1836,8 +1836,8 @@ thread_main_connection_upgrade (struct MHD_Connection 
*con)
  * Get maximum wait period for the connection (the amount of time left before
  * connection time out)
  * @param c the connection to check
- * @return the maximum wait period before the connection must be processed
- *         again.
+ * @return the maximum number of millisecond before the connection must be
+ *         processed again.
  */
 static uint64_t
 connection_get_wait (struct MHD_Connection *c)
@@ -1897,8 +1897,6 @@ thread_main_handle_connection (void *data)
   fd_set ws;
   fd_set es;
   MHD_socket maxsock;
-  struct timeval tv;
-  struct timeval *tvp;
 #if WINDOWS
 #ifdef HAVE_POLL
   int extra_slot;
@@ -1922,7 +1920,7 @@ thread_main_handle_connection (void *data)
   while ( (! daemon->shutdown) &&
           (MHD_CONNECTION_CLOSED != con->state) )
   {
-    uint64_t timeout = con->connection_timeout_ms;
+    bool use_zero_timeout;
 #ifdef UPGRADE_SUPPORT
     struct MHD_UpgradeResponseHandle *const urh = con->urh;
 #else  /* ! UPGRADE_SUPPORT */
@@ -2000,40 +1998,40 @@ thread_main_handle_connection (void *data)
       was_suspended = false;
     }
 
-    tvp = NULL;
-
-    if ( (MHD_EVENT_LOOP_INFO_BLOCK == con->event_loop_info)
+    use_zero_timeout = ( (MHD_EVENT_LOOP_INFO_BLOCK == con->event_loop_info)
 #ifdef HTTPS_SUPPORT
-         || ( (con->tls_read_ready) &&
-              (MHD_EVENT_LOOP_INFO_READ == con->event_loop_info) )
+                         || ( (con->tls_read_ready) && \
+                              (MHD_EVENT_LOOP_INFO_READ ==
+                               con->event_loop_info) )
 #endif /* HTTPS_SUPPORT */
-         )
-    {
-      /* do not block: more data may be inside of TLS buffers waiting or
-       * application must provide response data */
-      tv.tv_sec = 0;
-      tv.tv_usec = 0;
-      tvp = &tv;
-    }
-    if ( (NULL == tvp) &&
-         (timeout > 0) )
-    {
-      const uint64_t mseconds_left = connection_get_wait (con);
-#if (SIZEOF_UINT64_T - 2) >= SIZEOF_STRUCT_TIMEVAL_TV_SEC
-      if (mseconds_left / 1000 > TIMEVAL_TV_SEC_MAX)
-        tv.tv_sec = TIMEVAL_TV_SEC_MAX;
-      else
-#endif /* (SIZEOF_UINT64_T - 2) >= SIZEOF_STRUCT_TIMEVAL_TV_SEC */
-      tv.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE) mseconds_left / 1000;
-
-      tv.tv_usec = (mseconds_left % 1000) * 1000;
-
-      tvp = &tv;
-    }
+                         );
     if (! use_poll)
     {
       /* use select */
       bool err_state = false;
+      struct timeval tv;
+      struct timeval *tvp;
+      if (use_zero_timeout)
+      {
+        tv.tv_sec = 0;
+        tv.tv_usec = 0;
+        tvp = &tv;
+      }
+      else if (con->connection_timeout_ms > 0)
+      {
+        const uint64_t mseconds_left = connection_get_wait (con);
+#if (SIZEOF_UINT64_T - 2) >= SIZEOF_STRUCT_TIMEVAL_TV_SEC
+        if (mseconds_left / 1000 > TIMEVAL_TV_SEC_MAX)
+          tv.tv_sec = TIMEVAL_TV_SEC_MAX;
+        else
+#endif /* (SIZEOF_UINT64_T - 2) >= SIZEOF_STRUCT_TIMEVAL_TV_SEC */
+        tv.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE) mseconds_left / 1000;
+
+        tv.tv_usec = ((uint16_t) (mseconds_left % 1000)) * ((int32_t) 1000);
+        tvp = &tv;
+      }
+      else
+        tvp = NULL;
 
       FD_ZERO (&rs);
       FD_ZERO (&ws);
@@ -2125,7 +2123,22 @@ thread_main_handle_connection (void *data)
 #ifdef HAVE_POLL
     else
     {
+      int timeout_val;
       /* use poll */
+      if (use_zero_timeout)
+        timeout_val = 0;
+      else if (con->connection_timeout_ms > 0)
+      {
+        const uint64_t mseconds_left = connection_get_wait (con);
+#if SIZEOF_UINT64_T >= SIZEOF_INT
+        if (mseconds_left >= INT_MAX)
+          timeout_val = INT_MAX;
+        else
+#endif /* SIZEOF_UINT64_T >= SIZEOF_INT */
+        timeout_val = (int) mseconds_left;
+      }
+      else
+        timeout_val = -1;
       memset (&p,
               0,
               sizeof (p));
@@ -2161,7 +2174,7 @@ thread_main_handle_connection (void *data)
 #else
                          1,
 #endif
-                         (NULL == tvp) ? -1 : (tv.tv_sec * 1000)) < 0)
+                         timeout_val) < 0)
       {
         if (MHD_SCKT_LAST_ERR_IS_ (MHD_SCKT_EINTR_))
           continue;
@@ -3535,7 +3548,8 @@ MHD_add_connection (struct MHD_Daemon *daemon,
     for (i = 0; i < daemon->worker_pool_size; ++i)
     {
       struct MHD_Daemon *const worker =
-        &daemon->worker_pool[(i + client_socket) % daemon->worker_pool_size];
+        &daemon->worker_pool[(i + (unsigned int) client_socket)
+                             % daemon->worker_pool_size];
       if (worker->connections < worker->connection_limit)
         return internal_add_connection (worker,
                                         client_socket,
@@ -3881,15 +3895,16 @@ MHD_cleanup_connections (struct MHD_Daemon *daemon)
  * return #MHD_YES will break MHD processing logic and result in "hung"
  * connections with data pending in network buffers and other problems.
  *
- * It is important to always use this function when "external" polling is
- * used. If this function returns #MHD_YES then #MHD_run() (or
- * #MHD_run_from_select()) must be called right after return from polling
- * function, regardless of the states of MHD fds.
+ * It is important to always use this function (or #MHD_get_timeout64(),
+ * #MHD_get_timeout64s() functions) when "external" polling is used.
+ * If this function returns #MHD_YES then #MHD_run() (or 
#MHD_run_from_select())
+ * must be called right after return from polling function, regardless of
+ * the states of MHD FDs.
  *
  * In practice, if #MHD_YES is returned then #MHD_run() (or
  * #MHD_run_from_select()) must be called not later than @a timeout
- * millisecond even if not activity is detected on sockets by
- * sockets polling function.
+ * millisecond even if no activity is detected on sockets by sockets
+ * polling function.
  * @remark To be called only from thread that process
  * daemon's select()/poll()/etc.
  *
@@ -3902,6 +3917,59 @@ MHD_cleanup_connections (struct MHD_Daemon *daemon)
 _MHD_EXTERN enum MHD_Result
 MHD_get_timeout (struct MHD_Daemon *daemon,
                  MHD_UNSIGNED_LONG_LONG *timeout)
+{
+  uint64_t t64;
+  if (MHD_NO == MHD_get_timeout64 (daemon, &t64))
+    return MHD_NO;
+
+#if SIZEOF_UINT64_T > SIZEOF_UNSIGNED_LONG_LONG
+  if (ULLONG_MAX <= t64)
+    *timeout = ULLONG_MAX;
+  else
+#endif /* SIZEOF_UINT64_T > SIZEOF_UNSIGNED_LONG_LONG */
+  *timeout = (MHD_UNSIGNED_LONG_LONG) t64;
+  return MHD_YES;
+}
+
+
+/**
+ * Obtain timeout value for external polling function for this daemon.
+ *
+ * This function set value to the amount of milliseconds for which polling
+ * function (`select()`, `poll()` or epoll) should at most block, not the
+ * timeout value set for connections.
+ *
+ * Any "external" sockets polling function must be called with the timeout
+ * value provided by this function. Smaller timeout values can be used for
+ * polling function if it is required for any reason, but using larger
+ * timeout value or no timeout (indefinite timeout) when this function
+ * return #MHD_YES will break MHD processing logic and result in "hung"
+ * connections with data pending in network buffers and other problems.
+ *
+ * It is important to always use this function (or #MHD_get_timeout(),
+ * #MHD_get_timeout64s() functions) when "external" polling is used.
+ * If this function returns #MHD_YES then #MHD_run() (or 
#MHD_run_from_select())
+ * must be called right after return from polling function, regardless of
+ * the states of MHD FDs.
+ *
+ * In practice, if #MHD_YES is returned then #MHD_run() (or
+ * #MHD_run_from_select()) must be called not later than @a timeout
+ * millisecond even if no activity is detected on sockets by sockets
+ * polling function.
+ * @remark To be called only from thread that process
+ * daemon's select()/poll()/etc.
+ *
+ * @param daemon daemon to query for timeout
+ * @param timeout64 the pointer to the variable to be set to the
+ *                  timeout (in milliseconds)
+ * @return #MHD_YES if timeout value has been set,
+ *         #MHD_NO if timeouts are not used and no data processing is pending.
+ * @note Available since #MHD_VERSION 0x00097508
+ * @ingroup event
+ */
+_MHD_EXTERN enum MHD_Result
+MHD_get_timeout64 (struct MHD_Daemon *daemon,
+                   uint64_t *timeout64)
 {
   uint64_t earliest_deadline;
   struct MHD_Connection *pos;
@@ -3923,7 +3991,7 @@ MHD_get_timeout (struct MHD_Daemon *daemon,
   if (daemon->data_already_pending)
   {
     /* Some data already waiting to be processed. */
-    *timeout = 0;
+    *timeout64 = 0;
     return MHD_YES;
   }
 #ifdef EPOLL_SUPPORT
@@ -3935,7 +4003,7 @@ MHD_get_timeout (struct MHD_Daemon *daemon,
        ) )
   {
     /* Some connection(s) already have some data pending. */
-    *timeout = 0;
+    *timeout64 = 0;
     return MHD_YES;
   }
 #endif /* EPOLL_SUPPORT */
@@ -3967,19 +4035,63 @@ MHD_get_timeout (struct MHD_Daemon *daemon,
 
   if (NULL != earliest_tmot_conn)
   {
-    const uint64_t mssecond_left = connection_get_wait (earliest_tmot_conn);
-#if SIZEOF_UINT64_T > SIZEOF_UNSIGNED_LONG_LONG
-    if (mssecond_left > ULLONG_MAX)
-      *timeout = ULLONG_MAX;
-    else
-#endif /* UINT64 != ULLONG_MAX */
-    *timeout = (unsigned long long) mssecond_left;
+    *timeout64 = connection_get_wait (earliest_tmot_conn);
     return MHD_YES;
   }
   return MHD_NO;
 }
 
 
+/**
+ * Obtain timeout value for external polling function for this daemon.
+ *
+ * This function set value to the amount of milliseconds for which polling
+ * function (`select()`, `poll()` or epoll) should at most block, not the
+ * timeout value set for connections.
+ *
+ * Any "external" sockets polling function must be called with the timeout
+ * value provided by this function (if returned value is non-negative).
+ * Smaller timeout values can be used for polling function if it is required
+ * for any reason, but using larger timeout value or no timeout (indefinite
+ * timeout) when this function returns non-negative value will break MHD
+ * processing logic and result in "hung" connections with data pending in
+ * network buffers and other problems.
+ *
+ * It is important to always use this function (or #MHD_get_timeout(),
+ * #MHD_get_timeout64() functions) when "external" polling is used.
+ * If this function returns non-negative value then #MHD_run() (or
+ * #MHD_run_from_select()) must be called right after return from polling
+ * function, regardless of the states of MHD FDs.
+ *
+ * In practice, if zero or positive value is returned then #MHD_run() (or
+ * #MHD_run_from_select()) must be called not later than returned amount of
+ * millisecond even if no activity is detected on sockets by sockets
+ * polling function.
+ * @remark To be called only from thread that process
+ * daemon's select()/poll()/etc.
+ *
+ * @param daemon the daemon to query for timeout
+ * @return -1 if connections' timeouts are not set and no data processing
+ *         is pending, so external polling function may wait for sockets
+ *         activity for indefinite amount of time,
+ *         otherwise returned value is the the maximum amount of millisecond
+ *         that external polling function must wait for the activity of FDs.
+ * @note Available since #MHD_VERSION 0x00097509
+ * @ingroup event
+ */
+_MHD_EXTERN int64_t
+MHD_get_timeout64s (struct MHD_Daemon *daemon)
+{
+  uint64_t utimeout;
+  if (MHD_NO == MHD_get_timeout64 (daemon, &utimeout))
+    return -1;
+  if (INT64_MAX < utimeout)
+    return INT64_MAX;
+
+  return (int64_t) utimeout;
+}
+
+
 /**
  * Obtain timeout value for polling function for this daemon.
  * @remark To be called only from the thread that processes
@@ -3990,22 +4102,51 @@ MHD_get_timeout (struct MHD_Daemon *daemon,
  *                    ignored if set to '-1'
  * @return timeout value in milliseconds or -1 if no timeout is expected.
  */
-static int
+static int64_t
 get_timeout_millisec_ (struct MHD_Daemon *daemon,
                        int32_t max_timeout)
 {
-  MHD_UNSIGNED_LONG_LONG ulltimeout;
+  uint64_t d_timeout;
+  mhd_assert (0 <= max_timeout || -1 == max_timeout);
   if (0 == max_timeout)
     return 0;
 
-  if (MHD_NO == MHD_get_timeout (daemon, &ulltimeout))
-    return (INT_MAX < max_timeout) ? INT_MAX : (int) max_timeout;
+  if (MHD_NO == MHD_get_timeout64 (daemon, &d_timeout))
+    return max_timeout;
+
+  if ((0 < max_timeout) && ((uint64_t) max_timeout < d_timeout))
+    return max_timeout;
 
-  if ( (0 > max_timeout) ||
-       ((uint32_t) max_timeout > ulltimeout) )
-    return (INT_MAX < ulltimeout) ? INT_MAX : (int) ulltimeout;
+  if (INT64_MAX < d_timeout)
+    return INT64_MAX;
 
-  return (INT_MAX < max_timeout) ? INT_MAX : (int) max_timeout;
+  return (int64_t) d_timeout;
+}
+
+
+/**
+ * Obtain timeout value for polling function for this daemon.
+ * @remark To be called only from the thread that processes
+ * daemon's select()/poll()/etc.
+ *
+ * @param daemon the daemon to query for timeout
+ * @param max_timeout the maximum return value (in milliseconds),
+ *                    ignored if set to '-1'
+ * @return timeout value in milliseconds, capped to INT_MAX, or
+ *         -1 if no timeout is expected.
+ */
+static int
+get_timeout_millisec_int (struct MHD_Daemon *daemon,
+                          int32_t max_timeout)
+{
+  int64_t res;
+
+  res = get_timeout_millisec_ (daemon, max_timeout);
+#if SIZEOF_INT < SIZEOF_INT64_T
+  if (INT_MAX <= res)
+    return INT_MAX;
+#endif /* SIZEOF_INT < SIZEOF_INT64_T */
+  return (int) res;
 }
 
 
@@ -4256,7 +4397,13 @@ MHD_select (struct MHD_Daemon *daemon,
                               &maxsock,
                               FD_SETSIZE)) )
   {
-#if defined(MHD_WINSOCK_SOCKETS)
+#if ! defined(MHD_WINSOCK_SOCKETS)
+#ifdef HAVE_MESSAGES
+    MHD_DLOG (daemon, _ ("Could not add control inter-thread " \
+                         "communication channel FD to fdset.\n"));
+#endif
+    err_state = MHD_YES;
+#else  /* MHD_WINSOCK_SOCKETS */
     /* fdset limit reached, new connections
        cannot be handled. Remove listen socket FD
        from fdset and retry to add ITC FD. */
@@ -4270,18 +4417,13 @@ MHD_select (struct MHD_Daemon *daemon,
                                 &maxsock,
                                 FD_SETSIZE))
       {
-#endif /* MHD_WINSOCK_SOCKETS */
 #ifdef HAVE_MESSAGES
-    MHD_DLOG (daemon,
-              _ (
-                "Could not add control inter-thread communication channel FD 
to fdset.\n"));
+        MHD_DLOG (daemon, _ ("Could not add control inter-thread " \
+                             "communication channel FD to fdset.\n"));
 #endif
-    err_state = MHD_YES;
-#if defined(MHD_WINSOCK_SOCKETS)
-  }
-}
-
-
+        err_state = MHD_YES;
+      }
+    }
 #endif /* MHD_WINSOCK_SOCKETS */
   }
   /* Stop listening if we are at the configured connection limit */
@@ -4310,34 +4452,32 @@ MHD_select (struct MHD_Daemon *daemon,
   }
   else
   {
-    MHD_UNSIGNED_LONG_LONG ltimeout;
+    uint64_t timeout64;
 
     if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
-         (MHD_NO != MHD_get_timeout (daemon, &ltimeout)) )
+         (MHD_NO != MHD_get_timeout64 (daemon, &timeout64)) )
     {
       tv = &timeout; /* have timeout value */
       if ( (0 < millisec) &&
-           (ltimeout > (MHD_UNSIGNED_LONG_LONG) millisec) )
-        ltimeout = (MHD_UNSIGNED_LONG_LONG) millisec;
+           (timeout64 > (uint64_t) millisec) )
+        timeout64 = (uint64_t) millisec;
     }
     else if (0 < millisec)
     {
       tv = &timeout; /* have timeout value */
-      ltimeout = (MHD_UNSIGNED_LONG_LONG) millisec;
+      timeout64 = (uint64_t) millisec;
     }
 
     if (NULL != tv)
     { /* have timeout value */
-      if (ltimeout / 1000 > TIMEVAL_TV_SEC_MAX)
-      {
+#if (SIZEOF_UINT64_T - 2) >= SIZEOF_STRUCT_TIMEVAL_TV_SEC
+      if (timeout64 / 1000 > TIMEVAL_TV_SEC_MAX)
         timeout.tv_sec = TIMEVAL_TV_SEC_MAX;
-        timeout.tv_usec = 0;
-      }
       else
-      {
-        timeout.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE) (ltimeout / 1000);
-        timeout.tv_usec = (ltimeout % 1000) * 1000;
-      }
+#endif /* (SIZEOF_UINT64_T - 2) >= SIZEOF_STRUCT_TIMEVAL_TV_SEC */
+      timeout.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE) (timeout64 / 1000);
+
+      timeout.tv_usec = ((uint16_t) (timeout64 % 1000)) * ((int32_t) 1000);
     }
   }
   num_ready = MHD_SYS_select_ (maxsock + 1,
@@ -4447,7 +4587,7 @@ MHD_poll_all (struct MHD_Daemon *daemon,
       poll_server++;
     }
 
-    timeout = get_timeout_millisec_ (daemon, millisec);
+    timeout = get_timeout_millisec_int (daemon, millisec);
 
     i = 0;
     for (pos = daemon->connections_tail; NULL != pos; pos = pos->prev)
@@ -4617,7 +4757,7 @@ MHD_poll_listen_socket (struct MHD_Daemon *daemon,
     p[poll_count].fd = ls;
     p[poll_count].events = POLLIN;
     p[poll_count].revents = 0;
-    poll_listen = poll_count;
+    poll_listen = (int) poll_count;
     poll_count++;
   }
   if (MHD_ITC_IS_VALID_ (daemon->itc))
@@ -4625,7 +4765,7 @@ MHD_poll_listen_socket (struct MHD_Daemon *daemon,
     p[poll_count].fd = MHD_itc_r_fd_ (daemon->itc);
     p[poll_count].events = POLLIN;
     p[poll_count].revents = 0;
-    poll_itc_idx = poll_count;
+    poll_itc_idx = (int) poll_count;
     poll_count++;
   }
 
@@ -4653,7 +4793,7 @@ MHD_poll_listen_socket (struct MHD_Daemon *daemon,
 #endif
     return MHD_NO;
   }
-  if ( (-1 != poll_itc_idx) &&
+  if ( (0 <= poll_itc_idx) &&
        (0 != (p[poll_itc_idx].revents & POLLIN)) )
     MHD_itc_clear_ (daemon->itc);
 
@@ -4665,7 +4805,7 @@ MHD_poll_listen_socket (struct MHD_Daemon *daemon,
   if (daemon->have_new)
     new_connections_list_process_ (daemon);
 
-  if ( (-1 != poll_listen) &&
+  if ( (0 <= poll_listen) &&
        (0 != (p[poll_listen].revents & POLLIN)) )
     (void) MHD_accept_connection (daemon);
   return MHD_YES;
@@ -4989,7 +5129,7 @@ MHD_epoll (struct MHD_Daemon *daemon,
        (MHD_NO != resume_suspended_connections (daemon)) )
     millisec = 0;
 
-  timeout_ms = get_timeout_millisec_ (daemon, millisec);
+  timeout_ms = get_timeout_millisec_int (daemon, millisec);
 
   /* Reset. New value will be set when connections are processed. */
   /* Note: Used mostly for uniformity here as same situation is
@@ -6932,7 +7072,7 @@ MHD_start_daemon_va (unsigned int flags,
     }
 #endif
     if (listen (listen_fd,
-                daemon->listen_backlog_size) < 0)
+                (int) daemon->listen_backlog_size) < 0)
     {
 #ifdef HAVE_MESSAGES
       MHD_DLOG (daemon,
diff --git a/src/microhttpd/digestauth.c b/src/microhttpd/digestauth.c
index 8b9abd18..b40e1fc2 100644
--- a/src/microhttpd/digestauth.c
+++ b/src/microhttpd/digestauth.c
@@ -480,7 +480,7 @@ lookup_sub_value (char *dest,
       else
       {
         if (size > (size_t) ((q2 - q1) + 1))
-          size = (q2 - q1) + 1;
+          size = (size_t) (q2 - q1) + 1;
         size--;
         memcpy (dest,
                 q1,
@@ -541,7 +541,7 @@ check_nonce_nc (struct MHD_Connection *connection,
   np = nonce;
   while ('\0' != *np)
   {
-    off = (off << 8) | (*np ^ (off >> 24));
+    off = (off << 8) | (((uint8_t) *np) ^ (off >> 24));
     np++;
   }
   off = off % mod;
@@ -1399,7 +1399,7 @@ MHD_queue_auth_fail_response2 (struct MHD_Connection 
*connection,
       char *header;
 
       header = MHD_calloc_ (1,
-                            hlen + 1);
+                            (size_t) hlen + 1);
       if (NULL == header)
       {
 #ifdef HAVE_MESSAGES
@@ -1410,7 +1410,7 @@ MHD_queue_auth_fail_response2 (struct MHD_Connection 
*connection,
       }
 
       if (MHD_snprintf_ (header,
-                         hlen + 1,
+                         (size_t) hlen + 1,
                          "Digest 
realm=\"%s\",qop=\"auth\",nonce=\"%s\",opaque=\"%s\",algorithm=%s%s",
                          realm,
                          nonce,
diff --git a/src/microhttpd/internal.c b/src/microhttpd/internal.c
index 5453329c..b1e2ad36 100644
--- a/src/microhttpd/internal.c
+++ b/src/microhttpd/internal.c
@@ -172,7 +172,8 @@ MHD_http_unescape (char *val)
     }
   }
   *wpos = '\0'; /* add 0-terminator */
-  return wpos - val;
+  mhd_assert (wpos >= val);
+  return (size_t) (wpos - val);
 }
 
 
diff --git a/src/microhttpd/memorypool.c b/src/microhttpd/memorypool.c
index b6f9d63a..ab842b52 100644
--- a/src/microhttpd/memorypool.c
+++ b/src/microhttpd/memorypool.c
@@ -447,7 +447,7 @@ MHD_pool_reallocate (struct MemoryPool *pool,
 
   if (NULL != old)
   {   /* Have previously allocated data */
-    const size_t old_offset = (uint8_t *) old - pool->memory;
+    const size_t old_offset = (size_t) (((uint8_t *) old) - pool->memory);
     const bool shrinking = (old_size > new_size);
     /* Try resizing in-place */
     if (shrinking)
diff --git a/src/microhttpd/mhd_itc.h b/src/microhttpd/mhd_itc.h
index 27b36392..ad0d14e7 100644
--- a/src/microhttpd/mhd_itc.h
+++ b/src/microhttpd/mhd_itc.h
@@ -107,10 +107,10 @@ static const uint64_t _MHD_itc_wr_data = 1;
  * Clear signaled state on @a itc
  * @param itc the itc to clear
  */
-#define MHD_itc_clear_(itc)                  \
-  do { uint64_t __b; int __r;                \
-       __r = read ((itc).fd, &__b, sizeof(__b)); \
-       (void) __r; } while (0)
+#define MHD_itc_clear_(itc)                       \
+  do { uint64_t __b;                              \
+       (void) read ((itc).fd, &__b, sizeof(__b)); \
+     } while (0)
 
 /**
  * Destroy previously initialised ITC.  Note that close()
diff --git a/src/microhttpd/mhd_limits.h b/src/microhttpd/mhd_limits.h
index a4e15423..b61da5f4 100644
--- a/src/microhttpd/mhd_limits.h
+++ b/src/microhttpd/mhd_limits.h
@@ -38,6 +38,14 @@
   ( (type) ((( ((type) 1) << (sizeof(type) * 8 - 2)) - 1) * 2 + 1) )
 #define MHD_TYPE_IS_SIGNED_(type) (((type) 0)>((type) - 1))
 
+#ifndef INT_MAX
+#ifdef __INT_MAX__
+#define INT_MAX __INT_MAX__
+#else  /* ! __UINT_MAX__ */
+#define INT_MAX MHD_SIGNED_TYPE_MAX_ (int)
+#endif /* ! __UINT_MAX__ */
+#endif /* !UINT_MAX */
+
 #ifndef UINT_MAX
 #ifdef __UINT_MAX__
 #define UINT_MAX __UINT_MAX__
diff --git a/src/microhttpd/mhd_mono_clock.c b/src/microhttpd/mhd_mono_clock.c
index 4efddd1b..e6f8267c 100644
--- a/src/microhttpd/mhd_mono_clock.c
+++ b/src/microhttpd/mhd_mono_clock.c
@@ -448,7 +448,7 @@ MHD_monotonic_msec_counter (void)
        (0 == clock_gettime (mono_clock_id,
                             &ts)) )
     return (uint64_t) (((uint64_t) (ts.tv_sec - mono_clock_start)) * 1000
-                       + (ts.tv_nsec / 1000000));
+                       + (uint64_t) (ts.tv_nsec / 1000000));
 #endif /* HAVE_CLOCK_GETTIME */
 #ifdef HAVE_CLOCK_GET_TIME
   if (_MHD_INVALID_CLOCK_SERV != mono_clock_service)
@@ -458,7 +458,7 @@ MHD_monotonic_msec_counter (void)
     if (KERN_SUCCESS == clock_get_time (mono_clock_service,
                                         &cur_time))
       return (uint64_t) (((uint64_t) (cur_time.tv_sec - mono_clock_start))
-                         * 1000 + (cur_time.tv_nsec / 1000000));
+                         * 1000 + (uint64_t) (cur_time.tv_nsec / 1000000));
   }
 #endif /* HAVE_CLOCK_GET_TIME */
 #if defined(_WIN32)
@@ -487,14 +487,14 @@ MHD_monotonic_msec_counter (void)
 #ifdef HAVE_TIMESPEC_GET
   if (TIME_UTC == timespec_get (&ts, TIME_UTC))
     return (uint64_t) (((uint64_t) (ts.tv_sec - gettime_start)) * 1000
-                       + (ts.tv_nsec / 1000000));
+                       + (uint64_t) (ts.tv_nsec / 1000000));
 #elif defined(HAVE_GETTIMEOFDAY)
   if (1)
   {
     struct timeval tv;
     if (0 == gettimeofday (&tv, NULL))
       return (uint64_t) (((uint64_t) (tv.tv_sec - gettime_start)) * 1000
-                         + (tv.tv_usec / 1000));
+                         + (uint64_t) (tv.tv_usec / 1000));
   }
 #endif /* HAVE_GETTIMEOFDAY */
 
diff --git a/src/microhttpd/mhd_send.c b/src/microhttpd/mhd_send.c
index 18328e7e..c607a4c8 100644
--- a/src/microhttpd/mhd_send.c
+++ b/src/microhttpd/mhd_send.c
@@ -125,11 +125,15 @@ iov_max_init_ (void)
 {
   long res = sysconf (_SC_IOV_MAX);
   if (res >= 0)
-    mhd_iov_max_ = res;
-#if defined(IOV_MAX)
+    mhd_iov_max_ = (unsigned long) res;
   else
+  {
+#if defined(IOV_MAX)
     mhd_iov_max_ = IOV_MAX;
-#endif /* IOV_MAX */
+#else  /* ! IOV_MAX */
+    mhd_iov_max_ = 8; /* Should be the safe limit */
+#endif /* ! IOV_MAX */
+  }
 }
 
 
@@ -1399,7 +1403,6 @@ send_iov_nontls (struct MHD_Connection *connection,
                  bool push_data)
 {
   ssize_t res;
-  ssize_t total_sent;
   size_t items_to_send;
 #ifdef HAVE_SENDMSG
   struct msghdr msg;
@@ -1501,35 +1504,38 @@ send_iov_nontls (struct MHD_Connection *connection,
   }
 
   /* Some data has been sent */
-  total_sent = res;
-  /* Adjust the internal tracking information for the iovec to
-   * take this last send into account. */
-  while ((0 != res) && (r_iov->iov[r_iov->sent].iov_len <= (size_t) res))
+  if (1)
   {
-    res -= r_iov->iov[r_iov->sent].iov_len;
-    r_iov->sent++; /* The iov element has been completely sent */
-    mhd_assert ((r_iov->cnt > r_iov->sent) || (0 == res));
-  }
+    size_t track_sent = (size_t) res;
+    /* Adjust the internal tracking information for the iovec to
+     * take this last send into account. */
+    while ((0 != track_sent) && (r_iov->iov[r_iov->sent].iov_len <= 
track_sent))
+    {
+      track_sent -= r_iov->iov[r_iov->sent].iov_len;
+      r_iov->sent++; /* The iov element has been completely sent */
+      mhd_assert ((r_iov->cnt > r_iov->sent) || (0 == track_sent));
+    }
 
-  if (r_iov->cnt == r_iov->sent)
-    post_send_setopt (connection, true, push_data);
-  else
-  {
+    if (r_iov->cnt == r_iov->sent)
+      post_send_setopt (connection, true, push_data);
+    else
+    {
 #ifdef EPOLL_SUPPORT
-    connection->epoll_state &=
-      ~((enum MHD_EpollState) MHD_EPOLL_STATE_WRITE_READY);
+      connection->epoll_state &=
+        ~((enum MHD_EpollState) MHD_EPOLL_STATE_WRITE_READY);
 #endif /* EPOLL_SUPPORT */
-    if (0 != res)
-    {
-      mhd_assert (r_iov->cnt > r_iov->sent);
-      /* The last iov element has been partially sent */
-      r_iov->iov[r_iov->sent].iov_base =
-        (void *) ((uint8_t *) r_iov->iov[r_iov->sent].iov_base + (size_t) res);
-      r_iov->iov[r_iov->sent].iov_len -= (MHD_iov_size_) res;
+      if (0 != track_sent)
+      {
+        mhd_assert (r_iov->cnt > r_iov->sent);
+        /* The last iov element has been partially sent */
+        r_iov->iov[r_iov->sent].iov_base =
+          (void *) ((uint8_t *) r_iov->iov[r_iov->sent].iov_base + track_sent);
+        r_iov->iov[r_iov->sent].iov_len -= (MHD_iov_size_) track_sent;
+      }
     }
   }
 
-  return total_sent;
+  return res;
 }
 
 
@@ -1567,7 +1573,7 @@ send_iov_emu (struct MHD_Connection *connection,
   do
   {
     if ((size_t) SSIZE_MAX - total_sent < r_iov->iov[r_iov->sent].iov_len)
-      return total_sent; /* return value would overflow */
+      return (ssize_t) total_sent; /* return value would overflow */
 
     res = MHD_send_data_ (connection,
                           r_iov->iov[r_iov->sent].iov_base,
@@ -1580,7 +1586,7 @@ send_iov_emu (struct MHD_Connection *connection,
         return res; /* Nothing was sent, return result as is */
 
       if (MHD_ERR_AGAIN_ == res)
-        return total_sent; /* Some data has been sent, return the amount */
+        return (ssize_t) total_sent; /* Return the amount of the sent data */
 
       return res; /* Any kind of a hard error */
     }
@@ -1589,13 +1595,14 @@ send_iov_emu (struct MHD_Connection *connection,
 
     if (r_iov->iov[r_iov->sent].iov_len != (size_t) res)
     {
+      const size_t sent = (size_t) res;
       /* Incomplete buffer has been sent.
        * Adjust buffer of the last element. */
       r_iov->iov[r_iov->sent].iov_base =
-        (void *) ((uint8_t *) r_iov->iov[r_iov->sent].iov_base + (size_t) res);
-      r_iov->iov[r_iov->sent].iov_len -= res;
+        (void *) ((uint8_t *) r_iov->iov[r_iov->sent].iov_base + sent);
+      r_iov->iov[r_iov->sent].iov_len -= sent;
 
-      return total_sent;
+      return (ssize_t) total_sent;
     }
     /* The iov element has been completely sent */
     r_iov->sent++;
diff --git a/src/microhttpd/mhd_str.c b/src/microhttpd/mhd_str.c
index fdbed4f8..da60b18d 100644
--- a/src/microhttpd/mhd_str.c
+++ b/src/microhttpd/mhd_str.c
@@ -899,12 +899,12 @@ MHD_str_to_uint64_ (const char *str,
       return 0;
 
     res *= 10;
-    res += digit;
+    res += (unsigned int) digit;
     str++;
   } while (isasciidigit (*str));
 
   *out_val = res;
-  return str - start;
+  return (size_t) (str - start);
 }
 
 
@@ -944,7 +944,7 @@ MHD_str_to_uint64_n_ (const char *str,
       return 0;
 
     res *= 10;
-    res += digit;
+    res += (unsigned int) digit;
     i++;
   } while ( (i < maxlen) &&
             isasciidigit (str[i]) );
@@ -984,7 +984,7 @@ MHD_strx_to_uint32_ (const char *str,
                                                                % 16)) ) )
     {
       res *= 16;
-      res += digit;
+      res += (unsigned int) digit;
     }
     else
       return 0;
@@ -994,7 +994,7 @@ MHD_strx_to_uint32_ (const char *str,
 
   if (str - start > 0)
     *out_val = res;
-  return str - start;
+  return (size_t) (str - start);
 }
 
 
@@ -1032,7 +1032,7 @@ MHD_strx_to_uint32_n_ (const char *str,
       return 0;
 
     res *= 16;
-    res += digit;
+    res += (unsigned int) digit;
     i++;
   }
 
@@ -1071,7 +1071,7 @@ MHD_strx_to_uint64_ (const char *str,
                                                                % 16)) ) )
     {
       res *= 16;
-      res += digit;
+      res += (unsigned int) digit;
     }
     else
       return 0;
@@ -1081,7 +1081,7 @@ MHD_strx_to_uint64_ (const char *str,
 
   if (str - start > 0)
     *out_val = res;
-  return str - start;
+  return (size_t) (str - start);
 }
 
 
@@ -1119,7 +1119,7 @@ MHD_strx_to_uint64_n_ (const char *str,
       return 0;
 
     res *= 16;
-    res += digit;
+    res += (unsigned int) digit;
     i++;
   }
 
@@ -1178,7 +1178,7 @@ MHD_str_to_uvalue_n_ (const char *str,
       return 0;
 
     res *= base;
-    res += digit;
+    res += (unsigned int) digit;
     i++;
   }
 
@@ -1330,7 +1330,7 @@ MHD_uint8_to_str_pad (uint8_t val,
   }
   else
   {
-    buf[pos++] = '0' + digit;
+    buf[pos++] = '0' + (char) digit;
     val %= 100;
     min_digits = 2;
   }
@@ -1345,13 +1345,13 @@ MHD_uint8_to_str_pad (uint8_t val,
   }
   else
   {
-    buf[pos++] = '0' + digit;
+    buf[pos++] = '0' + (char) digit;
     val %= 10;
   }
 
   if (buf_size <= pos)
     return 0;
-  buf[pos++] = '0' + val;
+  buf[pos++] = '0' + (char) val;
   return pos;
 }
 
diff --git a/src/microhttpd/postprocessor.c b/src/microhttpd/postprocessor.c
index d32ecc22..39070334 100644
--- a/src/microhttpd/postprocessor.c
+++ b/src/microhttpd/postprocessor.c
@@ -367,20 +367,23 @@ process_value (struct MHD_PostProcessor *pp,
   if ( (NULL != last_escape) &&
        (((size_t) (value_end - last_escape)) < sizeof (pp->xbuf)) )
   {
-    pp->xbuf_pos = value_end - last_escape;
+    mhd_assert (value_end >= last_escape);
+    pp->xbuf_pos = (size_t) (value_end - last_escape);
     memcpy (pp->xbuf,
             last_escape,
-            value_end - last_escape);
+            (size_t) (value_end - last_escape));
     value_end = last_escape;
   }
   while ( (value_start != value_end) ||
           (pp->must_ikvi) ||
           (xoff > 0) )
   {
-    size_t delta = value_end - value_start;
+    size_t delta = (size_t) (value_end - value_start);
     bool cut = false;
     size_t clen = 0;
 
+    mhd_assert (value_end >= value_start);
+
     if (delta > XBUF_SIZE - xoff)
       delta = XBUF_SIZE - xoff;
     /* move (additional) input into processing buffer */
@@ -660,7 +663,8 @@ post_process_urlencoded (struct MHD_PostProcessor *pp,
       mhd_assert ((NULL != end_key) || (NULL == start_key));
       if (1)
       {
-        const size_t key_len = end_key - start_key;
+        const size_t key_len = (size_t) (end_key - start_key);
+        mhd_assert (end_key >= start_key);
         if (0 != key_len)
         {
           if ( (pp->buffer_pos + key_len >= pp->buffer_size) ||
@@ -725,7 +729,8 @@ post_process_urlencoded (struct MHD_PostProcessor *pp,
     mhd_assert ((PP_ProcessKey == pp->state) || (NULL != end_key));
     if (NULL == end_key)
       end_key = &post_data[poff];
-    key_len = end_key - start_key;
+    mhd_assert (end_key >= start_key);
+    key_len = (size_t) (end_key - start_key);
     mhd_assert (0 != key_len); /* it must be always non-zero here */
     if (pp->buffer_pos + key_len >= pp->buffer_size)
     {
@@ -854,13 +859,13 @@ find_boundary (struct MHD_PostProcessor *pp,
                      '-',
                      pp->buffer_pos);
       if (NULL == dash)
-        (*ioffptr) += pp->buffer_pos;  /* skip entire buffer */
+        (*ioffptr) += pp->buffer_pos;         /* skip entire buffer */
       else if (dash == buf)
-        (*ioffptr)++;                  /* at least skip one byte */
+        (*ioffptr)++;                         /* at least skip one byte */
       else
-        (*ioffptr) += dash - buf;      /* skip to first possible boundary */
+        (*ioffptr) += (size_t) (dash - buf);  /* skip to first possible 
boundary */
     }
-    return MHD_NO;                     /* expected boundary */
+    return MHD_NO;                            /* expected boundary */
   }
   /* remove boundary from buffer */
   (*ioffptr) += 2 + blen;
@@ -908,7 +913,7 @@ try_get_value (const char *buf,
     if (NULL == (endv = strchr (&spos[klen + 2],
                                 '\"')))
       return;                   /* no end-quote */
-    vlen = endv - spos - klen - 1;
+    vlen = (size_t) (endv - spos) - klen - 1;
     *destination = malloc (vlen);
     if (NULL == *destination)
       return;                   /* out of memory */
@@ -1037,7 +1042,7 @@ process_value_to_boundary (struct MHD_PostProcessor *pp,
         newline = pp->buffer_pos - 4;
         break;
       }
-      newline = r - buf;
+      newline = (size_t) (r - buf);
       if (0 == memcmp ("\r\n--",
                        &buf[newline],
                        4))
diff --git a/src/microhttpd/response.c b/src/microhttpd/response.c
index 47e28046..fd3cd192 100644
--- a/src/microhttpd/response.c
+++ b/src/microhttpd/response.c
@@ -213,11 +213,11 @@ add_response_header_connection (struct MHD_Response 
*response,
   /** the length of the "Connection" key */
   static const size_t key_len =
     MHD_STATICSTR_LEN_ (MHD_HTTP_HEADER_CONNECTION);
-  size_t value_len;  /**< the length of the @a value */
+  size_t value_len; /**< the length of the @a value */
   size_t old_value_len; /**< the length of the existing "Connection" value */
-  size_t buf_size;   /**< the size of the buffer */
-  ssize_t norm_len;  /**< the length of the normalised value */
-  char *buf;         /**< the temporal buffer */
+  size_t buf_size;  /**< the size of the buffer */
+  size_t norm_len;  /**< the length of the normalised value */
+  char *buf;        /**< the temporal buffer */
   struct MHD_HTTP_Res_Header *hdr; /**< existing "Connection" header */
   bool value_has_close; /**< the @a value has "close" token */
   bool already_has_close; /**< existing "Connection" header has "close" token 
*/
@@ -253,19 +253,29 @@ add_response_header_connection (struct MHD_Response 
*response,
   value_len = strlen (value);
   if (value_len >= SSIZE_MAX)
     return MHD_NO;
-  /* Additional space for normalisation and zero-termination*/
-  norm_len = (ssize_t) (value_len + value_len / 2 + 1);
+  /* Additional space for normalisation and zero-termination */
+  norm_len = value_len + value_len / 2 + 1;
+  if (norm_len >= SSIZE_MAX)
+    return MHD_NO;
   buf_size = old_value_len + (size_t) norm_len;
 
   buf = malloc (buf_size);
   if (NULL == buf)
     return MHD_NO;
-  /* Remove "close" token (if any), it will be moved to the front */
-  value_has_close = MHD_str_remove_token_caseless_ (value, value_len, "close",
-                                                    MHD_STATICSTR_LEN_ ( \
-                                                      "close"),
-                                                    buf + old_value_len,
-                                                    &norm_len);
+  if (1)
+  { /* local scope */
+    ssize_t norm_len_s = (ssize_t) norm_len;
+    /* Remove "close" token (if any), it will be moved to the front */
+    value_has_close = MHD_str_remove_token_caseless_ (value, value_len, 
"close",
+                                                      MHD_STATICSTR_LEN_ ( \
+                                                        "close"),
+                                                      buf + old_value_len,
+                                                      &norm_len_s);
+    mhd_assert (0 <= norm_len_s);
+    if (0 > norm_len_s)
+      norm_len = 0; /* Must never happen */
+    norm_len = (size_t) norm_len;
+  }
 #ifdef UPGRADE_SUPPORT
   if ( (NULL != response->upgrade_handler) && value_has_close)
   { /* The "close" token cannot be used with connection "upgrade" */
@@ -273,17 +283,10 @@ add_response_header_connection (struct MHD_Response 
*response,
     return MHD_NO;
   }
 #endif /* UPGRADE_SUPPORT */
-  mhd_assert (0 <= norm_len);
-  if (0 > norm_len)
-    norm_len = 0; /* Must never happen */
   if (0 != norm_len)
-  {
-    size_t len = norm_len;
-    MHD_str_remove_tokens_caseless_ (buf + old_value_len, &len,
+    MHD_str_remove_tokens_caseless_ (buf + old_value_len, &norm_len,
                                      "keep-alive",
                                      MHD_STATICSTR_LEN_ ("keep-alive"));
-    norm_len = (ssize_t) len;
-  }
   if (0 == norm_len)
   { /* New value is empty after normalisation */
     if (! value_has_close)
@@ -301,7 +304,7 @@ add_response_header_connection (struct MHD_Response 
*response,
   if (value_has_close && ! already_has_close)
   {
     /* Need to insert "close" token at the first position */
-    mhd_assert (buf_size >= old_value_len + (size_t) norm_len   \
+    mhd_assert (buf_size >= old_value_len + norm_len   \
                 + MHD_STATICSTR_LEN_ ("close, ") + 1);
     if (0 != norm_len)
       memmove (buf + MHD_STATICSTR_LEN_ ("close, ") + old_value_len,
@@ -333,7 +336,7 @@ add_response_header_connection (struct MHD_Response 
*response,
     mhd_assert ((value_has_close && ! already_has_close) ? \
                 (MHD_STATICSTR_LEN_ ("close, ") + old_value_len == pos) : \
                 (old_value_len == pos));
-    pos += (size_t) norm_len;
+    pos += norm_len;
   }
   mhd_assert (buf_size > pos);
   buf[pos] = 0; /* Null terminate the result */
@@ -1116,9 +1119,11 @@ MHD_create_response_from_fd_at_offset (size_t size,
                                        int fd,
                                        off_t offset)
 {
+  if (0 > offset)
+    return NULL;
   return MHD_create_response_from_fd_at_offset64 (size,
                                                   fd,
-                                                  offset);
+                                                  (uint64_t) offset);
 }
 
 
@@ -1631,7 +1636,7 @@ MHD_create_response_from_iovec (const struct MHD_IoVec 
*iov,
     MHD_iovec_ *iov_copy;
     int num_copy_elements = i_cp;
 
-    iov_copy = MHD_calloc_ (num_copy_elements,
+    iov_copy = MHD_calloc_ ((size_t) num_copy_elements, \
                             sizeof(MHD_iovec_));
     if (NULL == iov_copy)
     {
@@ -1662,8 +1667,9 @@ MHD_create_response_from_iovec (const struct MHD_IoVec 
*iov,
       i_cp++;
     }
     mhd_assert (num_copy_elements == i_cp);
+    mhd_assert (0 <= i_cp);
     response->data_iov = iov_copy;
-    response->data_iovcnt = i_cp;
+    response->data_iovcnt = (unsigned int) i_cp;
   }
   return response;
 }

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]