Signed-off-by: Daniel Lehman dlehman25@gmail.com --- v3: - more tests - check errno v2: - just use strtoulW with overflow check - make this patch first since it's really 0003 that needs it --- dlls/wininet/http.c | 22 +++++++++-- dlls/wininet/tests/http.c | 82 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+), 3 deletions(-)
diff --git a/dlls/wininet/http.c b/dlls/wininet/http.c index 538fc2bf6b..3230749d40 100644 --- a/dlls/wininet/http.c +++ b/dlls/wininet/http.c @@ -42,6 +42,7 @@ #include <stdio.h> #include <time.h> #include <assert.h> +#include <errno.h>
#include "windef.h" #include "winbase.h" @@ -3724,9 +3725,24 @@ static DWORD HTTP_HttpQueryInfoW(http_request_t *request, DWORD dwInfoLevel, /* coalesce value to requested type */ if (dwInfoLevel & HTTP_QUERY_FLAG_NUMBER && lpBuffer) { - *(int *)lpBuffer = atoiW(lphttpHdr->lpszValue); - TRACE(" returning number: %d\n", *(int *)lpBuffer); - } + unsigned long value; + + if (*lpdwBufferLength != sizeof(DWORD)) + { + LeaveCriticalSection( &request->headers_section ); + return ERROR_HTTP_INVALID_HEADER; + } + + value = strtoulW( lphttpHdr->lpszValue, NULL, 10 ); + if (value > UINT_MAX || (value == ULONG_MAX && errno == ERANGE)) + { + LeaveCriticalSection( &request->headers_section ); + return ERROR_HTTP_INVALID_HEADER; + } + + *(DWORD *)lpBuffer = value; + TRACE(" returning number: %u\n", *(DWORD *)lpBuffer); + } else if (dwInfoLevel & HTTP_QUERY_FLAG_SYSTEMTIME && lpBuffer) { time_t tmpTime; diff --git a/dlls/wininet/tests/http.c b/dlls/wininet/tests/http.c index cb96abe612..fcbd95b837 100644 --- a/dlls/wininet/tests/http.c +++ b/dlls/wininet/tests/http.c @@ -23,6 +23,7 @@ #include <stdarg.h> #include <stdio.h> #include <stdlib.h> +#include <limits.h>
#include "windef.h" #include "winbase.h" @@ -2061,6 +2062,12 @@ static const char okmsg2[] = "Set-Cookie: two\r\n" "\r\n";
+static DWORD64 content_length; +static const char largemsg[] = +"HTTP/1.1 200 OK\r\n" +"Content-Length: %I64u\r\n" +"\r\n"; + static const char notokmsg[] = "HTTP/1.1 400 Bad Request\r\n" "Server: winetest\r\n" @@ -2455,6 +2462,12 @@ static DWORD CALLBACK server_thread(LPVOID param) { send(c, okmsg, sizeof(okmsg)-1, 0); } + if (strstr(buffer, "HEAD /test_large_content")) + { + char msg[sizeof(largemsg) + 16]; + sprintf(msg, largemsg, content_length); + send(c, msg, strlen(msg), 0); + } shutdown(c, 2); closesocket(c); c = -1; @@ -5515,6 +5528,74 @@ static void test_remove_dot_segments(int port) close_request(&req); }
+struct large_test +{ + DWORD64 content_length; + BOOL ret; +}; + +static void test_large_content(int port) +{ + struct large_test tests[] = { + { 0, TRUE }, + { UINT_MAX-1, TRUE }, + { UINT_MAX, TRUE }, + { (DWORD64)UINT_MAX+1, FALSE }, + { ~0, FALSE }, + }; + test_request_t req; + DWORD sizelen, len; + DWORD64 len64; + BOOL ret; + size_t i; + + open_simple_request(&req, "localhost", port, "HEAD", "/test_large_content"); + + for (i = 0; i < ARRAY_SIZE(tests); i++) + { + content_length = tests[i].content_length; + ret = HttpSendRequestA(req.request, NULL, 0, NULL, 0); + ok(ret, "HttpSendRequest failed: %u\n", GetLastError()); + + len = ~0; + sizelen = sizeof(len); + SetLastError(0xdeadbeef); + ret = HttpQueryInfoA(req.request, HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_CONTENT_LENGTH, + &len, &sizelen, 0); + if (tests[i].ret) + { + ok(ret, "HttpQueryInfo should have succeeded\n"); + ok(GetLastError() == ERROR_SUCCESS || + broken(GetLastError() == 0xdeadbeef), /* xp, 2k8, vista */ + "expected ERROR_SUCCESS, got %x\n", GetLastError()); + ok(len == (DWORD)tests[i].content_length, "expected %u, got %u\n", + (DWORD)tests[i].content_length, len); + } + else + { + ok(!ret, "HttpQueryInfo should have failed\n"); + ok(GetLastError() == ERROR_HTTP_INVALID_HEADER, + "expected ERROR_HTTP_INVALID_HEADER, got %x\n", GetLastError()); + ok(len == ~0, "expected ~0, got %u\n", len); + } + ok(sizelen == sizeof(DWORD), "sizelen %u\n", sizelen); + } + + /* test argument size */ + len64 = ~0; + sizelen = sizeof(len64); + SetLastError(0xdeadbeef); + ret = HttpQueryInfoA(req.request, HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_CONTENT_LENGTH, + &len64, &len, 0); + ok(!ret, "HttpQueryInfo should have failed\n"); + ok(GetLastError() == ERROR_HTTP_INVALID_HEADER, + "expected ERROR_HTTP_INVALID_HEADER, got %x\n", GetLastError()); + ok(sizelen == sizeof(DWORD64), "sizelen %u\n", sizelen); + ok(len64 == ~0, "len64 %x%08x\n", (DWORD)(len64 >> 32), (DWORD)len64); + + close_request(&req); +} + static void test_http_connection(void) { struct server_info si; @@ -5573,6 +5654,7 @@ static void test_http_connection(void) test_redirect(si.port); test_persistent_connection(si.port); test_remove_dot_segments(si.port); + test_large_content(si.port);
/* send the basic request again to shutdown the server thread */ test_basic_request(si.port, "GET", "/quit");