]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
[Fix] Add fd validation in libev watcher functions to prevent invalid ev_io_start...
authorVsevolod Stakhov <vsevolod@rspamd.com>
Tue, 21 Oct 2025 21:46:19 +0000 (22:46 +0100)
committerVsevolod Stakhov <vsevolod@rspamd.com>
Thu, 23 Oct 2025 10:25:23 +0000 (11:25 +0100)
Fix assertion failure when using timers with fd=-1 by adding checks before
calling ev_io_start. Timers use fd=-1 which is valid, but ev_io_start requires
fd>=0. This prevents crashes in fuzzy TCP connections when setting up request
timeouts.

src/libutil/libev_helper.c

index 82fead9bb97a8afdc17848f30f779ae4444d2825..1d89251491d6c318c2146f6e92e45eb1143b7473 100644 (file)
@@ -57,7 +57,9 @@ void rspamd_ev_watcher_start(struct ev_loop *loop,
 {
        g_assert(ev->cb != NULL);
 
-       ev_io_start(EV_A, &ev->io);
+       if (ev->io.fd >= 0) {
+               ev_io_start(EV_A, &ev->io);
+       }
 
        if (timeout > 0) {
                /* Update timestamp to avoid timers running early */
@@ -92,15 +94,17 @@ void rspamd_ev_watcher_reschedule(struct ev_loop *loop,
 {
        g_assert(ev->cb != NULL);
 
-       if (ev_can_stop(&ev->io)) {
-               ev_io_stop(EV_A, &ev->io);
-               ev_io_set(&ev->io, ev->io.fd, what);
-               ev_io_start(EV_A, &ev->io);
-       }
-       else {
-               ev->io.data = ev;
-               ev_io_init(&ev->io, rspamd_ev_watcher_io_cb, ev->io.fd, what);
-               ev_io_start(EV_A, &ev->io);
+       if (ev->io.fd >= 0) {
+               if (ev_can_stop(&ev->io)) {
+                       ev_io_stop(EV_A, &ev->io);
+                       ev_io_set(&ev->io, ev->io.fd, what);
+                       ev_io_start(EV_A, &ev->io);
+               }
+               else {
+                       ev->io.data = ev;
+                       ev_io_init(&ev->io, rspamd_ev_watcher_io_cb, ev->io.fd, what);
+                       ev_io_start(EV_A, &ev->io);
+               }
        }
 
        if (ev->timeout > 0) {
@@ -122,15 +126,17 @@ void rspamd_ev_watcher_reschedule_at(struct ev_loop *loop,
 {
        g_assert(ev->cb != NULL);
 
-       if (ev_can_stop(&ev->io)) {
-               ev_io_stop(EV_A, &ev->io);
-               ev_io_set(&ev->io, ev->io.fd, what);
-               ev_io_start(EV_A, &ev->io);
-       }
-       else {
-               ev->io.data = ev;
-               ev_io_init(&ev->io, rspamd_ev_watcher_io_cb, ev->io.fd, what);
-               ev_io_start(EV_A, &ev->io);
+       if (ev->io.fd >= 0) {
+               if (ev_can_stop(&ev->io)) {
+                       ev_io_stop(EV_A, &ev->io);
+                       ev_io_set(&ev->io, ev->io.fd, what);
+                       ev_io_start(EV_A, &ev->io);
+               }
+               else {
+                       ev->io.data = ev;
+                       ev_io_init(&ev->io, rspamd_ev_watcher_io_cb, ev->io.fd, what);
+                       ev_io_start(EV_A, &ev->io);
+               }
        }
 
        if (at > 0) {