From 9653760547b87b00fb5f43f2bd40654b68c3eda8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sat, 23 Mar 2019 11:20:35 +0100 Subject: [PATCH] CheckBufferOverrun: Improved CTU analysis for array --- lib/ctu.cpp | 14 ++++++++++++++ lib/tokenize.h | 4 ++++ test/testbufferoverrun.cpp | 18 ++++++++++++++---- 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/lib/ctu.cpp b/lib/ctu.cpp index 8160fcbdb..44260e9d7 100644 --- a/lib/ctu.cpp +++ b/lib/ctu.cpp @@ -331,6 +331,20 @@ CTU::FileInfo *CTU::getFileInfo(const Tokenizer *tokenizer) } fileInfo->functionCalls.push_back(functionCall); } + // array + if (argtok->variable() && argtok->variable()->isArray() && argtok->variable()->dimensions().size()==1 && argtok->variable()->dimension(0)>1) { + 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->variable()->dimension(0) * argtok->valueType()->typeSize(*tokenizer->getSettings()); + functionCall.warning = false; + fileInfo->functionCalls.push_back(functionCall); + } // pointer to uninitialized data.. if (!argtok->isUnaryOp("&")) continue; diff --git a/lib/tokenize.h b/lib/tokenize.h index e08f3c8e5..f42bcd40d 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -857,6 +857,10 @@ public: #endif } + const Settings *getSettings() const { + return mSettings; + } + private: /** Disable copy constructor */ Tokenizer(const Tokenizer &) = delete; diff --git a/test/testbufferoverrun.cpp b/test/testbufferoverrun.cpp index 8df2473da..5f4fd88b9 100644 --- a/test/testbufferoverrun.cpp +++ b/test/testbufferoverrun.cpp @@ -247,6 +247,7 @@ private: // TODO TEST_CASE(pointerAddition1); TEST_CASE(ctu_1); + TEST_CASE(ctu_2); } @@ -4141,28 +4142,37 @@ private: } void ctu_1() { - ctu("void dostuff(const char *p) {\n" + ctu("void dostuff(char *p) {\n" " p[-3] = 0;\n" "}\n" "\n" "int main() {\n" " char *s = malloc(4);\n" " dostuff(s);\n" - " return 0;\n" "}"); ASSERT_EQUALS("[test.cpp:6] -> [test.cpp:7] -> [test.cpp:2]: (error) Buffer access out of bounds; buffer 'p' is accessed at offset -3.\n", errout.str()); - ctu("void dostuff(const char *p) {\n" + ctu("void dostuff(char *p) {\n" " p[4] = 0;\n" "}\n" "\n" "int main() {\n" " char *s = malloc(4);\n" " dostuff(s);\n" - " return 0;\n" "}"); 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() { + ctu("void dostuff(char *p) {\n" + " p[10] = 0;\n" + "}\n" + "int main() {\n" + " char str[4];\n" + " dostuff(str);\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 10.\n", errout.str()); + } }; REGISTER_TEST(TestBufferOverrun)