From 030d0ffadef6b5a0321ba9737955b1116cb2f19d Mon Sep 17 00:00:00 2001 From: Ryan Lucia Date: Sat, 10 Oct 2026 10:51:10 -0700 Subject: [PATCH] Use the standard library's numeric facets in the global locale Boost.Locale's num_parse forwards to std::num_get::do_get, so the binary gets its own copy of num_get::__do_get_floating_point from the SDK's libc++ headers. Since LLVM 19 that copy allocates a 28-character buffer and has the system libc++'s __num_get::__stage2_float_prep fill it, but the libc++ in older macOS releases writes 32 characters. Parsing any floating-point number then aborts with a stack buffer overflow, which crashes 3.5.0 on startup on macOS 13 while reading the default config. Take the numeric category from the classic locale instead. Nothing uses Boost.Locale's locale-aware number formatting, and its ICU backend doesn't supply its own numpunct, so parsing and formatting behave the same. Fixes #733. Co-Authored-By: Claude Opus 5.5 --- libaegisub/common/util.cpp | 7 +++++++ tests/tests/util.cpp | 10 ++++++++++ 2 files changed, 17 insertions(+) diff --git a/libaegisub/common/util.cpp b/libaegisub/common/util.cpp index 117696e424..de23eeabc3 100644 --- a/libaegisub/common/util.cpp +++ b/libaegisub/common/util.cpp @@ -186,6 +186,13 @@ void InitLocale() { // FIXME: Should the ICU locale also be forced to en_US here? if (result != std::codecvt_base::ok) locale = boost::locale::generator().generate("en_US.UTF-8"); + + // Use the standard library's number parsing and formatting rather than + // Boost.Locale's, which nothing relies on. Boost.Locale's facets fall back + // to std::num_get code inlined from the SDK's libc++ headers, and with + // newer SDKs that code overflows a stack buffer when it calls into an + // older system libc++ (e.g. on macOS 13). + locale = std::locale(locale, std::locale::classic(), std::locale::numeric); std::locale::global(locale); } } // namespace util diff --git a/tests/tests/util.cpp b/tests/tests/util.cpp index 14757f8bbd..afb3632395 100644 --- a/tests/tests/util.cpp +++ b/tests/tests/util.cpp @@ -18,6 +18,9 @@ #include +#include +#include + class lagi_util : public libagi { }; namespace agi { @@ -42,4 +45,11 @@ TEST(lagi_util, try_parse_int) { EXPECT_EQ(1.0, i); } +TEST(lagi_util, init_locale_uses_std_numeric_facets) { + // Boost.Locale's numeric facets crash on older macOS when built with a + // newer SDK (#733), so InitLocale must not install them + EXPECT_EQ(typeid(std::num_get), typeid(std::use_facet>(std::locale()))); + EXPECT_EQ(typeid(std::num_put), typeid(std::use_facet>(std::locale()))); +} + }