Fix overflow of time value

This commit is contained in:
Ben Meadors 2025-09-14 07:37:36 -05:00
parent bf4e2e8e86
commit 0847969201
2 changed files with 35 additions and 12 deletions

View File

@ -136,20 +136,35 @@ RTCSetResult perhapsSetRTC(RTCQuality q, const struct timeval *tv, bool forceUpd
static uint32_t lastSetMsec = 0; static uint32_t lastSetMsec = 0;
uint32_t now = millis(); uint32_t now = millis();
uint32_t printableEpoch = tv->tv_sec; // Print lib only supports 32 bit but time_t can be 64 bit on some platforms uint32_t printableEpoch = tv->tv_sec; // Print lib only supports 32 bit but time_t can be 64 bit on some platforms
#ifdef BUILD_EPOCH
// Debug the comparison before entering the block
uint64_t maxAllowedTime64_debug = (uint64_t)BUILD_EPOCH + FORTY_YEARS;
time_t maxAllowedTime_cast = (time_t)maxAllowedTime64_debug;
LOG_DEBUG("GPS comparison debug: tv_sec=%ld, maxAllowed64=%lu, maxAllowed_cast=%ld, sizeof(time_t)=%d", (long)tv->tv_sec,
(unsigned long)maxAllowedTime64_debug, (long)maxAllowedTime_cast, sizeof(time_t));
#if defined(BUILD_EPOCH)
if (tv->tv_sec < BUILD_EPOCH) { if (tv->tv_sec < BUILD_EPOCH) {
if (Throttle::isWithinTimespanMs(lastTimeValidationWarning, TIME_VALIDATION_WARNING_INTERVAL_MS) == false) { if (Throttle::isWithinTimespanMs(lastTimeValidationWarning, TIME_VALIDATION_WARNING_INTERVAL_MS) == false) {
LOG_WARN("Ignore time (%ld) before build epoch (%ld)!", printableEpoch, BUILD_EPOCH); LOG_WARN("Ignore time (%ld) before build epoch (%ld)!", printableEpoch, BUILD_EPOCH);
lastTimeValidationWarning = millis(); lastTimeValidationWarning = millis();
} }
return RTCSetResultInvalidTime; return RTCSetResultInvalidTime;
} else if (tv->tv_sec > (time_t)(BUILD_EPOCH + FORTY_YEARS)) { } else if ((uint64_t)tv->tv_sec > ((uint64_t)BUILD_EPOCH + FORTY_YEARS)) {
if (Throttle::isWithinTimespanMs(lastTimeValidationWarning, TIME_VALIDATION_WARNING_INTERVAL_MS) == false) { if (Throttle::isWithinTimespanMs(lastTimeValidationWarning, TIME_VALIDATION_WARNING_INTERVAL_MS) == false) {
// Calculate max allowed time safely to avoid overflow in logging // Calculate max allowed time safely to avoid overflow in logging
uint64_t maxAllowedTime = (uint64_t)BUILD_EPOCH + FORTY_YEARS; uint64_t maxAllowedTime64 = (uint64_t)BUILD_EPOCH + FORTY_YEARS;
uint32_t maxAllowedPrintable = (maxAllowedTime > UINT32_MAX) ? UINT32_MAX : (uint32_t)maxAllowedTime; LOG_DEBUG("GPS time validation: BUILD_EPOCH=%lu, maxAllowedTime64=%lu, UINT32_MAX=%lu", (unsigned long)BUILD_EPOCH,
LOG_WARN("Ignore time (%ld) too far in the future (build epoch: %ld, max allowed: %ld)!", printableEpoch, (unsigned long)maxAllowedTime64, (unsigned long)UINT32_MAX);
(uint32_t)BUILD_EPOCH, maxAllowedPrintable);
// For logging, show the actual 64-bit value or indicate overflow
if (maxAllowedTime64 <= UINT32_MAX) {
LOG_WARN("Ignore time (%ld) too far in the future (build epoch: %ld, max allowed: %ld)!", printableEpoch,
(uint32_t)BUILD_EPOCH, (uint32_t)maxAllowedTime64);
} else {
LOG_WARN("Ignore time (%ld) too far in the future (build epoch: %ld, max allowed: >4294967295)!", printableEpoch,
(uint32_t)BUILD_EPOCH);
}
lastTimeValidationWarning = millis(); lastTimeValidationWarning = millis();
} }
return RTCSetResultInvalidTime; return RTCSetResultInvalidTime;
@ -274,13 +289,21 @@ RTCSetResult perhapsSetRTC(RTCQuality q, struct tm &t)
lastTimeValidationWarning = millis(); lastTimeValidationWarning = millis();
} }
return RTCSetResultInvalidTime; return RTCSetResultInvalidTime;
} else if (tv.tv_sec > (time_t)(BUILD_EPOCH + FORTY_YEARS)) { } else if ((uint64_t)tv.tv_sec > ((uint64_t)BUILD_EPOCH + FORTY_YEARS)) {
if (Throttle::isWithinTimespanMs(lastTimeValidationWarning, TIME_VALIDATION_WARNING_INTERVAL_MS) == false) { if (Throttle::isWithinTimespanMs(lastTimeValidationWarning, TIME_VALIDATION_WARNING_INTERVAL_MS) == false) {
// Calculate max allowed time safely to avoid overflow in logging // Calculate max allowed time safely to avoid overflow in logging
uint64_t maxAllowedTime = (uint64_t)BUILD_EPOCH + FORTY_YEARS; uint64_t maxAllowedTime64 = (uint64_t)BUILD_EPOCH + FORTY_YEARS;
uint32_t maxAllowedPrintable = (maxAllowedTime > UINT32_MAX) ? UINT32_MAX : (uint32_t)maxAllowedTime; LOG_DEBUG("GPS time validation: BUILD_EPOCH=%lu, maxAllowedTime64=%lu, UINT32_MAX=%lu", (unsigned long)BUILD_EPOCH,
LOG_WARN("Ignore time (%ld) too far in the future (build epoch: %ld, max allowed: %ld)!", printableEpoch, (unsigned long)maxAllowedTime64, (unsigned long)UINT32_MAX);
(uint32_t)BUILD_EPOCH, maxAllowedPrintable);
// For logging, show the actual 64-bit value or indicate overflow
if (maxAllowedTime64 <= UINT32_MAX) {
LOG_WARN("Ignore time (%ld) too far in the future (build epoch: %ld, max allowed: %ld)!", printableEpoch,
(uint32_t)BUILD_EPOCH, (uint32_t)maxAllowedTime64);
} else {
LOG_WARN("Ignore time (%ld) too far in the future (build epoch: %ld, max allowed: >4294967295)!", printableEpoch,
(uint32_t)BUILD_EPOCH);
}
lastTimeValidationWarning = millis(); lastTimeValidationWarning = millis();
} }
return RTCSetResultInvalidTime; return RTCSetResultInvalidTime;

View File

@ -56,5 +56,5 @@ time_t gm_mktime(struct tm *tm);
#define SEC_PER_HOUR 3600 #define SEC_PER_HOUR 3600
#define SEC_PER_MIN 60 #define SEC_PER_MIN 60
#ifdef BUILD_EPOCH #ifdef BUILD_EPOCH
#define FORTY_YEARS (40ULL * 365 * SEC_PER_DAY) // Use 64-bit arithmetic to prevent overflow static constexpr uint64_t FORTY_YEARS = (40ULL * 365 * SEC_PER_DAY); // Use 64-bit arithmetic to prevent overflow
#endif #endif