diff --git a/lib/easy.c b/lib/easy.c index 398b20edd1..8f32698b93 100644 --- a/lib/easy.c +++ b/lib/easy.c @@ -891,7 +891,7 @@ static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src) /* Copy src->set into dst->set first, then deal with the strings afterwards */ dst->set = src->set; - Curl_mime_initpart(&dst->set.mimepost); + dst->set.mimepostp = NULL; /* clear all dest string and blob pointers first, in case we error out mid-function */ @@ -927,8 +927,17 @@ static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src) dst->set.postfields = dst->set.str[i]; } - /* Duplicate mime data. */ - result = Curl_mime_duppart(dst, &dst->set.mimepost, &src->set.mimepost); + if(src->set.mimepostp) { + /* Duplicate mime data. Get a mimepost struct for the clone as well */ + dst->set.mimepostp = curlx_malloc(sizeof(*dst->set.mimepostp)); + if(!dst->set.mimepostp) + return CURLE_OUT_OF_MEMORY; + + Curl_mime_initpart(dst->set.mimepostp); + result = Curl_mime_duppart(dst, dst->set.mimepostp, src->set.mimepostp); + if(result) + return result; + } if(src->set.resolve) dst->state.resolve = dst->set.resolve; diff --git a/lib/http.c b/lib/http.c index 0343aba3e7..f452fe2550 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2117,7 +2117,7 @@ static CURLcode set_post_reader(struct Curl_easy *data, Curl_HttpReq httpreq) switch(httpreq) { #ifndef CURL_DISABLE_MIME case HTTPREQ_POST_MIME: - data->state.mimepost = &data->set.mimepost; + data->state.mimepost = data->set.mimepostp; break; #endif #ifndef CURL_DISABLE_FORM_API diff --git a/lib/imap.c b/lib/imap.c index 0af18780d4..8fe87d9932 100644 --- a/lib/imap.c +++ b/lib/imap.c @@ -859,22 +859,23 @@ static CURLcode imap_perform_append(struct Curl_easy *data, #ifndef CURL_DISABLE_MIME /* Prepare the mime data if some. */ - if(data->set.mimepost.kind != MIMEKIND_NONE) { + if(IS_MIME_POST(data)) { + curl_mimepart *postp = data->set.mimepostp; /* Use the whole structure as data. */ - data->set.mimepost.flags &= ~(unsigned int)MIME_BODY_ONLY; + postp->flags &= ~(unsigned int)MIME_BODY_ONLY; /* Add external headers and mime version. */ - curl_mime_headers(&data->set.mimepost, data->set.headers, 0); - result = Curl_mime_prepare_headers(data, &data->set.mimepost, NULL, + curl_mime_headers(postp, data->set.headers, 0); + result = Curl_mime_prepare_headers(data, postp, NULL, NULL, MIMESTRATEGY_MAIL); if(!result) if(!Curl_checkheaders(data, STRCONST("Mime-Version"))) - result = Curl_mime_add_header(&data->set.mimepost.curlheaders, + result = Curl_mime_add_header(&postp->curlheaders, "Mime-Version: 1.0"); if(!result) - result = Curl_creader_set_mime(data, &data->set.mimepost); + result = Curl_creader_set_mime(data, postp); if(result) return result; data->state.infilesize = Curl_creader_client_length(data); diff --git a/lib/setopt.c b/lib/setopt.c index 5ea3cbbb9b..44fcde6fe6 100644 --- a/lib/setopt.c +++ b/lib/setopt.c @@ -1383,6 +1383,38 @@ static CURLcode setopt_slist(struct Curl_easy *data, CURLoption option, return result; } +#if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_SMTP) || \ + !defined(CURL_DISABLE_IMAP) +# ifndef CURL_DISABLE_MIME +static CURLcode setopt_mimepost(struct Curl_easy *data, curl_mime *mimep) +{ + /* + * Set to make us do MIME POST + */ + CURLcode result; + struct UserDefined *s = &data->set; + if(!s->mimepostp) { + s->mimepostp = curlx_malloc(sizeof(*s->mimepostp)); + if(!s->mimepostp) + return CURLE_OUT_OF_MEMORY; + Curl_mime_initpart(s->mimepostp); + } + + result = Curl_mime_set_subparts(s->mimepostp, mimep, FALSE); + if(!result) { + s->method = HTTPREQ_POST_MIME; + s->opt_no_body = FALSE; /* this is implied */ +#ifndef CURL_DISABLE_FORM_API + Curl_mime_cleanpart(data->state.formp); + Curl_safefree(data->state.formp); + data->state.mimepost = NULL; +#endif + } + return result; +} +#endif /* !CURL_DISABLE_MIME */ +#endif /* !CURL_DISABLE_HTTP || !CURL_DISABLE_SMTP || !CURL_DISABLE_IMAP */ + /* assorted pointer type arguments */ static CURLcode setopt_pointers(struct Curl_easy *data, CURLoption option, va_list param) @@ -1405,25 +1437,11 @@ static CURLcode setopt_pointers(struct Curl_easy *data, CURLoption option, break; #endif /* !CURL_DISABLE_FORM_API */ #endif /* !CURL_DISABLE_HTTP */ -#if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_SMTP) || \ +#if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_SMTP) || \ !defined(CURL_DISABLE_IMAP) # ifndef CURL_DISABLE_MIME case CURLOPT_MIMEPOST: - /* - * Set to make us do MIME POST - */ - result = Curl_mime_set_subparts(&s->mimepost, - va_arg(param, curl_mime *), - FALSE); - if(!result) { - s->method = HTTPREQ_POST_MIME; - s->opt_no_body = FALSE; /* this is implied */ -#ifndef CURL_DISABLE_FORM_API - Curl_mime_cleanpart(data->state.formp); - Curl_safefree(data->state.formp); - data->state.mimepost = NULL; -#endif - } + result = setopt_mimepost(data, va_arg(param, curl_mime *)); break; #endif /* !CURL_DISABLE_MIME */ #endif /* !CURL_DISABLE_HTTP || !CURL_DISABLE_SMTP || !CURL_DISABLE_IMAP */ diff --git a/lib/smtp.c b/lib/smtp.c index 471c823152..f3f3fe52d5 100644 --- a/lib/smtp.c +++ b/lib/smtp.c @@ -766,22 +766,24 @@ static CURLcode smtp_perform_mail(struct Curl_easy *data, #ifndef CURL_DISABLE_MIME /* Prepare the mime data if some. */ - if(data->set.mimepost.kind != MIMEKIND_NONE) { + if(IS_MIME_POST(data)) { + curl_mimepart *postp = data->set.mimepostp; + /* Use the whole structure as data. */ - data->set.mimepost.flags &= ~(unsigned int)MIME_BODY_ONLY; + postp->flags &= ~(unsigned int)MIME_BODY_ONLY; /* Add external headers and mime version. */ - curl_mime_headers(&data->set.mimepost, data->set.headers, 0); - result = Curl_mime_prepare_headers(data, &data->set.mimepost, NULL, + curl_mime_headers(postp, data->set.headers, 0); + result = Curl_mime_prepare_headers(data, postp, NULL, NULL, MIMESTRATEGY_MAIL); if(!result) if(!Curl_checkheaders(data, STRCONST("Mime-Version"))) - result = Curl_mime_add_header(&data->set.mimepost.curlheaders, + result = Curl_mime_add_header(&postp->curlheaders, "Mime-Version: 1.0"); if(!result) - result = Curl_creader_set_mime(data, &data->set.mimepost); + result = Curl_creader_set_mime(data, postp); if(result) goto out; data->state.infilesize = Curl_creader_total_length(data); diff --git a/lib/url.c b/lib/url.c index 130be1952c..47df6b3913 100644 --- a/lib/url.c +++ b/lib/url.c @@ -175,7 +175,8 @@ void Curl_freeset(struct Curl_easy *data) Curl_bufref_free(&data->state.referer); Curl_bufref_free(&data->state.url); - Curl_mime_cleanpart(&data->set.mimepost); + Curl_mime_cleanpart(data->set.mimepostp); + Curl_safefree(data->set.mimepostp); #ifndef CURL_DISABLE_COOKIES curl_slist_free_all(data->state.cookielist); @@ -385,8 +386,6 @@ void Curl_init_userdefined(struct Curl_easy *data) set->socks5auth = CURLAUTH_BASIC | CURLAUTH_GSSAPI; #endif - Curl_mime_initpart(&set->mimepost); - Curl_ssl_easy_config_init(data); #ifndef CURL_DISABLE_DOH set->doh_verifyhost = TRUE; diff --git a/lib/urldata.h b/lib/urldata.h index 0517b9b2d0..a41e1e62dd 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -1341,7 +1341,7 @@ struct UserDefined { struct curl_slist *headers; /* linked list of extra headers */ struct curl_httppost *httppost; /* linked list of old POST data */ #if !defined(CURL_DISABLE_MIME) || !defined(CURL_DISABLE_FORM_API) - curl_mimepart mimepost; /* MIME/POST data. */ + curl_mimepart *mimepostp; /* MIME/POST data. */ #endif #ifndef CURL_DISABLE_TELNET struct curl_slist *telnet_options; /* linked list of telnet options */ @@ -1591,7 +1591,8 @@ struct UserDefined { }; #ifndef CURL_DISABLE_MIME -#define IS_MIME_POST(a) ((a)->set.mimepost.kind != MIMEKIND_NONE) +#define IS_MIME_POST(a) \ + ((a)->set.mimepostp && ((a)->set.mimepostp->kind != MIMEKIND_NONE)) #else #define IS_MIME_POST(a) FALSE #endif diff --git a/tests/libtest/lib589.c b/tests/libtest/lib589.c index b8d9e2350d..cf85652378 100644 --- a/tests/libtest/lib589.c +++ b/tests/libtest/lib589.c @@ -27,6 +27,8 @@ static CURLcode test_lib589(const char *URL) { CURL *curl; CURLcode result = CURLE_OK; + curl_mime *mime = NULL; + curl_mimepart *part; if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { curl_mfprintf(stderr, "curl_global_init() failed\n"); @@ -46,13 +48,14 @@ static CURLcode test_lib589(const char *URL) test_setopt(curl, CURLOPT_HEADER, 1L); /* include header */ if(testnum == 584) { - curl_mime *mime = curl_mime_init(curl); - curl_mimepart *part = curl_mime_addpart(mime); - curl_mime_name(part, "fake"); - curl_mime_data(part, "party", 5); - test_setopt(curl, CURLOPT_MIMEPOST, mime); - result = curl_easy_perform(curl); - curl_mime_free(mime); + mime = curl_mime_init(curl); + part = curl_mime_addpart(mime); + if(mime && part) { + curl_mime_name(part, "fake"); + curl_mime_data(part, "party", 5); + test_setopt(curl, CURLOPT_MIMEPOST, mime); + result = curl_easy_perform(curl); + } if(result) goto test_cleanup; } @@ -65,6 +68,7 @@ static CURLcode test_lib589(const char *URL) test_cleanup: /* always cleanup */ + curl_mime_free(mime); curl_easy_cleanup(curl); curl_global_cleanup(); diff --git a/tests/unit/unit3214.c b/tests/unit/unit3214.c index ae03d5410c..6b10352953 100644 --- a/tests/unit/unit3214.c +++ b/tests/unit/unit3214.c @@ -41,7 +41,7 @@ static void checksize(const char *name, size_t size, size_t allowed) } /* the maximum sizes we allow specific structs to grow to */ -#define MAX_CURL_EASY 5850 +#define MAX_CURL_EASY 5370 #define MAX_CONNECTDATA 1300 #define MAX_CURL_MULTI 850 #define MAX_CURL_HTTPPOST 112