Fix memory leak in arbitrary-RR caching.
authorSimon Kelley <simon@thekelleys.org.uk>
Mon, 9 Oct 2023 20:00:11 +0000 (21:00 +0100)
committerSimon Kelley <simon@thekelleys.org.uk>
Mon, 9 Oct 2023 20:00:11 +0000 (21:00 +0100)
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

index da8713a..ae6b46a 100644 (file)
@@ -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)