Browse Source

curl: make --libcurl show binary posts correctly

Reported-by: Stephan Mühlstrasser
Fixes #6031
Closes #6032
Daniel Stenberg 3 years ago
parent
commit
3997b3e2a4
3 changed files with 41 additions and 24 deletions
  1. 3 1
      src/tool_operate.c
  2. 32 18
      src/tool_setopt.c
  3. 6 5
      src/tool_setopt.h

+ 3 - 1
src/tool_operate.c

@@ -320,8 +320,10 @@ static CURLcode pre_transfer(struct GlobalConfig *global,
     if(S_ISREG(fileinfo.st_mode))
       uploadfilesize = fileinfo.st_size;
 
-    if(uploadfilesize != -1)
+    if(uploadfilesize != -1) {
+      struct OperationConfig *config = per->config; /* for the macro below */
       my_setopt(per->curl, CURLOPT_INFILESIZE_LARGE, uploadfilesize);
+    }
     per->input.fd = per->infd;
   }
   return result;

+ 32 - 18
src/tool_setopt.c

@@ -219,26 +219,34 @@ static const struct NameValue setopt_nv_CURLNONZERODEFAULTS[] = {
 
 /* Escape string to C string syntax.  Return NULL if out of memory.
  * Is this correct for those wacky EBCDIC guys? */
-static char *c_escape(const char *str, size_t len)
+
+#define MAX_STRING_LENGTH_OUTPUT 2000
+#define ZERO_TERMINATED -1
+
+static char *c_escape(const char *str, curl_off_t len)
 {
   const char *s;
   unsigned char c;
   char *escaped, *e;
+  unsigned int cutoff = 0;
 
-  if(len == CURL_ZERO_TERMINATED)
+  if(len == ZERO_TERMINATED)
     len = strlen(str);
 
-  /* Check for possible overflow. */
-  if(len > (~(size_t) 0) / 4)
-    return NULL;
+  if(len > MAX_STRING_LENGTH_OUTPUT) {
+    /* cap ridiculously long strings */
+    len = MAX_STRING_LENGTH_OUTPUT;
+    cutoff = 3;
+  }
 
   /* Allocate space based on worst-case */
-  escaped = malloc(4 * len + 1);
+  escaped = malloc(4 * (size_t)len + 1 + cutoff);
   if(!escaped)
     return NULL;
 
   e = escaped;
-  for(s = str; (c = *s) != '\0'; s++) {
+  for(s = str; len; s++, len--) {
+    c = *s;
     if(c == '\n') {
       strcpy(e, "\\n");
       e += 2;
@@ -266,6 +274,8 @@ static char *c_escape(const char *str, size_t len)
     else
       *e++ = c;
   }
+  while(cutoff--)
+    *e++ = '.';
   *e = '\0';
   return escaped;
 }
@@ -404,7 +414,7 @@ static CURLcode libcurl_generate_slist(struct curl_slist *slist, int *slistno)
   CLEAN1("slist%d = NULL;", *slistno);
   for(; slist; slist = slist->next) {
     Curl_safefree(escaped);
-    escaped = c_escape(slist->data, CURL_ZERO_TERMINATED);
+    escaped = c_escape(slist->data, ZERO_TERMINATED);
     if(!escaped)
       return CURLE_OUT_OF_MEMORY;
     DATA3("slist%d = curl_slist_append(slist%d, \"%s\");",
@@ -455,7 +465,7 @@ static CURLcode libcurl_generate_mime_part(CURL *curl,
   case TOOLMIME_DATA:
 #ifdef CURL_DOES_CONVERSIONS
     /* Data will be set in ASCII, thus issue a comment with clear text. */
-    escaped = c_escape(part->data, CURL_ZERO_TERMINATED);
+    escaped = c_escape(part->data, ZERO_TERMINATED);
     NULL_CHECK(escaped);
     CODE1("/* \"%s\" */", escaped);
 
@@ -474,7 +484,7 @@ static CURLcode libcurl_generate_mime_part(CURL *curl,
 #endif
     if(!ret) {
       Curl_safefree(escaped);
-      escaped = c_escape(data, CURL_ZERO_TERMINATED);
+      escaped = c_escape(data, ZERO_TERMINATED);
       NULL_CHECK(escaped);
       CODE2("curl_mime_data(part%d, \"%s\", CURL_ZERO_TERMINATED);",
                             mimeno, escaped);
@@ -483,7 +493,7 @@ static CURLcode libcurl_generate_mime_part(CURL *curl,
 
   case TOOLMIME_FILE:
   case TOOLMIME_FILEDATA:
-    escaped = c_escape(part->data, CURL_ZERO_TERMINATED);
+    escaped = c_escape(part->data, ZERO_TERMINATED);
     NULL_CHECK(escaped);
     CODE2("curl_mime_filedata(part%d, \"%s\");", mimeno, escaped);
     if(part->kind == TOOLMIME_FILEDATA && !filename) {
@@ -508,28 +518,28 @@ static CURLcode libcurl_generate_mime_part(CURL *curl,
 
   if(!ret && part->encoder) {
     Curl_safefree(escaped);
-    escaped = c_escape(part->encoder, CURL_ZERO_TERMINATED);
+    escaped = c_escape(part->encoder, ZERO_TERMINATED);
     NULL_CHECK(escaped);
     CODE2("curl_mime_encoder(part%d, \"%s\");", mimeno, escaped);
   }
 
   if(!ret && filename) {
     Curl_safefree(escaped);
-    escaped = c_escape(filename, CURL_ZERO_TERMINATED);
+    escaped = c_escape(filename, ZERO_TERMINATED);
     NULL_CHECK(escaped);
     CODE2("curl_mime_filename(part%d, \"%s\");", mimeno, escaped);
   }
 
   if(!ret && part->name) {
     Curl_safefree(escaped);
-    escaped = c_escape(part->name, CURL_ZERO_TERMINATED);
+    escaped = c_escape(part->name, ZERO_TERMINATED);
     NULL_CHECK(escaped);
     CODE2("curl_mime_name(part%d, \"%s\");", mimeno, escaped);
   }
 
   if(!ret && part->type) {
     Curl_safefree(escaped);
-    escaped = c_escape(part->type, CURL_ZERO_TERMINATED);
+    escaped = c_escape(part->type, ZERO_TERMINATED);
     NULL_CHECK(escaped);
     CODE2("curl_mime_type(part%d, \"%s\");", mimeno, escaped);
   }
@@ -623,7 +633,8 @@ CURLcode tool_setopt_slist(CURL *curl, struct GlobalConfig *config,
 
 /* generic setopt wrapper for all other options.
  * Some type information is encoded in the tag value. */
-CURLcode tool_setopt(CURL *curl, bool str, struct GlobalConfig *config,
+CURLcode tool_setopt(CURL *curl, bool str, struct GlobalConfig *global,
+                     struct OperationConfig *config,
                      const char *name, CURLoption tag, ...)
 {
   va_list arg;
@@ -711,14 +722,17 @@ CURLcode tool_setopt(CURL *curl, bool str, struct GlobalConfig *config,
 
   va_end(arg);
 
-  if(config->libcurl && !skip && !ret) {
+  if(global->libcurl && !skip && !ret) {
     /* we only use this for real if --libcurl was used */
 
     if(remark)
       REM2("%s set to a %s", name, value);
     else {
       if(escape) {
-        escaped = c_escape(value, CURL_ZERO_TERMINATED);
+        curl_off_t len = ZERO_TERMINATED;
+        if(tag == CURLOPT_POSTFIELDS)
+          len = config->postfieldsize;
+        escaped = c_escape(value, len);
         NULL_CHECK(escaped);
         CODE2("curl_easy_setopt(hnd, %s, \"%s\");", name, escaped);
       }

+ 6 - 5
src/tool_setopt.h

@@ -98,14 +98,15 @@ CURLcode tool_setopt_mimepost(CURL *curl, struct GlobalConfig *config,
 CURLcode tool_setopt_slist(CURL *curl, struct GlobalConfig *config,
                            const char *name, CURLoption tag,
                            struct curl_slist *list);
-CURLcode tool_setopt(CURL *curl, bool str, struct GlobalConfig *config,
+CURLcode tool_setopt(CURL *curl, bool str, struct GlobalConfig *global,
+                     struct OperationConfig *config,
                      const char *name, CURLoption tag, ...);
 
 #define my_setopt(x,y,z) \
-  SETOPT_CHECK(tool_setopt(x, FALSE, global, #y, y, z), y)
+  SETOPT_CHECK(tool_setopt(x, FALSE, global, config, #y, y, z), y)
 
 #define my_setopt_str(x,y,z) \
-  SETOPT_CHECK(tool_setopt(x, TRUE, global, #y, y, z), y)
+  SETOPT_CHECK(tool_setopt(x, TRUE, global, config, #y, y, z), y)
 
 #define my_setopt_enum(x,y,z) \
   SETOPT_CHECK(tool_setopt_enum(x, global, #y, y, setopt_nv_ ## y, z), y)
@@ -122,9 +123,9 @@ CURLcode tool_setopt(CURL *curl, bool str, struct GlobalConfig *config,
 #define my_setopt_slist(x,y,z) \
   SETOPT_CHECK(tool_setopt_slist(x, global, #y, y, z), y)
 
-#define res_setopt(x,y,z) tool_setopt(x, FALSE, global, #y, y, z)
+#define res_setopt(x,y,z) tool_setopt(x, FALSE, global, config, #y, y, z)
 
-#define res_setopt_str(x,y,z) tool_setopt(x, TRUE, global, #y, y, z)
+#define res_setopt_str(x,y,z) tool_setopt(x, TRUE, global, config, #y, y, z)
 
 #else /* CURL_DISABLE_LIBCURL_OPTION */