diff --git a/src/cfgparse.c b/src/cfgparse.c index 191698e2b..9f65d8389 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -1938,7 +1938,7 @@ next_line: uint32_t err; char *errptr; - arg = MAX_LINE_ARGS; + arg = MAX_LINE_ARGS + 1; outlen = outlinesize; err = parse_line(line, outline, &outlen, args, &arg, PARSE_OPT_ENV | PARSE_OPT_DQUOTE | PARSE_OPT_SQUOTE | @@ -1977,7 +1977,7 @@ next_line: } if (err & PARSE_ERR_TOOMANY) { - ha_alert("parsing [%s:%d]: too many words, truncating at word %d, position %ld: <%s>.\n", + ha_alert("parsing [%s:%d]: too many words, truncating after word %d, position %ld: <%s>.\n", file, linenum, MAX_LINE_ARGS, (long)(args[MAX_LINE_ARGS-1] - outline + 1), args[MAX_LINE_ARGS-1]); err_code |= ERR_ALERT | ERR_FATAL; fatal++; diff --git a/src/tools.c b/src/tools.c index 10c973761..964170065 100644 --- a/src/tools.c +++ b/src/tools.c @@ -4738,7 +4738,9 @@ void ha_generate_uuid(struct buffer *output) * extraneous ones are not emitted but is updated so that the caller * knows how much to realloc. Similarly, are not updated beyond * but the returned indicates how many were found. All trailing args - * up to point to the trailing zero. + * up to point to the trailing zero, and as long as is > 0, + * it is guaranteed that at least one arg will point to the zero. It is safe + * to call it with a NULL if is 0. * * may overlap with provided that it never goes further, in which * case the parser will accept to perform in-place parsing and unquoting/ @@ -4761,7 +4763,7 @@ uint32_t parse_line(char *in, char *out, size_t *outlen, char **args, int *nbarg char *brace = NULL; unsigned char hex1, hex2; size_t outmax = *outlen; - int argsmax = *nbargs; + int argsmax = *nbargs - 1; size_t outpos = 0; int squote = 0; int dquote = 0; @@ -4771,7 +4773,10 @@ uint32_t parse_line(char *in, char *out, size_t *outlen, char **args, int *nbarg *nbargs = 0; *outlen = 0; - args[arg] = out; + /* argsmax may be -1 here, protecting args[] from any write */ + if (arg < argsmax) + args[arg] = out; + while (1) { if (*in >= '-' && *in != '\\') { /* speedup: directly send all regular chars starting @@ -4972,8 +4977,13 @@ uint32_t parse_line(char *in, char *out, size_t *outlen, char **args, int *nbarg *nbargs = arg; *outlen = outpos; - /* empty all trailing args by making them point to the trailing zero */ - while (arg < argsmax) + /* empty all trailing args by making them point to the trailing zero, + * at least the last one in any case. + */ + if (arg > argsmax) + arg = argsmax; + + while (arg >= 0 && arg <= argsmax) args[arg++] = out + outpos - 1; return err;