From 70e3b534d54b566aedff78be3361adac3db4143f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 14 Nov 2023 22:52:18 +0100 Subject: [PATCH] urldata: move cookielist from UserDefined to UrlState 1. Because the value is not strictly set with a setopt option. 2. Because otherwise when duping a handle when all the set.* fields are first copied and an error happens (think out of memory mid-function), the function would easily free the list *before* it was deep-copied, which could lead to a double-free. Closes #12323 --- lib/cookie.c | 2 +- lib/easy.c | 11 ++++++----- lib/setopt.c | 12 ++++++------ lib/url.c | 4 ++-- lib/urldata.h | 8 ++++---- 5 files changed, 19 insertions(+), 18 deletions(-) diff --git a/lib/cookie.c b/lib/cookie.c index 3918746cc9..568cf537ad 100644 --- a/lib/cookie.c +++ b/lib/cookie.c @@ -330,7 +330,7 @@ static char *sanitize_cookie_path(const char *cookie_path) */ void Curl_cookie_loadfiles(struct Curl_easy *data) { - struct curl_slist *list = data->set.cookielist; + struct curl_slist *list = data->state.cookielist; if(list) { Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); while(list) { diff --git a/lib/easy.c b/lib/easy.c index f97003fc66..d1e7d9b31a 100644 --- a/lib/easy.c +++ b/lib/easy.c @@ -914,6 +914,7 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data) outcurl->progress.callback = data->progress.callback; #ifndef CURL_DISABLE_COOKIES + outcurl->state.cookielist = NULL; if(data->cookies && data->state.cookie_engine) { /* If cookies are enabled in the parent handle, we enable them in the clone as well! */ @@ -923,9 +924,9 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data) goto fail; } - if(data->set.cookielist) { - outcurl->set.cookielist = Curl_slist_duplicate(data->set.cookielist); - if(!outcurl->set.cookielist) + if(data->state.cookielist) { + outcurl->state.cookielist = Curl_slist_duplicate(data->state.cookielist); + if(!outcurl->state.cookielist) goto fail; } #endif @@ -984,8 +985,8 @@ fail: if(outcurl) { #ifndef CURL_DISABLE_COOKIES - curl_slist_free_all(outcurl->set.cookielist); - outcurl->set.cookielist = NULL; + curl_slist_free_all(outcurl->state.cookielist); + outcurl->state.cookielist = NULL; #endif Curl_safefree(outcurl->state.buffer); Curl_dyn_free(&outcurl->state.headerb); diff --git a/lib/setopt.c b/lib/setopt.c index 9bebcaa8fb..282aef4003 100644 --- a/lib/setopt.c +++ b/lib/setopt.c @@ -756,18 +756,18 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) return CURLE_BAD_FUNCTION_ARGUMENT; /* append the cookie file name to the list of file names, and deal with them later */ - cl = curl_slist_append(data->set.cookielist, argptr); + cl = curl_slist_append(data->state.cookielist, argptr); if(!cl) { - curl_slist_free_all(data->set.cookielist); - data->set.cookielist = NULL; + curl_slist_free_all(data->state.cookielist); + data->state.cookielist = NULL; return CURLE_OUT_OF_MEMORY; } - data->set.cookielist = cl; /* store the list for later use */ + data->state.cookielist = cl; /* store the list for later use */ } else { /* clear the list of cookie files */ - curl_slist_free_all(data->set.cookielist); - data->set.cookielist = NULL; + curl_slist_free_all(data->state.cookielist); + data->state.cookielist = NULL; if(!data->share || !data->share->cookies) { /* throw away all existing cookies if this isn't a shared cookie diff --git a/lib/url.c b/lib/url.c index cf8da4aedf..42731a9e74 100644 --- a/lib/url.c +++ b/lib/url.c @@ -318,8 +318,8 @@ void Curl_freeset(struct Curl_easy *data) Curl_mime_cleanpart(&data->set.mimepost); #ifndef CURL_DISABLE_COOKIES - curl_slist_free_all(data->set.cookielist); - data->set.cookielist = NULL; + curl_slist_free_all(data->state.cookielist); + data->state.cookielist = NULL; #endif } diff --git a/lib/urldata.h b/lib/urldata.h index 30d6a43943..2eb7da328a 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -1439,6 +1439,10 @@ struct UrlState { trailers_state trailers_state; /* whether we are sending trailers and what stage are we at */ #endif +#ifndef CURL_DISABLE_COOKIES + struct curl_slist *cookielist; /* list of cookie files set by + curl_easy_setopt(COOKIEFILE) calls */ +#endif #ifdef USE_HYPER bool hconnect; /* set if a CONNECT request */ CURLcode hresult; /* used to pass return codes back from hyper callbacks */ @@ -1694,10 +1698,6 @@ struct UserDefined { void *prereq_userp; /* pre-initial request user data */ void *seek_client; /* pointer to pass to the seek callback */ -#ifndef CURL_DISABLE_COOKIES - struct curl_slist *cookielist; /* list of cookie files set by - curl_easy_setopt(COOKIEFILE) calls */ -#endif #ifndef CURL_DISABLE_HSTS curl_hstsread_callback hsts_read; void *hsts_read_userp; -- 2.47.3