From 8b606543a3fb687f0e49d4e832f98be9a08924d0 Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Mon, 9 Oct 2023 21:00:11 +0100 Subject: [PATCH] Fix memory leak in arbitrary-RR caching. If the cache insertion process fails for any reason, any blockdata storage allocated needs to be freed. Thanks to Damian Sawicki for spotting the problem and supplying patches against earlier releases. This patch by SRK, and any bugs are his. --- src/rfc1035.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/rfc1035.c b/src/rfc1035.c index da8713a..ae6b46a 100644 --- a/src/rfc1035.c +++ b/src/rfc1035.c @@ -847,11 +847,18 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t int len; if (!extract_name(header, qlen, &p1, name, 1, 0)) - return 2; + { + blockdata_free(addr.rrblock.rrdata); + return 2; + } len = to_wire(name); if (!blockdata_expand(addr.rrblock.rrdata, addr.rrblock.datalen, name, len)) - return 0; + { + blockdata_free(addr.rrblock.rrdata); + return 0; + } + addr.rrblock.datalen += len; } else @@ -859,8 +866,13 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t /* desc is length of a block of data to be used as-is */ if (desc > endrr - p1) desc = endrr - p1; + if (!blockdata_expand(addr.rrblock.rrdata, addr.rrblock.datalen, (char *)p1, desc)) - return 0; + { + blockdata_free(addr.rrblock.rrdata); + return 0; + } + addr.rrblock.datalen += desc; p1 += desc; } @@ -868,7 +880,10 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t /* we overwrote the original name, so get it back here. */ if (!extract_name(header, qlen, &tmp, name, 1, 0)) - return 2; + { + blockdata_free(addr.rrblock.rrdata); + return 2; + } } } else if (flags & (F_IPV4 | F_IPV6)) @@ -914,6 +929,10 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t cpp->addr.cname.uid = newc->uid; } cpp = NULL; + + /* cache insert failed, don't leak blockdata. */ + if (!newc && (flags & F_RR) && (flags & F_KEYTAG)) + blockdata_free(addr.rrblock.rrdata); } if (aqtype == T_TXT)