]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
libcurl: some OOM handling fixes
authorYang Tse <yangsita@gmail.com>
Fri, 7 Oct 2011 18:50:57 +0000 (20:50 +0200)
committerYang Tse <yangsita@gmail.com>
Fri, 7 Oct 2011 18:50:57 +0000 (20:50 +0200)
13 files changed:
lib/cookie.c
lib/easy.c
lib/hash.c
lib/llist.c
lib/multi.c
lib/slist.c
lib/sslgen.c
lib/ssluse.c
lib/telnet.c
lib/url.c
src/tool_doswin.c
src/tool_operate.c
tests/libtest/lib540.c

index 52a2ccb055bde9dceceaabe035eee1561789ed36..fc684ca1b6e5fedd97b13378a14930a4bd93ec79 100644 (file)
@@ -1107,23 +1107,20 @@ struct curl_slist *Curl_cookie_list(struct SessionHandle *data)
 
   c = data->cookies->cookies;
 
-  beg = list;
   while(c) {
     /* fill the list with _all_ the cookies we know */
     line = get_netscape_format(c);
-    if(line == NULL) {
-      curl_slist_free_all(beg);
+    if(!line) {
+      curl_slist_free_all(list);
       return NULL;
     }
-    list = curl_slist_append(list, line);
+    beg = curl_slist_append(list, line);
     free(line);
-    if(list == NULL) {
-      curl_slist_free_all(beg);
+    if(!beg) {
+      curl_slist_free_all(list);
       return NULL;
     }
-    else if(beg == NULL) {
-      beg = list;
-    }
+    list = beg;
     c = c->next;
   }
 
@@ -1148,10 +1145,12 @@ void Curl_flush_cookies(struct SessionHandle *data, int cleanup)
             data->set.str[STRING_COOKIEJAR]);
   }
   else {
-    if(cleanup && data->change.cookielist)
+    if(cleanup && data->change.cookielist) {
       /* since nothing is written, we can just free the list of cookie file
          names */
       curl_slist_free_all(data->change.cookielist); /* clean up list */
+      data->change.cookielist = NULL;
+    }
     Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
   }
 
index a183211725b3c8aed4c183f9bd5a2be533e2e305..9e06dc23b004b36b718b01c8ba943f2fe859bb93 100644 (file)
@@ -676,16 +676,15 @@ CURL *curl_easy_duphandle(CURL *incurl)
 
   if(outcurl) {
     if(outcurl->state.connc &&
-       (outcurl->state.connc->type == CONNCACHE_PRIVATE))
+       (outcurl->state.connc->type == CONNCACHE_PRIVATE)) {
       Curl_rm_connc(outcurl->state.connc);
-    if(outcurl->state.headerbuff)
-      free(outcurl->state.headerbuff);
-    if(outcurl->change.cookielist)
-      curl_slist_free_all(outcurl->change.cookielist);
-    if(outcurl->change.url)
-      free(outcurl->change.url);
-    if(outcurl->change.referer)
-      free(outcurl->change.referer);
+      outcurl->state.connc = NULL;
+    }
+    curl_slist_free_all(outcurl->change.cookielist);
+    outcurl->change.cookielist = NULL;
+    Curl_safefree(outcurl->state.headerbuff);
+    Curl_safefree(outcurl->change.url);
+    Curl_safefree(outcurl->change.referer);
     Curl_freeset(outcurl);
     free(outcurl);
   }
index 3a6e312a3b277bb55e8a186c36bf047b76059842..15b3efff6c68cb64f8ef456140b30a8475f4da9a 100644 (file)
@@ -72,9 +72,12 @@ Curl_hash_init(struct curl_hash *h,
     for(i = 0; i < slots; ++i) {
       h->table[i] = Curl_llist_alloc((curl_llist_dtor) hash_element_dtor);
       if(!h->table[i]) {
-        while(i--)
+        while(i--) {
           Curl_llist_destroy(h->table[i], NULL);
+          h->table[i] = NULL;
+        }
         free(h->table);
+        h->table = NULL;
         return 1; /* failure */
       }
     }
@@ -240,6 +243,7 @@ Curl_hash_clean(struct curl_hash *h)
   }
 
   free(h->table);
+  h->table = NULL;
 }
 
 void
index 9ad1db59bbf374245a119d71e33046fc57d64ccc..0aecf1083e7f39054fdf20b0073fa93f049eb755 100644 (file)
@@ -131,6 +131,10 @@ Curl_llist_remove(struct curl_llist *list, struct curl_llist_element *e,
 
   list->dtor(user, e->ptr);
 
+  e->ptr  = NULL;
+  e->prev = NULL;
+  e->next = NULL;
+
   free(e);
   --list->size;
 
index 0f7a24993f401b5e6a87ea4d4fcf79aa7619b89c..7786cccedd3551a8aeba31f58ee80f3800eda234 100644 (file)
@@ -1804,6 +1804,7 @@ CURLMcode curl_multi_cleanup(CURLM *multi_handle)
 
     /* remove the pending list of messages */
     Curl_llist_destroy(multi->msglist, NULL);
+    multi->msglist = NULL;
 
     /* remove all easy handles */
     easy = multi->easy.next;
index 8b4bd9d6b66ce7330fc26b66b26b1f9984cafb5a..4ddebb6091e5a8120c967813a28eea77f5bdd4ed 100644 (file)
@@ -119,10 +119,7 @@ void curl_slist_free_all(struct curl_slist *list)
   item = list;
   do {
     next = item->next;
-
-    if(item->data) {
-      free(item->data);
-    }
+    Curl_safefree(item->data);
     free(item);
     item = next;
   } while(next);
index 77c641b24604f77043af0c772bdf8fe506800c30..3b7340244646ec1d350e4417e222e15f85c26439 100644 (file)
@@ -504,9 +504,12 @@ void Curl_ssl_free_certinfo(struct SessionHandle *data)
   struct curl_certinfo *ci = &data->info.certs;
   if(ci->num_of_certs) {
     /* free all individual lists used */
-    for(i=0; i<ci->num_of_certs; i++)
+    for(i=0; i<ci->num_of_certs; i++) {
       curl_slist_free_all(ci->certinfo[i]);
+      ci->certinfo[i] = NULL;
+    }
     free(ci->certinfo); /* free the actual array too */
+    ci->certinfo = NULL;
     ci->num_of_certs = 0;
   }
 }
index e5b84f93ac49d3005c7050eb6bcb3c45c2af5172..51bd909a1ca50f92bf594eee9937a84bd145aba1 100644 (file)
@@ -810,18 +810,16 @@ struct curl_slist *Curl_ossl_engines_list(struct SessionHandle *data)
 {
   struct curl_slist *list = NULL;
 #if defined(USE_SSLEAY) && defined(HAVE_OPENSSL_ENGINE_H)
-  struct curl_slist *beg = NULL;
+  struct curl_slist *beg;
   ENGINE *e;
 
   for(e = ENGINE_get_first(); e; e = ENGINE_get_next(e)) {
-    list = curl_slist_append(list, ENGINE_get_id(e));
-    if(list == NULL) {
-      curl_slist_free_all(beg);
+    beg = curl_slist_append(list, ENGINE_get_id(e));
+    if(!beg) {
+      curl_slist_free_all(list);
       return NULL;
     }
-    else if(beg == NULL) {
-      beg = list;
-    }
+    list = beg;
   }
 #endif
   (void) data;
@@ -1859,6 +1857,7 @@ static CURLcode push_certinfo_len(struct SessionHandle *data,
   nl = curl_slist_append(ci->certinfo[certnum], output);
   if(!nl) {
     curl_slist_free_all(ci->certinfo[certnum]);
+    ci->certinfo[certnum] = NULL;
     res = CURLE_OUT_OF_MEMORY;
   }
   else
index 5af7c39701719a12a41e558d48ee7b30566fd6cd..d1bc43cc90651bc4fcb986c5d90a9d0677aa46d5 100644 (file)
@@ -763,18 +763,25 @@ static void printsub(struct SessionHandle *data,
 static CURLcode check_telnet_options(struct connectdata *conn)
 {
   struct curl_slist *head;
+  struct curl_slist *beg;
   char option_keyword[128];
   char option_arg[256];
   char *buf;
   struct SessionHandle *data = conn->data;
   struct TELNET *tn = (struct TELNET *)conn->data->state.proto.telnet;
+  CURLcode result = CURLE_OK;
 
   /* Add the user name as an environment variable if it
      was given on the command line */
   if(conn->bits.user_passwd) {
     snprintf(option_arg, sizeof(option_arg), "USER,%s", conn->user);
-    tn->telnet_vars = curl_slist_append(tn->telnet_vars, option_arg);
-
+    beg = curl_slist_append(tn->telnet_vars, option_arg);
+    if(!beg) {
+      curl_slist_free_all(tn->telnet_vars);
+      tn->telnet_vars = NULL;
+      return CURLE_OUT_OF_MEMORY;
+    }
+    tn->telnet_vars = beg;
     tn->us_preferred[CURL_TELOPT_NEW_ENVIRON] = CURL_YES;
   }
 
@@ -800,24 +807,33 @@ static CURLcode check_telnet_options(struct connectdata *conn)
 
       /* Environment variable */
       if(Curl_raw_equal(option_keyword, "NEW_ENV")) {
-        buf = strdup(option_arg);
-        if(!buf)
-          return CURLE_OUT_OF_MEMORY;
-        tn->telnet_vars = curl_slist_append(tn->telnet_vars, buf);
+        beg = curl_slist_append(tn->telnet_vars, option_arg);
+        if(!beg) {
+          result = CURLE_OUT_OF_MEMORY;
+          break;
+        }
+        tn->telnet_vars = beg;
         tn->us_preferred[CURL_TELOPT_NEW_ENVIRON] = CURL_YES;
         continue;
       }
 
       failf(data, "Unknown telnet option %s", head->data);
-      return CURLE_UNKNOWN_TELNET_OPTION;
+      result = CURLE_UNKNOWN_TELNET_OPTION;
+      break;
     }
     else {
       failf(data, "Syntax error in telnet option: %s", head->data);
-      return CURLE_TELNET_OPTION_SYNTAX;
+      result = CURLE_TELNET_OPTION_SYNTAX;
+      break;
     }
   }
 
-  return CURLE_OK;
+  if(result) {
+    curl_slist_free_all(tn->telnet_vars);
+    tn->telnet_vars = NULL;
+  }
+
+  return result;
 }
 
 /*
@@ -1109,6 +1125,7 @@ static CURLcode telnet_done(struct connectdata *conn,
   (void)premature; /* not used */
 
   curl_slist_free_all(tn->telnet_vars);
+  tn->telnet_vars = NULL;
 
   free(conn->data->state.proto.telnet);
   conn->data->state.proto.telnet = NULL;
index abb5a9ccc5fddb48305c260bcbf2ad1969bfd677..7813b82855cc22b8730e9d295d961677b7a34080 100644 (file)
--- a/lib/url.c
+++ b/lib/url.c
@@ -2569,6 +2569,11 @@ static void conn_free(struct connectdata *conn)
   Curl_llist_destroy(conn->pend_pipe, NULL);
   Curl_llist_destroy(conn->done_pipe, NULL);
 
+  conn->send_pipe = NULL;
+  conn->recv_pipe = NULL;
+  conn->pend_pipe = NULL;
+  conn->done_pipe = NULL;
+
   Curl_safefree(conn->localdev);
   Curl_free_ssl_config(&conn->ssl_config);
 
@@ -3583,6 +3588,12 @@ static struct connectdata *allocate_conn(struct SessionHandle *data)
   Curl_llist_destroy(conn->recv_pipe, NULL);
   Curl_llist_destroy(conn->pend_pipe, NULL);
   Curl_llist_destroy(conn->done_pipe, NULL);
+
+  conn->send_pipe = NULL;
+  conn->recv_pipe = NULL;
+  conn->pend_pipe = NULL;
+  conn->done_pipe = NULL;
+
   Curl_safefree(conn->master_buffer);
   Curl_safefree(conn->localdev);
   Curl_safefree(conn);
@@ -4650,10 +4661,17 @@ static void reuse_conn(struct connectdata *old_conn,
   Curl_safefree(old_conn->passwd);
   Curl_safefree(old_conn->proxyuser);
   Curl_safefree(old_conn->proxypasswd);
+
   Curl_llist_destroy(old_conn->send_pipe, NULL);
   Curl_llist_destroy(old_conn->recv_pipe, NULL);
   Curl_llist_destroy(old_conn->pend_pipe, NULL);
   Curl_llist_destroy(old_conn->done_pipe, NULL);
+
+  old_conn->send_pipe = NULL;
+  old_conn->recv_pipe = NULL;
+  old_conn->pend_pipe = NULL;
+  old_conn->done_pipe = NULL;
+
   Curl_safefree(old_conn->master_buffer);
 }
 
index b45522b5393088ec9a0a707f854ae96eda4a72c2..b23b50af17bb5ed279b9e8d4ed08083213f8473a 100644 (file)
@@ -109,7 +109,7 @@ char *sanitize_dos_name(char *file_name)
 
   strcpy(new_name, msdosify(file_name));
 
-  free(file_name);
+  Curl_safefree(file_name);
 
   return strdup(rename_if_dos_device_name(new_name));
 }
@@ -288,7 +288,7 @@ CURLcode FindWin32CACert(struct Configurable *config, const char *bundle_file)
     else
       result = CURLE_SSL_CACERT;
 
-    free(buf);
+    Curl_safefree(buf);
   }
 
   return result;
index 3ee1d10d203b5439fd00ef8b5f6c780e9ba57d70..481116ddf9c0547edd20fcb342293671c703ed6d 100644 (file)
@@ -971,7 +971,7 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
                   /* libssh2 version older than 1.1.1 */
                   res = CURLE_OK;
               }
-              free(home);
+              Curl_safefree(home);
             }
             if(res)
               goto show_error;
index 8fb409f07dc0e1c8eef948d1cb5a87e37c719409..467e87dc4ac669360b65b60fabecfb7c63c6b53b 100644 (file)
@@ -49,23 +49,45 @@ static int init(CURLM *cm, const char* url, const char* userpwd,
   }
 
   res = curl_easy_setopt(eh, CURLOPT_URL, url);
-  if(res) return 1;
+  if(res) {
+    curl_easy_cleanup(eh);
+    return 1;
+  }
   res = curl_easy_setopt(eh, CURLOPT_PROXY, PROXY);
-  if(res) return 1;
+  if(res) {
+    curl_easy_cleanup(eh);
+    return 1;
+  }
   res = curl_easy_setopt(eh, CURLOPT_PROXYUSERPWD, userpwd);
-  if(res) return 1;
+  if(res) {
+    curl_easy_cleanup(eh);
+    return 1;
+  }
   res = curl_easy_setopt(eh, CURLOPT_PROXYAUTH, (long)CURLAUTH_ANY);
-  if(res) return 1;
+  if(res) {
+    curl_easy_cleanup(eh);
+    return 1;
+  }
   res = curl_easy_setopt(eh, CURLOPT_VERBOSE, 1L);
-  if(res) return 1;
+  if(res) {
+    curl_easy_cleanup(eh);
+    return 1;
+  }
   res = curl_easy_setopt(eh, CURLOPT_HEADER, 1L);
-  if(res) return 1;
+  if(res) {
+    curl_easy_cleanup(eh);
+    return 1;
+  }
   res = curl_easy_setopt(eh, CURLOPT_HTTPHEADER, headers); /* custom Host: */
-  if(res) return 1;
+  if(res) {
+    curl_easy_cleanup(eh);
+    return 1;
+  }
 
   if ((res = (int)curl_multi_add_handle(cm, eh)) != CURLM_OK) {
     fprintf(stderr, "curl_multi_add_handle() failed, "
             "with code %d\n", res);
+    curl_easy_cleanup(eh);
     return 1; /* failure */
   }
 
@@ -80,13 +102,16 @@ static int loop(CURLM *cm, const char* url, const char* userpwd,
   int M, Q, U = -1;
   fd_set R, W, E;
   struct timeval T;
+  CURLMcode rc;
 
   if(init(cm, url, userpwd, headers))
     return 1; /* failure */
 
   while (U) {
 
-    (void) curl_multi_perform(cm, &U);
+    rc = curl_multi_perform(cm, &U);
+    if(rc == CURLM_OUT_OF_MEMORY)
+      return 1; /* failure */
 
     if (U) {
       FD_ZERO(&R);