From: Daniel Stenberg Date: Fri, 8 Aug 2025 15:41:30 +0000 (+0200) Subject: tool_parsecfg: use dynbuf for quoted arguments X-Git-Tag: curl-8_16_0~211 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b823966d66c9aec9000d7493cfaf5eb9224567cc;p=thirdparty%2Fcurl.git tool_parsecfg: use dynbuf for quoted arguments Instead of doing malloc/free every time and "manual" buffer population. This reuses the dynbuf for this purpose for the duration of parsing the file. Closes #18230 --- diff --git a/src/tool_parsecfg.c b/src/tool_parsecfg.c index d5303e679b..bc22b9d5b7 100644 --- a/src/tool_parsecfg.c +++ b/src/tool_parsecfg.c @@ -36,7 +36,47 @@ specified with an initial dash! */ #define ISSEP(x,dash) (!dash && (((x) == '=') || ((x) == ':'))) -static const char *unslashquote(const char *line, char *param); +/* + * Copies the string from line to the param dynbuf, unquoting backslash-quoted + * characters and null-terminating the output string. Stops at the first + * non-backslash-quoted double quote character or the end of the input string. + * param must be at least as long as the input string. Returns 0 on success. + */ +static int unslashquote(const char *line, struct dynbuf *param) +{ + curlx_dyn_reset(param); + + while(*line && (*line != '\"')) { + if(*line == '\\') { + char out; + line++; + + /* default is to output the letter after the backslash */ + switch(out = *line) { + case '\0': + continue; /* this'll break out of the loop */ + case 't': + out = '\t'; + break; + case 'n': + out = '\n'; + break; + case 'r': + out = '\r'; + break; + case 'v': + out = '\v'; + break; + } + if(curlx_dyn_addn(param, &out, 1)) + return 1; + line++; + } + else if(curlx_dyn_addn(param, line++, 1)) + return 1; + } + return 0; /* ok */ +} #define MAX_CONFIG_LINE_LENGTH (10*1024*1024) @@ -87,13 +127,14 @@ int parseconfig(const char *filename) int lineno = 0; bool dashed_option; struct dynbuf buf; + struct dynbuf pbuf; bool fileerror = FALSE; curlx_dyn_init(&buf, MAX_CONFIG_LINE_LENGTH); + curlx_dyn_init(&pbuf, MAX_CONFIG_LINE_LENGTH); DEBUGASSERT(filename); while(!rc && my_get_line(file, &buf, &fileerror)) { ParameterError res; - bool alloced_param = FALSE; lineno++; line = curlx_dyn_ptr(&buf); if(!line) { @@ -125,15 +166,10 @@ int parseconfig(const char *filename) /* the parameter starts here (unless quoted) */ if(*line == '\"') { /* quoted parameter, do the quote dance */ - line++; - param = malloc(strlen(line) + 1); /* parameter */ - if(!param) { - /* out of memory */ - rc = 1; + rc = unslashquote(++line, &pbuf); + if(rc) break; - } - alloced_param = TRUE; - (void)unslashquote(line, param); + param = curlx_dyn_len(&pbuf) ? curlx_dyn_ptr(&pbuf) : CURL_UNCONST(""); } else { param = line; /* parameter starts here */ @@ -156,10 +192,9 @@ int parseconfig(const char *filename) case '#': /* comment */ break; default: - warnf("%s:%d: warning: '%s' uses unquoted " - "whitespace", filename, lineno, option); - warnf("This may cause side-effects. " - "Consider using double quotes?"); + warnf("%s:%d: warning: '%s' uses unquoted whitespace. " + "This may cause side-effects. Consider double quotes.", + filename, lineno, option); } } if(!*param) @@ -211,11 +246,9 @@ int parseconfig(const char *filename) rc = (int)res; } } - - if(alloced_param) - tool_safefree(param); } curlx_dyn_free(&buf); + curlx_dyn_free(&pbuf); if(file != stdin) fclose(file); if(fileerror) @@ -228,46 +261,6 @@ int parseconfig(const char *filename) return rc; } -/* - * Copies the string from line to the buffer at param, unquoting - * backslash-quoted characters and null-terminating the output string. Stops - * at the first non-backslash-quoted double quote character or the end of the - * input string. param must be at least as long as the input string. Returns - * the pointer after the last handled input character. - */ -static const char *unslashquote(const char *line, char *param) -{ - while(*line && (*line != '\"')) { - if(*line == '\\') { - char out; - line++; - - /* default is to output the letter after the backslash */ - switch(out = *line) { - case '\0': - continue; /* this'll break out of the loop */ - case 't': - out = '\t'; - break; - case 'n': - out = '\n'; - break; - case 'r': - out = '\r'; - break; - case 'v': - out = '\v'; - break; - } - *param++ = out; - line++; - } - else - *param++ = *line++; - } - *param = '\0'; /* always null-terminate */ - return line; -} static bool get_line(FILE *input, struct dynbuf *buf, bool *error) { diff --git a/tests/data/test459 b/tests/data/test459 index e46d029732..198e67d2a3 100644 --- a/tests/data/test459 +++ b/tests/data/test459 @@ -56,8 +56,8 @@ Content-Type: application/x-www-form-urlencoded arg -Warning: %LOGDIR/config:1: warning: 'data' uses unquoted whitespace -Warning: This may cause side-effects. Consider using double quotes? +Warning: %LOGDIR/config:1: warning: 'data' uses unquoted whitespace. This may +Warning: cause side-effects. Consider double quotes.