a DNAME record. This stops bad answers, and checks that
the authoritative server gives correct replies.
Thanks to Qifan Zhang, Palo Alto Networks for the report.
+ - Fix for missing bounds check for decompressing dnames
+ for downloaded authority zones. This fixes that the server
+ could end up with malformed zone content after receiving
+ truncated packet contents from an AXFR. In addition, the
+ domain names in the SOA rdata are checked before the
+ authority code picks up the zone serial.
+ Thanks to Halil Oktay for the report.
20 April 2026: Wouter
- Fix compile warnings for thread setname routine, and test compile.
uncompressed_len = pkt_dname_len(&pktbuf);
if(!uncompressed_len)
return 0; /* parse error in dname */
+ compressed_len = sldns_buffer_position(
+ &pktbuf) - oldpos;
+ if(compressed_len > rdlen)
+ return 0; /* dname exceeds rdata */
if(!sldns_buffer_available(buf,
uncompressed_len))
/* dname too long for buffer */
dname_pkt_copy(&pktbuf,
sldns_buffer_current(buf), rd);
sldns_buffer_skip(buf, (ssize_t)uncompressed_len);
- compressed_len = sldns_buffer_position(
- &pktbuf) - oldpos;
rd += compressed_len;
rdlen -= compressed_len;
count--;
struct auth_data* apex;
struct auth_rrset* soa;
struct packed_rrset_data* d;
+ size_t primlen, mboxlen;
apex = az_find_name(z, z->name, z->namelen);
if(!apex) return 0;
soa = az_domain_rrset(apex, LDNS_RR_TYPE_SOA);
if(!soa || soa->data->count==0)
return 0; /* no RRset or no RRs in rrset */
if(soa->data->rr_len[0] < 2+4*5) return 0; /* SOA too short */
+ if((primlen = dname_valid(soa->data->rr_data[0]+2,
+ soa->data->rr_len[0]-2)) == 0)
+ return 0; /* primary dname malformed */
+ if((mboxlen = dname_valid(soa->data->rr_data[0]+2+primlen,
+ soa->data->rr_len[0]-2-primlen)) == 0)
+ return 0; /* mailbox dname malformed */
+ if(2+primlen+mboxlen+4*5 != soa->data->rr_len[0])
+ return 0; /* rdata malformed */
d = soa->data;
*serial = sldns_read_uint32(d->rr_data[0]+(d->rr_len[0]-20));
return 1;
struct auth_data* apex;
struct auth_rrset* soa;
struct packed_rrset_data* d;
+ size_t primlen, mboxlen;
apex = az_find_name(z, z->name, z->namelen);
if(!apex) return 0;
soa = az_domain_rrset(apex, LDNS_RR_TYPE_SOA);
if(!soa || soa->data->count==0)
return 0; /* no RRset or no RRs in rrset */
if(soa->data->rr_len[0] < 2+4*5) return 0; /* SOA too short */
+ if((primlen = dname_valid(soa->data->rr_data[0]+2,
+ soa->data->rr_len[0]-2)) == 0)
+ return 0; /* primary dname malformed */
+ if((mboxlen = dname_valid(soa->data->rr_data[0]+2+primlen,
+ soa->data->rr_len[0]-2-primlen)) == 0)
+ return 0; /* mailbox dname malformed */
+ if(2+primlen+mboxlen+4*5 != soa->data->rr_len[0])
+ return 0; /* rdata malformed */
/* SOA record ends with serial, refresh, retry, expiry, minimum,
* as 4 byte fields */
d = soa->data;