cookies: Improved OOM handling in cookies

This fixes the test 506 torture test. The internal cookie API really
ought to be improved to separate cookie parsing errors (which may be
ignored) with OOM errors (which should be fatal).
This commit is contained in:
Dan Fandrich
2014-12-07 12:24:29 +01:00
parent c3b85c12a9
commit 41f1f6e830
3 changed files with 62 additions and 32 deletions

View File

@@ -262,7 +262,8 @@ static char *sanitize_cookie_path(const char *cookie_path)
/* /*
* Load cookies from all given cookie files (CURLOPT_COOKIEFILE). * Load cookies from all given cookie files (CURLOPT_COOKIEFILE).
* NOTE: failures are ignored *
* NOTE: OOM or cookie parsing failures are ignored.
*/ */
void Curl_cookie_loadfiles(struct SessionHandle *data) void Curl_cookie_loadfiles(struct SessionHandle *data)
{ {
@@ -270,10 +271,17 @@ void Curl_cookie_loadfiles(struct SessionHandle *data)
if(list) { if(list) {
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
while(list) { while(list) {
data->cookies = Curl_cookie_init(data, struct CookieInfo *newcookies = Curl_cookie_init(data,
list->data, list->data,
data->cookies, data->cookies,
data->set.cookiesession); data->set.cookiesession);
if(!newcookies)
/* Failure may be due to OOM or a bad cookie; both are ignored
* but only the first should be
*/
infof(data, "ignoring failed cookie_init for %s\n", list->data);
else
data->cookies = newcookies;
list = list->next; list = list->next;
} }
curl_slist_free_all(data->change.cookielist); /* clean up list */ curl_slist_free_all(data->change.cookielist); /* clean up list */
@@ -355,6 +363,8 @@ static bool isip(const char *domain)
* Be aware that sometimes we get an IP-only host name, and that might also be * Be aware that sometimes we get an IP-only host name, and that might also be
* a numerical IPv6 address. * a numerical IPv6 address.
* *
* Returns NULL on out of memory or invalid cookie. This is suboptimal,
* as they should be treated separately.
***************************************************************************/ ***************************************************************************/
struct Cookie * struct Cookie *
@@ -886,6 +896,7 @@ Curl_cookie_add(struct SessionHandle *data,
* *
* If 'newsession' is TRUE, discard all "session cookies" on read from file. * If 'newsession' is TRUE, discard all "session cookies" on read from file.
* *
* Returns NULL on out of memory. Invalid cookies are ignored.
****************************************************************************/ ****************************************************************************/
struct CookieInfo *Curl_cookie_init(struct SessionHandle *data, struct CookieInfo *Curl_cookie_init(struct SessionHandle *data,
const char *file, const char *file,
@@ -893,8 +904,9 @@ struct CookieInfo *Curl_cookie_init(struct SessionHandle *data,
bool newsession) bool newsession)
{ {
struct CookieInfo *c; struct CookieInfo *c;
FILE *fp; FILE *fp = NULL;
bool fromfile=TRUE; bool fromfile=TRUE;
char *line = NULL;
if(NULL == inc) { if(NULL == inc) {
/* we didn't get a struct, create one */ /* we didn't get a struct, create one */
@@ -902,6 +914,8 @@ struct CookieInfo *Curl_cookie_init(struct SessionHandle *data,
if(!c) if(!c)
return NULL; /* failed to get memory */ return NULL; /* failed to get memory */
c->filename = strdup(file?file:"none"); /* copy the name just in case */ c->filename = strdup(file?file:"none"); /* copy the name just in case */
if(!c->filename)
goto fail; /* failed to get memory */
} }
else { else {
/* we got an already existing one, use that */ /* we got an already existing one, use that */
@@ -926,8 +940,9 @@ struct CookieInfo *Curl_cookie_init(struct SessionHandle *data,
char *lineptr; char *lineptr;
bool headerline; bool headerline;
char *line = malloc(MAX_COOKIE_LINE); line = malloc(MAX_COOKIE_LINE);
if(line) { if(!line)
goto fail;
while(fgets(line, MAX_COOKIE_LINE, fp)) { while(fgets(line, MAX_COOKIE_LINE, fp)) {
if(checkprefix("Set-Cookie:", line)) { if(checkprefix("Set-Cookie:", line)) {
/* This is a cookie line, get it! */ /* This is a cookie line, get it! */
@@ -944,7 +959,7 @@ struct CookieInfo *Curl_cookie_init(struct SessionHandle *data,
Curl_cookie_add(data, c, headerline, lineptr, NULL, NULL); Curl_cookie_add(data, c, headerline, lineptr, NULL, NULL);
} }
free(line); /* free the line buffer */ free(line); /* free the line buffer */
}
if(fromfile) if(fromfile)
fclose(fp); fclose(fp);
} }
@@ -952,6 +967,16 @@ struct CookieInfo *Curl_cookie_init(struct SessionHandle *data,
c->running = TRUE; /* now, we're running */ c->running = TRUE; /* now, we're running */
return c; return c;
fail:
Curl_safefree(line);
if(!inc)
/* Only clean up if we allocated it here, as the original could still be in
* use by a share handle */
Curl_cookie_cleanup(c);
if(fromfile && fp)
fclose(fp);
return NULL; /* out of memory */
} }
/* sort this so that the longest path gets before the shorter path */ /* sort this so that the longest path gets before the shorter path */

View File

@@ -1164,6 +1164,8 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
/* /*
* Set cookie file name to dump all cookies to when we're done. * Set cookie file name to dump all cookies to when we're done.
*/ */
{
struct CookieInfo *newcookies;
result = setstropt(&data->set.str[STRING_COOKIEJAR], result = setstropt(&data->set.str[STRING_COOKIEJAR],
va_arg(param, char *)); va_arg(param, char *));
@@ -1171,8 +1173,12 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
* Activate the cookie parser. This may or may not already * Activate the cookie parser. This may or may not already
* have been made. * have been made.
*/ */
data->cookies = Curl_cookie_init(data, NULL, data->cookies, newcookies = Curl_cookie_init(data, NULL, data->cookies,
data->set.cookiesession); data->set.cookiesession);
if(!newcookies)
result = CURLE_OUT_OF_MEMORY;
data->cookies = newcookies;
}
break; break;
case CURLOPT_COOKIESESSION: case CURLOPT_COOKIESESSION:
@@ -1227,8 +1233,9 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
data->cookies = Curl_cookie_init(data, NULL, NULL, TRUE); data->cookies = Curl_cookie_init(data, NULL, NULL, TRUE);
argptr = strdup(argptr); argptr = strdup(argptr);
if(!argptr) { if(!argptr || !data->cookies) {
result = CURLE_OUT_OF_MEMORY; result = CURLE_OUT_OF_MEMORY;
Curl_safefree(argptr);
} }
else { else {
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

@@ -328,17 +328,15 @@ int test(char *URL)
if ( code != CURLE_OK ) if ( code != CURLE_OK )
{ {
fprintf(stderr, "curl_easy_getinfo() failed\n"); fprintf(stderr, "curl_easy_getinfo() failed\n");
curl_share_cleanup(share); res = TEST_ERR_MAJOR_BAD;
curl_global_cleanup(); goto test_cleanup;
return TEST_ERR_MAJOR_BAD;
} }
printf("loaded cookies:\n"); printf("loaded cookies:\n");
if ( !cookies ) if ( !cookies )
{ {
fprintf(stderr, " reloading cookies from '%s' failed\n", JAR); fprintf(stderr, " reloading cookies from '%s' failed\n", JAR);
curl_share_cleanup(share); res = TEST_ERR_MAJOR_BAD;
curl_global_cleanup(); goto test_cleanup;
return TEST_ERR_MAJOR_BAD;
} }
printf("-----------------\n"); printf("-----------------\n");
next_cookie = cookies; next_cookie = cookies;