diff --git a/lib/checkother.cpp b/lib/checkother.cpp index b673410a1..63ac7ccf3 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -1625,6 +1625,26 @@ private: return &tok; } + // += etc + if (Token::Match(tok.previous(), "[;{}]") || Token::Match(tok.tokAt(-2), "[;{}] *")) + { + // goto the equal.. + const Token *eq = tok.next(); + if (eq && eq->str() == "[" && eq->link() && eq->link()->next()) + eq = eq->link()->next(); + + // is it X= + if (Token::Match(eq, "+=|-=|*=|/=|&=|^=") || eq->str() == "|=") + { + if (tok.previous()->str() == "*") + use_pointer(foundError, checks, &tok); + else if (tok.next()->str() == "[") + use_array(foundError, checks, &tok); + else + use(foundError, checks, &tok); + } + } + if (Token::Match(tok.next(), "= malloc|kmalloc") || Token::simpleMatch(tok.next(), "= new char [")) { alloc_pointer(checks, tok.varId()); diff --git a/lib/executionpath.cpp b/lib/executionpath.cpp index 586027e5c..96f85e628 100644 --- a/lib/executionpath.cpp +++ b/lib/executionpath.cpp @@ -95,6 +95,12 @@ static const Token *checkExecutionPaths_(const Token *tok, std::listtokAt(2)->link(); diff --git a/test/testbufferoverrun.cpp b/test/testbufferoverrun.cpp index 4726584c2..912e32365 100644 --- a/test/testbufferoverrun.cpp +++ b/test/testbufferoverrun.cpp @@ -95,6 +95,7 @@ private: TEST_CASE(array_index_23); TEST_CASE(array_index_multidim); TEST_CASE(array_index_switch_in_for); + TEST_CASE(array_index_calculation); TEST_CASE(buffer_overrun_1); TEST_CASE(buffer_overrun_2); @@ -819,9 +820,24 @@ private: " };\n" " }\n" "}\n"); + ASSERT_EQUALS("", errout.str()); TODO_ASSERT_EQUALS("[test.cpp:12]: (error) Array index out of bounds\n", errout.str()); } + void array_index_calculation() + { + // #1193 - false negative: array out of bounds in loop when there is calculation + check("void f()\n" + "{\n" + " char data[8];\n" + " for (int i = 19; i < 36; ++i) {\n" + " data[(i-0)/2] = 0;\n" + " }\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + TODO_ASSERT_EQUALS("[test.cpp:5]: (error) Array index out of bounds\n", errout.str()); + } + void buffer_overrun_1() { check("void f()\n" diff --git a/test/testother.cpp b/test/testother.cpp index d1a827767..8f11a8719 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -954,6 +954,14 @@ private: "}\n"); ASSERT_EQUALS("", errout.str()); + checkNullPointer("static void foo()\n" + "{\n" + " int *p = 0;\n" + " exit();\n" + " *p = 0;\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + checkNullPointer("static void foo(int a)\n" "{\n" " Foo *p = 0;\n" @@ -1176,6 +1184,28 @@ private: "}\n"); ASSERT_EQUALS("", errout.str()); + // += + checkUninitVar("void f()\n" + "{\n" + " int c;\n" + " c += 2;\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: c\n", errout.str()); + + checkUninitVar("void f()\n" + "{\n" + " char *s = malloc(100);\n" + " *s += 10;\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:4]: (error) Data is allocated but not initialized: s\n", errout.str()); + + checkUninitVar("void f()\n" + "{\n" + " int a[10];\n" + " a[0] += 10;\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: a\n", errout.str()); + // goto.. checkUninitVar("void foo(int x)\n" "{\n"