]> git.kaiwu.me - haproxy.git/commitdiff
BUG/MINOR: resolvers: accept fields at the response boundary
authorManu Nicolas <e.nicolas@criteo.com>
Tue, 18 Aug 2026 17:24:45 +0000 (17:24 +0000)
committerWilly Tarreau <w@1wt.eu>
Wed, 19 Aug 2026 09:19:51 +0000 (11:19 +0200)
resolv_validate_dns_response() treats <bufend> as an exclusive end
pointer. Its fixed-width field checks nevertheless reject
"reader + 2 == bufend", although reader[0] and reader[1] are both
within the response.

Use a strict greater-than comparison for every two-byte DNS header and
question field. No complete successful answer is affected, but this
corrects the parser contract and lets later checks classify minimal
responses instead of rejecting them early as invalid.

This may be backported as far as 2.4.

src/resolvers.c

index 706882767b61de15ec0747acac716b381dfcc1f0..b6da43d887130dcd1aadbc278a3d2e18325d7d54 100644 (file)
@@ -1035,7 +1035,7 @@ static int resolv_validate_dns_response(unsigned char *resp, unsigned char *bufe
        r_res = &resolution->response;
 
        /* query id */
-       if (reader + 2 >= bufend)
+       if (reader + 2 > bufend)
                goto invalid_resp;
 
        r_res->header.id = reader[0] * 256 + reader[1];
@@ -1049,7 +1049,7 @@ static int resolv_validate_dns_response(unsigned char *resp, unsigned char *bufe
         *  - truncated (1 bit)
         *  - recursion desired (1 bit)
         */
-       if (reader + 2 >= bufend)
+       if (reader + 2 > bufend)
                goto invalid_resp;
 
        flags = reader[0] * 256 + reader[1];
@@ -1073,7 +1073,7 @@ static int resolv_validate_dns_response(unsigned char *resp, unsigned char *bufe
        reader += 2;
 
        /* 2 bytes for question count */
-       if (reader + 2 >= bufend)
+       if (reader + 2 > bufend)
                goto invalid_resp;
        r_res->header.qdcount = reader[0] * 256 + reader[1];
        /* (for now) we send one query only, so we expect only one in the
@@ -1088,7 +1088,7 @@ static int resolv_validate_dns_response(unsigned char *resp, unsigned char *bufe
        reader += 2;
 
        /* 2 bytes for answer count */
-       if (reader + 2 >= bufend)
+       if (reader + 2 > bufend)
                goto invalid_resp;
        r_res->header.ancount = reader[0] * 256 + reader[1];
        if (r_res->header.ancount == 0) {
@@ -1102,13 +1102,13 @@ static int resolv_validate_dns_response(unsigned char *resp, unsigned char *bufe
        reader += 2;
 
        /* 2 bytes authority count */
-       if (reader + 2 >= bufend)
+       if (reader + 2 > bufend)
                goto invalid_resp;
        r_res->header.nscount = reader[0] * 256 + reader[1];
        reader += 2;
 
        /* 2 bytes additional count */
-       if (reader + 2 >= bufend)
+       if (reader + 2 > bufend)
                goto invalid_resp;
        r_res->header.arcount = reader[0] * 256 + reader[1];
        reader += 2;
@@ -1138,13 +1138,13 @@ static int resolv_validate_dns_response(unsigned char *resp, unsigned char *bufe
        previous_dname = query->name;
 
        /* move forward 2 bytes for question type */
-       if (reader + 2 >= bufend)
+       if (reader + 2 > bufend)
                goto invalid_resp;
        query->type = reader[0] * 256 + reader[1];
        reader += 2;
 
        /* move forward 2 bytes for question class */
-       if (reader + 2 >= bufend)
+       if (reader + 2 > bufend)
                goto invalid_resp;
        query->class = reader[0] * 256 + reader[1];
        reader += 2;