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
This commit is contained in:
Patrick Monnerat 2022-10-05 18:51:16 +02:00 committed by Daniel Stenberg
parent eada290098
commit 2e475deb80
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
2 changed files with 40 additions and 49 deletions

View 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;
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);
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;
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 */

Binary file not shown.