summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Roulin <andy.roulin@gmail.com>2022-11-23 00:09:14 +0000
committerAndy Roulin <andy.roulin@gmail.com>2022-11-23 17:30:52 +0000
commit8b4688c2a6ed65f383327d7267ffcb60e3205d32 (patch)
tree53bc8533b07e652cd4d24ab8dbe1849498a0d31a
parentcdd8d4e59c8a042f97f3983bfe26ccf4172c1884 (diff)
downloadlibnet-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.c26
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);
}