Jacek Caban : wininet: Properly handle output buffer size in InternetGetCookieW.

Alexandre Julliard julliard at winehq.org
Fri Dec 28 15:05:15 CST 2012


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

Author: Jacek Caban <jacek at 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");




More information about the wine-cvs mailing list