warn when buffer is not zero terminated after strncpy

This commit is contained in:
Robert Reif 2011-09-05 15:19:38 -04:00
parent 2601733ff7
commit 3c8988e7a5
3 changed files with 29 additions and 12 deletions

View File

@ -155,15 +155,22 @@ void CheckBufferOverrun::sizeArgumentAsCharError(const Token *tok)
} }
void CheckBufferOverrun::terminateStrncpyError(const Token *tok, const std::string &varname) void CheckBufferOverrun::terminateStrncpyError(const Token *tok, const std::string &varname, bool conclusive)
{ {
reportError(tok, Severity::warning, "terminateStrncpy", if (conclusive)
"The buffer '" + varname + "' may not be zero-terminated after the call to strncpy().\n" reportError(tok, Severity::warning, "terminateStrncpy",
"The use of strncpy() usually indicates that the programmer wants to ensure " "The buffer '" + varname + "' is not zero-terminated after the call to strncpy().\n"
"the buffer is zero-terminated after the call. However if the (buffer) size given for " "The use of strncpy() usually indicates that the programmer wants to ensure "
"the strncpy() call matches the actual buffer size strncpy() does not add the " "the buffer is zero-terminated after the call. This will cause bugs later in the code if "
"zero at the end of the buffer. This may cause bugs later in the code if " "the code assumes buffer is zero-terminated.");
"the code assumes buffer is zero-terminated."); else
reportError(tok, Severity::warning, "terminateStrncpy",
"The buffer '" + varname + "' may not be zero-terminated after the call to strncpy().\n"
"The use of strncpy() usually indicates that the programmer wants to ensure "
"the buffer is zero-terminated after the call. However if the (buffer) size given for "
"the strncpy() call matches the actual buffer size strncpy() does not add the "
"zero at the end of the buffer. This may cause bugs later in the code if "
"the code assumes buffer is zero-terminated.");
} }
void CheckBufferOverrun::cmdLineArgsError(const Token *tok) void CheckBufferOverrun::cmdLineArgsError(const Token *tok)
@ -1221,6 +1228,16 @@ void CheckBufferOverrun::checkScope(const Token *tok, const ArrayInfo &arrayInfo
checkFunctionCall(tok, arrayInfo); checkFunctionCall(tok, arrayInfo);
} }
if (Token::Match(tok, "strncpy ( %varid% , %str% , %num% )", arrayInfo.varid()))
{
unsigned int num = (unsigned int)MathLib::toLongNumber(tok->strAt(6));
if (Token::getStrLength(tok->tokAt(4)) >= total_size && total_size == num)
{
if (_settings->inconclusive)
terminateStrncpyError(tok, tok->strAt(2), true);
}
}
if ((Token::Match(tok, "strncpy|strncat ( %varid% , %var% , %num% )", arrayInfo.varid())) || if ((Token::Match(tok, "strncpy|strncat ( %varid% , %var% , %num% )", arrayInfo.varid())) ||
(Token::Match(tok, "strncpy|strncat ( %varid% , %var% [ %any% ] , %num% )", arrayInfo.varid()))) (Token::Match(tok, "strncpy|strncat ( %varid% , %var% [ %any% ] , %num% )", arrayInfo.varid())))
{ {
@ -1243,7 +1260,7 @@ void CheckBufferOverrun::checkScope(const Token *tok, const ArrayInfo &arrayInfo
{ {
// this is currently 'inconclusive'. See TestBufferOverrun::terminateStrncpy3 // this is currently 'inconclusive'. See TestBufferOverrun::terminateStrncpy3
if (_settings->isEnabled("style") && _settings->inconclusive) if (_settings->isEnabled("style") && _settings->inconclusive)
terminateStrncpyError(tok, tok->strAt(2)); terminateStrncpyError(tok, tok->strAt(2), false);
} }
break; break;

View File

@ -216,7 +216,7 @@ public:
void strncatUsageError(const Token *tok); void strncatUsageError(const Token *tok);
void outOfBoundsError(const Token *tok, const std::string &what); void outOfBoundsError(const Token *tok, const std::string &what);
void sizeArgumentAsCharError(const Token *tok); void sizeArgumentAsCharError(const Token *tok);
void terminateStrncpyError(const Token *tok, const std::string &varname); void terminateStrncpyError(const Token *tok, const std::string &varname, bool conclusive);
void negativeIndexError(const Token *tok, MathLib::bigint index); void negativeIndexError(const Token *tok, MathLib::bigint index);
void cmdLineArgsError(const Token *tok); void cmdLineArgsError(const Token *tok);
void pointerOutOfBoundsError(const Token *tok, const std::string &object); // UB when result of calculation is out of bounds void pointerOutOfBoundsError(const Token *tok, const std::string &object); // UB when result of calculation is out of bounds
@ -231,7 +231,7 @@ public:
c.strncatUsageError(0); c.strncatUsageError(0);
c.outOfBoundsError(0, "index"); c.outOfBoundsError(0, "index");
c.sizeArgumentAsCharError(0); c.sizeArgumentAsCharError(0);
c.terminateStrncpyError(0, "buffer"); c.terminateStrncpyError(0, "buffer", false);
c.negativeIndexError(0, -1); c.negativeIndexError(0, -1);
c.cmdLineArgsError(0); c.cmdLineArgsError(0);
c.pointerOutOfBoundsError(0, "array"); c.pointerOutOfBoundsError(0, "array");

View File

@ -2908,7 +2908,7 @@ private:
" char c[6];\n" " char c[6];\n"
" strncpy(c,\"hello!\",sizeof(c));\n" " strncpy(c,\"hello!\",sizeof(c));\n"
"}\n"); "}\n");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (warning) The buffer 'c' is not zero-terminated after the call to strncpy().\n", errout.str());
check("void f()\n" check("void f()\n"
"{\n" "{\n"