- bug report #2796358 (http://curl.haxx.se/bug/view.cgi?id=2796358) pointed
authorDaniel Stenberg <daniel@haxx.se>
Mon, 25 May 2009 12:23:22 +0000 (12:23 +0000)
committerDaniel Stenberg <daniel@haxx.se>
Mon, 25 May 2009 12:23:22 +0000 (12:23 +0000)
  out that the cookie parser would leak memory when it parses cookies that are
  received with domain, path etc set multiple times in the same header. While
  such a cookie is questionable, they occur in the wild and libcurl no longer
  leaks memory for them. I added such a header to test case 8.

CHANGES
RELEASE-NOTES
lib/cookie.c
tests/data/test8

diff --git a/CHANGES b/CHANGES
index 4eafc09..2271116 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -6,6 +6,13 @@
 
                                   Changelog
 
+Daniel Stenberg (25 May 2009)
+- bug report #2796358 (http://curl.haxx.se/bug/view.cgi?id=2796358) pointed
+  out that the cookie parser would leak memory when it parses cookies that are
+  received with domain, path etc set multiple times in the same header. While
+  such a cookie is questionable, they occur in the wild and libcurl no longer
+  leaks memory for them. I added such a header to test case 8.
+
 Daniel Fandrich (22 May 2009)
 - Removed some obsolete digest code that caused a valgrind error in test 551.
 
index 6388ea5..58deec1 100644 (file)
@@ -14,6 +14,7 @@ This release includes the following changes:
 This release includes the following bugfixes:
 
  o crash on bad socket close with FTP
+ o leaking cookie memory when duplicate domains or paths were used
 
 This release includes the following known bugs:
 
index 6a88130..241f7ff 100644 (file)
@@ -156,6 +156,19 @@ void Curl_cookie_loadfiles(struct SessionHandle *data)
   }
 }
 
+/*
+ * strstore() makes a strdup() on the 'newstr' and if '*str' is non-NULL
+ * that will be freed before the allocated string is stored there.
+ *
+ * It is meant to easily replace strdup()
+ */
+static void strstore(char **str, const char *newstr)
+{
+  if(*str)
+    free(*str);
+  *str = strdup(newstr);
+}
+
 /****************************************************************************
  *
  * Curl_cookie_add()
@@ -227,7 +240,9 @@ Curl_cookie_add(struct SessionHandle *data,
         if(1 <= sscanf(ptr, "%" MAX_NAME_TXT "[^;=]=%"
                        MAX_COOKIE_LINE_TXT "[^;\r\n]",
                        name, what)) {
-          /* this is a <name>=<what> pair */
+          /* this is a <name>=<what> pair. We use strstore() below to properly
+             deal with received cookie headers that have the same string
+             property set more than once, and then we use the last one. */
 
           const char *whatptr;
 
@@ -245,7 +260,7 @@ Curl_cookie_add(struct SessionHandle *data,
           }
 
           if(Curl_raw_equal("path", name)) {
-            co->path=strdup(whatptr);
+            strstore(&co->path, whatptr);
             if(!co->path) {
               badcookie = TRUE; /* out of memory bad */
               break;
@@ -297,8 +312,8 @@ Curl_cookie_add(struct SessionHandle *data,
                 const char *tailptr=whatptr;
                 if(tailptr[0] == '.')
                   tailptr++;
-                co->domain=strdup(tailptr); /* don't prefix w/dots
-                                               internally */
+                strstore(&co->domain, tailptr); /* don't prefix w/dots
+                                                   internally */
                 if(!co->domain) {
                   badcookie = TRUE;
                   break;
@@ -317,7 +332,7 @@ Curl_cookie_add(struct SessionHandle *data,
             }
           }
           else if(Curl_raw_equal("version", name)) {
-            co->version=strdup(whatptr);
+            strstore(&co->version, whatptr);
             if(!co->version) {
               badcookie = TRUE;
               break;
@@ -333,7 +348,7 @@ Curl_cookie_add(struct SessionHandle *data,
                cookie should be discarded immediately.
 
              */
-            co->maxage = strdup(whatptr);
+            strstore(&co->maxage, whatptr);
             if(!co->maxage) {
               badcookie = TRUE;
               break;
@@ -343,7 +358,7 @@ Curl_cookie_add(struct SessionHandle *data,
               (long)now;
           }
           else if(Curl_raw_equal("expires", name)) {
-            co->expirestr=strdup(whatptr);
+            strstore(&co->expirestr, whatptr);
             if(!co->expirestr) {
               badcookie = TRUE;
               break;
index 3af9c81..959b880 100644 (file)
@@ -38,6 +38,7 @@ Funny-head: yesyes
 Set-Cookie: foobar=name; domain=127.0.0.1; path=/;
 Set-Cookie: mismatch=this; domain=127.0.0.1; path="/silly/";
 Set-Cookie: partmatch=present; domain=.0.0.1; path=/;
+Set-Cookie: duplicate=test; domain=.0.0.1; domain=.0.0.1; path=/donkey;
 Set-Cookie: cookie=yes; path=/we;
 Set-Cookie: nocookie=yes; path=/WE;