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 |
}
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++;
* extraneous ones are not emitted but <outlen> is updated so that the caller
* knows how much to realloc. Similarly, <args> are not updated beyond <nbargs>
* but the returned <nbargs> indicates how many were found. All trailing args
- * up to <nbargs> point to the trailing zero.
+ * up to <nbargs> point to the trailing zero, and as long as <nbargs> is > 0,
+ * it is guaranteed that at least one arg will point to the zero. It is safe
+ * to call it with a NULL <args> if <nbargs> is 0.
*
* <out> may overlap with <in> provided that it never goes further, in which
* case the parser will accept to perform in-place parsing and unquoting/
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;
*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
*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;