diff options
author | Andy Roulin <andy.roulin@gmail.com> | 2022-11-23 00:09:14 +0000 |
---|---|---|
committer | Andy Roulin <andy.roulin@gmail.com> | 2022-11-23 17:30:52 +0000 |
commit | 8b4688c2a6ed65f383327d7267ffcb60e3205d32 (patch) | |
tree | 53bc8533b07e652cd4d24ab8dbe1849498a0d31a | |
parent | cdd8d4e59c8a042f97f3983bfe26ccf4172c1884 (diff) | |
download | libnet-8b4688c2a6ed65f383327d7267ffcb60e3205d32.tar.gz |
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.
-rw-r--r-- | src/libnet_if_addr.c | 26 |
1 files 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); } |