On Fri, Jan 09, 2026 at 11:34:54AM +0100, Andy Spiegl wrote:
> > That change was done here:
> > https://salsa.debian.org/debian/dovecot/-/commit/74e7dcd8c01731861777005a6c49b9093aec19c6
> Thanks.
> 
> > TIME_T_MAX_BITS is set to 31 because Debian on i386 uses a signed 32-bit
> > integer for time_t.
> Ok.  But then, this line in ioloop.c has to be adapted on i386 as well?
> >     ioloop->next_max_time.tv_sec = (1ULL << (TIME_T_MAX_BITS-1)) - 1;
> It is supposed to be a very large value, "infinity" but on i386 is 1073741823
> which corresponds to 2004-01-10 instead of 2038-01-19.

So, it turns out that dovecot doesn't correctly handle 32-bit signed
time_t at all right now.  If we attempt to make it work by setting
TIME_T_MAX_BITS=31, it misbehaves in the manner described in this bug.

If we set TIME_T_MAX_BITS=32, then the tm_is_too_large() function
(src/lib-imap/imap-date.c) misbehaves by assuming that time_t is
unsigned, in which case it ends up with a "maximum" value corresponding
to Wed Dec 31 18:59:59 1969.

The attached patch updates tm_is_too_large() to set the correct maximum
unsigned 32-bit time_t correctly.  In my testing, it resolves the issue
described in this bug when TIME_T_MAX_BITS=32.

Will you be able to test this patch?  Trixie packages with version
1:2.4.1+dfsg1-6+deb13u2+32bit are available in my apt repo at
https://people.debian.org/~noahm/repo/

The patch is also at https://salsa.debian.org/noahm/dovecot/-/commits/bug1124541

noah

From: Noah Meyerhans <[email protected]>
Subject: [PATCH] Correctly handle signed 32-bit time_t types
Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1124541
Forwarded: no

dovecot handles 32-bit time_t in a couple of different ways, but neither quite
works currently.  Setting TIME_T_MAX_BITS to 31 isn't correctly handled in
places where time_t values are constructed, for example in
io_loop_get_wait_time().

Similarly, setting TIME_T_MAX_BITS = 32 and defining TIME_T_SIGNED is not
correctly handled by tm_is_too_large().

This change fixes tm_is_too_large() to set max_time to the correct maximum date
representable by a signed 32-bit time_t.

Closes: #1124541
---
 src/lib-imap/imap-date.c      |  4 ++++
 src/lib-imap/test-imap-date.c | 14 ++++++++------
 2 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/src/lib-imap/imap-date.c b/src/lib-imap/imap-date.c
index c9262932c..df9d11605 100644
--- a/src/lib-imap/imap-date.c
+++ b/src/lib-imap/imap-date.c
@@ -86,7 +86,11 @@ static bool tm_is_too_large(const struct tm *tm, time_t *max_time_r)
 
 	if (max_time == 0) {
 #if TIME_T_MAX_BITS == 32
+#ifdef TIME_T_SIGNED
+		max_time = ((time_t)1 << TIME_T_MAX_BITS - 1) - 1;
+#else
 		max_time = 0xffffffffUL;
+#endif
 #elif TIME_T_MAX_BITS == 64
 		max_time = 0xffffffffffffffffULL;
 #else
diff --git a/src/lib-imap/test-imap-date.c b/src/lib-imap/test-imap-date.c
index 5a2a36402..94c1a820d 100644
--- a/src/lib-imap/test-imap-date.c
+++ b/src/lib-imap/test-imap-date.c
@@ -15,7 +15,7 @@ static void test_imap_date(void)
 	} tests[] = {
 		{ "01-Jan-1970", 0 },
 		{ "19-Jan-2038", 2147472000 },
-#if TIME_T_MAX_BITS >= 32
+#if TIME_T_MAX_BITS > 32 || !defined(TIME_T_SIGNED)
 		{ "07-Feb-2106", 4294944000 },
 #endif
 #if TIME_T_MAX_BITS >= 37
@@ -25,10 +25,10 @@ static void test_imap_date(void)
 		{ "31-Dec-9999", 253402214400LL },
 #endif
 		/* conversions to maximum values */
-#if TIME_T_MAX_BITS == 31
+#if TIME_T_MAX_BITS == 32 && !defined(TIME_T_SIGNED)
 		{ "20-Jan-2038", 2147483647 },
 		{ "31-Dec-9999", 2147483647 },
-#elif TIME_T_MAX_BITS == 32
+#elif TIME_T_MAX_BITS == 32 && !defined(TIME_T_SIGNED)
 		{ "08-Feb-2106", 4294967295 },
 		{ "31-Dec-9999", 4294967295 },
 #endif
@@ -59,8 +59,10 @@ static void test_imap_datetime(void)
 	} tests[] = {
 		{ "01-Jan-1970 00:00:00 +0000", 0, 0 },
 		{ "19-Jan-2038 03:14:07 +0000", 2147483647, 0 },
-		{ "19-Jan-2038 05:14:07 +0200", 2147483647, 2*60 },
 #if TIME_T_MAX_BITS >= 32
+		{ "19-Jan-2038 05:14:07 +0200", 2147483647, 2*60 },
+#endif
+#if TIME_T_MAX_BITS > 32 || !defined(TIME_T_SIGNED)
 		{ "07-Feb-2106 06:28:15 +0000", 4294967295, 0 },
 #endif
 #if TIME_T_MAX_BITS >= 37
@@ -71,10 +73,10 @@ static void test_imap_datetime(void)
 		{ "31-Dec-9999 23:59:59 -2359", 253402300799LL + 23*60*60 + 59*60, -23*60 - 59 },
 #endif
 		/* conversions to maximum values */
-#if TIME_T_MAX_BITS == 31
+#if TIME_T_MAX_BITS == 32 && defined(TIME_T_SIGNED)
 		{ "19-Jan-2038 03:14:08 +0000", 2147483647, 0 },
 		{ "31-Dec-9999 23:59:59 -2359", 2147483647, -23*60 - 59 },
-#elif TIME_T_MAX_BITS == 32
+#elif TIME_T_MAX_BITS == 32 && !defined(TIME_T_SIGNED)
 		{ "07-Feb-2106 06:28:16 +0000", 4294967295, 0 },
 		{ "31-Dec-9999 23:59:59 -2359", 4294967295, -23*60 - 59 },
 #endif
-- 
2.47.3

Reply via email to