#10244: Fixed false negative: bufferAccessOutOfBounds

This commit is contained in:
orbitcowboy 2021-04-13 16:40:38 +02:00
parent 44c8b315c6
commit e869452240
3 changed files with 49 additions and 10 deletions

View File

@ -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);
}
//---------------------------------------------------------------------------

View File

@ -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<Dimension>(), std::vector<const ValueFlow::Value *>());
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);

View File

@ -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"