]> git.kaiwu.me - haproxy.git/commitdiff
BUG/MINOR: resolvers: compute a name's wire length by walking its labels
authorChristopher Faulet <cfaulet@haproxy.com>
Tue, 29 Sep 2026 07:43:40 +0000 (09:43 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Tue, 10 Nov 2026 14:47:52 +0000 (15:47 +0100)
After decoding a name, resolv_read_name() computes the number of bytes
the name occupies in the message by scanning it byte by byte until it
finds either a zero byte or a byte with the two upper bits set, which it
takes for the terminating zero or a compression pointer. But labels may
contain any byte, so a label containing a zero byte or a byte >= 0xc0
stops the scan in the middle of the name, and the rest of the message is
parsed from this wrong position, generally resulting in the response
being considered invalid.

Such bytes are found for example in names using raw UTF-8 characters
instead of their IDNA form, which do-resolve may be asked to resolve:
"caf\xc3\xa9.test" is correctly sent in the query, but the valid response
is rejected because the question name is believed to end at 0xc3 (seen
as a pointer), and do-resolve fails while plain names work.

Let's walk the labels instead, as the first loop already validated them.

This patch may be backported to stable branches.

src/resolvers.c

index db8714ac8da65e04a25da02e2637a56568d51a2b..95259f068952be24fa42751c4615c74bdf15cf25 100644 (file)
@@ -699,7 +699,9 @@ int resolv_read_name(unsigned char *buffer, unsigned char *bufend,
 
   out:
        /* offset computation:
-        * parse from <name> until finding either NULL or a pointer "c0xx"
+        * walk the labels from <name> until finding either the terminating
+        * zero or a pointer "c0xx". Labels may contain any byte, and were
+        * already validated above.
         */
        reader  = name;
        *offset = 0;
@@ -712,8 +714,8 @@ int resolv_read_name(unsigned char *buffer, unsigned char *bufend,
                        *offset += 1;
                        break;
                }
-               *offset += 1;
-               ++reader;
+               *offset += *reader + 1;
+               reader  += *reader + 1;
        }
        return nb_bytes;