Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20260805141033.841558-10-matthias.goergens@gmail.com>
Date: Wed,  5 Aug 2026 22:10:32 +0800
From: Matthias Goergens <matthias.goergens@...il.com>
To: musl@...ts.openwall.com
Cc: Matthias Goergens <matthias.goergens@...il.com>
Subject: [PATCH 09/10] regression: test mktime with extreme tm_mday

mktime and timegm must normalize the complete int range of
tm_mday; INT_MIN must not overflow before the long long
multiplication.

Covered by the musl patch "time: avoid overflow normalizing
extreme tm_mday".
---
 src/regression/mktime-mday-overflow.c | 46 +++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)
 create mode 100644 src/regression/mktime-mday-overflow.c

diff --git a/src/regression/mktime-mday-overflow.c b/src/regression/mktime-mday-overflow.c
new file mode 100644
index 0000000..aa1ff35
--- /dev/null
+++ b/src/regression/mktime-mday-overflow.c
@@ -0,0 +1,46 @@
+// mktime and timegm must normalize out-of-range struct tm fields, but
+// __tm_to_secs evaluated tm->tm_mday - 1 in int, so the valid value
+// INT_MIN overflowed before the long long multiplication and produced
+// a result with the wrong sign. The subtraction must happen in
+// long long so the complete int range of tm_mday normalizes.
+#define _GNU_SOURCE
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <time.h>
+#include "test.h"
+
+static void check(const char *name, time_t (*convert)(struct tm *))
+{
+	struct tm tm = {
+		.tm_year = 70,
+		.tm_mon = 0,
+		.tm_mday = INT_MIN,
+	};
+	long long want = 86400LL * (INT_MIN - 1LL);
+	time_t r;
+
+	errno = 0;
+	r = convert(&tm);
+	if (sizeof(time_t) < sizeof(long long)) {
+		/* not representable: must fail, not wrap */
+		if (r != (time_t)-1 || errno != EOVERFLOW)
+			t_error("%s(tm_mday = INT_MIN) = %lld (errno %d), want -1/EOVERFLOW\n",
+				name, (long long)r, errno);
+	} else if ((long long)r != want) {
+		t_error("%s(tm_mday = INT_MIN) = %lld, want %lld\n",
+			name, (long long)r, want);
+	}
+}
+
+int main(void)
+{
+	if (setenv("TZ", "UTC0", 1)) {
+		t_error("setenv failed\n");
+		return t_status;
+	}
+	tzset();
+	check("timegm", timegm);
+	check("mktime", mktime);
+	return t_status;
+}
-- 
2.55.0

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.