Module: wine Branch: master Commit: 0c02e358418986c8139b787d098a1c41c8014254 URL: http://source.winehq.org/git/wine.git/?a=commit;h=0c02e358418986c8139b787d09...
Author: Jacek Caban jacek@codeweavers.com Date: Thu Dec 27 17:54:19 2012 +0100
wininet: Properly handle output buffer size in InternetGetCookieW.
---
dlls/wininet/cookie.c | 75 +++++++++++++++++++++++++--------------- dlls/wininet/http.c | 2 +- dlls/wininet/internet.h | 2 +- dlls/wininet/tests/internet.c | 7 ++++ 4 files changed, 56 insertions(+), 30 deletions(-)
diff --git a/dlls/wininet/cookie.c b/dlls/wininet/cookie.c index 0dd93d9..cd761b1 100644 --- a/dlls/wininet/cookie.c +++ b/dlls/wininet/cookie.c @@ -31,6 +31,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <assert.h> #ifdef HAVE_UNISTD_H # include <unistd.h> #endif @@ -529,9 +530,10 @@ static void COOKIE_deleteDomain(cookie_domain *deadDomain) heap_free(deadDomain); }
-BOOL get_cookie(const WCHAR *host, const WCHAR *path, WCHAR *cookie_data, DWORD *size) +DWORD get_cookie(const WCHAR *host, const WCHAR *path, WCHAR *cookie_data, DWORD *size) { - unsigned cnt = 0, len, domain_count = 0, cookie_count = 0; + unsigned cnt = 0, len, name_len, domain_count = 0, cookie_count = 0; + WCHAR *ptr = cookie_data; cookie_domain *domain; FILETIME tm;
@@ -562,49 +564,62 @@ BOOL get_cookie(const WCHAR *host, const WCHAR *path, WCHAR *cookie_data, DWORD continue; }
- if(!cookie_data) { /* return the size of the buffer required to lpdwSize */ - if (cookie_count) - cnt += 2; /* '; ' */ - cnt += strlenW(cookie_iter->lpCookieName); - if ((len = strlenW(cookie_iter->lpCookieData))) { - cnt += 1; /* = */ - cnt += len; - } - }else { - static const WCHAR szsc[] = { ';',' ',0 }; - static const WCHAR szname[] = { '%','s',0 }; - static const WCHAR szdata[] = { '=','%','s',0 }; - - if (cookie_count) cnt += snprintfW(cookie_data + cnt, *size - cnt, szsc); - cnt += snprintfW(cookie_data + cnt, *size - cnt, szname, cookie_iter->lpCookieName); - - if (cookie_iter->lpCookieData[0]) - cnt += snprintfW(cookie_data + cnt, *size - cnt, szdata, cookie_iter->lpCookieData); + if (cookie_count) + cnt += 2; /* '; ' */ + cnt += name_len = strlenW(cookie_iter->lpCookieName); + if ((len = strlenW(cookie_iter->lpCookieData))) { + cnt += 1; /* = */ + cnt += len; + }
- TRACE("Cookie: %s\n", debugstr_w(cookie_data)); + if(ptr) { + if(*size > cnt) { + if(cookie_count) { + *ptr++ = ';'; + *ptr++ = ' '; + } + + memcpy(ptr, cookie_iter->lpCookieName, name_len*sizeof(WCHAR)); + ptr += name_len; + + if(len) { + *ptr++ = '='; + memcpy(ptr, cookie_iter->lpCookieData, len*sizeof(WCHAR)); + ptr += len; + } + + assert(cookie_data+cnt == ptr); + TRACE("Cookie: %s\n", debugstr_wn(cookie_data, cnt)); + }else { + /* Stop writing data, just compute the size */ + ptr = NULL; + } } + cookie_count++; } }
LeaveCriticalSection(&cookie_cs);
- if (!domain_count) { + if(ptr) + *ptr = 0; + + if (!cnt) { TRACE("no cookies found for %s\n", debugstr_w(host)); - SetLastError(ERROR_NO_MORE_ITEMS); - return FALSE; + return ERROR_NO_MORE_ITEMS; }
- if(!cookie_data) { + if(!cookie_data || !ptr) { *size = (cnt + 1) * sizeof(WCHAR); TRACE("returning %u\n", *size); - return TRUE; + return cookie_data ? ERROR_INSUFFICIENT_BUFFER : ERROR_SUCCESS; }
*size = cnt + 1;
TRACE("Returning %u (from %u domains): %s\n", cnt, domain_count, debugstr_w(cookie_data)); - return cnt != 0; + return ERROR_SUCCESS; }
/*********************************************************************** @@ -624,6 +639,7 @@ BOOL WINAPI InternetGetCookieW(LPCWSTR lpszUrl, LPCWSTR lpszCookieName, LPWSTR lpCookieData, LPDWORD lpdwSize) { WCHAR host[INTERNET_MAX_HOST_NAME_LENGTH], path[INTERNET_MAX_PATH_LENGTH]; + DWORD res; BOOL ret;
TRACE("(%s, %s, %p, %p)\n", debugstr_w(lpszUrl),debugstr_w(lpszCookieName), lpCookieData, lpdwSize); @@ -641,7 +657,10 @@ BOOL WINAPI InternetGetCookieW(LPCWSTR lpszUrl, LPCWSTR lpszCookieName, return FALSE; }
- return get_cookie(host, path, lpCookieData, lpdwSize); + res = get_cookie(host, path, lpCookieData, lpdwSize); + if(res != ERROR_SUCCESS) + SetLastError(res); + return res == ERROR_SUCCESS; }
diff --git a/dlls/wininet/http.c b/dlls/wininet/http.c index f890363..9e3e8e4 100644 --- a/dlls/wininet/http.c +++ b/dlls/wininet/http.c @@ -4008,7 +4008,7 @@ static void HTTP_InsertCookies(http_request_t *request) if(!host) return;
- if(!get_cookie(host->lpszValue, request->path, NULL, &cookie_size)) + if(get_cookie(host->lpszValue, request->path, NULL, &cookie_size) != ERROR_SUCCESS) return;
size = sizeof(cookieW) + cookie_size * sizeof(WCHAR) + sizeof(szCrLf); diff --git a/dlls/wininet/internet.h b/dlls/wininet/internet.h index 10002d4..3d2bd35 100644 --- a/dlls/wininet/internet.h +++ b/dlls/wininet/internet.h @@ -517,7 +517,7 @@ DWORD HTTP_Connect(appinfo_t*,LPCWSTR, BOOL GetAddress(LPCWSTR lpszServerName, INTERNET_PORT nServerPort, struct sockaddr *psa, socklen_t *sa_len) DECLSPEC_HIDDEN;
-BOOL get_cookie(const WCHAR*,const WCHAR*,WCHAR*,DWORD*) DECLSPEC_HIDDEN; +DWORD get_cookie(const WCHAR*,const WCHAR*,WCHAR*,DWORD*) DECLSPEC_HIDDEN; BOOL set_cookie(const WCHAR*,const WCHAR*,const WCHAR*,const WCHAR*) DECLSPEC_HIDDEN;
void INTERNET_SetLastError(DWORD dwError) DECLSPEC_HIDDEN; diff --git a/dlls/wininet/tests/internet.c b/dlls/wininet/tests/internet.c index 1b4ee46..8b0071c 100644 --- a/dlls/wininet/tests/internet.c +++ b/dlls/wininet/tests/internet.c @@ -426,6 +426,13 @@ static void test_complicated_cookie(void) ok(len == 19, "len = %u\n", len); ok(lstrlenW(wbuf) == 18, "strlenW(wbuf) = %u\n", lstrlenW(wbuf));
+ len = 10; + memset(wbuf, 0xac, sizeof(wbuf)); + ret = InternetGetCookieW(testing_example_comW, NULL, wbuf, &len); + ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, + "InternetGetCookieW returned: %x(%u), expected ERROR_INSUFFICIENT_BUFFER\n", ret, GetLastError()); + ok(len == 38, "len = %u\n", len); + len = 1024; ret = InternetGetCookie("http://testing.example.com/foobar", NULL, buffer, &len); ok(ret == TRUE,"InternetGetCookie failed\n");