Christian Grothoff 9 роки тому
батько
коміт
bf7418b3d9
3 змінених файлів з 36 додано та 17 видалено
  1. 5 0
      ChangeLog
  2. 29 15
      src/microhttpd/connection.c
  3. 2 2
      src/microhttpd/internal.h

+ 5 - 0
ChangeLog

@@ -1,3 +1,8 @@
+Sat Mar 25 20:40:10 CET 2017
+	Allow chunk size > 16 MB (up to 2^64-1). Ignore
+	chunk extensions instead of triggering an error.
+	(fixes #4967). -CG
+
 Tue Mar 25 20:59:18 MSK 2017
 	Check for invalid combinations of flags and options in
 	MHD_start_daemon(). -EG

+ 29 - 15
src/microhttpd/connection.c

@@ -1852,10 +1852,11 @@ call_connection_handler (struct MHD_Connection *connection)
 static void
 process_request_body (struct MHD_Connection *connection)
 {
-  size_t processed;
+  uint64_t processed;
   size_t available;
   size_t used;
   size_t i;
+  size_t end_size;
   int instant_retry;
   int malformed;
   char *buffer_head;
@@ -1872,7 +1873,7 @@ process_request_body (struct MHD_Connection *connection)
            (MHD_SIZE_UNKNOWN == connection->remaining_upload_size) )
         {
           if ( (connection->current_chunk_offset == connection->current_chunk_size) &&
-               (0 != connection->current_chunk_offset) &&
+               (0LLU != connection->current_chunk_offset) &&
                (available >= 2) )
             {
               /* skip new line at the *end* of a chunk */
@@ -1915,28 +1916,41 @@ process_request_body (struct MHD_Connection *connection)
               while (i < available)
                 {
                   if ( ('\r' == buffer_head[i]) ||
-                       ('\n' == buffer_head[i]) )
+                       ('\n' == buffer_head[i]) ||
+		       (';' == buffer_head[i]) )
                     break;
                   i++;
-                  if (i >= 6)
+                  if (i >= 16)
                     break;
                 }
-              /* take '\n' into account; if '\n'
-                 is the unavailable character, we
-                 will need to wait until we have it
+	      end_size = i;
+	      /* find beginning of CRLF (skip over chunk extensions) */
+	      if (';' == buffer_head[i])
+		{
+		  while (i < available)
+		  {
+		    if ( ('\r' == buffer_head[i]) ||
+			 ('\n' == buffer_head[i]) )
+		      break;
+		    i++;
+		  }
+		}	      
+              /* take '\n' into account; if '\n' is the unavailable
+                 character, we will need to wait until we have it
                  before going further */
               if ( (i + 1 >= available) &&
                    ! ( (1 == i) &&
                        (2 == available) &&
                        ('0' == buffer_head[0]) ) )
                 break;          /* need more data... */
-              malformed = (i >= 6);
+	      i++;
+              malformed = (end_size >= 16);
               if (! malformed)
                 {
-                  size_t num_dig = MHD_strx_to_sizet_n_ (buffer_head,
-                                                         i,
-                                                         &connection->current_chunk_size);
-                  malformed = (i != num_dig);
+                  size_t num_dig = MHD_strx_to_uint64_n_ (buffer_head,
+							  end_size,
+							  &connection->current_chunk_size);
+                  malformed = (end_size != num_dig);
                 }
               if (malformed)
                 {
@@ -1945,11 +1959,11 @@ process_request_body (struct MHD_Connection *connection)
 					  _("Received malformed HTTP request (bad chunked encoding). Closing connection.\n"));
                   return;
                 }
-              i++;
+	      /* skip 2nd part of line feed */
               if ( (i < available) &&
                    ( ('\r' == buffer_head[i]) ||
                      ('\n' == buffer_head[i]) ) )
-                i++;            /* skip 2nd part of line feed */
+                i++;            
 
               buffer_head += i;
               available -= i;
@@ -1957,7 +1971,7 @@ process_request_body (struct MHD_Connection *connection)
 
               if (available > 0)
                 instant_retry = MHD_YES;
-              if (0 == connection->current_chunk_size)
+              if (0LLU == connection->current_chunk_size)
                 {
                   connection->remaining_upload_size = 0;
                   break;

+ 2 - 2
src/microhttpd/internal.h

@@ -863,13 +863,13 @@ struct MHD_Connection
    * otherwise, this is the size of the current chunk.  A value of
    * zero is also used when we're at the end of the chunks.
    */
-  size_t current_chunk_size;
+  uint64_t current_chunk_size;
 
   /**
    * If we are receiving with chunked encoding, where are we currently
    * with respect to the current chunk (at what offset / position)?
    */
-  size_t current_chunk_offset;
+  uint64_t current_chunk_offset;
 
   /**
    * Handler used for processing read connection operations