]> granicus.if.org Git - curl/commitdiff
mime: improve unbinding top multipart from easy handle.
authorPatrick Monnerat <patrick@monnerat.net>
Sun, 8 Oct 2017 17:38:34 +0000 (18:38 +0100)
committerPatrick Monnerat <patrick@monnerat.net>
Sun, 8 Oct 2017 17:38:34 +0000 (18:38 +0100)
Also avoid dangling pointers in referencing parts.

lib/mime.c
lib/mime.h
lib/url.c

index 7cfce6ae826a176dc07d6486361a308a0dba5355..0759ad50e4193f4315c4fa9be71049844db60c0e 100644 (file)
@@ -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,
index a144857076d239d65d0e169e56986c1da5106d4e..7827f7412602c9ef8ca77628a78741eca887fb5f 100644 (file)
@@ -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,
index 584635bc3fd4897c8167729870f26165d599a1c8..3b66ae33b1994c83d8985e142a65085273d04601 100644 (file)
--- 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 */
     }