Fixed #1409 (False positive: Buffer access out-of-bounds with strncpy and an array in typedef'ed struct)

This commit is contained in:
Daniel Marjamäki 2010-02-21 15:23:50 +01:00
parent 66f17d3fcb
commit 8f4edb5e45
5 changed files with 30 additions and 19 deletions

View File

@ -81,7 +81,7 @@ void CheckBufferOverrun::arrayIndexOutOfBounds(int size, int index)
reportError(_callStack, severity, "arrayIndexOutOfBounds", "Array index out of bounds"); reportError(_callStack, severity, "arrayIndexOutOfBounds", "Array index out of bounds");
} }
void CheckBufferOverrun::bufferOverrun(const Token *tok) void CheckBufferOverrun::bufferOverrun(const Token *tok, const std::string &varnames)
{ {
Severity::e severity; Severity::e severity;
if (_callStack.size() > 0) if (_callStack.size() > 0)
@ -95,7 +95,15 @@ void CheckBufferOverrun::bufferOverrun(const Token *tok)
severity = Severity::error; severity = Severity::error;
} }
reportError(tok, severity, "bufferAccessOutOfBounds", "Buffer access out-of-bounds"); std::string v = varnames;
while (v.find(" ") != std::string::npos)
v.erase(v.find(" "), 1);
std::string errmsg("Buffer access out-of-bounds");
if (!v.empty())
errmsg += ": " + v;
reportError(tok, severity, "bufferAccessOutOfBounds", errmsg);
} }
void CheckBufferOverrun::dangerousStdCin(const Token *tok) void CheckBufferOverrun::dangerousStdCin(const Token *tok)
@ -273,26 +281,22 @@ void CheckBufferOverrun::checkScope(const Token *tok, const std::vector<std::str
const std::string num = tok->strAt(6); const std::string num = tok->strAt(6);
if (MathLib::toLongNumber(num) < 0 || MathLib::toLongNumber(num) > total_size) if (MathLib::toLongNumber(num) < 0 || MathLib::toLongNumber(num) > total_size)
{ {
bufferOverrun(tok); bufferOverrun(tok, varnames);
} }
} }
} }
} }
else if (Token::Match(tok, "memset|memcpy|memmove|memcmp|strncpy|fgets")) else if (Token::Match(tok, ("memset|memcpy|memmove|memcmp|strncpy|fgets ( " + varnames + " , %num% , %num% )").c_str()) ||
Token::Match(tok, ("memcpy|memcmp ( %var% , " + varnames + " , %num% )").c_str()))
{ {
if (Token::Match(tok->next(), ("( " + varnames + " , %num% , %num% )").c_str()) || const std::string num = tok->strAt(varc + 6);
Token::Match(tok->next(), ("( %var% , " + varnames + " , %num% )").c_str())) if (MathLib::toLongNumber(num) < 0 || MathLib::toLongNumber(num) > total_size)
{ {
const std::string num = tok->strAt(varc + 6); bufferOverrun(tok, varnames);
if (MathLib::toLongNumber(num) < 0 || MathLib::toLongNumber(num) > total_size)
{
bufferOverrun(tok);
}
} }
continue; continue;
} }
// Loop.. // Loop..
if (Token::simpleMatch(tok, "for (")) if (Token::simpleMatch(tok, "for ("))
{ {
@ -503,7 +507,7 @@ void CheckBufferOverrun::checkScope(const Token *tok, const std::vector<std::str
if (condition_out_of_bounds && Token::Match(tok2, pattern.str().c_str(), varid)) if (condition_out_of_bounds && Token::Match(tok2, pattern.str().c_str(), varid))
{ {
bufferOverrun(tok2); bufferOverrun(tok2, varid > 0 ? "" : varnames.c_str());
break; break;
} }
@ -556,7 +560,7 @@ void CheckBufferOverrun::checkScope(const Token *tok, const std::vector<std::str
size_t len = Token::getStrLength(tok->tokAt(varc + 4)); size_t len = Token::getStrLength(tok->tokAt(varc + 4));
if (len >= static_cast<size_t>(total_size)) if (len >= static_cast<size_t>(total_size))
{ {
bufferOverrun(tok); bufferOverrun(tok, varid > 0 ? "" : varnames.c_str());
continue; continue;
} }
} }

View File

@ -83,7 +83,7 @@ private:
void arrayIndexOutOfBounds(const Token *tok, int size, int index); void arrayIndexOutOfBounds(const Token *tok, int size, int index);
void arrayIndexOutOfBounds(int size, int index); void arrayIndexOutOfBounds(int size, int index);
void bufferOverrun(const Token *tok); void bufferOverrun(const Token *tok, const std::string &varnames = "");
void dangerousStdCin(const Token *tok); void dangerousStdCin(const Token *tok);
void strncatUsage(const Token *tok); void strncatUsage(const Token *tok);
void outOfBounds(const Token *tok, const std::string &what); void outOfBounds(const Token *tok, const std::string &what);
@ -93,7 +93,7 @@ private:
void getErrorMessages() void getErrorMessages()
{ {
arrayIndexOutOfBounds(0, 2, 2); arrayIndexOutOfBounds(0, 2, 2);
bufferOverrun(0); bufferOverrun(0, std::string("buffer"));
dangerousStdCin(0); dangerousStdCin(0);
strncatUsage(0); strncatUsage(0);
outOfBounds(0, "index"); outOfBounds(0, "index");

View File

@ -1490,7 +1490,7 @@ void CheckClass::checkConst()
continue; continue;
// don't warn if type is LP.. // don't warn if type is LP..
if (tok2->str().compare(0,2,"LP") == 0) if (tok2->str().compare(0, 2, "LP") == 0)
continue; continue;
// member function? // member function?

View File

@ -953,7 +953,7 @@ private:
"{\n" "{\n"
" strcpy( abc->str, \"abcdef\" );\n" " strcpy( abc->str, \"abcdef\" );\n"
"}\n"); "}\n");
ASSERT_EQUALS("[test.cpp:8]: (error) Buffer access out-of-bounds\n", errout.str()); ASSERT_EQUALS("[test.cpp:8]: (error) Buffer access out-of-bounds: abc.str\n", errout.str());
} }
@ -1574,6 +1574,13 @@ private:
" strncpy(c,\"hello!\",sizeof(c)+1);\n" " strncpy(c,\"hello!\",sizeof(c)+1);\n"
"}\n"); "}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Buffer access out-of-bounds\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Buffer access out-of-bounds\n", errout.str());
check("struct AB { char a[10]; };\n"
"void foo(AB *ab)\n"
"{\n"
" strncpy(x, ab->a, 100);\n"
"}\n");
ASSERT_EQUALS("", errout.str());
} }
void unknownType() void unknownType()

View File

@ -1798,7 +1798,7 @@ private:
"};\n"); "};\n");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
// A function that returns LPVOID can't be const // A function that returns LPVOID can't be const
void constLPVOID() void constLPVOID()
{ {