From 8b4688c2a6ed65f383327d7267ffcb60e3205d32 Mon Sep 17 00:00:00 2001 From: Andy Roulin Date: Wed, 23 Nov 2022 00:09:14 +0000 Subject: libnet_if_addr.c: fix segfault when number of IPs > 512 The current code has a hardcoded limit of 512 IP addresses. The static array will be overflowed when more addresses are present. Fix the static limit by using realloc when the array needs to grow to accomodate more interfaces. Growing the array by a factor of 1.5 each time (close to golden ratio) to maximize reuse of previously allocated space. --- src/libnet_if_addr.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/src/libnet_if_addr.c b/src/libnet_if_addr.c index ef1d6c0..3f1fac3 100644 --- a/src/libnet_if_addr.c +++ b/src/libnet_if_addr.c @@ -47,6 +47,7 @@ #include "../include/ifaddrlist.h" #define MAX_IPADDR 512 +static size_t ip_addr_num = MAX_IPADDR; #if !(__WIN32__) @@ -104,10 +105,17 @@ int libnet_ifaddrlist(register struct libnet_ifaddr_list **ipaddrp, char *dev, register char *errbuf) { (void)dev; /* unused */ - static struct libnet_ifaddr_list ifaddrlist[MAX_IPADDR]; + static struct libnet_ifaddr_list *ifaddrlist = NULL, *ifaddrlist_tmp = NULL; struct ifaddrs *ifap, *ifa; int i = 0; - memset (ifaddrlist, 0 , sizeof(ifaddrlist)); + + if (!ifaddrlist) { + ifaddrlist = calloc(ip_addr_num, sizeof(struct libnet_ifaddr_list)); + if (!ifaddrlist) { + snprintf(errbuf, LIBNET_ERRBUF_SIZE, "%s(): OOM when allocating initial ifaddrlist", __func__); + return 0; + } + } if (getifaddrs(&ifap) != 0) { @@ -130,6 +138,18 @@ libnet_ifaddrlist(register struct libnet_ifaddr_list **ipaddrp, char *dev, regis ifaddrlist[i].addr = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr; ++i; } + + if (i == ip_addr_num) { + // grow by a factor of 1.5, close enough to golden ratio + ip_addr_num += ip_addr_num >> 2; + ifaddrlist_tmp = realloc(ifaddrlist, ip_addr_num * sizeof(struct libnet_ifaddr_list)); + if (!ifaddrlist_tmp) { + snprintf(errbuf, LIBNET_ERRBUF_SIZE, "%s(): OOM when reallocating larger ifaddrlist", __func__); + break; + } + + ifaddrlist = ifaddrlist_tmp; + } } freeifaddrs(ifap); @@ -485,6 +505,7 @@ good: free(al[i].device); al[i].device = NULL; } + free(al); return (1); bad: @@ -493,6 +514,7 @@ bad: free(al[i].device); al[i].device = NULL; } + free(al); return (-1); } -- cgit v1.2.1