Skip to content

Commit e336026

Browse files
committed
Fix localtime/1 mem leak
espressif/esp-idf#9764 Signed-off-by: Peter M <petermm@gmail.com>
1 parent dbc1540 commit e336026

1 file changed

Lines changed: 32 additions & 5 deletions

File tree

src/libAtomVM/nifs.c

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1728,6 +1728,28 @@ term nif_erlang_universaltime_0(Context *ctx, int argc, term argv[])
17281728
return build_datetime_from_tm(ctx, gmtime_r(&ts.tv_sec, &broken_down_time));
17291729
}
17301730

1731+
// Workaround for newlib setenv memory leak: use putenv with a fixed-size
1732+
// static buffer. The buffer is installed once and then modified in place.
1733+
// See: https://github.com/espressif/esp-idf/issues/3046
1734+
#define TZ_BUFFER_SIZE 64
1735+
1736+
static char tz_buffer[TZ_BUFFER_SIZE] = "TZ=";
1737+
static bool tz_buffer_installed = false;
1738+
1739+
static void set_tz_value(const char *tz)
1740+
{
1741+
if (!tz_buffer_installed) {
1742+
putenv(tz_buffer);
1743+
tz_buffer_installed = true;
1744+
}
1745+
size_t tz_len = strlen(tz);
1746+
if (tz_len > TZ_BUFFER_SIZE - 4) {
1747+
tz_len = TZ_BUFFER_SIZE - 4;
1748+
}
1749+
memcpy(tz_buffer + 3, tz, tz_len);
1750+
tz_buffer[3 + tz_len] = '\0';
1751+
}
1752+
17311753
term nif_erlang_localtime(Context *ctx, int argc, term argv[])
17321754
{
17331755
char *tz;
@@ -1751,17 +1773,22 @@ term nif_erlang_localtime(Context *ctx, int argc, term argv[])
17511773
smp_spinlock_lock(&ctx->global->env_spinlock);
17521774
#endif
17531775
if (tz) {
1754-
char *oldtz = getenv("TZ");
1755-
setenv("TZ", tz, 1);
1776+
char *oldtz = NULL;
1777+
char *oldtz_env = getenv("TZ");
1778+
if (oldtz_env) {
1779+
oldtz = strdup(oldtz_env);
1780+
}
1781+
set_tz_value(tz);
17561782
tzset();
17571783
localtime = localtime_r(&ts.tv_sec, &storage);
17581784
if (oldtz) {
1759-
setenv("TZ", oldtz, 1);
1785+
set_tz_value(oldtz);
1786+
free(oldtz);
17601787
} else {
1761-
unsetenv("TZ");
1788+
set_tz_value("");
17621789
}
1790+
tzset();
17631791
} else {
1764-
// Call tzset to handle DST changes
17651792
tzset();
17661793
localtime = localtime_r(&ts.tv_sec, &storage);
17671794
}

0 commit comments

Comments
 (0)