From be39d538d02d6154e0d64bff4edbbe41fdc461f9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 18 Oct 2025 16:22:37 +0000 Subject: [PATCH 1/7] Initial plan From 61a2bf5e1b451c2ffa0ba25e8fb04580020da31a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 18 Oct 2025 16:27:58 +0000 Subject: [PATCH 2/7] Fix critical memory issues in Debug.h: implement timezone caching and buffer safety Co-authored-by: rvdbreemen <8645876+rvdbreemen@users.noreply.github.com> --- Debug.h | 67 ++++++++++++++++++++++++--------------------------------- 1 file changed, 28 insertions(+), 39 deletions(-) diff --git a/Debug.h b/Debug.h index 1eda377..d8a0c13 100644 --- a/Debug.h +++ b/Debug.h @@ -44,47 +44,36 @@ void _debugBOL(const char *fn, int line) { - char _bol[128]; - // This commented out code is using mix of system time and acetime to print, but it will not work on microsecond level correctly - // // //calculate fractional seconds to millis fraction - // double fractional_seconds; - // int microseconds; - // struct timespec tp; //to enable clock_gettime() - // clock_gettime(CLOCK_REALTIME, &tp); - // fractional_seconds = (double) tp.tv_nsec; - // fractional_seconds /= 1e3; - // fractional_seconds = round(fractional_seconds); - // microseconds = (int) fractional_seconds; - - /* snprintf(_bol, sizeof(_bol), "%02d:%02d:%02d.%06d (%7u|%6u) %-12.12s(%4d): ", \ - hour(), minute(), second(), microseconds, \ - ESP.getFreeHeap(), ESP.getMaxFreeBlockSize(),\ - fn, line); - */ - - //Alternative based on localtime function + static char _bol[160]; // Increased size + static for stack reduction + + // Cache timezone manager calls to avoid recreating objects + static TimeZone cachedTz; + static time_t lastTzUpdate = 0; + time_t now_sec = time(nullptr); + + // Only update timezone every 5 minutes (300 seconds) + if (now_sec - lastTzUpdate > 300) { + cachedTz = timezoneManager.createForZoneName(CSTR(settingNTPtimezone)); + lastTzUpdate = now_sec; + } + timeval now; - //struct tm *tod; gettimeofday(&now, nullptr); - //tod = localtime(&now.tv_sec); - - /* - snprintf(_bol, sizeof(_bol), "%02d:%02d:%02d.%06d (%7u|%6u) %-12.12s(%4d): ", \ - tod->tm_hour, tod->tm_min, tod->tm_sec, (int)now.tv_usec, \ - ESP.getFreeHeap(), ESP.getMaxFreeBlockSize(),\ - fn, line); - */ - - TimeZone myTz = timezoneManager.createForZoneName(CSTR(settingNTPtimezone)); - ZonedDateTime myTime = ZonedDateTime::forUnixSeconds64(time(nullptr), myTz); - //DebugTf(PSTR("%02d:%02d:%02d %02d-%02d-%04d\r\n"), myTime.hour(), myTime.minute(), myTime.second(), myTime.day(), myTime.month(), myTime.year()); - - snprintf(_bol, sizeof(_bol), "%02d:%02d:%02d.%06d (%7u|%6u) %-12.12s(%4d): ", \ - myTime.hour(), myTime.minute(), myTime.second(), (int)now.tv_usec, \ - ESP.getFreeHeap(), ESP.getMaxFreeBlockSize(),\ - fn, line); - - TelnetStream.print (_bol); + ZonedDateTime myTime = ZonedDateTime::forUnixSeconds64(now_sec, cachedTz); + + // Use snprintf safely with return value checking + int written = snprintf(_bol, sizeof(_bol), + "%02d:%02d:%02d.%06d (%7u|%6u) %-12.12s(%4d): ", + myTime.hour(), myTime.minute(), myTime.second(), (int)now.tv_usec, + ESP.getFreeHeap(), ESP.getMaxFreeBlockSize(), + fn, line); + + // Ensure null termination even if truncated + if (written >= (int)sizeof(_bol)) { + _bol[sizeof(_bol) - 1] = '\0'; + } + + TelnetStream.print(_bol); } #endif From fafd6d44cf842e7b4230f27d9765f1b977eacaa6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 18 Oct 2025 16:29:33 +0000 Subject: [PATCH 3/7] Add error handling for timezone creation failures Co-authored-by: rvdbreemen <8645876+rvdbreemen@users.noreply.github.com> --- Debug.h | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Debug.h b/Debug.h index d8a0c13..5d13c95 100644 --- a/Debug.h +++ b/Debug.h @@ -51,10 +51,16 @@ void _debugBOL(const char *fn, int line) static time_t lastTzUpdate = 0; time_t now_sec = time(nullptr); - // Only update timezone every 5 minutes (300 seconds) - if (now_sec - lastTzUpdate > 300) { - cachedTz = timezoneManager.createForZoneName(CSTR(settingNTPtimezone)); - lastTzUpdate = now_sec; + // Only update timezone every 5 minutes (300 seconds) or on first call + // Check now_sec > 0 to ensure time is set + if ((now_sec > 0) && (now_sec - lastTzUpdate > 300)) { + TimeZone newTz = timezoneManager.createForZoneName(CSTR(settingNTPtimezone)); + // Only update cache if timezone is valid + if (!newTz.isError()) { + cachedTz = newTz; + lastTzUpdate = now_sec; + } + // If timezone creation fails, keep using previous cached timezone } timeval now; From 87c04f5047b0471f47aeb796d6075bc25a385cbf Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 18 Oct 2025 16:31:11 +0000 Subject: [PATCH 4/7] Improve timezone initialization logic with explicit tracking Co-authored-by: rvdbreemen <8645876+rvdbreemen@users.noreply.github.com> --- Debug.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Debug.h b/Debug.h index 5d13c95..2f3479a 100644 --- a/Debug.h +++ b/Debug.h @@ -49,16 +49,18 @@ void _debugBOL(const char *fn, int line) // Cache timezone manager calls to avoid recreating objects static TimeZone cachedTz; static time_t lastTzUpdate = 0; + static bool tzInitialized = false; time_t now_sec = time(nullptr); - // Only update timezone every 5 minutes (300 seconds) or on first call + // Initialize timezone on first call or refresh every 5 minutes (300 seconds) // Check now_sec > 0 to ensure time is set - if ((now_sec > 0) && (now_sec - lastTzUpdate > 300)) { + if (now_sec > 0 && (!tzInitialized || now_sec - lastTzUpdate > 300)) { TimeZone newTz = timezoneManager.createForZoneName(CSTR(settingNTPtimezone)); // Only update cache if timezone is valid if (!newTz.isError()) { cachedTz = newTz; lastTzUpdate = now_sec; + tzInitialized = true; } // If timezone creation fails, keep using previous cached timezone } From 702791dfc76742d3e95739985547a95ebe6555d5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 18 Oct 2025 16:33:15 +0000 Subject: [PATCH 5/7] Add fallback initialization to ensure cachedTz is always initialized Co-authored-by: rvdbreemen <8645876+rvdbreemen@users.noreply.github.com> --- Debug.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Debug.h b/Debug.h index 2f3479a..f3ced5b 100644 --- a/Debug.h +++ b/Debug.h @@ -68,6 +68,12 @@ void _debugBOL(const char *fn, int line) timeval now; gettimeofday(&now, nullptr); + // If timezone not yet initialized, try to initialize it now (first call fallback) + if (!tzInitialized) { + cachedTz = timezoneManager.createForZoneName(CSTR(settingNTPtimezone)); + tzInitialized = true; // Set to true even if it fails to avoid repeated attempts + } + ZonedDateTime myTime = ZonedDateTime::forUnixSeconds64(now_sec, cachedTz); // Use snprintf safely with return value checking From a57a8b02c5c07c4d0f6831aea95c7da762553c81 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 18 Oct 2025 16:35:17 +0000 Subject: [PATCH 6/7] Clarify fallback initialization logic and behavior Co-authored-by: rvdbreemen <8645876+rvdbreemen@users.noreply.github.com> --- Debug.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Debug.h b/Debug.h index f3ced5b..8733e6d 100644 --- a/Debug.h +++ b/Debug.h @@ -69,9 +69,11 @@ void _debugBOL(const char *fn, int line) gettimeofday(&now, nullptr); // If timezone not yet initialized, try to initialize it now (first call fallback) + // This handles the case when time is not set yet (now_sec <= 0) if (!tzInitialized) { cachedTz = timezoneManager.createForZoneName(CSTR(settingNTPtimezone)); - tzInitialized = true; // Set to true even if it fails to avoid repeated attempts + tzInitialized = true; // Mark as initialized to avoid repeated attempts on every call + // Note: Even if timezone creation fails, the error object is safe to use } ZonedDateTime myTime = ZonedDateTime::forUnixSeconds64(now_sec, cachedTz); From be55794f7073a867b2cff8432e70b0f675dbe522 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 18 Oct 2025 16:37:28 +0000 Subject: [PATCH 7/7] Improve comment accuracy for fallback initialization Co-authored-by: rvdbreemen <8645876+rvdbreemen@users.noreply.github.com> --- Debug.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Debug.h b/Debug.h index 8733e6d..2461be1 100644 --- a/Debug.h +++ b/Debug.h @@ -69,7 +69,7 @@ void _debugBOL(const char *fn, int line) gettimeofday(&now, nullptr); // If timezone not yet initialized, try to initialize it now (first call fallback) - // This handles the case when time is not set yet (now_sec <= 0) + // This handles cases when time is not set yet (now_sec <= 0) or when primary initialization failed if (!tzInitialized) { cachedTz = timezoneManager.createForZoneName(CSTR(settingNTPtimezone)); tzInitialized = true; // Mark as initialized to avoid repeated attempts on every call