libcurl: some OOM handling fixes

This commit is contained in:
Yang Tse 2011-10-07 20:50:57 +02:00
parent b82bd05354
commit 17f48fe879
13 changed files with 118 additions and 52 deletions

View File

@ -1107,23 +1107,20 @@ struct curl_slist *Curl_cookie_list(struct SessionHandle *data)
c = data->cookies->cookies; c = data->cookies->cookies;
beg = list;
while(c) { while(c) {
/* fill the list with _all_ the cookies we know */ /* fill the list with _all_ the cookies we know */
line = get_netscape_format(c); line = get_netscape_format(c);
if(line == NULL) { if(!line) {
curl_slist_free_all(beg); curl_slist_free_all(list);
return NULL; return NULL;
} }
list = curl_slist_append(list, line); beg = curl_slist_append(list, line);
free(line); free(line);
if(list == NULL) { if(!beg) {
curl_slist_free_all(beg); curl_slist_free_all(list);
return NULL; return NULL;
} }
else if(beg == NULL) { list = beg;
beg = list;
}
c = c->next; c = c->next;
} }
@ -1148,10 +1145,12 @@ void Curl_flush_cookies(struct SessionHandle *data, int cleanup)
data->set.str[STRING_COOKIEJAR]); data->set.str[STRING_COOKIEJAR]);
} }
else { else {
if(cleanup && data->change.cookielist) if(cleanup && data->change.cookielist) {
/* since nothing is written, we can just free the list of cookie file /* since nothing is written, we can just free the list of cookie file
names */ names */
curl_slist_free_all(data->change.cookielist); /* clean up list */ 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); Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
} }

View File

@ -676,16 +676,15 @@ CURL *curl_easy_duphandle(CURL *incurl)
if(outcurl) { if(outcurl) {
if(outcurl->state.connc && if(outcurl->state.connc &&
(outcurl->state.connc->type == CONNCACHE_PRIVATE)) (outcurl->state.connc->type == CONNCACHE_PRIVATE)) {
Curl_rm_connc(outcurl->state.connc); Curl_rm_connc(outcurl->state.connc);
if(outcurl->state.headerbuff) outcurl->state.connc = NULL;
free(outcurl->state.headerbuff); }
if(outcurl->change.cookielist) curl_slist_free_all(outcurl->change.cookielist);
curl_slist_free_all(outcurl->change.cookielist); outcurl->change.cookielist = NULL;
if(outcurl->change.url) Curl_safefree(outcurl->state.headerbuff);
free(outcurl->change.url); Curl_safefree(outcurl->change.url);
if(outcurl->change.referer) Curl_safefree(outcurl->change.referer);
free(outcurl->change.referer);
Curl_freeset(outcurl); Curl_freeset(outcurl);
free(outcurl); free(outcurl);
} }

View File

@ -72,9 +72,12 @@ Curl_hash_init(struct curl_hash *h,
for(i = 0; i < slots; ++i) { for(i = 0; i < slots; ++i) {
h->table[i] = Curl_llist_alloc((curl_llist_dtor) hash_element_dtor); h->table[i] = Curl_llist_alloc((curl_llist_dtor) hash_element_dtor);
if(!h->table[i]) { if(!h->table[i]) {
while(i--) while(i--) {
Curl_llist_destroy(h->table[i], NULL); Curl_llist_destroy(h->table[i], NULL);
h->table[i] = NULL;
}
free(h->table); free(h->table);
h->table = NULL;
return 1; /* failure */ return 1; /* failure */
} }
} }
@ -240,6 +243,7 @@ Curl_hash_clean(struct curl_hash *h)
} }
free(h->table); free(h->table);
h->table = NULL;
} }
void void

View File

@ -131,6 +131,10 @@ Curl_llist_remove(struct curl_llist *list, struct curl_llist_element *e,
list->dtor(user, e->ptr); list->dtor(user, e->ptr);
e->ptr = NULL;
e->prev = NULL;
e->next = NULL;
free(e); free(e);
--list->size; --list->size;

View File

@ -1804,6 +1804,7 @@ CURLMcode curl_multi_cleanup(CURLM *multi_handle)
/* remove the pending list of messages */ /* remove the pending list of messages */
Curl_llist_destroy(multi->msglist, NULL); Curl_llist_destroy(multi->msglist, NULL);
multi->msglist = NULL;
/* remove all easy handles */ /* remove all easy handles */
easy = multi->easy.next; easy = multi->easy.next;

View File

@ -119,10 +119,7 @@ void curl_slist_free_all(struct curl_slist *list)
item = list; item = list;
do { do {
next = item->next; next = item->next;
Curl_safefree(item->data);
if(item->data) {
free(item->data);
}
free(item); free(item);
item = next; item = next;
} while(next); } while(next);

View File

@ -504,9 +504,12 @@ void Curl_ssl_free_certinfo(struct SessionHandle *data)
struct curl_certinfo *ci = &data->info.certs; struct curl_certinfo *ci = &data->info.certs;
if(ci->num_of_certs) { if(ci->num_of_certs) {
/* free all individual lists used */ /* 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]); curl_slist_free_all(ci->certinfo[i]);
ci->certinfo[i] = NULL;
}
free(ci->certinfo); /* free the actual array too */ free(ci->certinfo); /* free the actual array too */
ci->certinfo = NULL;
ci->num_of_certs = 0; ci->num_of_certs = 0;
} }
} }

View File

@ -810,18 +810,16 @@ struct curl_slist *Curl_ossl_engines_list(struct SessionHandle *data)
{ {
struct curl_slist *list = NULL; struct curl_slist *list = NULL;
#if defined(USE_SSLEAY) && defined(HAVE_OPENSSL_ENGINE_H) #if defined(USE_SSLEAY) && defined(HAVE_OPENSSL_ENGINE_H)
struct curl_slist *beg = NULL; struct curl_slist *beg;
ENGINE *e; ENGINE *e;
for(e = ENGINE_get_first(); e; e = ENGINE_get_next(e)) { for(e = ENGINE_get_first(); e; e = ENGINE_get_next(e)) {
list = curl_slist_append(list, ENGINE_get_id(e)); beg = curl_slist_append(list, ENGINE_get_id(e));
if(list == NULL) { if(!beg) {
curl_slist_free_all(beg); curl_slist_free_all(list);
return NULL; return NULL;
} }
else if(beg == NULL) { list = beg;
beg = list;
}
} }
#endif #endif
(void) data; (void) data;
@ -1859,6 +1857,7 @@ static CURLcode push_certinfo_len(struct SessionHandle *data,
nl = curl_slist_append(ci->certinfo[certnum], output); nl = curl_slist_append(ci->certinfo[certnum], output);
if(!nl) { if(!nl) {
curl_slist_free_all(ci->certinfo[certnum]); curl_slist_free_all(ci->certinfo[certnum]);
ci->certinfo[certnum] = NULL;
res = CURLE_OUT_OF_MEMORY; res = CURLE_OUT_OF_MEMORY;
} }
else else

View File

@ -763,18 +763,25 @@ static void printsub(struct SessionHandle *data,
static CURLcode check_telnet_options(struct connectdata *conn) static CURLcode check_telnet_options(struct connectdata *conn)
{ {
struct curl_slist *head; struct curl_slist *head;
struct curl_slist *beg;
char option_keyword[128]; char option_keyword[128];
char option_arg[256]; char option_arg[256];
char *buf; char *buf;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
struct TELNET *tn = (struct TELNET *)conn->data->state.proto.telnet; struct TELNET *tn = (struct TELNET *)conn->data->state.proto.telnet;
CURLcode result = CURLE_OK;
/* Add the user name as an environment variable if it /* Add the user name as an environment variable if it
was given on the command line */ was given on the command line */
if(conn->bits.user_passwd) { if(conn->bits.user_passwd) {
snprintf(option_arg, sizeof(option_arg), "USER,%s", conn->user); 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; tn->us_preferred[CURL_TELOPT_NEW_ENVIRON] = CURL_YES;
} }
@ -800,24 +807,33 @@ static CURLcode check_telnet_options(struct connectdata *conn)
/* Environment variable */ /* Environment variable */
if(Curl_raw_equal(option_keyword, "NEW_ENV")) { if(Curl_raw_equal(option_keyword, "NEW_ENV")) {
buf = strdup(option_arg); beg = curl_slist_append(tn->telnet_vars, option_arg);
if(!buf) if(!beg) {
return CURLE_OUT_OF_MEMORY; result = CURLE_OUT_OF_MEMORY;
tn->telnet_vars = curl_slist_append(tn->telnet_vars, buf); break;
}
tn->telnet_vars = beg;
tn->us_preferred[CURL_TELOPT_NEW_ENVIRON] = CURL_YES; tn->us_preferred[CURL_TELOPT_NEW_ENVIRON] = CURL_YES;
continue; continue;
} }
failf(data, "Unknown telnet option %s", head->data); failf(data, "Unknown telnet option %s", head->data);
return CURLE_UNKNOWN_TELNET_OPTION; result = CURLE_UNKNOWN_TELNET_OPTION;
break;
} }
else { else {
failf(data, "Syntax error in telnet option: %s", head->data); 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 */ (void)premature; /* not used */
curl_slist_free_all(tn->telnet_vars); curl_slist_free_all(tn->telnet_vars);
tn->telnet_vars = NULL;
free(conn->data->state.proto.telnet); free(conn->data->state.proto.telnet);
conn->data->state.proto.telnet = NULL; conn->data->state.proto.telnet = NULL;

View File

@ -2569,6 +2569,11 @@ static void conn_free(struct connectdata *conn)
Curl_llist_destroy(conn->pend_pipe, NULL); Curl_llist_destroy(conn->pend_pipe, NULL);
Curl_llist_destroy(conn->done_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_safefree(conn->localdev);
Curl_free_ssl_config(&conn->ssl_config); 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->recv_pipe, NULL);
Curl_llist_destroy(conn->pend_pipe, NULL); Curl_llist_destroy(conn->pend_pipe, NULL);
Curl_llist_destroy(conn->done_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->master_buffer);
Curl_safefree(conn->localdev); Curl_safefree(conn->localdev);
Curl_safefree(conn); Curl_safefree(conn);
@ -4650,10 +4661,17 @@ static void reuse_conn(struct connectdata *old_conn,
Curl_safefree(old_conn->passwd); Curl_safefree(old_conn->passwd);
Curl_safefree(old_conn->proxyuser); Curl_safefree(old_conn->proxyuser);
Curl_safefree(old_conn->proxypasswd); Curl_safefree(old_conn->proxypasswd);
Curl_llist_destroy(old_conn->send_pipe, NULL); Curl_llist_destroy(old_conn->send_pipe, NULL);
Curl_llist_destroy(old_conn->recv_pipe, NULL); Curl_llist_destroy(old_conn->recv_pipe, NULL);
Curl_llist_destroy(old_conn->pend_pipe, NULL); Curl_llist_destroy(old_conn->pend_pipe, NULL);
Curl_llist_destroy(old_conn->done_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); Curl_safefree(old_conn->master_buffer);
} }

View File

@ -109,7 +109,7 @@ char *sanitize_dos_name(char *file_name)
strcpy(new_name, msdosify(file_name)); strcpy(new_name, msdosify(file_name));
free(file_name); Curl_safefree(file_name);
return strdup(rename_if_dos_device_name(new_name)); return strdup(rename_if_dos_device_name(new_name));
} }
@ -288,7 +288,7 @@ CURLcode FindWin32CACert(struct Configurable *config, const char *bundle_file)
else else
result = CURLE_SSL_CACERT; result = CURLE_SSL_CACERT;
free(buf); Curl_safefree(buf);
} }
return result; return result;

View File

@ -971,7 +971,7 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
/* libssh2 version older than 1.1.1 */ /* libssh2 version older than 1.1.1 */
res = CURLE_OK; res = CURLE_OK;
} }
free(home); Curl_safefree(home);
} }
if(res) if(res)
goto show_error; goto show_error;

View File

@ -49,23 +49,45 @@ static int init(CURLM *cm, const char* url, const char* userpwd,
} }
res = curl_easy_setopt(eh, CURLOPT_URL, url); 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); 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); 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); 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); 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); 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: */ 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) { if ((res = (int)curl_multi_add_handle(cm, eh)) != CURLM_OK) {
fprintf(stderr, "curl_multi_add_handle() failed, " fprintf(stderr, "curl_multi_add_handle() failed, "
"with code %d\n", res); "with code %d\n", res);
curl_easy_cleanup(eh);
return 1; /* failure */ return 1; /* failure */
} }
@ -80,13 +102,16 @@ static int loop(CURLM *cm, const char* url, const char* userpwd,
int M, Q, U = -1; int M, Q, U = -1;
fd_set R, W, E; fd_set R, W, E;
struct timeval T; struct timeval T;
CURLMcode rc;
if(init(cm, url, userpwd, headers)) if(init(cm, url, userpwd, headers))
return 1; /* failure */ return 1; /* failure */
while (U) { 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) { if (U) {
FD_ZERO(&R); FD_ZERO(&R);