From 16fd277def4c15e9f78ac98f3179d0ffb689c255 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 1 Dec 2025 09:24:11 -0800 Subject: [PATCH 1/2] Extract sprintf_s(), defend against negative values. --- stl/inc/xlocnum | 74 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 58 insertions(+), 16 deletions(-) diff --git a/stl/inc/xlocnum b/stl/inc/xlocnum index fca7454e0b4..e1585151826 100644 --- a/stl/inc/xlocnum +++ b/stl/inc/xlocnum @@ -1313,8 +1313,14 @@ protected: char _Buf[2 * _Max_int_dig]; char _Fmt[6]; - return _Iput(_Dest, _Iosbase, _Fill, _Buf, - static_cast(_CSTD sprintf_s(_Buf, sizeof(_Buf), _Ifmt(_Fmt, "ld", _Iosbase.flags()), _Val))); + const int _Count = _CSTD sprintf_s(_Buf, sizeof(_Buf), _Ifmt(_Fmt, "ld", _Iosbase.flags()), _Val); + + if (_Count < 0) { // It should be impossible for sprintf_s() to fail here. + _STL_INTERNAL_CHECK(false); // In STL tests, report an error. + return _Dest; // In production, return early to avoid static_cast of a negative _Count. + } + + return _Iput(_Dest, _Iosbase, _Fill, _Buf, static_cast(_Count)); } virtual _OutIt __CLR_OR_THIS_CALL do_put(_OutIt _Dest, ios_base& _Iosbase, _Elem _Fill, @@ -1322,8 +1328,14 @@ protected: char _Buf[2 * _Max_int_dig]; char _Fmt[6]; - return _Iput(_Dest, _Iosbase, _Fill, _Buf, - static_cast(_CSTD sprintf_s(_Buf, sizeof(_Buf), _Ifmt(_Fmt, "lu", _Iosbase.flags()), _Val))); + const int _Count = _CSTD sprintf_s(_Buf, sizeof(_Buf), _Ifmt(_Fmt, "lu", _Iosbase.flags()), _Val); + + if (_Count < 0) { // It should be impossible for sprintf_s() to fail here. + _STL_INTERNAL_CHECK(false); // In STL tests, report an error. + return _Dest; // In production, return early to avoid static_cast of a negative _Count. + } + + return _Iput(_Dest, _Iosbase, _Fill, _Buf, static_cast(_Count)); } virtual _OutIt __CLR_OR_THIS_CALL do_put( @@ -1331,8 +1343,14 @@ protected: char _Buf[2 * _Max_int_dig]; char _Fmt[8]; - return _Iput(_Dest, _Iosbase, _Fill, _Buf, - static_cast(_CSTD sprintf_s(_Buf, sizeof(_Buf), _Ifmt(_Fmt, "Ld", _Iosbase.flags()), _Val))); + const int _Count = _CSTD sprintf_s(_Buf, sizeof(_Buf), _Ifmt(_Fmt, "Ld", _Iosbase.flags()), _Val); + + if (_Count < 0) { // It should be impossible for sprintf_s() to fail here. + _STL_INTERNAL_CHECK(false); // In STL tests, report an error. + return _Dest; // In production, return early to avoid static_cast of a negative _Count. + } + + return _Iput(_Dest, _Iosbase, _Fill, _Buf, static_cast(_Count)); } virtual _OutIt __CLR_OR_THIS_CALL do_put(_OutIt _Dest, ios_base& _Iosbase, _Elem _Fill, @@ -1340,8 +1358,14 @@ protected: char _Buf[2 * _Max_int_dig]; char _Fmt[8]; - return _Iput(_Dest, _Iosbase, _Fill, _Buf, - static_cast(_CSTD sprintf_s(_Buf, sizeof(_Buf), _Ifmt(_Fmt, "Lu", _Iosbase.flags()), _Val))); + const int _Count = _CSTD sprintf_s(_Buf, sizeof(_Buf), _Ifmt(_Fmt, "Lu", _Iosbase.flags()), _Val); + + if (_Count < 0) { // It should be impossible for sprintf_s() to fail here. + _STL_INTERNAL_CHECK(false); // In STL tests, report an error. + return _Dest; // In production, return early to avoid static_cast of a negative _Count. + } + + return _Iput(_Dest, _Iosbase, _Fill, _Buf, static_cast(_Count)); } virtual _OutIt __CLR_OR_THIS_CALL do_put( @@ -1365,10 +1389,16 @@ protected: const bool _Is_finite = (_STD isfinite) (_Val); const auto _Adjusted_flags = // TRANSITION, DevCom-10519861 _Is_finite ? _Iosbase.flags() : _Iosbase.flags() & ~ios_base::showpoint; - const auto _Ngen = static_cast(_CSTD sprintf_s( - &_Buf[0], _Buf.size(), _Ffmt(_Fmt, 0, _Adjusted_flags), static_cast(_Precision), _Val)); - return _Fput_v3(_Dest, _Iosbase, _Fill, _Buf.c_str(), _Ngen, _Is_finite); + const int _Count = + _CSTD sprintf_s(&_Buf[0], _Buf.size(), _Ffmt(_Fmt, 0, _Adjusted_flags), static_cast(_Precision), _Val); + + if (_Count < 0) { // It should be impossible for sprintf_s() to fail here. + _STL_INTERNAL_CHECK(false); // In STL tests, report an error. + return _Dest; // In production, return early to avoid static_cast of a negative _Count. + } + + return _Fput_v3(_Dest, _Iosbase, _Fill, _Buf.c_str(), static_cast(_Count), _Is_finite); } virtual _OutIt __CLR_OR_THIS_CALL do_put( @@ -1392,10 +1422,16 @@ protected: const bool _Is_finite = (_STD isfinite) (_Val); const auto _Adjusted_flags = // TRANSITION, DevCom-10519861 _Is_finite ? _Iosbase.flags() : _Iosbase.flags() & ~ios_base::showpoint; - const auto _Ngen = static_cast(_CSTD sprintf_s( - &_Buf[0], _Buf.size(), _Ffmt(_Fmt, 'L', _Adjusted_flags), static_cast(_Precision), _Val)); - return _Fput_v3(_Dest, _Iosbase, _Fill, _Buf.c_str(), _Ngen, _Is_finite); + const int _Count = _CSTD sprintf_s( + &_Buf[0], _Buf.size(), _Ffmt(_Fmt, 'L', _Adjusted_flags), static_cast(_Precision), _Val); + + if (_Count < 0) { // It should be impossible for sprintf_s() to fail here. + _STL_INTERNAL_CHECK(false); // In STL tests, report an error. + return _Dest; // In production, return early to avoid static_cast of a negative _Count. + } + + return _Fput_v3(_Dest, _Iosbase, _Fill, _Buf.c_str(), static_cast(_Count), _Is_finite); } #pragma warning(pop) @@ -1403,8 +1439,14 @@ protected: _OutIt _Dest, ios_base& _Iosbase, _Elem _Fill, const void* _Val) const { // put formatted void pointer to _Dest char _Buf[2 * _Max_int_dig]; - return _Iput( - _Dest, _Iosbase, _Fill, _Buf, static_cast(_CSTD sprintf_s(_Buf, sizeof(_Buf), "%p", _Val))); + const int _Count = _CSTD sprintf_s(_Buf, sizeof(_Buf), "%p", _Val); + + if (_Count < 0) { // It should be impossible for sprintf_s() to fail here. + _STL_INTERNAL_CHECK(false); // In STL tests, report an error. + return _Dest; // In production, return early to avoid static_cast of a negative _Count. + } + + return _Iput(_Dest, _Iosbase, _Fill, _Buf, static_cast(_Count)); } private: From 46dfbdc62cfa7feabcbaf2dbe017eb8f7e893062 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 1 Dec 2025 09:35:02 -0800 Subject: [PATCH 2/2] Extract `_Ifmt()` and `_Ffmt()` to debulk the `sprintf_s()` calls. --- stl/inc/xlocnum | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/stl/inc/xlocnum b/stl/inc/xlocnum index e1585151826..c44f552c1ee 100644 --- a/stl/inc/xlocnum +++ b/stl/inc/xlocnum @@ -1313,7 +1313,9 @@ protected: char _Buf[2 * _Max_int_dig]; char _Fmt[6]; - const int _Count = _CSTD sprintf_s(_Buf, sizeof(_Buf), _Ifmt(_Fmt, "ld", _Iosbase.flags()), _Val); + (void) _Ifmt(_Fmt, "ld", _Iosbase.flags()); + + const int _Count = _CSTD sprintf_s(_Buf, sizeof(_Buf), _Fmt, _Val); if (_Count < 0) { // It should be impossible for sprintf_s() to fail here. _STL_INTERNAL_CHECK(false); // In STL tests, report an error. @@ -1328,7 +1330,9 @@ protected: char _Buf[2 * _Max_int_dig]; char _Fmt[6]; - const int _Count = _CSTD sprintf_s(_Buf, sizeof(_Buf), _Ifmt(_Fmt, "lu", _Iosbase.flags()), _Val); + (void) _Ifmt(_Fmt, "lu", _Iosbase.flags()); + + const int _Count = _CSTD sprintf_s(_Buf, sizeof(_Buf), _Fmt, _Val); if (_Count < 0) { // It should be impossible for sprintf_s() to fail here. _STL_INTERNAL_CHECK(false); // In STL tests, report an error. @@ -1343,7 +1347,9 @@ protected: char _Buf[2 * _Max_int_dig]; char _Fmt[8]; - const int _Count = _CSTD sprintf_s(_Buf, sizeof(_Buf), _Ifmt(_Fmt, "Ld", _Iosbase.flags()), _Val); + (void) _Ifmt(_Fmt, "Ld", _Iosbase.flags()); + + const int _Count = _CSTD sprintf_s(_Buf, sizeof(_Buf), _Fmt, _Val); if (_Count < 0) { // It should be impossible for sprintf_s() to fail here. _STL_INTERNAL_CHECK(false); // In STL tests, report an error. @@ -1358,7 +1364,9 @@ protected: char _Buf[2 * _Max_int_dig]; char _Fmt[8]; - const int _Count = _CSTD sprintf_s(_Buf, sizeof(_Buf), _Ifmt(_Fmt, "Lu", _Iosbase.flags()), _Val); + (void) _Ifmt(_Fmt, "Lu", _Iosbase.flags()); + + const int _Count = _CSTD sprintf_s(_Buf, sizeof(_Buf), _Fmt, _Val); if (_Count < 0) { // It should be impossible for sprintf_s() to fail here. _STL_INTERNAL_CHECK(false); // In STL tests, report an error. @@ -1390,8 +1398,9 @@ protected: const auto _Adjusted_flags = // TRANSITION, DevCom-10519861 _Is_finite ? _Iosbase.flags() : _Iosbase.flags() & ~ios_base::showpoint; - const int _Count = - _CSTD sprintf_s(&_Buf[0], _Buf.size(), _Ffmt(_Fmt, 0, _Adjusted_flags), static_cast(_Precision), _Val); + (void) _Ffmt(_Fmt, 0, _Adjusted_flags); + + const int _Count = _CSTD sprintf_s(&_Buf[0], _Buf.size(), _Fmt, static_cast(_Precision), _Val); if (_Count < 0) { // It should be impossible for sprintf_s() to fail here. _STL_INTERNAL_CHECK(false); // In STL tests, report an error. @@ -1423,8 +1432,9 @@ protected: const auto _Adjusted_flags = // TRANSITION, DevCom-10519861 _Is_finite ? _Iosbase.flags() : _Iosbase.flags() & ~ios_base::showpoint; - const int _Count = _CSTD sprintf_s( - &_Buf[0], _Buf.size(), _Ffmt(_Fmt, 'L', _Adjusted_flags), static_cast(_Precision), _Val); + (void) _Ffmt(_Fmt, 'L', _Adjusted_flags); + + const int _Count = _CSTD sprintf_s(&_Buf[0], _Buf.size(), _Fmt, static_cast(_Precision), _Val); if (_Count < 0) { // It should be impossible for sprintf_s() to fail here. _STL_INTERNAL_CHECK(false); // In STL tests, report an error. @@ -1450,8 +1460,9 @@ protected: } private: - char* __CLRCALL_OR_CDECL _Ffmt( - char* _Fmt, char _Spec, ios_base::fmtflags _Flags) const { // generate sprintf format for floating-point + // TRANSITION, ABI: This always returns _Fmt, which is now ignored. + char* __CLRCALL_OR_CDECL _Ffmt(char* _Fmt, char _Spec, ios_base::fmtflags _Flags) const { + // generate sprintf format for floating-point char* _Ptr = _Fmt; *_Ptr++ = '%'; @@ -1573,8 +1584,9 @@ private: return _Rep(_Dest, _Fill, _Fillcount); // put trailing fill } - char* __CLRCALL_OR_CDECL _Ifmt( - char* _Fmt, const char* _Spec, ios_base::fmtflags _Flags) const { // generate sprintf format for integer + // TRANSITION, ABI: This always returns _Fmt, which is now ignored. + char* __CLRCALL_OR_CDECL _Ifmt(char* _Fmt, const char* _Spec, ios_base::fmtflags _Flags) const { + // generate sprintf format for integer char* _Ptr = _Fmt; *_Ptr++ = '%';