From 73a569be979739c0a51bdbedb714fea2d39ae786 Mon Sep 17 00:00:00 2001 From: Rikard Falkeborn Date: Mon, 21 Oct 2019 07:11:22 +0200 Subject: [PATCH] TestBufferOverRun: Handle string literals (#2287) --- lib/checkbufferoverrun.cpp | 9 +++------ test/testbufferoverrun.cpp | 31 +++++++++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/lib/checkbufferoverrun.cpp b/lib/checkbufferoverrun.cpp index e9c56ef10..a2bcd1db0 100644 --- a/lib/checkbufferoverrun.cpp +++ b/lib/checkbufferoverrun.cpp @@ -188,10 +188,7 @@ static bool getDimensionsEtc(const Token * const arrayToken, const Settings *set while (Token::Match(array, ".|::")) array = array->astOperand2(); - if (!array->variable()) - return false; - - if (array->variable()->isArray() && !array->variable()->dimensions().empty()) { + if (array->variable() && array->variable()->isArray() && !array->variable()->dimensions().empty()) { *dimensions = array->variable()->dimensions(); if (dimensions->size() >= 1 && ((*dimensions)[0].num <= 1 || !(*dimensions)[0].tok)) { visitAstNodes(arrayToken, @@ -244,7 +241,7 @@ static std::vector getOverrunIndexValues(const Token * continue; allKnown = false; } - if (array->variable()->isArray() && dimensions[i].num == 0) + if (array->variable() && array->variable()->isArray() && dimensions[i].num == 0) continue; if (value->intvalue == dimensions[i].num) equal = true; @@ -275,7 +272,7 @@ void CheckBufferOverrun::arrayIndex() const Token *array = tok->astOperand1(); while (Token::Match(array, ".|::")) array = array->astOperand2(); - if (!array|| !array->variable() || array->variable()->nameToken() == array) + if (!array || ((!array->variable() || array->variable()->nameToken() == array) && array->tokType() != Token::eString)) continue; if (!array->scope()->isExecutable()) { // LHS in non-executable scope => This is just a definition diff --git a/test/testbufferoverrun.cpp b/test/testbufferoverrun.cpp index e322e67f3..cbf61c1c0 100644 --- a/test/testbufferoverrun.cpp +++ b/test/testbufferoverrun.cpp @@ -86,7 +86,7 @@ private: TEST_CASE(array_index_1); TEST_CASE(array_index_2); TEST_CASE(array_index_3); - // TODO string TEST_CASE(array_index_4); + TEST_CASE(array_index_4); TEST_CASE(array_index_6); TEST_CASE(array_index_7); TEST_CASE(array_index_11); @@ -189,6 +189,7 @@ private: TEST_CASE(pointer_out_of_bounds_1); // TODO TEST_CASE(pointer_out_of_bounds_2); TEST_CASE(pointer_out_of_bounds_3); + TEST_CASE(pointer_out_of_bounds_4); // TODO TEST_CASE(pointer_out_of_bounds_sub); // TODO TEST_CASE(strncat1); @@ -385,13 +386,16 @@ private: void array_index_4() { check("char c = \"abc\"[4];"); - ASSERT_EQUALS("[test.cpp:1]: (error) Array index out of bounds: \"abc\"\n", errout.str()); + ASSERT_EQUALS("[test.cpp:1]: (error) Array '\"abc\"[4]' accessed at index 4, which is out of bounds.\n", errout.str()); check("p = &\"abc\"[4];"); ASSERT_EQUALS("", errout.str()); check("char c = \"\\0abc\"[2];"); ASSERT_EQUALS("", errout.str()); + + check("char c = L\"abc\"[4];"); + ASSERT_EQUALS("[test.cpp:1]: (error) Array 'L\"abc\"[4]' accessed at index 4, which is out of bounds.\n", errout.str()); } void array_index_3() { @@ -2814,6 +2818,29 @@ private: ASSERT_EQUALS("[test.cpp:3]: (portability) Undefined behaviour, pointer arithmetic 's->a+100' is out of bounds.\n", errout.str()); } + void pointer_out_of_bounds_4() { + check("const char* f() {\n" + " g(\"Hello\" + 6);\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + check("const char* f() {\n" + " g(\"Hello\" + 7);\n" + "}"); + ASSERT_EQUALS("[test.cpp:2]: (portability) Undefined behaviour, pointer arithmetic '\"Hello\"+7' is out of bounds.\n", errout.str()); + + check("const char16_t* f() {\n" + " g(u\"Hello\" + 6);\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + check("const char16_t* f() {\n" + " g(u\"Hello\" + 7);\n" + "}"); + ASSERT_EQUALS("[test.cpp:2]: (portability) Undefined behaviour, pointer arithmetic 'u\"Hello\"+7' is out of bounds.\n", errout.str()); + } + + void pointer_out_of_bounds_sub() { check("void f() {\n" " char x[10];\n"