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:
parent
eada290098
commit
2e475deb80
@ -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.
Loading…
Reference in New Issue
Block a user