wininet: Properly handle output buffer size in InternetGetCookieW.

This commit is contained in:
Jacek Caban 2012-12-27 17:54:19 +01:00 committed by Alexandre Julliard
parent 8f03c51e55
commit 0c02e35841
4 changed files with 57 additions and 31 deletions

View file

@ -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);
TRACE("Cookie: %s\n", debugstr_w(cookie_data));
if (cookie_count)
cnt += 2; /* '; ' */
cnt += name_len = strlenW(cookie_iter->lpCookieName);
if ((len = strlenW(cookie_iter->lpCookieData))) {
cnt += 1; /* = */
cnt += len;
}
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;
}

View file

@ -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);

View file

@ -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;

View file

@ -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");