diff --git a/doc/Changelog b/doc/Changelog index f92de7fd0..5981ac2fa 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,10 @@ +24 March 2026: Wouter + - Fix to check for invalid http content length and chunk size, + and to check the RR rdata field lengths when decompressing and + inserting RRs from an authority zone transfer. This stops + large memory use and heap buffer-overflow read errors. Thanks + to Haruto Kimura (Stella) for the report. + 20 March 2026: Wouter - Fix for testcode pktview to check buffer size and log errors. diff --git a/services/authzone.c b/services/authzone.c index 3965b5e17..9778cf1b7 100644 --- a/services/authzone.c +++ b/services/authzone.c @@ -1384,6 +1384,9 @@ decompress_rr_into_buffer(struct sldns_buffer* buf, uint8_t* pkt, len = 0; break; case LDNS_RDF_TYPE_STR: + /* Check rdlen for resilience, because it is + * checked above, that rdlen > 0 */ + if(rdlen < 1) return 0; /* malformed */ len = rd[0] + 1; break; default: @@ -1391,6 +1394,8 @@ decompress_rr_into_buffer(struct sldns_buffer* buf, uint8_t* pkt, break; } if(len) { + if(len > rdlen) + return 0; /* malformed */ if(!sldns_buffer_available(buf, len)) return 0; /* too long for buffer */ sldns_buffer_write(buf, rd, len); diff --git a/util/netevent.c b/util/netevent.c index 01ef54dfe..a86e22518 100644 --- a/util/netevent.c +++ b/util/netevent.c @@ -4870,8 +4870,17 @@ http_process_initial_header(struct comm_point* c) return 0; } } else if(strncasecmp(line, "Content-Length: ", 16) == 0) { - if(!c->http_is_chunked) - c->tcp_byte_count = (size_t)atoi(line+16); + if(!c->http_is_chunked) { + char* end = NULL; + long long cl; + errno = 0; + cl = strtoll(line+16, &end, 10); + if(end == line+16 || errno != 0 || cl < 0) { + verbose(VERB_ALGO, "http invalid Content-Length: " ARG_LL "d", cl); + return 0; /* reject */ + } + c->tcp_byte_count = (size_t)cl; + } } else if(strncasecmp(line, "Transfer-Encoding: chunked", 19+7) == 0) { c->tcp_byte_count = 0; c->http_is_chunked = 1; @@ -4927,9 +4936,15 @@ http_process_chunk_header(struct comm_point* c) if(c->http_in_chunk_headers == 1) { /* read chunked start line */ char* end = NULL; - c->tcp_byte_count = (size_t)strtol(line, &end, 16); - if(end == line) + long chunk_sz; + errno = 0; + chunk_sz = strtol(line, &end, 16); + if(end == line || errno != 0 || chunk_sz < 0) { + verbose(VERB_ALGO, "http invalid chunk size: %ld", + chunk_sz); return 0; + } + c->tcp_byte_count = (size_t)chunk_sz; c->http_in_chunk_headers = 0; /* remove header text from front of buffer */ http_moveover_buffer(c->buffer);