Read http request in 4byte chunks until '\r\n\r\n' is found
authorArmin Novak <armin.novak@thincast.com>
Fri, 19 Oct 2018 09:59:28 +0000 (11:59 +0200)
committerArmin Novak <armin.novak@thincast.com>
Fri, 19 Oct 2018 10:16:04 +0000 (12:16 +0200)
Avoid reading too much data in a single call to BIO_read as some
implementations may return a lot more data than is part of the response.

libfreerdp/core/gateway/http.c

index 85248ed..e862d35 100644 (file)
@@ -742,10 +742,12 @@ HttpResponse* http_response_recv(rdpTls* tls)
 
        response->ContentLength = 0;
 
-       while (!payloadOffset)
+       while (payloadOffset == 0)
        {
-               int status = BIO_read(tls->bio, Stream_Pointer(response->data),
-                                     Stream_Capacity(response->data) - Stream_GetPosition(response->data));
+               size_t s;
+               char* end;
+               /* Read until we encounter \r\n\r\n */
+               int status = BIO_read(tls->bio, Stream_Pointer(response->data), 4);
 
                if (status <= 0)
                {
@@ -761,28 +763,26 @@ HttpResponse* http_response_recv(rdpTls* tls)
 #endif
                Stream_Seek(response->data, (size_t)status);
 
-               if (Stream_GetRemainingLength(response->data) < 1024)
-               {
-                       if (!Stream_EnsureRemainingCapacity(response->data, 1024))
-                               goto out_error;
-               }
+               if (!Stream_EnsureRemainingCapacity(response->data, 1024))
+                       goto out_error;
 
                position = Stream_GetPosition(response->data);
 
-               if (position > RESPONSE_SIZE_LIMIT)
+               if (position < 4)
+                       continue;
+               else if (position > RESPONSE_SIZE_LIMIT)
                {
                        WLog_ERR(TAG, "Request header too large! (%"PRIdz" bytes) Aborting!", bodyLength);
                        goto out_error;
                }
 
-               if (position >= 4)
-               {
-                       char* buffer = (char*)Stream_Buffer(response->data);
-                       const char* line = string_strnstr(buffer, "\r\n\r\n", position);
+               /* Always check at most the lase 8 bytes for occurance of the desired
+                * sequence of \r\n\r\n */
+               s = (position > 8) ? 8 : position;
+               end = (char*)Stream_Pointer(response->data) - s;
 
-                       if (line)
-                               payloadOffset = (line - buffer) + 4UL;
-               }
+               if (string_strnstr(end, "\r\n\r\n", s) != NULL)
+                       payloadOffset = Stream_GetPosition(response->data);
        }
 
        if (payloadOffset)