From ed5992cd40a21a9c0af16ffd816a8e0a2f8af7dd Mon Sep 17 00:00:00 2001 From: "S. B. Tam" Date: Sat, 31 May 2025 12:40:34 +0800 Subject: [PATCH 1/3] `tzdb.cpp`: Fall back to numeric offset when time zone short ID isn't representable --- stl/src/tzdb.cpp | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/stl/src/tzdb.cpp b/stl/src/tzdb.cpp index 720064fefc5..8a0e725342e 100644 --- a/stl/src/tzdb.cpp +++ b/stl/src/tzdb.cpp @@ -567,7 +567,30 @@ void __stdcall __std_tzdb_delete_current_zone(__std_tzdb_current_zone_info* cons _Info->_Abbrev = _Allocate_wide_to_narrow(_Abbrev.get(), _Abbrev_len, _Info->_Err); if (_Info->_Abbrev == nullptr) { - return _Propagate_error(_Info); + const auto _Fallback_abbrev = new (_STD nothrow) char[]{"+0000"}; + + if (_Fallback_abbrev == nullptr) { + return nullptr; + } + + const auto _Abs_offset = _Info->_Offset < 0 ? -_Info->_Offset : _Info->_Offset; + const auto _Offset_in_minutes = _Abs_offset / (60 * 1000); + const auto _Hours = _Offset_in_minutes / 60; + const auto _Mins = _Offset_in_minutes % 60; + + _Fallback_abbrev[0] = _Info->_Offset < 0 ? '-' : '+'; + _Fallback_abbrev[1] = static_cast('0' + _Hours / 10); + _Fallback_abbrev[2] = static_cast('0' + _Hours % 10); + + if (_Mins == 0) { + _Fallback_abbrev[3] = '\0'; + } else { + _Fallback_abbrev[3] = static_cast('0' + _Mins / 10); + _Fallback_abbrev[4] = static_cast('0' + _Mins % 10); + } + + _Info->_Err = __std_tzdb_error::_Success; + _Info->_Abbrev = _Fallback_abbrev; } return _Info.release(); From 751f4b70b3bf2c3415ee9b611edd570bdc465bbb Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 3 Jun 2025 09:09:39 -0700 Subject: [PATCH 2/3] Use `unique_ptr` to hold `_Fallback_abbrev`. --- stl/src/tzdb.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/src/tzdb.cpp b/stl/src/tzdb.cpp index 8a0e725342e..202d19ab60b 100644 --- a/stl/src/tzdb.cpp +++ b/stl/src/tzdb.cpp @@ -567,7 +567,7 @@ void __stdcall __std_tzdb_delete_current_zone(__std_tzdb_current_zone_info* cons _Info->_Abbrev = _Allocate_wide_to_narrow(_Abbrev.get(), _Abbrev_len, _Info->_Err); if (_Info->_Abbrev == nullptr) { - const auto _Fallback_abbrev = new (_STD nothrow) char[]{"+0000"}; + _STD unique_ptr _Fallback_abbrev{new (_STD nothrow) char[]{"+0000"}}; if (_Fallback_abbrev == nullptr) { return nullptr; @@ -590,7 +590,7 @@ void __stdcall __std_tzdb_delete_current_zone(__std_tzdb_current_zone_info* cons } _Info->_Err = __std_tzdb_error::_Success; - _Info->_Abbrev = _Fallback_abbrev; + _Info->_Abbrev = _Fallback_abbrev.release(); } return _Info.release(); From 98ecee36fa439e0a416cfd7a9d78d155f811227d Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 3 Jun 2025 09:14:42 -0700 Subject: [PATCH 3/3] Allocate exactly 4 or 6 chars. --- stl/src/tzdb.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/stl/src/tzdb.cpp b/stl/src/tzdb.cpp index 202d19ab60b..511951451b7 100644 --- a/stl/src/tzdb.cpp +++ b/stl/src/tzdb.cpp @@ -567,17 +567,17 @@ void __stdcall __std_tzdb_delete_current_zone(__std_tzdb_current_zone_info* cons _Info->_Abbrev = _Allocate_wide_to_narrow(_Abbrev.get(), _Abbrev_len, _Info->_Err); if (_Info->_Abbrev == nullptr) { - _STD unique_ptr _Fallback_abbrev{new (_STD nothrow) char[]{"+0000"}}; - - if (_Fallback_abbrev == nullptr) { - return nullptr; - } - const auto _Abs_offset = _Info->_Offset < 0 ? -_Info->_Offset : _Info->_Offset; const auto _Offset_in_minutes = _Abs_offset / (60 * 1000); const auto _Hours = _Offset_in_minutes / 60; const auto _Mins = _Offset_in_minutes % 60; + _STD unique_ptr _Fallback_abbrev{new (_STD nothrow) char[_Mins == 0 ? 4 : 6]}; + + if (_Fallback_abbrev == nullptr) { + return nullptr; + } + _Fallback_abbrev[0] = _Info->_Offset < 0 ? '-' : '+'; _Fallback_abbrev[1] = static_cast('0' + _Hours / 10); _Fallback_abbrev[2] = static_cast('0' + _Hours % 10); @@ -587,6 +587,7 @@ void __stdcall __std_tzdb_delete_current_zone(__std_tzdb_current_zone_info* cons } else { _Fallback_abbrev[3] = static_cast('0' + _Mins / 10); _Fallback_abbrev[4] = static_cast('0' + _Mins % 10); + _Fallback_abbrev[5] = '\0'; } _Info->_Err = __std_tzdb_error::_Success;