aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYang Tse <yangsita@gmail.com>2011-10-07 20:50:57 +0200
committerYang Tse <yangsita@gmail.com>2011-10-07 20:50:57 +0200
commit17f48fe87979f159e2d8769d678641c60f4c0eed (patch)
tree322c1d34d9c8d0a4d203d127765818f297ac93c7
parentb82bd05354cfa756a013d2bed4ffdc951ce903db (diff)
libcurl: some OOM handling fixes
-rw-r--r--lib/cookie.c19
-rw-r--r--lib/easy.c17
-rw-r--r--lib/hash.c6
-rw-r--r--lib/llist.c4
-rw-r--r--lib/multi.c1
-rw-r--r--lib/slist.c5
-rw-r--r--lib/sslgen.c5
-rw-r--r--lib/ssluse.c13
-rw-r--r--lib/telnet.c35
-rw-r--r--lib/url.c18
-rw-r--r--src/tool_doswin.c4
-rw-r--r--src/tool_operate.c2
-rw-r--r--tests/libtest/lib540.c41
13 files changed, 118 insertions, 52 deletions
diff --git a/lib/cookie.c b/lib/cookie.c
index 52a2ccb05..fc684ca1b 100644
--- a/lib/cookie.c
+++ b/lib/cookie.c
@@ -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);
}
diff --git a/lib/easy.c b/lib/easy.c
index a18321172..9e06dc23b 100644
--- a/lib/easy.c
+++ b/lib/easy.c
@@ -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);
}
diff --git a/lib/hash.c b/lib/hash.c
index 3a6e312a3..15b3efff6 100644
--- a/lib/hash.c
+++ b/lib/hash.c
@@ -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
diff --git a/lib/llist.c b/lib/llist.c
index 9ad1db59b..0aecf1083 100644
--- a/lib/llist.c
+++ b/lib/llist.c
@@ -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;
diff --git a/lib/multi.c b/lib/multi.c
index 0f7a24993..7786ccced 100644
--- a/lib/multi.c
+++ b/lib/multi.c
@@ -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;
diff --git a/lib/slist.c b/lib/slist.c
index 8b4bd9d6b..4ddebb609 100644
--- a/lib/slist.c
+++ b/lib/slist.c
@@ -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);
diff --git a/lib/sslgen.c b/lib/sslgen.c
index 77c641b24..3b7340244 100644
--- a/lib/sslgen.c
+++ b/lib/sslgen.c
@@ -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;
}
}
diff --git a/lib/ssluse.c b/lib/ssluse.c
index e5b84f93a..51bd909a1 100644
--- a/lib/ssluse.c
+++ b/lib/ssluse.c
@@ -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
diff --git a/lib/telnet.c b/lib/telnet.c
index 5af7c3970..d1bc43cc9 100644
--- a/lib/telnet.c
+++ b/lib/telnet.c
@@ -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;
diff --git a/lib/url.c b/lib/url.c
index abb5a9ccc..7813b8285 100644
--- 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);
}
diff --git a/src/tool_doswin.c b/src/tool_doswin.c
index b45522b53..b23b50af1 100644
--- a/src/tool_doswin.c
+++ b/src/tool_doswin.c
@@ -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;
diff --git a/src/tool_operate.c b/src/tool_operate.c
index 3ee1d10d2..481116ddf 100644
--- a/src/tool_operate.c
+++ b/src/tool_operate.c
@@ -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;
diff --git a/tests/libtest/lib540.c b/tests/libtest/lib540.c
index 8fb409f07..467e87dc4 100644
--- a/tests/libtest/lib540.c
+++ b/tests/libtest/lib540.c
@@ -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);