]> granicus.if.org Git - libevent/commitdiff
kqueue: Avoid undefined behaviour.
authorTobias Stoeckmann <tobias@stoeckmann.org>
Fri, 10 May 2019 21:54:14 +0000 (23:54 +0200)
committerAzat Khuzhin <azat@libevent.org>
Sat, 11 May 2019 08:29:55 +0000 (11:29 +0300)
As ploxiln pointed out in pull request 811 the check "newsize < 0"
is undefined behaviour (signed int overflow).

Follow the advice and check kqop->changes_size instead.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
Closes: #813 (cherry-picked)
kqueue.c

index 9a249511769895b24e5fcf4d8f18717247859047..d08f512ce4b68debaff086929f9d5077cc5d725e 100644 (file)
--- a/kqueue.c
+++ b/kqueue.c
@@ -37,6 +37,7 @@
 #endif
 #include <sys/queue.h>
 #include <sys/event.h>
+#include <limits.h>
 #include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -208,15 +209,17 @@ kq_build_changes_list(const struct event_changelist *changelist,
                struct event_change *in_ch = &changelist->changes[i];
                struct kevent *out_ch;
                if (n_changes >= kqop->changes_size - 1) {
-                       int newsize = kqop->changes_size * 2;
+                       int newsize;
                        struct kevent *newchanges;
 
-                       if (newsize < 0 || (size_t)newsize >
-                           EV_SIZE_MAX / sizeof(struct kevent)) {
+                       if (kqop->changes_size > INT_MAX / 2 ||
+                           (size_t)kqop->changes_size * 2 > EV_SIZE_MAX /
+                           sizeof(struct kevent)) {
                                event_warnx("%s: int overflow", __func__);
                                return (-1);
                        }
 
+                       newsize = kqop->changes_size * 2;
                        newchanges = mm_realloc(kqop->changes,
                            newsize * sizeof(struct kevent));
                        if (newchanges == NULL) {