diff options
author | Patrick Monnerat <patrick@monnerat.net> | 2017-10-08 18:38:34 +0100 |
---|---|---|
committer | Patrick Monnerat <patrick@monnerat.net> | 2017-10-08 18:38:34 +0100 |
commit | b557182db1622510ebba3344747b6787994a75e2 (patch) | |
tree | 8659088a34fa0088fca2922ce4390e212658fc59 | |
parent | dd97fd3bb3e365681de3b3254169bea3608688ea (diff) |
mime: improve unbinding top multipart from easy handle.
Also avoid dangling pointers in referencing parts.
-rw-r--r-- | lib/mime.c | 51 | ||||
-rw-r--r-- | lib/mime.h | 2 | ||||
-rw-r--r-- | 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, @@ -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 */ } |