Hans Leidekker : winhttp: Make sure not to read more data than expected on a redirect.

Alexandre Julliard julliard at winehq.org
Tue Sep 9 05:50:24 CDT 2008


Module: wine
Branch: master
Commit: 7f28c5f87e23fe4a079d1f1fb184228212a39709
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=7f28c5f87e23fe4a079d1f1fb184228212a39709

Author: Hans Leidekker <hans at codeweavers.com>
Date:   Mon Sep  8 22:02:21 2008 +0200

winhttp: Make sure not to read more data than expected on a redirect.

Fixes a bug in automatic redirects with content.

---

 dlls/winhttp/request.c |  213 ++++++++++++++++++++++++------------------------
 1 files changed, 106 insertions(+), 107 deletions(-)

diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c
index 46c6d6d..b11c426 100644
--- a/dlls/winhttp/request.c
+++ b/dlls/winhttp/request.c
@@ -1132,16 +1132,120 @@ static BOOL receive_data( request_t *request, void *buffer, DWORD size, DWORD *r
     return TRUE;
 }
 
+static DWORD get_chunk_size( const char *buffer )
+{
+    const char *p;
+    DWORD size = 0;
+
+    for (p = buffer; *p; p++)
+    {
+        if (*p >= '0' && *p <= '9') size = size * 16 + *p - '0';
+        else if (*p >= 'a' && *p <= 'f') size = size * 16 + *p - 'a' + 10;
+        else if (*p >= 'A' && *p <= 'F') size = size * 16 + *p - 'A' + 10;
+        else if (*p == ';') break;
+    }
+    return size;
+}
+
+static BOOL receive_data_chunked( request_t *request, void *buffer, DWORD size, DWORD *read, BOOL async )
+{
+    char reply[MAX_REPLY_LEN], *p = buffer;
+    DWORD buflen, to_read, to_write = size;
+    int bytes_read;
+
+    *read = 0;
+    for (;;)
+    {
+        if (*read == size) break;
+
+        if (request->content_length == ~0UL) /* new chunk */
+        {
+            buflen = sizeof(reply);
+            if (!netconn_get_next_line( &request->netconn, reply, &buflen )) break;
+
+            if (!(request->content_length = get_chunk_size( reply )))
+            {
+                /* zero sized chunk marks end of transfer; read any trailing headers and return */
+                read_reply( request, FALSE );
+                break;
+            }
+        }
+        to_read = min( to_write, request->content_length - request->content_read );
+
+        if (!netconn_recv( &request->netconn, p, to_read, async ? 0 : MSG_WAITALL, &bytes_read ))
+        {
+            if (bytes_read != to_read)
+            {
+                ERR("Not all data received %d/%d\n", bytes_read, to_read);
+            }
+            /* always return success, even if the network layer returns an error */
+            *read = 0;
+            break;
+        }
+        if (!bytes_read) break;
+
+        request->content_read += bytes_read;
+        to_write -= bytes_read;
+        *read += bytes_read;
+        p += bytes_read;
+
+        if (request->content_read == request->content_length) /* chunk complete */
+        {
+            request->content_read = 0;
+            request->content_length = ~0UL;
+
+            buflen = sizeof(reply);
+            if (!netconn_get_next_line( &request->netconn, reply, &buflen ))
+            {
+                ERR("Malformed chunk\n");
+                *read = 0;
+                break;
+            }
+        }
+    }
+    return TRUE;
+}
+
+static BOOL read_data( request_t *request, void *buffer, DWORD to_read, DWORD *read, BOOL async )
+{
+    static const WCHAR chunked[] = {'c','h','u','n','k','e','d',0};
+
+    BOOL ret;
+    WCHAR encoding[20];
+    DWORD num_bytes, buflen = sizeof(encoding);
+
+    if (query_headers( request, WINHTTP_QUERY_TRANSFER_ENCODING, NULL, encoding, &buflen, NULL ) &&
+        !strcmpiW( encoding, chunked ))
+    {
+        ret = receive_data_chunked( request, buffer, to_read, &num_bytes, async );
+    }
+    else
+        ret = receive_data( request, buffer, to_read, &num_bytes, async );
+
+    if (async)
+    {
+        if (ret) send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_READ_COMPLETE, buffer, num_bytes );
+        else
+        {
+            WINHTTP_ASYNC_RESULT result;
+            result.dwResult = API_READ_DATA;
+            result.dwError  = get_last_error();
+            send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, &result, sizeof(result) );
+        }
+    }
+    if (ret && read) *read = num_bytes;
+    return ret;
+}
+
 /* read any content returned by the server so that the connection can be reused */
 static void drain_content( request_t *request )
 {
     DWORD bytes_read;
     char buffer[2048];
 
-    if (request->content_length == ~0UL) return;
     for (;;)
     {
-        if (!receive_data( request, buffer, sizeof(buffer), &bytes_read, FALSE ) || !bytes_read) return;
+        if (!read_data( request, buffer, sizeof(buffer), &bytes_read, FALSE ) || !bytes_read) return;
     }
 }
 
@@ -1321,111 +1425,6 @@ BOOL WINAPI WinHttpQueryDataAvailable( HINTERNET hrequest, LPDWORD available )
     return ret;
 }
 
-static DWORD get_chunk_size( const char *buffer )
-{
-    const char *p;
-    DWORD size = 0;
-
-    for (p = buffer; *p; p++)
-    {
-        if (*p >= '0' && *p <= '9') size = size * 16 + *p - '0';
-        else if (*p >= 'a' && *p <= 'f') size = size * 16 + *p - 'a' + 10;
-        else if (*p >= 'A' && *p <= 'F') size = size * 16 + *p - 'A' + 10;
-        else if (*p == ';') break;
-    }
-    return size;
-}
-
-static BOOL receive_data_chunked( request_t *request, void *buffer, DWORD size, DWORD *read, BOOL async )
-{
-    char reply[MAX_REPLY_LEN], *p = buffer;
-    DWORD buflen, to_read, to_write = size;
-    int bytes_read;
-
-    *read = 0;
-    for (;;)
-    {
-        if (*read == size) break;
-
-        if (request->content_length == ~0UL) /* new chunk */
-        {
-            buflen = sizeof(reply);
-            if (!netconn_get_next_line( &request->netconn, reply, &buflen )) break;
-
-            if (!(request->content_length = get_chunk_size( reply )))
-            {
-                /* zero sized chunk marks end of transfer; read any trailing headers and return */
-                read_reply( request, FALSE );
-                break;
-            }
-        }
-        to_read = min( to_write, request->content_length - request->content_read );
-
-        if (!netconn_recv( &request->netconn, p, to_read, async ? 0 : MSG_WAITALL, &bytes_read ))
-        {
-            if (bytes_read != to_read)
-            {
-                ERR("Not all data received %d/%d\n", bytes_read, to_read);
-            }
-            /* always return success, even if the network layer returns an error */
-            *read = 0;
-            break;
-        }
-        if (!bytes_read) break;
-
-        request->content_read += bytes_read;
-        to_write -= bytes_read;
-        *read += bytes_read;
-        p += bytes_read;
-
-        if (request->content_read == request->content_length) /* chunk complete */
-        {
-            request->content_read = 0;
-            request->content_length = ~0UL;
-
-            buflen = sizeof(reply);
-            if (!netconn_get_next_line( &request->netconn, reply, &buflen ))
-            {
-                ERR("Malformed chunk\n");
-                *read = 0;
-                break;
-            }
-        }
-    }
-    return TRUE;
-}
-
-static BOOL read_data( request_t *request, void *buffer, DWORD to_read, DWORD *read, BOOL async )
-{
-    static const WCHAR chunked[] = {'c','h','u','n','k','e','d',0};
-
-    BOOL ret;
-    WCHAR encoding[20];
-    DWORD num_bytes, buflen = sizeof(encoding);
-
-    if (query_headers( request, WINHTTP_QUERY_TRANSFER_ENCODING, NULL, encoding, &buflen, NULL ) &&
-        !strcmpiW( encoding, chunked ))
-    {
-        ret = receive_data_chunked( request, buffer, to_read, &num_bytes, async );
-    }
-    else
-        ret = receive_data( request, buffer, to_read, &num_bytes, async );
-
-    if (async)
-    {
-        if (ret) send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_READ_COMPLETE, buffer, num_bytes );
-        else
-        {
-            WINHTTP_ASYNC_RESULT result;
-            result.dwResult = API_READ_DATA;
-            result.dwError  = get_last_error();
-            send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, &result, sizeof(result) );
-        }
-    }
-    if (ret && read) *read = num_bytes;
-    return ret;
-}
-
 static void task_read_data( task_header_t *task )
 {
     read_data_t *r = (read_data_t *)task;




More information about the wine-cvs mailing list