]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
mimepost: allocate main struct on-demand
authorDaniel Stenberg <daniel@haxx.se>
Mon, 12 Jan 2026 08:30:25 +0000 (09:30 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Mon, 12 Jan 2026 15:21:02 +0000 (16:21 +0100)
This makes the easy handle 432 bytes smaller (totally 5352 bytes on my
rather maximized Linux 64 bit build). The 440 byte mimepost struct is
now allocated only when needed.

Closes #20260

lib/easy.c
lib/http.c
lib/imap.c
lib/setopt.c
lib/smtp.c
lib/url.c
lib/urldata.h
tests/libtest/lib589.c
tests/unit/unit3214.c

index 398b20edd12bdde7b450ef16d2c1ea198e2dc923..8f32698b936f6a19f067606bfc7c0f5ee0d96d79 100644 (file)
@@ -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;
index 0343aba3e7df096ba1c2dc067624b6968e728b04..f452fe2550f1a8c9309b495f36d1646e3ac352f0 100644 (file)
@@ -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
index 0af18780d4c7951653661d67430b7f23f35209ef..8fe87d993258a1cc0895e0f8237922fb5a104fb0 100644 (file)
@@ -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);
index 5ea3cbbb9bee80aabf4d202cf8fbeb798b1c8a87..44fcde6fe66b65c5b5692004a6f652b8e321300d 100644 (file)
@@ -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 */
index 471c8231528903bb1d54182afd50f8ea8c116e61..f3f3fe52d58856fd16a0c4335034d586d5a1e9c2 100644 (file)
@@ -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);
index 130be1952c2ecafe84cdb9e5cb94b2dfc46d1b47..47df6b39136fb5b53475c5ee6c9b839750b79064 100644 (file)
--- 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;
index 0517b9b2d069a7c5ca2f2b154ba6d851aeddd988..a41e1e62dd6b960d6ad4b4a09f2848c3a95b7a70 100644 (file)
@@ -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
index b8d9e2350d4b5c1ff8e9bccf501ed6908eabe5b9..cf85652378293aee75c45b4427c147d18c900a9a 100644 (file)
@@ -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();
 
index ae03d5410ca94c0f5504f28f80f1797ec8850cf2..6b10352953cd337135589f2ea40f1489e397231d 100644 (file)
@@ -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