]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: master/cli: only parse the '@@' prefix on complete lines
authorWilly Tarreau <w@1wt.eu>
Fri, 25 Apr 2025 06:40:57 +0000 (08:40 +0200)
committerWilly Tarreau <w@1wt.eu>
Fri, 25 Apr 2025 07:05:00 +0000 (09:05 +0200)
The new adhoc parser for the '@@' prefix forgot to require the presence
of the LF character marking the end of the line. This is the reason why
entering incomplete commands would display garbage, because the line was
expected to have its LF character replaced with a zero.

The problem is well illustrated by using socat in raw mode:

   socat /tmp/master.sock STDIO,raw,echo=0

then entering "@@1 show info" one character at a time would error just
after the second "@". The command must take care to report an incomplete
line and wait for more data in such a case.

src/cli.c

index a64c2f448967cdae573016173d5d1dfe5d7ec8b3..5791a89ce613bc4b80afe9bb556776bb90d0d8b5 100644 (file)
--- a/src/cli.c
+++ b/src/cli.c
@@ -2906,7 +2906,8 @@ int pcli_find_and_exec_kw(struct stream *s, char **args, int argl, char **errmsg
  * for the '@@' prefix. If found, the pid is returned in <next_pid> and the
  * function returns a positive value representing the number of bytes
  * processed. If the prefix is found but the pid couldn't be parsed, <0 is
- * returned with an error placed into <errmsg>. If nothing is found, zero is
+ * returned with an error placed into <errmsg>. If the string is incomplete
+ * (missing '\n'), -1 is returned with no error. If nothing is found, zero is
  * returned. In any case, <str> is advanced by the number of chars to be
  * skipped.
  */
@@ -2919,6 +2920,12 @@ int pcli_find_bidir_prefix(struct stream *s, struct channel *req, char **str, co
        while (p < end && (*p == '\t' || *p == ' '))
                p++;
 
+       /* We only parse complete lines */
+       if (memchr(p, '\n', end - p) == NULL) {
+               ret = -1;
+               goto leave;
+       }
+
        /* check for '@@' prefix */
        if (p + 2 <= end && p[0] == '@' && p[1] == '@') {
                const char *pid_str = p;