diff --git a/src/io/devices/ZipFileDevice.cpp b/src/io/devices/ZipFileDevice.cpp index 2c52439ae..025c1c335 100644 --- a/src/io/devices/ZipFileDevice.cpp +++ b/src/io/devices/ZipFileDevice.cpp @@ -58,11 +58,22 @@ namespace { } uint32_t to_ms_dos_timestamp(const file_time_type& fileTime) { + // 1980-01-01 00:00, the earliest MS-DOS date; used for unknown time + // (devices without timestamps return file_time_type::min()) + constexpr uint32_t DOS_EPOCH = (0 << 9 | 1 << 5 | 1) << 16; + if (fileTime == file_time_type::min()) { + return DOS_EPOCH; + } auto timePoint = time_point_cast( fileTime - file_time_type::clock::now() + system_clock::now() ); std::time_t timeT = system_clock::to_time_t(timePoint); - std::tm tm = *std::localtime(&timeT); + // localtime returns nullptr for out of range time on Windows + const std::tm* tmPtr = std::localtime(&timeT); + if (tmPtr == nullptr || tmPtr->tm_year < 80) { + return DOS_EPOCH; + } + const std::tm& tm = *tmPtr; uint16_t date = (tm.tm_year - 80) << 9 | (tm.tm_mon + 1) << 5 | tm.tm_mday; uint16_t time = (tm.tm_hour << 11) | (tm.tm_min << 5) | (tm.tm_sec / 2); return (date << 16) | time;