From 2942be53f7d19032b36f9acc73137d09595135a8 Mon Sep 17 00:00:00 2001 From: Paul Fultz II Date: Fri, 30 Aug 2019 01:41:17 -0500 Subject: [PATCH] Add more tests for valueFlowUninit (#2124) --- lib/valueflow.cpp | 2 +- test/testuninitvar.cpp | 278 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 279 insertions(+), 1 deletion(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index f3f1f8d64..040c4a37b 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -2510,7 +2510,7 @@ static bool valueFlowForward(Token * const startToken, return false; } - else if (indentlevel <= 0 && Token::Match(tok2, "return|throw")) + else if (indentlevel <= 0 && Token::Match(tok2, "return|throw|setjmp|longjmp")) returnStatement = true; else if (returnStatement && tok2->str() == ";") diff --git a/test/testuninitvar.cpp b/test/testuninitvar.cpp index 2eab19683..8e21b77fa 100644 --- a/test/testuninitvar.cpp +++ b/test/testuninitvar.cpp @@ -3991,6 +3991,284 @@ private: " int x[] = {a,2};\n" "}"); ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: a\n", errout.str()); + + valueFlowUninit("void foo()\n" + "{\n" + " int x;\n" + " int *y = &x;\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + valueFlowUninit("void foo()\n" + "{\n" + " int *x;\n" + " int *&y = x;\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + valueFlowUninit("void foo()\n" + "{\n" + " int x = xyz::x;\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + valueFlowUninit("void f()\n" + "{\n" + " extern int a;\n" + " a++;\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + valueFlowUninit("static void foo()\n" + "{\n" + " int x, y;\n" + " x = (y = 10);\n" + " int z = y * 2;\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + valueFlowUninit("static void foo() {\n" + " int x, y;\n" + " x = ((y) = 10);\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + valueFlowUninit("static void foo()\n" + "{\n" + " Foo p;\n" + " p.abcd();\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + valueFlowUninit("static void foo()\n" + "{\n" + " Foo p;\n" + " int x = p.abcd();\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + // Unknown types + { + valueFlowUninit("void a()\n" + "{\n" + " A ret;\n" + " return ret;\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + // #3916 - avoid false positive + valueFlowUninit("void f(float x) {\n" + " union lf { long l; float f; } u_lf;\n" + " float hx = (u_lf.f = (x), u_lf.l);\n" + "}"); + ASSERT_EQUALS("", errout.str()); + } + + valueFlowUninit("void a()\n" + "{\n" + " int x[10];\n" + " int *y = x;\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + valueFlowUninit("void a()\n" + "{\n" + " int x;\n" + " int *y = &x;\n" + " *y = 0;\n" + " x++;\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + valueFlowUninit("void a()\n" + "{\n" + " char x[10], y[10];\n" + " char *z = x;\n" + " memset(z, 0, sizeof(x));\n" + " memcpy(y, x, sizeof(x));\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + // Handling >> and << + { + valueFlowUninit("int a() {\n" + " int ret;\n" + " std::cin >> ret;\n" + " ret++;\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + valueFlowUninit("void f(int b) {\n" + " int a;\n" + " std::cin >> b >> a;\n" + " return a;" + "}"); + ASSERT_EQUALS("", errout.str()); + + valueFlowUninit("void foo() {\n" // #3707 + " Node node;\n" + " int x;\n" + " node[\"abcd\"] >> x;\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + valueFlowUninit("int a(FArchive &arc) {\n" + " int *p;\n" + " arc << p;\n" + " return *p;\n" + "}"); + ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: p\n", errout.str()); + + // #4320 + valueFlowUninit("void f() {\n" + " int a;\n" + " a << 1;\n" + " return a;\n" + "}"); + ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: a\n", errout.str()); + + } + + valueFlowUninit("void a() {\n" // asm + " int x;\n" + " asm();\n" + " x++;\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + valueFlowUninit("void a()\n" + "{\n" + " int x[10];\n" + " struct xyz xyz1 = { .x = x };\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + valueFlowUninit("void foo()\n" + "{\n" + " char *buf = malloc(100);\n" + " struct ABC *abc = buf;\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + valueFlowUninit("class Fred {\n" + "public:\n" + " FILE *f;\n" + " ~Fred();\n" + "}\n" + "Fred::~Fred()\n" + "{\n" + " fclose(f);\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + valueFlowUninit("void f()\n" + "{\n" + " int c;\n" + " ab(sizeof(xyz), &c);\n" + " if (c);\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + valueFlowUninit("void f()\n" + "{\n" + " int c;\n" + " a = (f2(&c));\n" + " c++;\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + // goto/setjmp/longjmp.. + valueFlowUninit("void foo(int x)\n" + "{\n" + " long b;\n" + " if (g()) {\n" + " b =2;\n" + " goto found;\n" + " }\n" + "\n" + " return;\n" + "\n" + "found:\n" + " int a = b;\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + valueFlowUninit("int foo()\n" + "{\n" + " jmp_buf env;\n" + " int a;\n" + " int val = setjmp(env);\n" + " if(val)\n" + " return a;\n" + " a = 1;\n" + " longjmp(env, 1);\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + // macro_for.. + valueFlowUninit("int foo()\n" + "{\n" + " int retval;\n" + " if (condition) {\n" + " for12(1,2) { }\n" + " retval = 1;\n" + " }\n" + " else\n" + " retval = 2;\n" + " return retval;\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + valueFlowUninit("int foo()\n" + "{\n" + " int i;\n" + " goto exit;\n" + " i++;\n" + "exit:\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + valueFlowUninit("int foo() {\n" + " int x,y=0;\n" + "again:\n" + " if (y) return x;\n" + " x = a;\n" + " y = 1;\n" + " goto again;\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + // #4040 - False positive + valueFlowUninit("int f(int x) {\n" + " int iter;\n" + " {\n" + " union\n" + " {\n" + " int asInt;\n" + " double asDouble;\n" + " };\n" + "\n" + " iter = x;\n" + " }\n" + " return 1 + iter;\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + // C++11 style initialization + valueFlowUninit("int f() {\n" + " int i = 0;\n" + " int j{ i };\n" + " return j;\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + // Ticket #5646 + valueFlowUninit("float foo() {\n" + " float source[2] = {3.1, 3.1};\n" + " float (*sink)[2] = &source;\n" + " return (*sink)[0];\n" + "}"); + ASSERT_EQUALS("", errout.str()); } void uninitvar_ipa() {