diff --git a/lib/checkbufferoverrun.cpp b/lib/checkbufferoverrun.cpp index 74089bcb6..d59e6dfb6 100644 --- a/lib/checkbufferoverrun.cpp +++ b/lib/checkbufferoverrun.cpp @@ -600,21 +600,21 @@ void CheckBufferOverrun::bufferOverflow() continue; // TODO: strcpy(buf+10, "hello"); const ValueFlow::Value bufferSize = getBufferSize(argtok); - if (bufferSize.intvalue <= 1) + if (bufferSize.intvalue <= 0) continue; - bool error = std::none_of(minsizes->begin(), minsizes->end(), [=](const Library::ArgumentChecks::MinSize &minsize) { + const bool error = std::none_of(minsizes->begin(), minsizes->end(), [=](const Library::ArgumentChecks::MinSize &minsize) { return checkBufferSize(tok, minsize, args, bufferSize.intvalue, mSettings); }); if (error) - bufferOverflowError(args[argnr], &bufferSize); + bufferOverflowError(args[argnr], &bufferSize, (bufferSize.intvalue == 1) ? Certainty::inconclusive : Certainty::normal); } } } } -void CheckBufferOverrun::bufferOverflowError(const Token *tok, const ValueFlow::Value *value) +void CheckBufferOverrun::bufferOverflowError(const Token *tok, const ValueFlow::Value *value, const Certainty::CertaintyLevel &certainty) { - reportError(getErrorPath(tok, value, "Buffer overrun"), Severity::error, "bufferAccessOutOfBounds", "Buffer is accessed out of bounds: " + (tok ? tok->expressionString() : "buf"), CWE_BUFFER_OVERRUN, Certainty::normal); + reportError(getErrorPath(tok, value, "Buffer overrun"), Severity::error, "bufferAccessOutOfBounds", "Buffer is accessed out of bounds: " + (tok ? tok->expressionString() : "buf"), CWE_BUFFER_OVERRUN, certainty); } //--------------------------------------------------------------------------- diff --git a/lib/checkbufferoverrun.h b/lib/checkbufferoverrun.h index cbcf86d11..44ba1150b 100644 --- a/lib/checkbufferoverrun.h +++ b/lib/checkbufferoverrun.h @@ -25,6 +25,7 @@ #include "check.h" #include "config.h" #include "ctu.h" +#include "errortypes.h" #include "mathlib.h" #include "symboldatabase.h" #include "valueflow.h" @@ -83,7 +84,7 @@ public: c.pointerArithmeticError(nullptr, nullptr, nullptr); c.negativeIndexError(nullptr, std::vector(), std::vector()); c.arrayIndexThenCheckError(nullptr, "i"); - c.bufferOverflowError(nullptr, nullptr); + c.bufferOverflowError(nullptr, nullptr, Certainty::normal); c.objectIndexError(nullptr, nullptr, true); } @@ -103,7 +104,7 @@ private: void pointerArithmeticError(const Token *tok, const Token *indexToken, const ValueFlow::Value *indexValue); void bufferOverflow(); - void bufferOverflowError(const Token *tok, const ValueFlow::Value *value); + void bufferOverflowError(const Token *tok, const ValueFlow::Value *value, const Certainty::CertaintyLevel& certainty); void arrayIndexThenCheck(); void arrayIndexThenCheckError(const Token *tok, const std::string &indexName); diff --git a/test/testbufferoverrun.cpp b/test/testbufferoverrun.cpp index 2d81e62b8..f01fb0d95 100644 --- a/test/testbufferoverrun.cpp +++ b/test/testbufferoverrun.cpp @@ -180,6 +180,7 @@ private: TEST_CASE(buffer_overrun_29); // #7083: false positive: typedef and initialization with strings TEST_CASE(buffer_overrun_30); // #6367 TEST_CASE(buffer_overrun_31); + TEST_CASE(buffer_overrun_32); //#10244 TEST_CASE(buffer_overrun_errorpath); TEST_CASE(buffer_overrun_bailoutIfSwitch); // ticket #2378 : bailoutIfSwitch // TODO TEST_CASE(buffer_overrun_function_array_argument); @@ -2652,6 +2653,43 @@ private: ASSERT_EQUALS("", errout.str()); } + void buffer_overrun_32() { + // destination size is too small + check("void f(void) {\n" + " const char src[3] = \"abc\";\n" + " char dest[1] = \"a\";\n" + " (void)strxfrm(dest,src,1);\n" + " (void)strxfrm(dest,src,2);\n"// << + "}"); + ASSERT_EQUALS("[test.cpp:5]: (error, inconclusive) Buffer is accessed out of bounds: dest\n", errout.str()); + // destination size is too small + check("void f(void) {\n" + " const char src[3] = \"abc\";\n" + " char dest[2] = \"ab\";\n" + " (void)strxfrm(dest,src,1);\n" + " (void)strxfrm(dest,src,2);\n" + " (void)strxfrm(dest,src,3);\n" // << + "}"); + ASSERT_EQUALS("[test.cpp:6]: (error) Buffer is accessed out of bounds: dest\n", errout.str()); + // source size is too small + check("void f(void) {\n" + " const char src[2] = \"ab\";\n" + " char dest[3] = \"abc\";\n" + " (void)strxfrm(dest,src,1);\n" + " (void)strxfrm(dest,src,2);\n" + " (void)strxfrm(dest,src,3);\n" // << + "}"); + ASSERT_EQUALS("[test.cpp:6]: (error) Buffer is accessed out of bounds: src\n", errout.str()); + // source size is too small + check("void f(void) {\n" + " const char src[1] = \"a\";\n" + " char dest[3] = \"abc\";\n" + " (void)strxfrm(dest,src,1);\n" + " (void)strxfrm(dest,src,2);\n" // << + "}"); + ASSERT_EQUALS("[test.cpp:5]: (error, inconclusive) Buffer is accessed out of bounds: src\n", errout.str()); + } + void buffer_overrun_errorpath() { setMultiline(); settings0.templateLocation = "{file}:{line}:note:{info}"; @@ -3609,7 +3647,7 @@ private: " struct Foo x;\n" " mysprintf(x.a, \"aa\");\n" "}", settings); - TODO_ASSERT_EQUALS("[test.cpp:4]: (error) Buffer is accessed out of bounds: x.a\n", "", errout.str()); + ASSERT_EQUALS("[test.cpp:4]: (error, inconclusive) Buffer is accessed out of bounds: x.a\n", errout.str()); // ticket #900 check("void f() {\n" @@ -3630,14 +3668,14 @@ private: " struct Foo *x = malloc(sizeof(Foo));\n" " mysprintf(x.a, \"aa\");\n" "}", settings); - ASSERT_EQUALS("", errout.str()); // TODO: Inconclusive error? + ASSERT_EQUALS("[test.cpp:4]: (error, inconclusive) Buffer is accessed out of bounds: x.a\n", errout.str()); check("struct Foo { char a[1]; };\n" "void f() {\n" " struct Foo *x = malloc(sizeof(Foo) + 10);\n" " mysprintf(x.a, \"aa\");\n" "}", settings); - ASSERT_EQUALS("", errout.str()); + ASSERT_EQUALS("[test.cpp:4]: (error, inconclusive) Buffer is accessed out of bounds: x.a\n", errout.str()); check("struct Foo {\n" // #6668 - unknown size " char a[LEN];\n"