[Dnsmasq-discuss] [PATCH] Don't bump arrsize in poll_listen() until the realloc has succeeded.
Martin Vlach
userhuge at gmail.com
Wed Sep 30 23:00:05 UTC 2026
If whine_realloc() fails in poll_listen(), arrsize has already been
doubled while pollfds keeps its old size. The next call then sees
arrsize != nfds, skips the extension and writes past the end of the
array (or through NULL if the very first allocation failed).
poll_reset() only clears nfds, so this sticks around until restart.
Only update arrsize once the reallocation has succeeded.
Co-Authored-By: Claude Sonnet 5.5 <noreply at anthropic.com>
---
Found as a side effect of testing SCA BudgetScan (ex nano-analyzer) on
dnsmasq, then checked by hand: poll.c under ASAN, whine_realloc() stubbed
to fail on the Nth call, 100 fds pushed through poll_listen(). Failing the
first allocation gives a NULL write, failing the first doubling gives a
heap overflow just past the 512-byte block. Both run clean with the patch.
It only matters if realloc() really fails, so nothing urgent, just a nicer
failure mode. Master builds fine with it (checked on macOS only).
src/poll.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/poll.c b/src/poll.c
index d2d1fb9..5f0bf5a 100644
--- a/src/poll.c
+++ b/src/poll.c
@@ -100,13 +100,13 @@ void poll_listen(int fd, short event)
{
/* Array too small. Extend. */
struct pollfd *new;
+ nfds_t newsize = (arrsize == 0) ? 64 : arrsize * 2;
- arrsize = (arrsize == 0) ? 64 : arrsize * 2;
-
- if (!(new = whine_realloc(pollfds, arrsize * sizeof(struct pollfd))))
+ if (!(new = whine_realloc(pollfds, newsize * sizeof(struct pollfd))))
return;
pollfds = new;
+ arrsize = newsize;
}
memmove(&pollfds[i+1], &pollfds[i], (nfds - i) * sizeof(struct pollfd));
More information about the Dnsmasq-discuss
mailing list