Jacek Caban : wininet: Don' t return available data sizes larger than the read buffer.

Alexandre Julliard julliard at winehq.org
Mon Aug 15 10:37:29 CDT 2016


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

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Fri Aug 12 18:08:21 2016 +0200

wininet: Don't return available data sizes larger than the read buffer.

Based on patch by Hans Leidekker.

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/wininet/http.c       | 11 +++++++-
 dlls/wininet/tests/http.c | 65 ++++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 69 insertions(+), 7 deletions(-)

diff --git a/dlls/wininet/http.c b/dlls/wininet/http.c
index ac79404..b51c6c9 100644
--- a/dlls/wininet/http.c
+++ b/dlls/wininet/http.c
@@ -2621,7 +2621,16 @@ static DWORD refill_read_buffer(http_request_t *req, blocking_mode_t blocking_mo
 /* return the size of data available to be read immediately (the read section must be held) */
 static DWORD get_avail_data( http_request_t *req )
 {
-    return req->read_size + req->data_stream->vtbl->get_avail_data(req->data_stream, req);
+    DWORD avail = req->read_size;
+
+    /*
+     * Different Windows versions have different limits of returned data, but all
+     * of them return no more than centrain amount. We use READ_BUFFER_SIZE as a limit.
+     */
+    if(avail < READ_BUFFER_SIZE)
+        avail += req->data_stream->vtbl->get_avail_data(req->data_stream, req);
+
+    return min(avail, READ_BUFFER_SIZE);
 }
 
 static DWORD netconn_get_avail_data(data_stream_t *stream, http_request_t *req)
diff --git a/dlls/wininet/tests/http.c b/dlls/wininet/tests/http.c
index bf3f690..fc68fe1 100644
--- a/dlls/wininet/tests/http.c
+++ b/dlls/wininet/tests/http.c
@@ -4622,11 +4622,10 @@ static void open_read_test_request(int port, test_request_t *req, const char *re
     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
 }
 
-#define readex_expect_sync_data(a,b,c,d,e) _readex_expect_sync_data(__LINE__,a,b,c,d,e)
-static void _readex_expect_sync_data(unsigned line, HINTERNET req, DWORD flags, INTERNET_BUFFERSW *buf,
-        DWORD buf_size, const char *exdata)
+#define readex_expect_sync_data_len(a,b,c,d,e,f) _readex_expect_sync_data_len(__LINE__,a,b,c,d,e,f)
+static void _readex_expect_sync_data_len(unsigned line, HINTERNET req, DWORD flags, INTERNET_BUFFERSW *buf,
+        DWORD buf_size, const char *exdata, DWORD len)
 {
-    DWORD len = strlen(exdata);
     BOOL ret;
 
     SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE);
@@ -4636,12 +4635,19 @@ static void _readex_expect_sync_data(unsigned line, HINTERNET req, DWORD flags,
     ret = InternetReadFileExW(req, buf, flags, 0xdeadbeef);
     ok_(__FILE__,line)(ret, "InternetReadFileExW failed: %u\n", GetLastError());
     ok_(__FILE__,line)(buf->dwBufferLength == len, "dwBufferLength = %u, expected %u\n", buf->dwBufferLength, len);
-    if(len)
+    if(len && exdata)
         ok_(__FILE__,line)(!memcmp(buf->lpvBuffer, exdata, len), "Unexpected data\n");
 
     CLEAR_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
 }
 
+#define readex_expect_sync_data(a,b,c,d,e) _readex_expect_sync_data(__LINE__,a,b,c,d,e)
+static void _readex_expect_sync_data(unsigned line, HINTERNET req, DWORD flags, INTERNET_BUFFERSW *buf,
+        DWORD buf_size, const char *exdata)
+{
+    _readex_expect_sync_data_len(line, req, flags, buf, buf_size, exdata, strlen(exdata));
+}
+
 static void send_response_and_wait(const char *response, BOOL close_connection, INTERNET_BUFFERSW *buf)
 {
     DWORD orig_size = buf->dwBufferLength;
@@ -4666,6 +4672,17 @@ static void send_response_and_wait(const char *response, BOOL close_connection,
     ok(!*(int*)buf->lpvBuffer, "buffer data changed\n");
 }
 
+static void send_response_len_and_wait(unsigned len, BOOL close_connection, INTERNET_BUFFERSW *buf)
+{
+    char *response;
+
+    response = HeapAlloc(GetProcessHeap(), 0, len+1);
+    memset(response, 'x', len);
+    response[len] = 0;
+    send_response_and_wait(response, close_connection, buf);
+    HeapFree(GetProcessHeap(), 0, response);
+}
+
 static void readex_expect_async(HINTERNET req, DWORD flags, INTERNET_BUFFERSW *buf, DWORD buf_size)
 {
     BOOL ret;
@@ -4678,11 +4695,26 @@ static void readex_expect_async(HINTERNET req, DWORD flags, INTERNET_BUFFERSW *b
     ok(!*(int*)buf->lpvBuffer, "buffer data changed\n");
 }
 
+#define expect_data_available(a,b) _expect_data_available(__LINE__,a,b)
+static DWORD _expect_data_available(unsigned line, HINTERNET req, int exsize)
+{
+    DWORD size = 0;
+    BOOL res;
+
+    res = InternetQueryDataAvailable(req, &size, 0, 0);
+    ok_(__FILE__,line)(res, "InternetQueryDataAvailable failed: %u\n", GetLastError());
+    if(exsize != -1)
+        ok_(__FILE__,line)(size  == exsize, "size = %u, expected %u\n", size, exsize);
+
+    return size;
+}
+
 static void test_http_read(int port)
 {
     INTERNET_BUFFERSW ib;
     test_request_t req;
-    char buf[4096];
+    char buf[24000];
+    DWORD avail;
 
     if(!is_ie7plus)
         return;
@@ -4759,6 +4791,27 @@ static void test_http_read(int port)
 
     close_async_handle(req.session, hCompleteEvent, 2);
 
+    trace("Testing InternetQueryDataAvailable...\n");
+
+    open_read_test_request(port, &req,
+                           "HTTP/1.1 200 OK\r\n"
+                           "Server: winetest\r\n"
+                           "\r\n"
+                           "123");
+    expect_data_available(req.request, 3);
+    readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "123");
+    readex_expect_async(req.request, IRF_NO_WAIT, &ib, sizeof(buf));
+
+    send_response_len_and_wait(20000, TRUE, &ib);
+    avail = expect_data_available(req.request, -1);
+    ok(avail < 17000, "avail = %u\n", avail);
+
+    SET_WINE_ALLOW(INTERNET_STATUS_CLOSING_CONNECTION);
+    SET_WINE_ALLOW(INTERNET_STATUS_CONNECTION_CLOSED);
+    close_async_handle(req.session, hCompleteEvent, 2);
+    todo_wine CHECK_NOT_NOTIFIED(INTERNET_STATUS_CLOSING_CONNECTION);
+    todo_wine CHECK_NOT_NOTIFIED(INTERNET_STATUS_CONNECTION_CLOSED);
+
     CloseHandle(hCompleteEvent);
     CloseHandle(conn_wait_event);
     CloseHandle(server_req_rec_event);




More information about the wine-cvs mailing list