]> granicus.if.org Git - curl/commitdiff
formpost: avoid silent snprintf() truncation
authorDaniel Stenberg <daniel@haxx.se>
Sat, 8 Oct 2016 10:50:42 +0000 (12:50 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Sat, 8 Oct 2016 11:00:45 +0000 (13:00 +0200)
The previous use of snprintf() could make libcurl silently truncate some
input data and not report that back on overly large input, which could
make data get sent over the network in a bad format.

Example:

 $ curl --form 'a=b' -H "Content-Type: $(perl -e 'print "A"x4100')"

lib/formdata.c
lib/formdata.h

index 13901b3304e0e5fa925df950990d947afbb4525a..ae75fe1758a71d4797861fc3942c404459603a2a 100644 (file)
@@ -845,16 +845,23 @@ static CURLcode AddFormData(struct FormData **formp,
       goto error;
     }
 #endif
+    if(type != FORM_DATAMEM) {
+      newform->line = malloc((size_t)length+1);
+      if(!newform->line) {
+        result = CURLE_OUT_OF_MEMORY;
+        goto error;
+      }
+      alloc2 = newform->line;
+      memcpy(newform->line, line, (size_t)length);
 
-    newform->line = malloc((size_t)length+1);
-    if(!newform->line) {
-      result = CURLE_OUT_OF_MEMORY;
-      goto error;
+      /* zero terminate for easier debugging */
+      newform->line[(size_t)length]=0;
+    }
+    else {
+      newform->line = (char *)line;
+      type = FORM_DATA; /* in all other aspects this is just FORM_DATA */
     }
-    alloc2 = newform->line;
-    memcpy(newform->line, line, (size_t)length);
     newform->length = (size_t)length;
-    newform->line[(size_t)length]=0; /* zero terminate for easier debugging */
   }
   else
     /* For callbacks and files we don't have any actual data so we just keep a
@@ -907,13 +914,21 @@ static CURLcode AddFormDataf(struct FormData **formp,
                              curl_off_t *size,
                              const char *fmt, ...)
 {
-  char s[4096];
+  char *s;
+  CURLcode result;
   va_list ap;
   va_start(ap, fmt);
-  vsnprintf(s, sizeof(s), fmt, ap);
+  s = curl_mvaprintf(fmt, ap);
   va_end(ap);
 
-  return AddFormData(formp, FORM_DATA, s, 0, size);
+  if(!s)
+    return CURLE_OUT_OF_MEMORY;
+
+  result = AddFormData(formp, FORM_DATAMEM, s, 0, size);
+  if(result)
+    free(s);
+
+  return result;
 }
 
 /*
index 6eb7c6c9e6f0a37dd4ab18969bd6231b904606dd..200470b50e6d0a4c0cb47ca5139c98991ef97bcd 100644 (file)
@@ -23,6 +23,7 @@
  ***************************************************************************/
 
 enum formtype {
+  FORM_DATAMEM, /* already allocated FORM_DATA memory */
   FORM_DATA,    /* form metadata (convert to network encoding if necessary) */
   FORM_CONTENT, /* form content  (never convert) */
   FORM_CALLBACK, /* 'line' points to the custom pointer we pass to the callback