From: Patrick Monnerat Date: Wed, 5 Oct 2022 16:51:16 +0000 (+0200) Subject: tool: reorganize function c_escape around a dynbuf X-Git-Tag: curl-7_86_0~115 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2e475deb802bfa8bbd41e03c3b3b256b26172b65;p=thirdparty%2Fcurl.git tool: reorganize function c_escape around a dynbuf 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 --- diff --git a/src/tool_setopt.c b/src/tool_setopt.c index 917191ef29..3db2fe3c68 100644 --- a/src/tool_setopt.c +++ b/src/tool_setopt.c @@ -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 */ diff --git a/tests/data/test1465 b/tests/data/test1465 index 9703f68cf2..1a28fb1c3f 100644 Binary files a/tests/data/test1465 and b/tests/data/test1465 differ