]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: tools: improve parse_line()'s robustness against empty args
authorWilly Tarreau <w@1wt.eu>
Mon, 12 May 2025 14:01:27 +0000 (16:01 +0200)
committerWilly Tarreau <w@1wt.eu>
Mon, 12 May 2025 14:11:15 +0000 (16:11 +0200)
The fix in 10e6d0bd57 ("BUG/MINOR: tools: only fill first empty arg when
not out of range") was not that good. It focused on protecting against
<arg> becoming out of range to detect we haven't emitted anything, but
it's not the right way to detect this. We're always maintaining arg_start
as a copy of outpos, and that later one is incremented when emitting a
char, so instead of testing args[arg] against out+arg_start, we should
instead check outpos against arg_start, thereby eliminating the <out>
offset and the need to access args[]. This way we now always know if
we've emitted an empty arg without dereferencing args[].

There's no need to backport this unless the fix above is also backported.

src/tools.c

index 97b8d65b4d0df1d3007408c9b501e84d956dbb0e..723ea660206d2a4124548cdc1bea425ae9b180e4 100644 (file)
@@ -6439,7 +6439,7 @@ uint32_t parse_line(char *in, char *out, size_t *outlen, char **args, int *nbarg
                                                        err |= PARSE_ERR_TOOMANY;
                                        }
                                        if (prev_in_arg && !in_arg) {
-                                               if (!empty_arg_ptr && arg < argsmax && args[arg] == out + arg_start)
+                                               if (!empty_arg_ptr && outpos == arg_start)
                                                        empty_arg_ptr = begin_new_arg;
                                                EMIT_CHAR(0);
                                                arg++;
@@ -6481,19 +6481,21 @@ uint32_t parse_line(char *in, char *out, size_t *outlen, char **args, int *nbarg
                }
 
                if (prev_in_arg && !in_arg) {
-                       if (!empty_arg_ptr && arg < argsmax && args[arg] == out + arg_start)
+                       if (!empty_arg_ptr && outpos == arg_start)
                                empty_arg_ptr = begin_new_arg;
                        EMIT_CHAR(0);
                        arg++;
+                       arg_start = outpos;
                }
        }
 
        /* end of output string */
        if (in_arg) {
-               if (!empty_arg_ptr && arg < argsmax && args[arg] == out + arg_start)
+               if (!empty_arg_ptr && outpos == arg_start)
                        empty_arg_ptr = begin_new_arg;
                EMIT_CHAR(0);
                arg++;
+               arg_start = outpos;
        }
 
        if (quote) {