From b557182db1622510ebba3344747b6787994a75e2 Mon Sep 17 00:00:00 2001 From: Patrick Monnerat Date: Sun, 8 Oct 2017 18:38:34 +0100 Subject: mime: improve unbinding top multipart from easy handle. Also avoid dangling pointers in referencing parts. --- lib/mime.c | 51 +++++++++++++++++++++++++++++++++++++++++---------- lib/mime.h | 2 ++ lib/url.c | 5 ++--- 3 files changed, 45 insertions(+), 13 deletions(-) diff --git a/lib/mime.c b/lib/mime.c index 7cfce6ae8..0759ad50e 100644 --- a/lib/mime.c +++ b/lib/mime.c @@ -1069,13 +1069,6 @@ static int mime_subparts_seek(void *instream, curl_off_t offset, int whence) return result; } -static void mime_subparts_free(void *ptr) -{ - curl_mime *mime = (curl_mime *) ptr; - curl_mime_free(mime); -} - - /* Release part content. */ static void cleanup_part_content(curl_mimepart *part) { @@ -1094,6 +1087,30 @@ static void cleanup_part_content(curl_mimepart *part) part->kind = MIMEKIND_NONE; } +static void mime_subparts_free(void *ptr) +{ + curl_mime *mime = (curl_mime *) ptr; + + if(mime && mime->parent) { + mime->parent->freefunc = NULL; /* Be sure we won't be called again. */ + cleanup_part_content(mime->parent); /* Avoid dangling pointer in part. */ + } + curl_mime_free(mime); +} + +/* Do not free subparts: unbind them. This is used for the top level only. */ +static void mime_subparts_unbind(void *ptr) +{ + curl_mime *mime = (curl_mime *) ptr; + + if(mime && mime->parent) { + mime->parent->freefunc = NULL; /* Be sure we won't be called again. */ + cleanup_part_content(mime->parent); /* Avoid dangling pointer in part. */ + mime->parent = NULL; + } +} + + void Curl_mime_cleanpart(curl_mimepart *part) { cleanup_part_content(part); @@ -1390,8 +1407,8 @@ CURLcode curl_mime_data_cb(curl_mimepart *part, curl_off_t datasize, } /* Set mime part content from subparts. */ -CURLcode curl_mime_subparts(curl_mimepart *part, - curl_mime *subparts) +CURLcode Curl_mime_set_subparts(curl_mimepart *part, + curl_mime *subparts, int take_ownership) { if(!part) return CURLE_BAD_FUNCTION_ARGUMENT; @@ -1414,7 +1431,7 @@ CURLcode curl_mime_subparts(curl_mimepart *part, subparts->parent = part; part->readfunc = mime_subparts_read; part->seekfunc = mime_subparts_seek; - part->freefunc = mime_subparts_free; + part->freefunc = take_ownership? mime_subparts_free: mime_subparts_unbind; part->arg = subparts; part->datasize = -1; part->kind = MIMEKIND_MULTIPART; @@ -1423,6 +1440,11 @@ CURLcode curl_mime_subparts(curl_mimepart *part, return CURLE_OK; } +CURLcode curl_mime_subparts(curl_mimepart *part, curl_mime *subparts) +{ + return Curl_mime_set_subparts(part, subparts, TRUE); +} + /* Readback from top mime. */ /* Argument is the dummy top part. */ @@ -1817,6 +1839,15 @@ void Curl_mime_cleanpart(curl_mimepart *part) (void) part; } +CURLcode Curl_mime_set_subparts(curl_mimepart *part, + curl_mime *subparts, int take_ownership) +{ + (void) part; + (void) subparts; + (void) take_ownership; + return CURLE_NOT_BUILT_IN; +} + CURLcode Curl_mime_prepare_headers(curl_mimepart *part, const char *contenttype, const char *disposition, diff --git a/lib/mime.h b/lib/mime.h index a14485707..7827f7412 100644 --- a/lib/mime.h +++ b/lib/mime.h @@ -122,6 +122,8 @@ struct curl_mimepart_s { /* Prototypes. */ void Curl_mime_initpart(curl_mimepart *part, struct Curl_easy *easy); void Curl_mime_cleanpart(curl_mimepart *part); +CURLcode Curl_mime_set_subparts(curl_mimepart *part, + curl_mime *subparts, int take_ownership); CURLcode Curl_mime_prepare_headers(curl_mimepart *part, const char *contenttype, const char *disposition, diff --git a/lib/url.c b/lib/url.c index 584635bc3..3b66ae33b 100644 --- a/lib/url.c +++ b/lib/url.c @@ -1158,10 +1158,9 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, /* * Set to make us do MIME/form POST */ - result = curl_mime_subparts(&data->set.mimepost, - va_arg(param, curl_mime *)); + result = Curl_mime_set_subparts(&data->set.mimepost, + va_arg(param, curl_mime *), FALSE); if(!result) { - data->set.mimepost.freefunc = NULL; /* Avoid free upon easy cleanup. */ data->set.httpreq = HTTPREQ_POST_MIME; data->set.opt_no_body = FALSE; /* this is implied */ } -- cgit v1.2.3