From 942c3fc5d37a864ab455c4f339471384da7243b7 Mon Sep 17 00:00:00 2001 From: nussaiba shaikh Date: Fri, 30 Oct 2026 23:52:22 +0530 Subject: [PATCH] fix internalError in checkFormatString on invalid width or position --- lib/checkio.cpp | 25 +++++++++++++++++++++---- test/testio.cpp | 16 ++++++++++++++++ 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/lib/checkio.cpp b/lib/checkio.cpp index 4fff7d46282..2fe938bef6e 100644 --- a/lib/checkio.cpp +++ b/lib/checkio.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -794,6 +795,20 @@ void CheckIOImpl::checkWrongPrintfScanfArguments() } } +// Convert the digits of a format string width or parameter position. +// A value that does not fit in an int is clamped to INT_MAX so a huge +// width or position is still reported instead of aborting the check. +static int formatStringNumber(const std::string& digits) +{ + MathLib::bigint value = 0; + for (const char c : digits) { + value = value * 10 + (c - '0'); + if (value > std::numeric_limits::max()) + return std::numeric_limits::max(); + } + return static_cast(value); +} + void CheckIOImpl::checkFormatString(const Token * const tok, const Token * const formatStringTok, const Token * argListTok, @@ -853,8 +868,10 @@ void CheckIOImpl::checkFormatString(const Token * const tok, } else if (std::isdigit(*i)) { width += *i; } else if (*i == '$') { - parameterPosition = strToInt(width); - hasParameterPosition = true; + if (!width.empty()) { + parameterPosition = formatStringNumber(width); + hasParameterPosition = true; + } width.clear(); } ++i; @@ -906,7 +923,7 @@ void CheckIOImpl::checkFormatString(const Token * const tok, specifier += (*i == 's' || bracketBeg == formatString.end()) ? std::string{ 's' } : std::string{ bracketBeg, i + 1 }; if (argInfo.variableInfo && argInfo.isKnownType() && argInfo.variableInfo->isArray() && (argInfo.variableInfo->dimensions().size() == 1) && argInfo.variableInfo->dimensions()[0].known) { if (!width.empty()) { - const int numWidth = strToInt(width); + const int numWidth = formatStringNumber(width); if (numWidth != (argInfo.variableInfo->dimension(0) - 1)) invalidScanfFormatWidthError(tok, numFormat, numWidth, argInfo.variableInfo, specifier); } @@ -929,7 +946,7 @@ void CheckIOImpl::checkFormatString(const Token * const tok, case 'c': if (argInfo.variableInfo && argInfo.isKnownType() && argInfo.variableInfo->isArray() && (argInfo.variableInfo->dimensions().size() == 1) && argInfo.variableInfo->dimensions()[0].known) { if (!width.empty()) { - const int numWidth = strToInt(width); + const int numWidth = formatStringNumber(width); if (numWidth > argInfo.variableInfo->dimension(0)) invalidScanfFormatWidthError(tok, numFormat, numWidth, argInfo.variableInfo, std::string(1, *i)); } diff --git a/test/testio.cpp b/test/testio.cpp index ad95345e1fd..821ebeb7eea 100644 --- a/test/testio.cpp +++ b/test/testio.cpp @@ -899,6 +899,14 @@ class TestIO : public TestFixture { " scanf (\"%70s\",str);\n" "}\n"); ASSERT_EQUALS("[test.cpp:4:3]: (error) Width 70 given in format string (no. 1) is larger than destination buffer 'str[8]', use %7s to prevent overflowing it. [invalidScanfFormatWidth]\n", errout_str()); + + // width that does not fit in an int + check("void f()\n" + "{\n" + " char str [8];\n" + " scanf (\"%99999999999s\",str);\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:4:3]: (error) Width 2147483647 given in format string (no. 1) is larger than destination buffer 'str[8]', use %7s to prevent overflowing it. [invalidScanfFormatWidth]\n", errout_str()); } void testScanf5() { // #10632 @@ -4274,6 +4282,14 @@ class TestIO : public TestFixture { "[test.cpp:5:3]: (warning) scanf: referencing parameter 2 while 1 arguments given [wrongPrintfScanfParameterPositionError]\n" "[test.cpp:6:3]: (warning) printf: parameter positions start at 1, not 0 [wrongPrintfScanfParameterPositionError]\n" "", errout_str()); + + // parameter position without digits, with a leading zero or too large for an int + check("void foo() {\n" + " printf(\"%$d\", 1);\n" + " printf(\"%01$d\", 1);\n" + " printf(\"%99999999999$d\", 1);\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:4:3]: (warning) printf: referencing parameter 2147483647 while 1 arguments given [wrongPrintfScanfParameterPositionError]\n", errout_str()); }