diff --git a/src/gps/RTC.cpp b/src/gps/RTC.cpp index e208e2df9..5528249c4 100644 --- a/src/gps/RTC.cpp +++ b/src/gps/RTC.cpp @@ -9,6 +9,10 @@ static RTCQuality currentQuality = RTCQualityNone; uint32_t lastSetFromPhoneNtpOrGps = 0; +// Rate limiting for GPS time validation warnings +static uint32_t lastTimeValidationWarning = 0; +static const uint32_t TIME_VALIDATION_WARNING_INTERVAL_MS = 15000; // 15 seconds + RTCQuality getRTCQuality() { return currentQuality; @@ -130,11 +134,20 @@ RTCSetResult perhapsSetRTC(RTCQuality q, const struct timeval *tv, bool forceUpd 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 if (tv->tv_sec < BUILD_EPOCH) { - LOG_WARN("Ignore time (%ld) before build epoch (%ld)!", printableEpoch, BUILD_EPOCH); + if (Throttle::isWithinTimespanMs(lastTimeValidationWarning, TIME_VALIDATION_WARNING_INTERVAL_MS) == false) { + LOG_WARN("Ignore time (%ld) before build epoch (%ld)!", printableEpoch, BUILD_EPOCH); + lastTimeValidationWarning = millis(); + } return RTCSetResultInvalidTime; - } else if (tv->tv_sec > (BUILD_EPOCH + FORTY_YEARS)) { - LOG_WARN("Ignore time (%ld) too far in the future (build epoch: %ld, max allowed: %ld)!", printableEpoch, BUILD_EPOCH, - BUILD_EPOCH + FORTY_YEARS); + } else if (tv->tv_sec > (time_t)(BUILD_EPOCH + FORTY_YEARS)) { + if (Throttle::isWithinTimespanMs(lastTimeValidationWarning, TIME_VALIDATION_WARNING_INTERVAL_MS) == false) { + // Calculate max allowed time safely to avoid overflow in logging + uint64_t maxAllowedTime = (uint64_t)BUILD_EPOCH + FORTY_YEARS; + uint32_t maxAllowedPrintable = (maxAllowedTime > UINT32_MAX) ? UINT32_MAX : (uint32_t)maxAllowedTime; + LOG_WARN("Ignore time (%ld) too far in the future (build epoch: %ld, max allowed: %ld)!", printableEpoch, + (uint32_t)BUILD_EPOCH, maxAllowedPrintable); + lastTimeValidationWarning = millis(); + } return RTCSetResultInvalidTime; } #endif @@ -252,11 +265,20 @@ RTCSetResult perhapsSetRTC(RTCQuality q, struct tm &t) 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 if (tv.tv_sec < BUILD_EPOCH) { - LOG_WARN("Ignore time (%ld) before build epoch (%ld)!", printableEpoch, BUILD_EPOCH); + if (Throttle::isWithinTimespanMs(lastTimeValidationWarning, TIME_VALIDATION_WARNING_INTERVAL_MS) == false) { + LOG_WARN("Ignore time (%ld) before build epoch (%ld)!", printableEpoch, BUILD_EPOCH); + lastTimeValidationWarning = millis(); + } return RTCSetResultInvalidTime; - } else if (tv.tv_sec > (BUILD_EPOCH + FORTY_YEARS)) { - LOG_WARN("Ignore time (%ld) too far in the future (build epoch: %ld, max allowed: %ld)!", printableEpoch, BUILD_EPOCH, - BUILD_EPOCH + FORTY_YEARS); + } else if (tv.tv_sec > (time_t)(BUILD_EPOCH + FORTY_YEARS)) { + if (Throttle::isWithinTimespanMs(lastTimeValidationWarning, TIME_VALIDATION_WARNING_INTERVAL_MS) == false) { + // Calculate max allowed time safely to avoid overflow in logging + uint64_t maxAllowedTime = (uint64_t)BUILD_EPOCH + FORTY_YEARS; + uint32_t maxAllowedPrintable = (maxAllowedTime > UINT32_MAX) ? UINT32_MAX : (uint32_t)maxAllowedTime; + LOG_WARN("Ignore time (%ld) too far in the future (build epoch: %ld, max allowed: %ld)!", printableEpoch, + (uint32_t)BUILD_EPOCH, maxAllowedPrintable); + lastTimeValidationWarning = millis(); + } return RTCSetResultInvalidTime; } #endif diff --git a/src/gps/RTC.h b/src/gps/RTC.h index 03350823c..1ecde79ae 100644 --- a/src/gps/RTC.h +++ b/src/gps/RTC.h @@ -56,5 +56,5 @@ time_t gm_mktime(struct tm *tm); #define SEC_PER_HOUR 3600 #define SEC_PER_MIN 60 #ifdef BUILD_EPOCH -#define FORTY_YEARS (40UL * 365 * SEC_PER_DAY) // probably time to update your firmware +#define FORTY_YEARS (40ULL * 365 * SEC_PER_DAY) // Use 64-bit arithmetic to prevent overflow #endif