diff --git a/lib/checkbufferoverrun.cpp b/lib/checkbufferoverrun.cpp index 1b3cd8b76..b0a7ff766 100644 --- a/lib/checkbufferoverrun.cpp +++ b/lib/checkbufferoverrun.cpp @@ -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", - "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."); + if (conclusive) + reportError(tok, Severity::warning, "terminateStrncpy", + "The buffer '" + varname + "' is not 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. This will cause bugs later in the code if " + "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) @@ -1221,6 +1228,16 @@ void CheckBufferOverrun::checkScope(const Token *tok, const ArrayInfo &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())) || (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 if (_settings->isEnabled("style") && _settings->inconclusive) - terminateStrncpyError(tok, tok->strAt(2)); + terminateStrncpyError(tok, tok->strAt(2), false); } break; diff --git a/lib/checkbufferoverrun.h b/lib/checkbufferoverrun.h index 6861db55f..4bb974d87 100644 --- a/lib/checkbufferoverrun.h +++ b/lib/checkbufferoverrun.h @@ -216,7 +216,7 @@ public: void strncatUsageError(const Token *tok); void outOfBoundsError(const Token *tok, const std::string &what); 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 cmdLineArgsError(const Token *tok); 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.outOfBoundsError(0, "index"); c.sizeArgumentAsCharError(0); - c.terminateStrncpyError(0, "buffer"); + c.terminateStrncpyError(0, "buffer", false); c.negativeIndexError(0, -1); c.cmdLineArgsError(0); c.pointerOutOfBoundsError(0, "array"); diff --git a/test/testbufferoverrun.cpp b/test/testbufferoverrun.cpp index 54cc0b291..2a1072e9a 100644 --- a/test/testbufferoverrun.cpp +++ b/test/testbufferoverrun.cpp @@ -2908,7 +2908,7 @@ private: " char c[6];\n" " strncpy(c,\"hello!\",sizeof(c));\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" "{\n"