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