From f9e9e5f9013cc2e9d238cbcad9a1dfaf3a529aac Mon Sep 17 00:00:00 2001
From: Tavian Barnes <tavianator@tavianator.com>
Date: Sun, 10 Mar 2024 11:39:34 -0400
Subject: tests/xtime: Add tests for integer overflow

---
 src/xtime.c   |  4 +++-
 tests/xtime.c | 28 ++++++++++++++++++++++++++++
 2 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/src/xtime.c b/src/xtime.c
index 8100f6c..05f0e1a 100644
--- a/src/xtime.c
+++ b/src/xtime.c
@@ -2,8 +2,9 @@
 // SPDX-License-Identifier: 0BSD
 
 #include "xtime.h"
-#include "atomic.h"
+#include "bfstd.h"
 #include "config.h"
+#include "diag.h"
 #include <errno.h>
 #include <limits.h>
 #include <stdlib.h>
@@ -19,6 +20,7 @@ int xmktime(struct tm *tm, time_t *timep) {
 
 		struct tm tmp;
 		if (!localtime_r(timep, &tmp)) {
+			bfs_bug("localtime_r(-1): %s", xstrerror(errno));
 			return -1;
 		}
 
diff --git a/tests/xtime.c b/tests/xtime.c
index 2609c1c..3f1fec2 100644
--- a/tests/xtime.c
+++ b/tests/xtime.c
@@ -99,6 +99,19 @@ static bool check_xmktime(void) {
 		ret &= check_one_xmktime(time);
 	}
 
+	// Attempt to trigger overflow (but don't test for it, since it's not mandatory)
+	struct tm tm = {
+		.tm_year = INT_MAX,
+		.tm_mon = INT_MAX,
+		.tm_mday = INT_MAX,
+		.tm_hour = INT_MAX,
+		.tm_min = INT_MAX,
+		.tm_sec = INT_MAX,
+		.tm_isdst = -1,
+	};
+	time_t time;
+	xmktime(&tm, &time);
+
 	return ret;
 }
 
@@ -131,7 +144,9 @@ static bool check_xtimegm(void) {
 	struct tm tm = {
 		.tm_isdst = -1,
 	};
+	time_t time;
 
+	// Check equivalence with mktime()
 	for (tm.tm_year =  10; tm.tm_year <= 200; tm.tm_year += 10)
 	for (tm.tm_mon  =  -3; tm.tm_mon  <=  15; tm.tm_mon  +=  3)
 	for (tm.tm_mday = -31; tm.tm_mday <=  61; tm.tm_mday +=  4)
@@ -141,6 +156,19 @@ static bool check_xtimegm(void) {
 		ret &= check_one_xtimegm(&tm);
 	}
 
+	// Check integer overflow cases
+	tm = (struct tm){ .tm_sec = INT_MAX, .tm_min = INT_MAX };
+	ret &= bfs_check(xtimegm(&tm, &time) == -1 && errno == EOVERFLOW);
+
+	tm = (struct tm){ .tm_min = INT_MAX, .tm_hour = INT_MAX };
+	ret &= bfs_check(xtimegm(&tm, &time) == -1 && errno == EOVERFLOW);
+
+	tm = (struct tm){ .tm_hour = INT_MAX, .tm_mday = INT_MAX };
+	ret &= bfs_check(xtimegm(&tm, &time) == -1 && errno == EOVERFLOW);
+
+	tm = (struct tm){ .tm_mon = INT_MAX, .tm_year = INT_MAX };
+	ret &= bfs_check(xtimegm(&tm, &time) == -1 && errno == EOVERFLOW);
+
 	return ret;
 }
 
-- 
cgit v1.2.3