From: Manu Nicolas Date: Tue, 18 Aug 2026 17:24:45 +0000 (+0000) Subject: BUG/MINOR: resolvers: accept fields at the response boundary X-Git-Tag: v3.5-dev5~9 X-Git-Url: https://git.kaiwu.me/?a=commitdiff_plain;h=fd9570f30319b2e845576fdd089e519e57b906e9;p=haproxy.git BUG/MINOR: resolvers: accept fields at the response boundary resolv_validate_dns_response() treats 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. --- diff --git a/src/resolvers.c b/src/resolvers.c index 706882767..b6da43d88 100644 --- a/src/resolvers.c +++ b/src/resolvers.c @@ -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;