From d6b806c59260e015e4187b79fe31faaaad6a46fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sat, 23 Mar 2019 15:57:17 +0100 Subject: [PATCH] CheckBufferOverrun: Better CTU checking when variable address is passed --- lib/ctu.cpp | 14 ++++++++++++++ test/testbufferoverrun.cpp | 20 ++++++++++++++++---- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/lib/ctu.cpp b/lib/ctu.cpp index 44260e9d7..c2c556186 100644 --- a/lib/ctu.cpp +++ b/lib/ctu.cpp @@ -345,6 +345,20 @@ CTU::FileInfo *CTU::getFileInfo(const Tokenizer *tokenizer) functionCall.warning = false; fileInfo->functionCalls.push_back(functionCall); } + // &var => buffer + if (argtok->isUnaryOp("&") && argtok->astOperand1()->variable() && argtok->astOperand1()->valueType() && !argtok->astOperand1()->variable()->isArray()) { + FileInfo::FunctionCall functionCall; + functionCall.callValueType = ValueFlow::Value::ValueType::BUFFER_SIZE; + functionCall.callId = getFunctionId(tokenizer, tok->astOperand1()->function()); + functionCall.callFunctionName = tok->astOperand1()->expressionString(); + functionCall.location.fileName = tokenizer->list.file(tok); + functionCall.location.linenr = tok->linenr(); + functionCall.callArgNr = argnr + 1; + functionCall.callArgumentExpression = argtok->expressionString(); + functionCall.callArgValue = argtok->astOperand1()->valueType()->typeSize(*tokenizer->getSettings()); + functionCall.warning = false; + fileInfo->functionCalls.push_back(functionCall); + } // pointer to uninitialized data.. if (!argtok->isUnaryOp("&")) continue; diff --git a/test/testbufferoverrun.cpp b/test/testbufferoverrun.cpp index 5f4fd88b9..a53bd3d44 100644 --- a/test/testbufferoverrun.cpp +++ b/test/testbufferoverrun.cpp @@ -246,8 +246,9 @@ private: // TODO TEST_CASE(pointerAddition1); - TEST_CASE(ctu_1); - TEST_CASE(ctu_2); + TEST_CASE(ctu_malloc); + TEST_CASE(ctu_array); + TEST_CASE(ctu_variable); } @@ -4141,7 +4142,7 @@ private: delete ctu; } - void ctu_1() { + void ctu_malloc() { ctu("void dostuff(char *p) {\n" " p[-3] = 0;\n" "}\n" @@ -4163,7 +4164,7 @@ private: ASSERT_EQUALS("[test.cpp:6] -> [test.cpp:7] -> [test.cpp:2]: (error) Buffer access out of bounds; 'p' buffer size is 4 and it is accessed at offset 4.\n", errout.str()); } - void ctu_2() { + void ctu_array() { ctu("void dostuff(char *p) {\n" " p[10] = 0;\n" "}\n" @@ -4173,6 +4174,17 @@ private: "}"); ASSERT_EQUALS("[test.cpp:6] -> [test.cpp:2]: (error) Buffer access out of bounds; 'p' buffer size is 4 and it is accessed at offset 10.\n", errout.str()); } + + void ctu_variable() { + ctu("void dostuff(int *p) {\n" + " p[10] = 0;\n" + "}\n" + "int main() {\n" + " int x = 4;\n" + " dostuff(&x);\n" + "}"); + ASSERT_EQUALS("[test.cpp:6] -> [test.cpp:2]: (error) Buffer access out of bounds; 'p' buffer size is 4 and it is accessed at offset 40.\n", errout.str()); + } }; REGISTER_TEST(TestBufferOverrun)