mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-04-18 13:05:38 +00:00
MINOR: cfgparse: sanitize the output a little bit
With the rework of the config line parser, we've started to emit a dump of the initial line underlined by a caret character indicating the error location. But with extremely large lines it starts to take time and can even cause trouble to slow terminals (e.g. over ssh), and this becomes useless. In addition, control characters could be dumped as-is which is bad, especially when the input file is accidently wrong (an executable). This patch adds a string sanitization function which isolates an area around the error position in order to report only that area if the string is too large. The limit was set to 80 characters, which will result in roughly 40 chars around the error being reported only, prefixed and suffixed with "..." as needed. In addition, non-printable characters in the line are now replaced with '?' so as not to corrupt the terminal. This way invalid variable names, unmatched quotes etc will be easier to spot. A typical output is now: [ALERT] 176/092336 (23852) : parsing [bad.cfg:8]: forbidden first char in environment variable name at position 811957: ...c$PATH$PATH$d(xlc`%?$PATH$PATH$dgc?T$%$P?AH?$PATH$PATH$d(?$PATH$PATH$dgc?%... ^
This commit is contained in:
parent
07d47060e0
commit
c54e5ad9cc
@ -862,6 +862,7 @@ int my_unsetenv(const char *name);
|
||||
*/
|
||||
char *env_expand(char *in);
|
||||
uint32_t parse_line(char *in, char *out, size_t *outlen, char **args, int *nbargs, uint32_t opts, char **errptr);
|
||||
size_t sanitize_for_printing(char *line, size_t pos, size_t width);
|
||||
|
||||
/* debugging macro to emit messages using write() on fd #-1 so that strace sees
|
||||
* them.
|
||||
|
@ -1945,32 +1945,40 @@ next_line:
|
||||
PARSE_OPT_BKSLASH | PARSE_OPT_SHARP, &errptr);
|
||||
|
||||
if (err & PARSE_ERR_QUOTE) {
|
||||
ha_alert("parsing [%s:%d]: unmatched quote below:\n"
|
||||
" %s\n %*s\n", file, linenum, line, (int)(errptr-line+1), "^");
|
||||
size_t newpos = sanitize_for_printing(line, errptr - line, 80);
|
||||
|
||||
ha_alert("parsing [%s:%d]: unmatched quote at position %d:\n"
|
||||
" %s\n %*s\n", file, linenum, (int)(errptr-thisline+1), line, (int)(newpos+1), "^");
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
fatal++;
|
||||
goto next_line;
|
||||
}
|
||||
|
||||
if (err & PARSE_ERR_BRACE) {
|
||||
ha_alert("parsing [%s:%d]: unmatched brace in environment variable name below:\n"
|
||||
" %s\n %*s\n", file, linenum, line, (int)(errptr-line+1), "^");
|
||||
size_t newpos = sanitize_for_printing(line, errptr - line, 80);
|
||||
|
||||
ha_alert("parsing [%s:%d]: unmatched brace in environment variable name at position %d:\n"
|
||||
" %s\n %*s\n", file, linenum, (int)(errptr-thisline+1), line, (int)(newpos+1), "^");
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
fatal++;
|
||||
goto next_line;
|
||||
}
|
||||
|
||||
if (err & PARSE_ERR_VARNAME) {
|
||||
ha_alert("parsing [%s:%d]: forbidden first char in environment variable name below:\n"
|
||||
" %s\n %*s\n", file, linenum, line, (int)(errptr-line+1), "^");
|
||||
size_t newpos = sanitize_for_printing(line, errptr - line, 80);
|
||||
|
||||
ha_alert("parsing [%s:%d]: forbidden first char in environment variable name at position %d:\n"
|
||||
" %s\n %*s\n", file, linenum, (int)(errptr-thisline+1), line, (int)(newpos+1), "^");
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
fatal++;
|
||||
goto next_line;
|
||||
}
|
||||
|
||||
if (err & PARSE_ERR_HEX) {
|
||||
ha_alert("parsing [%s:%d]: truncated or invalid hexadecimal sequence below:\n"
|
||||
" %s\n %*s\n", file, linenum, line, (int)(errptr-line+1), "^");
|
||||
size_t newpos = sanitize_for_printing(line, errptr - line, 80);
|
||||
|
||||
ha_alert("parsing [%s:%d]: truncated or invalid hexadecimal sequence at position %d:\n"
|
||||
" %s\n %*s\n", file, linenum, (int)(errptr-thisline+1), line, (int)(newpos+1), "^");
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
fatal++;
|
||||
goto next_line;
|
||||
|
45
src/tools.c
45
src/tools.c
@ -4990,6 +4990,51 @@ uint32_t parse_line(char *in, char *out, size_t *outlen, char **args, int *nbarg
|
||||
}
|
||||
#undef EMIT_CHAR
|
||||
|
||||
/* This is used to sanitize an input line that's about to be used for error reporting.
|
||||
* It will adjust <line> to print approximately <width> chars around <pos>, trying to
|
||||
* preserve the beginning, with leading or trailing "..." when the line is truncated.
|
||||
* If non-printable chars are present in the output. It returns the new offset <pos>
|
||||
* in the modified line. Non-printable characters are replaced with '?'. <width> must
|
||||
* be at least 6 to support two "..." otherwise the result is undefined. The line
|
||||
* itself must have at least 7 chars allocated for the same reason.
|
||||
*/
|
||||
size_t sanitize_for_printing(char *line, size_t pos, size_t width)
|
||||
{
|
||||
size_t shift = 0;
|
||||
char *out = line;
|
||||
char *in = line;
|
||||
char *end = line + width;
|
||||
|
||||
if (pos >= width) {
|
||||
/* if we have to shift, we'll be out of context, so let's
|
||||
* try to put <pos> at the center of width.
|
||||
*/
|
||||
shift = pos - width / 2;
|
||||
in += shift + 3;
|
||||
end = out + width - 3;
|
||||
out[0] = out[1] = out[2] = '.';
|
||||
out += 3;
|
||||
}
|
||||
|
||||
while (out < end && *in) {
|
||||
if (isspace((unsigned char)*in))
|
||||
*out++ = ' ';
|
||||
else if (isprint((unsigned char)*in))
|
||||
*out++ = *in;
|
||||
else
|
||||
*out++ = '?';
|
||||
in++;
|
||||
}
|
||||
|
||||
if (end < line + width) {
|
||||
out[0] = out[1] = out[2] = '.';
|
||||
out += 3;
|
||||
}
|
||||
|
||||
*out++ = 0;
|
||||
return pos - shift;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-indent-level: 8
|
||||
|
Loading…
Reference in New Issue
Block a user