Improved buffer overflow checking for scanf: %c with a width (#3494)
This commit is contained in:
parent
dce7128f30
commit
851c6e0ed5
|
@ -684,7 +684,7 @@ void CheckIO::checkFormatString(const Token * const tok,
|
|||
if (!width.empty()) {
|
||||
int numWidth = std::atoi(width.c_str());
|
||||
if (numWidth != (argInfo.variableInfo->dimension(0) - 1))
|
||||
invalidScanfFormatWidthError(tok, numFormat, numWidth, argInfo.variableInfo);
|
||||
invalidScanfFormatWidthError(tok, numFormat, numWidth, argInfo.variableInfo, 's');
|
||||
}
|
||||
}
|
||||
if (argListTok && argListTok->tokType() != Token::eString &&
|
||||
|
@ -703,6 +703,13 @@ void CheckIO::checkFormatString(const Token * const tok,
|
|||
done = true;
|
||||
break;
|
||||
case 'c':
|
||||
if (argInfo.variableInfo && argInfo.isKnownType() && argInfo.variableInfo->isArray() && (argInfo.variableInfo->dimensions().size() == 1) && argInfo.variableInfo->dimensions()[0].known) {
|
||||
if (!width.empty()) {
|
||||
int numWidth = std::atoi(width.c_str());
|
||||
if (numWidth > argInfo.variableInfo->dimension(0))
|
||||
invalidScanfFormatWidthError(tok, numFormat, numWidth, argInfo.variableInfo, 'c');
|
||||
}
|
||||
}
|
||||
if (scanf_s) {
|
||||
numSecure++;
|
||||
if (argListTok) {
|
||||
|
@ -2018,7 +2025,7 @@ void CheckIO::invalidLengthModifierError(const Token* tok, unsigned int numForma
|
|||
reportError(tok, Severity::warning, "invalidLengthModifierError", errmsg.str());
|
||||
}
|
||||
|
||||
void CheckIO::invalidScanfFormatWidthError(const Token* tok, unsigned int numFormat, int width, const Variable *var)
|
||||
void CheckIO::invalidScanfFormatWidthError(const Token* tok, unsigned int numFormat, int width, const Variable *var, char c)
|
||||
{
|
||||
MathLib::bigint arrlen = 0;
|
||||
std::string varname;
|
||||
|
@ -2037,7 +2044,7 @@ void CheckIO::invalidScanfFormatWidthError(const Token* tok, unsigned int numFor
|
|||
reportError(tok, Severity::warning, "invalidScanfFormatWidth_smaller", errmsg.str(), CWE(0U), true);
|
||||
} else {
|
||||
errmsg << "Width " << width << " given in format string (no. " << numFormat << ") is larger than destination buffer '"
|
||||
<< varname << "[" << arrlen << "]', use %" << (arrlen - 1) << "s to prevent overflowing it.";
|
||||
<< varname << "[" << arrlen << "]', use %" << (c == 'c' ? arrlen : (arrlen - 1)) << c << " to prevent overflowing it.";
|
||||
reportError(tok, Severity::error, "invalidScanfFormatWidth", errmsg.str(), CWE687, false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -126,7 +126,7 @@ private:
|
|||
void invalidPrintfArgTypeError_sint(const Token* tok, unsigned int numFormat, const std::string& specifier, const ArgumentInfo* argInfo);
|
||||
void invalidPrintfArgTypeError_float(const Token* tok, unsigned int numFormat, const std::string& specifier, const ArgumentInfo* argInfo);
|
||||
void invalidLengthModifierError(const Token* tok, unsigned int numFormat, const std::string& modifier);
|
||||
void invalidScanfFormatWidthError(const Token* tok, unsigned int numFormat, int width, const Variable *var);
|
||||
void invalidScanfFormatWidthError(const Token* tok, unsigned int numFormat, int width, const Variable *var, char c);
|
||||
static void argumentType(std::ostream & s, const ArgumentInfo * argInfo);
|
||||
|
||||
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const {
|
||||
|
@ -152,7 +152,7 @@ private:
|
|||
c.invalidPrintfArgTypeError_sint(nullptr, 1, "i", nullptr);
|
||||
c.invalidPrintfArgTypeError_float(nullptr, 1, "f", nullptr);
|
||||
c.invalidLengthModifierError(nullptr, 1, "I");
|
||||
c.invalidScanfFormatWidthError(nullptr, 10, 5, nullptr);
|
||||
c.invalidScanfFormatWidthError(nullptr, 10, 5, nullptr, 's');
|
||||
c.wrongPrintfScanfPosixParameterPositionError(nullptr, "printf", 2, 1);
|
||||
}
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@ private:
|
|||
|
||||
TEST_CASE(testScanf1); // Scanf without field limiters
|
||||
TEST_CASE(testScanf2);
|
||||
TEST_CASE(testScanf3); // #3494
|
||||
TEST_CASE(testScanf4); // #ticket 2553
|
||||
|
||||
TEST_CASE(testScanfArgument);
|
||||
|
@ -724,6 +725,16 @@ private:
|
|||
ASSERT_EQUALS("[test.cpp:4]: (warning) scanf format string requires 0 parameters but 1 is given.\n", errout.str());
|
||||
}
|
||||
|
||||
void testScanf3() { // ticket #3494
|
||||
check("void f() {\n"
|
||||
" char str[8];\n"
|
||||
" scanf(\"%7c\", str);\n"
|
||||
" scanf(\"%8c\", str);\n"
|
||||
" scanf(\"%9c\", str);\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:5]: (error) Width 9 given in format string (no. 1) is larger than destination buffer 'str[8]', use %8c to prevent overflowing it.\n", errout.str());
|
||||
}
|
||||
|
||||
void testScanf4() { // ticket #2553
|
||||
check("void f()\n"
|
||||
"{\n"
|
||||
|
|
Loading…
Reference in New Issue