Skip to content

Commit

Permalink
cookies: Improved OOM handling in cookies
Browse files Browse the repository at this point in the history
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).
  • Loading branch information
dfandrich committed Dec 9, 2014
1 parent c3b85c1 commit 41f1f6e
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 32 deletions.
71 changes: 48 additions & 23 deletions lib/cookie.c
Expand Up @@ -262,18 +262,26 @@ static char *sanitize_cookie_path(const char *cookie_path)

/*
* 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)
{
struct curl_slist *list = data->change.cookielist;
if(list) {
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
while(list) {
data->cookies = Curl_cookie_init(data,
list->data,
data->cookies,
data->set.cookiesession);
struct CookieInfo *newcookies = Curl_cookie_init(data,
list->data,
data->cookies,
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;
}
curl_slist_free_all(data->change.cookielist); /* clean up list */
Expand Down Expand Up @@ -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
* a numerical IPv6 address.
*
* Returns NULL on out of memory or invalid cookie. This is suboptimal,
* as they should be treated separately.
***************************************************************************/

struct Cookie *
Expand Down Expand Up @@ -886,22 +896,26 @@ Curl_cookie_add(struct SessionHandle *data,
*
* 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,
const char *file,
struct CookieInfo *inc,
bool newsession)
{
struct CookieInfo *c;
FILE *fp;
FILE *fp = NULL;
bool fromfile=TRUE;
char *line = NULL;

if(NULL == inc) {
/* we didn't get a struct, create one */
c = calloc(1, sizeof(struct CookieInfo));
if(!c)
return NULL; /* failed to get memory */
c->filename = strdup(file?file:"none"); /* copy the name just in case */
if(!c->filename)
goto fail; /* failed to get memory */
}
else {
/* we got an already existing one, use that */
Expand All @@ -926,32 +940,43 @@ struct CookieInfo *Curl_cookie_init(struct SessionHandle *data,
char *lineptr;
bool headerline;

char *line = malloc(MAX_COOKIE_LINE);
if(line) {
while(fgets(line, MAX_COOKIE_LINE, fp)) {
if(checkprefix("Set-Cookie:", line)) {
/* This is a cookie line, get it! */
lineptr=&line[11];
headerline=TRUE;
}
else {
lineptr=line;
headerline=FALSE;
}
while(*lineptr && ISBLANK(*lineptr))
lineptr++;

Curl_cookie_add(data, c, headerline, lineptr, NULL, NULL);
line = malloc(MAX_COOKIE_LINE);
if(!line)
goto fail;
while(fgets(line, MAX_COOKIE_LINE, fp)) {
if(checkprefix("Set-Cookie:", line)) {
/* This is a cookie line, get it! */
lineptr=&line[11];
headerline=TRUE;
}
free(line); /* free the line buffer */
else {
lineptr=line;
headerline=FALSE;
}
while(*lineptr && ISBLANK(*lineptr))
lineptr++;

Curl_cookie_add(data, c, headerline, lineptr, NULL, NULL);
}
free(line); /* free the line buffer */

if(fromfile)
fclose(fp);
}

c->running = TRUE; /* now, we're running */

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 */
Expand Down
13 changes: 10 additions & 3 deletions lib/url.c
Expand Up @@ -1164,15 +1164,21 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
/*
* Set cookie file name to dump all cookies to when we're done.
*/
{
struct CookieInfo *newcookies;
result = setstropt(&data->set.str[STRING_COOKIEJAR],
va_arg(param, char *));

/*
* Activate the cookie parser. This may or may not already
* have been made.
*/
data->cookies = Curl_cookie_init(data, NULL, data->cookies,
data->set.cookiesession);
newcookies = Curl_cookie_init(data, NULL, data->cookies,
data->set.cookiesession);
if(!newcookies)
result = CURLE_OUT_OF_MEMORY;
data->cookies = newcookies;
}
break;

case CURLOPT_COOKIESESSION:
Expand Down Expand Up @@ -1227,8 +1233,9 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
data->cookies = Curl_cookie_init(data, NULL, NULL, TRUE);

argptr = strdup(argptr);
if(!argptr) {
if(!argptr || !data->cookies) {
result = CURLE_OUT_OF_MEMORY;
Curl_safefree(argptr);
}
else {
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
Expand Down
10 changes: 4 additions & 6 deletions tests/libtest/lib506.c
Expand Up @@ -328,17 +328,15 @@ int test(char *URL)
if ( code != CURLE_OK )
{
fprintf(stderr, "curl_easy_getinfo() failed\n");
curl_share_cleanup(share);
curl_global_cleanup();
return TEST_ERR_MAJOR_BAD;
res = TEST_ERR_MAJOR_BAD;
goto test_cleanup;
}
printf("loaded cookies:\n");
if ( !cookies )
{
fprintf(stderr, " reloading cookies from '%s' failed\n", JAR);
curl_share_cleanup(share);
curl_global_cleanup();
return TEST_ERR_MAJOR_BAD;
res = TEST_ERR_MAJOR_BAD;
goto test_cleanup;
}
printf("-----------------\n");
next_cookie = cookies;
Expand Down

0 comments on commit 41f1f6e

Please sign in to comment.