[PATCH 4/6] alfred: reject invalid synchronization periods

Sven Eckelmann <[email protected]> Thu, 30 Jul 2026 21:31:58 +0200
Newsgroups org.open-mesh.lists.batman
Message-ID <[email protected]>
The -p option argument was parsed with strtod() without any validation. An
unparsable argument yields 0.0 and a zero it_value disarms a timerfd
instead of arming it. 'alfred -p 0' or a mistyped period therefore started
a daemon whose periodic timer never fired - no primary announcements, no
data synchronization and no purging of stale data - while everything looked
fine at startup.

Reject non-finite, zero and negative synchronization periods. And also
reject parse errors.

Signed-off-by: Sven Eckelmann <[email protected]>
---
 Makefile |  2 +-
 main.c   | 25 ++++++++++++++++++++++++-
 2 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/Makefile b/Makefile
index d71f41f..66b3a10 100755
--- a/Makefile
+++ b/Makefile
@@ -25,7 +25,7 @@ MANPAGE = man/alfred.8
 # alfred flags and options
 CFLAGS += -pedantic -Wall -W -std=gnu99 -fno-strict-aliasing -MD -MP
 CPPFLAGS += -D_GNU_SOURCE
-LDLIBS += -lrt
+LDLIBS += -lrt -lm
 
 # Turn on alfred capability dropping by default - set this to n if you don't want/need it
 export CONFIG_ALFRED_CAPABILITIES=y
diff --git a/main.c b/main.c
index baedbd2..6372ec8 100644
--- a/main.c
+++ b/main.c
@@ -7,7 +7,10 @@
  */
 
 #include <arpa/inet.h>
+#include <errno.h>
 #include <getopt.h>
+#include <limits.h>
+#include <math.h>
 #include <signal.h>
 #include <stdbool.h>
 #include <stdio.h>
@@ -172,6 +175,7 @@ static struct globals *alfred_init(int argc, char *argv[])
 	};
 	double sync_period = 0.0;
 	struct globals *globals;
+	char *endptr;
 	int opt_ind;
 	int opt;
 	int ret;
@@ -298,9 +302,28 @@ static struct globals *alfred_init(int argc, char *argv[])
 			printf("A.L.F.R.E.D. - Almighty Lightweight Remote Fact Exchange Daemon\n");
 			return NULL;
 		case 'p':
-			sync_period = strtod(optarg, NULL);
+			errno = 0;
+			sync_period = strtod(optarg, &endptr);
+			if (errno || *endptr != '\0' || endptr == optarg ||
+			    !isfinite(sync_period) || sync_period <= 0 ||
+			    sync_period > (double)INT_MAX) {
+				fprintf(stderr, "bad sync period argument\n");
+				return NULL;
+			}
+
 			globals->sync_period.tv_sec = (int)sync_period;
 			globals->sync_period.tv_nsec = (double)(sync_period - (int)sync_period) * 1e9;
+
+			/* a period which rounds down to an all zero timespec
+			 * would disarm the timer in timerfd_settime() instead
+			 * of triggering it
+			 */
+			if (globals->sync_period.tv_sec == 0 &&
+			    globals->sync_period.tv_nsec == 0) {
+				fprintf(stderr, "sync period argument too small\n");
+				return NULL;
+			}
+
 			printf(" ** Setting sync interval to: %.9f seconds (%lld.%09u)\n", sync_period,
 			       (long long)globals->sync_period.tv_sec,
 			       (unsigned int)globals->sync_period.tv_nsec);

-- 
2.47.3