From e1d623505edafd7a01523ab39910a3900dd682dc Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Fri, 15 May 2026 14:34:41 -0400
Subject: [PATCH] android: Remove call to mktime() in APK entry parsing.
---
src/core/android/SDL_android.c | 45 ++++++++++++++++++----------------
1 file changed, 24 insertions(+), 21 deletions(-)
diff --git a/src/core/android/SDL_android.c b/src/core/android/SDL_android.c
index a4c56f92bcab6..2b90ff03e8447 100644
--- a/src/core/android/SDL_android.c
+++ b/src/core/android/SDL_android.c
@@ -2027,27 +2027,30 @@ static APKNode *AddAPKDirs(char *path, APKNode *parent)
static SDL_Time ZipDosTimeToSDLTime(Uint32 dostime)
{
- Uint32 dosdate;
- struct tm unixtime;
- SDL_zero(unixtime);
-
- dosdate = (Uint32) ((dostime >> 16) & 0xFFFF);
- dostime &= 0xFFFF;
-
- /* dissect date */
- unixtime.tm_year = ((dosdate >> 9) & 0x7F) + 80;
- unixtime.tm_mon = ((dosdate >> 5) & 0x0F) - 1;
- unixtime.tm_mday = ((dosdate ) & 0x1F);
-
- /* dissect time */
- unixtime.tm_hour = ((dostime >> 11) & 0x1F);
- unixtime.tm_min = ((dostime >> 5) & 0x3F);
- unixtime.tm_sec = ((dostime << 1) & 0x3E);
-
- /* let mktime calculate daylight savings time. */
- unixtime.tm_isdst = -1;
-
- return ((SDL_Time) mktime(&unixtime));
+ // Note that DOS-style datetimes in a zip don't have timezone info, etc,
+ // so these are treated as UTC for lack of a better option. Also, they have
+ // 2-second precision and the year bits are going to roll over in 2108.
+ // There are possibly better timestamps in extended fields (!!! FIXME: add
+ // support for those), but this field is guaranteed to exist with all its
+ // flaws and is probably Good Enough anyhow.
+ const Uint32 dosdate = (Uint32) ((dostime >> 16) & 0xFFFF);
+ const Uint32 dostime16 = dostime & 0xFFFF;
+
+ const int m = (int) ((dosdate >> 5) & 0x0F);
+ const int d = (int) ((dosdate >> 0) & 0x1F) + 1;
+ const int y = (int) (((dosdate >> 9) & 0x7F) + 1980) - (m <= 2 ? 1 : 0);
+ const int hour = (int) ((dostime16 >> 11) & 0x1F);
+ const int minute = (int) ((dostime16 >> 5) & 0x3F);
+ const int sec = (int) ((dostime16 << 1) & 0x3E);
+
+ // days since 1/1/1970: https://howardhinnant.github.io/date_algorithms.html#days_from_civil
+ const int era = ((y >= 0) ? y : (y - 399)) / 400;
+ const unsigned int yoe = (unsigned int) (y - era * 400); // [0, 399]
+ const unsigned int doy = (((153 * ((m > 2) ? (m - 3) : (m + 9))) + 2) / 5) + (d - 1); // [0, 365]
+ const unsigned int doe = (yoe * 365) + (yoe / 4) - (yoe / 100) + doy; // [0, 146096]
+ const int days = (era * 146097) + ((int) doe) - 719468;
+ const int seconds = (hour * (60 * 60)) + (minute * 60) + (sec);
+ return (SDL_Time) (((Sint64) days) * 86400) + seconds;
}