From b4416a8282fefc93644713aeac1b0fb42b4de0f1 Mon Sep 17 00:00:00 2001 From: Vladimir Dubrovin <3proxy@3proxy.ru> Date: Fri, 30 Oct 2026 12:42:01 +0300 Subject: [PATCH] resolve: the PTR answer of dnsname walked inside its record data The label walk of a DNS PTR answer ran to the end of the whole message, not to the end of the record's data, and took a compression pointer for a label length, so it could write past the end of the answer buffer on the stack. An answer of 3841 bytes or more reached past the buffer itself. A record that ended exactly at the end of the message was also read one byte past it. The walk now stops at the end of the record's data, a name that does not end there, or one that is compressed or empty is not accepted, and the answer loop reads nothing past the message. --- src/resolve.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/resolve.c b/src/resolve.c index 083626f..19d1fcd 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -188,6 +188,7 @@ static uint32_t udpresolvec(struct extparam *c, int af, unsigned char * name, un k += 4; if(na > 255) na = 255; /* somebody is very evil */ for (j = 0; j < na; j++) { /* now there should be answers */ + if(k >= len) break; while(buf[k] < 192 && buf[k] !=0 && (k+buf[k]+14) < len) k+= (buf[k] + 1); if(!buf[k]) k--; if((k+(af == AF_INET6?28:16)) > len) { @@ -216,12 +217,14 @@ static uint32_t udpresolvec(struct extparam *c, int af, unsigned char * name, un k+= (12 + flen); continue; /* we need A PTR */ } - for (s2 = buf + k + 12; s2 < (buf + k + 12 + len) && *s2; ){ - s1 = s2 + ((unsigned)*s2) + 1; + s1 = buf + k + 12 + flen; /* the end of this record's data, inside the answer */ + for (s2 = buf + k + 12; s2 < s1 && *s2 && *s2 < 64; ){ + unsigned char *next = s2 + ((unsigned)*s2) + 1; *s2 = '.'; - s2 = s1; + s2 = next; } - *s2 = 0; + if(s2 >= s1 || *s2 || s2 == buf + k + 12) + break; /* the name runs past its data, is compressed or empty */ /* a name longer than the field is no name to authenticate */ if(PARAMSTR(param, username, buf + k + 13)) return 0;