aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2025-04-07 19:52:55 +0100
committerJonathan Wakely <redi@gcc.gnu.org>2025-04-08 08:43:22 +0100
commite33b62eed7fd0a82d758b23252d288585b6790d2 (patch)
tree5685df95e7322abee9a2054b7706f4a66e9c6d29
parenta9bbb60b7ca7bf83c0e8657c61867e3786091916 (diff)
downloadgcc-e33b62eed7fd0a82d758b23252d288585b6790d2.zip
gcc-e33b62eed7fd0a82d758b23252d288585b6790d2.tar.gz
gcc-e33b62eed7fd0a82d758b23252d288585b6790d2.tar.bz2
libstdc++: Fix use-after-free in std::format [PR119671]
When formatting floating-point values to wide strings there's a case where we invalidate a std::wstring buffer while a std::wstring_view is still referring to it. libstdc++-v3/ChangeLog: PR libstdc++/119671 * include/std/format (__formatter_fp::format): Do not invalidate __wstr unless _M_localized returns a valid string. * testsuite/std/format/functions/format.cc: Check wide string formatting of floating-point types with classic locale. Reviewed-by: Tomasz Kaminski <tkaminsk@redhat.com>
-rw-r--r--libstdc++-v3/include/std/format6
-rw-r--r--libstdc++-v3/testsuite/std/format/functions/format.cc12
2 files changed, 15 insertions, 3 deletions
diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format
index 01a5314..2e9319c 100644
--- a/libstdc++-v3/include/std/format
+++ b/libstdc++-v3/include/std/format
@@ -1838,9 +1838,9 @@ namespace __format
if (_M_spec._M_localized && __builtin_isfinite(__v))
{
- __wstr = _M_localize(__str, __expc, __fc.locale());
- if (!__wstr.empty())
- __str = __wstr;
+ auto __s = _M_localize(__str, __expc, __fc.locale());
+ if (!__s.empty())
+ __str = __wstr = std::move(__s);
}
size_t __width = _M_spec._M_get_width(__fc);
diff --git a/libstdc++-v3/testsuite/std/format/functions/format.cc b/libstdc++-v3/testsuite/std/format/functions/format.cc
index 000f267..93c33b4 100644
--- a/libstdc++-v3/testsuite/std/format/functions/format.cc
+++ b/libstdc++-v3/testsuite/std/format/functions/format.cc
@@ -370,6 +370,18 @@ test_wchar()
// P2909R4 Fix formatting of code units as integers (Dude, where’s my char?)
s = std::format(L"{:d} {:d}", wchar_t(-1), char(-1));
VERIFY( s.find('-') == std::wstring::npos );
+
+ auto ws = std::format(L"{:L}", 0.5);
+ VERIFY( ws == L"0.5" );
+ // The default C locale.
+ std::locale cloc = std::locale::classic();
+ // PR libstdc++/119671 use-after-free formatting floating-point to wstring
+ ws = std::format(cloc, L"{:L}", 0.5);
+ VERIFY( ws == L"0.5" );
+ // A locale with no name, but with the same facets as the C locale.
+ std::locale locx(cloc, &std::use_facet<std::ctype<char>>(cloc));
+ ws = std::format(locx, L"{:L}", 0.5);
+ VERIFY( ws == L"0.5" );
}
void