]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
tool: reorganize function c_escape around a dynbuf
authorPatrick Monnerat <patrick@monnerat.net>
Wed, 5 Oct 2022 16:51:16 +0000 (18:51 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Thu, 6 Oct 2022 07:03:33 +0000 (09:03 +0200)
This is a bit shorter and a lot safer.

Substrings of unescaped characters are added by a single call to reduce
overhead.

Extend test 1465 to handle more kind of escapes.

Closes #9653

src/tool_setopt.c
tests/data/test1465

index 917191ef29def3b5e6851cd634eb263e6a056344..3db2fe3c68d8611fd4b8b223d2111b8e4e0f48cd 100644 (file)
@@ -33,6 +33,7 @@
 #include "tool_easysrc.h"
 #include "tool_setopt.h"
 #include "tool_msgs.h"
+#include "dynbuf.h"
 
 #include "memdebug.h" /* keep this as LAST include */
 
@@ -205,9 +206,11 @@ static const struct NameValue setopt_nv_CURLNONZERODEFAULTS[] = {
 static char *c_escape(const char *str, curl_off_t len)
 {
   const char *s;
-  unsigned char c;
-  char *escaped, *e;
   unsigned int cutoff = 0;
+  CURLcode result;
+  struct curlx_dynbuf escaped;
+
+  curlx_dyn_init(&escaped, 4 * MAX_STRING_LENGTH_OUTPUT + 3);
 
   if(len == ZERO_TERMINATED)
     len = strlen(str);
@@ -218,56 +221,44 @@ static char *c_escape(const char *str, curl_off_t len)
     cutoff = 3;
   }
 
-  /* Allocate space based on worst-case */
-  escaped = malloc(4 * (size_t)len + 1 + cutoff);
-  if(!escaped)
-    return NULL;
-
-  e = escaped;
-  for(s = str; len; s++, len--) {
-    c = *s;
-    if(c == '\n') {
-      strcpy(e, "\\n");
-      e += 2;
-    }
-    else if(c == '\r') {
-      strcpy(e, "\\r");
-      e += 2;
-    }
-    else if(c == '\t') {
-      strcpy(e, "\\t");
-      e += 2;
-    }
-    else if(c == '\\') {
-      strcpy(e, "\\\\");
-      e += 2;
-    }
-    else if(c == '"') {
-      strcpy(e, "\\\"");
-      e += 2;
-    }
-    else if(c == '?') {
-      /* escape question marks as well, to prevent generating accidental
-         trigraphs */
-      strcpy(e, "\\?");
-      e += 2;
-    }
-    else if(ISPRINT(c))
-      *e++ = c;
-    else if(len > 1 && ISXDIGIT(s[1])) {
-      /* Octal escape to avoid >2 digit hex. */
-      msnprintf(e, 5, "\\%03o", (unsigned)c);
-      e += 4;
-    }
-    else {
-      msnprintf(e, 5, "\\x%02x", (unsigned)c);
-      e += 4;
+  result = curlx_dyn_addn(&escaped, STRCONST(""));
+  for(s = str; !result && len; s++, len--) {
+    /* escape question marks as well, to prevent generating accidental
+       trigraphs */
+    static const char from[] = "\t\r\n?\"\\";
+    static const char to[] = "\\t\\r\\n\\?\\\"\\\\";
+    const char *p = strchr(from, *s);
+
+    if(!p && ISPRINT(*s))
+      continue;
+
+    result = curlx_dyn_addn(&escaped, str, s - str);
+    str = s + 1;
+
+    if(!result) {
+      if(p && *p)
+        result = curlx_dyn_addn(&escaped, to + 2 * (p - from), 2);
+      else {
+        const char *format = "\\x%02x";
+
+        if(len > 1 && ISXDIGIT(s[1])) {
+          /* Octal escape to avoid >2 digit hex. */
+          format = "\\%03o";
+        }
+
+        result = curlx_dyn_addf(&escaped, format,
+                                (unsigned int) *(unsigned char *) s);
+      }
     }
   }
-  while(cutoff--)
-    *e++ = '.';
-  *e = '\0';
-  return escaped;
+
+  if(!result)
+    result = curlx_dyn_addn(&escaped, str, s - str);
+
+  if(!result)
+    (void) !curlx_dyn_addn(&escaped, "...", cutoff);
+
+  return curlx_dyn_ptr(&escaped);
 }
 
 /* setopt wrapper for enum types */
index 9703f68cf2c0786711876fb52d12bbda2b765b48..1a28fb1c3f29961ca7230d6af6d2a51a3bca6ad4 100644 (file)
Binary files a/tests/data/test1465 and b/tests/data/test1465 differ