Skip to content

Commit cb5ad5b

Browse files
committed
_LocInfo: Use _wsetlocale to query and restore locales
_LocInfo changes the locale temporarily and then reverts to the previous locale on destruction. The sequence of setlocale calls look as follows: 1. oldlocname = setlocale(LC_ALL, nullptr) to query the locale string 2. setlocale(LC_ALL, newlocname) to set the temporary locale 3. setlocale(LC_ALL, oldlocname) to restore the previous locale However there's a catch here: the fully-qualified locale names returned by setlocale are not always ASCII strings (more on that below). This creates challenges because the oldlocname is encoded depending on the "outer" locale, while the setlocale call at point 3) expects an encoding which depend on the "inner" locale, and the two may not match. To solve this issue, use the wide variant of setlocale: _wsetlocale. This way all strings are UTF-16 and there's no issue with varying narrow string encodings. Addendum: Actually, the C RunTime library does its best to use ASCII strings! It queries the english name of the locale using GetLocaleInfoEx. MSDN says that the returned string is always ASCII [1], but that's not always the case [2]. Fixes #5780 References: 1. https://learn.microsoft.com/en-us/windows/win32/intl/locale-senglish-constants 2. https://developercommunity.visualstudio.com/t/GetLocaleInfoEx-w-LOCALE_SENGLISHLANGUA/10981789
1 parent 85e4b57 commit cb5ad5b

File tree

3 files changed

+4
-9
lines changed

3 files changed

+4
-9
lines changed

stl/inc/xlocinfo

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ private:
382382
_Yarn<char> _Months; // month names
383383
_Yarn<wchar_t> _W_Days; // wide weekday names
384384
_Yarn<wchar_t> _W_Months; // wide month names
385-
_Yarn<char> _Oldlocname; // old locale name to revert to on destruction
385+
_Yarn<wchar_t> _Oldlocname; // old locale name to revert to on destruction
386386
_Yarn<char> _Newlocname; // new locale name for this object
387387
};
388388
_STD_END

stl/src/locale.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -137,9 +137,7 @@ void __CLRCALL_PURE_OR_CDECL locale::_Locimp::_Locimp_Addfac(
137137

138138
void __CLRCALL_PURE_OR_CDECL _Locinfo::_Locinfo_ctor(
139139
_Locinfo* pLocinfo, int cat, const char* locname) { // capture a named locale
140-
const char* oldlocname = setlocale(LC_ALL, nullptr);
141-
142-
pLocinfo->_Oldlocname = oldlocname == nullptr ? "" : oldlocname;
140+
pLocinfo->_Oldlocname = _wsetlocale(LC_ALL, nullptr);
143141
_Locinfo_Addcats(pLocinfo, cat, locname);
144142
}
145143

stl/src/locale0.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -222,9 +222,8 @@ void __CLRCALL_PURE_OR_CDECL locale::_Locimp::_Locimp_dtor(_Locimp* _This) { //
222222

223223
void __CLRCALL_PURE_OR_CDECL _Locinfo::_Locinfo_ctor(
224224
_Locinfo* pLocinfo, const char* locname) { // switch to a named locale
225-
const char* oldlocname = setlocale(LC_ALL, nullptr);
225+
pLocinfo->_Oldlocname = _wsetlocale(LC_ALL, nullptr);
226226

227-
pLocinfo->_Oldlocname = oldlocname == nullptr ? "" : oldlocname;
228227
if (locname != nullptr) {
229228
locname = setlocale(LC_ALL, locname);
230229
}
@@ -233,9 +232,7 @@ void __CLRCALL_PURE_OR_CDECL _Locinfo::_Locinfo_ctor(
233232
}
234233

235234
void __CLRCALL_PURE_OR_CDECL _Locinfo::_Locinfo_dtor(_Locinfo* pLocinfo) { // destroy a _Locinfo object, revert locale
236-
if (!pLocinfo->_Oldlocname._Empty()) {
237-
setlocale(LC_ALL, pLocinfo->_Oldlocname._C_str());
238-
}
235+
_wsetlocale(LC_ALL, pLocinfo->_Oldlocname._C_str());
239236
}
240237
_STD_END
241238

0 commit comments

Comments
 (0)