From 3497efea1000db43c58ab9eb987f9b611f855e4c Mon Sep 17 00:00:00 2001 From: Alexander Polyakov Date: Sun, 1 Jun 2025 14:23:07 +0300 Subject: [PATCH] [k2] fix memory leak in timezone_cache move assignment operator --- .../stdlib/time/timelib-timezone-cache.h | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/runtime-light/stdlib/time/timelib-timezone-cache.h b/runtime-light/stdlib/time/timelib-timezone-cache.h index 1eb11263d8..b7f9ec7081 100644 --- a/runtime-light/stdlib/time/timelib-timezone-cache.h +++ b/runtime-light/stdlib/time/timelib-timezone-cache.h @@ -48,18 +48,18 @@ class timezone_cache final { m_cache.emplace(tzinfo); } + void clear() noexcept { + (kphp::memory::libc_alloc_guard{}, std::ranges::for_each(m_cache, [](timelib_tzinfo* tzinfo) noexcept { timelib_tzinfo_dtor(tzinfo); })); + m_cache.clear(); + } + timezone_cache() noexcept = default; timezone_cache(std::initializer_list tzs) noexcept { kphp::memory::libc_alloc_guard _{}; std::ranges::for_each(tzs, [this](std::string_view tz) noexcept { int errc{}; // it's intentionally declared as 'int' since timelib_parse_tzfile accepts 'int' - auto* tzinfo{timelib_parse_tzfile(tz.data(), timelib_builtin_db(), std::addressof(errc))}; - if (tzinfo == nullptr) [[unlikely]] { - kphp::log::warning("can't get timezone info: timezone -> {}, error -> {}", tz, timelib_get_error_message(errc)); - return; - } - put(tzinfo); + put(timelib_parse_tzfile(tz.data(), timelib_builtin_db(), std::addressof(errc))); }); } @@ -68,6 +68,7 @@ class timezone_cache final { timezone_cache& operator=(timezone_cache&& other) noexcept { if (this != std::addressof(other)) { + clear(); m_cache = std::move(other.m_cache); } return *this; @@ -77,8 +78,9 @@ class timezone_cache final { timezone_cache& operator=(const timezone_cache&) = delete; ~timezone_cache() { - kphp::memory::libc_alloc_guard _{}; - std::ranges::for_each(m_cache, [](timelib_tzinfo* tzinfo) noexcept { timelib_tzinfo_dtor(tzinfo); }); + if (!m_cache.empty()) { + clear(); + } } };