wininet: Properly handle output buffer size in InternetGetCookieW.
This commit is contained in:
parent
8f03c51e55
commit
0c02e35841
|
@ -31,6 +31,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
#ifdef HAVE_UNISTD_H
|
#ifdef HAVE_UNISTD_H
|
||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -529,9 +530,10 @@ static void COOKIE_deleteDomain(cookie_domain *deadDomain)
|
||||||
heap_free(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;
|
cookie_domain *domain;
|
||||||
FILETIME tm;
|
FILETIME tm;
|
||||||
|
|
||||||
|
@ -562,49 +564,62 @@ BOOL get_cookie(const WCHAR *host, const WCHAR *path, WCHAR *cookie_data, DWORD
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!cookie_data) { /* return the size of the buffer required to lpdwSize */
|
if (cookie_count)
|
||||||
if (cookie_count)
|
cnt += 2; /* '; ' */
|
||||||
cnt += 2; /* '; ' */
|
cnt += name_len = strlenW(cookie_iter->lpCookieName);
|
||||||
cnt += strlenW(cookie_iter->lpCookieName);
|
if ((len = strlenW(cookie_iter->lpCookieData))) {
|
||||||
if ((len = strlenW(cookie_iter->lpCookieData))) {
|
cnt += 1; /* = */
|
||||||
cnt += 1; /* = */
|
cnt += len;
|
||||||
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(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++;
|
cookie_count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LeaveCriticalSection(&cookie_cs);
|
LeaveCriticalSection(&cookie_cs);
|
||||||
|
|
||||||
if (!domain_count) {
|
if(ptr)
|
||||||
|
*ptr = 0;
|
||||||
|
|
||||||
|
if (!cnt) {
|
||||||
TRACE("no cookies found for %s\n", debugstr_w(host));
|
TRACE("no cookies found for %s\n", debugstr_w(host));
|
||||||
SetLastError(ERROR_NO_MORE_ITEMS);
|
return ERROR_NO_MORE_ITEMS;
|
||||||
return FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!cookie_data) {
|
if(!cookie_data || !ptr) {
|
||||||
*size = (cnt + 1) * sizeof(WCHAR);
|
*size = (cnt + 1) * sizeof(WCHAR);
|
||||||
TRACE("returning %u\n", *size);
|
TRACE("returning %u\n", *size);
|
||||||
return TRUE;
|
return cookie_data ? ERROR_INSUFFICIENT_BUFFER : ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
*size = cnt + 1;
|
*size = cnt + 1;
|
||||||
|
|
||||||
TRACE("Returning %u (from %u domains): %s\n", cnt, domain_count, debugstr_w(cookie_data));
|
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)
|
LPWSTR lpCookieData, LPDWORD lpdwSize)
|
||||||
{
|
{
|
||||||
WCHAR host[INTERNET_MAX_HOST_NAME_LENGTH], path[INTERNET_MAX_PATH_LENGTH];
|
WCHAR host[INTERNET_MAX_HOST_NAME_LENGTH], path[INTERNET_MAX_PATH_LENGTH];
|
||||||
|
DWORD res;
|
||||||
BOOL ret;
|
BOOL ret;
|
||||||
|
|
||||||
TRACE("(%s, %s, %p, %p)\n", debugstr_w(lpszUrl),debugstr_w(lpszCookieName), lpCookieData, lpdwSize);
|
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 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4008,7 +4008,7 @@ static void HTTP_InsertCookies(http_request_t *request)
|
||||||
if(!host)
|
if(!host)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(!get_cookie(host->lpszValue, request->path, NULL, &cookie_size))
|
if(get_cookie(host->lpszValue, request->path, NULL, &cookie_size) != ERROR_SUCCESS)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
size = sizeof(cookieW) + cookie_size * sizeof(WCHAR) + sizeof(szCrLf);
|
size = sizeof(cookieW) + cookie_size * sizeof(WCHAR) + sizeof(szCrLf);
|
||||||
|
|
|
@ -517,7 +517,7 @@ DWORD HTTP_Connect(appinfo_t*,LPCWSTR,
|
||||||
BOOL GetAddress(LPCWSTR lpszServerName, INTERNET_PORT nServerPort,
|
BOOL GetAddress(LPCWSTR lpszServerName, INTERNET_PORT nServerPort,
|
||||||
struct sockaddr *psa, socklen_t *sa_len) DECLSPEC_HIDDEN;
|
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;
|
BOOL set_cookie(const WCHAR*,const WCHAR*,const WCHAR*,const WCHAR*) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
void INTERNET_SetLastError(DWORD dwError) DECLSPEC_HIDDEN;
|
void INTERNET_SetLastError(DWORD dwError) DECLSPEC_HIDDEN;
|
||||||
|
|
|
@ -426,6 +426,13 @@ static void test_complicated_cookie(void)
|
||||||
ok(len == 19, "len = %u\n", len);
|
ok(len == 19, "len = %u\n", len);
|
||||||
ok(lstrlenW(wbuf) == 18, "strlenW(wbuf) = %u\n", lstrlenW(wbuf));
|
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;
|
len = 1024;
|
||||||
ret = InternetGetCookie("http://testing.example.com/foobar", NULL, buffer, &len);
|
ret = InternetGetCookie("http://testing.example.com/foobar", NULL, buffer, &len);
|
||||||
ok(ret == TRUE,"InternetGetCookie failed\n");
|
ok(ret == TRUE,"InternetGetCookie failed\n");
|
||||||
|
|
Loading…
Reference in New Issue