[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/cppcheck-opensource/cppcheck/main/test/testuninitvar.cpp [Back]  [Original]

/*
 * Cppcheck - A tool for static C/C++ code analysis
 * Copyright (C) 2007-2026 Cppcheck team.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see .
 */

#include "check.h"
#include "checkuninitvar.h"
#include "ctu.h"
#include "fixture.h"
#include "helpers.h"
#include "settings.h"

#include 
#include 
#include 

class TestUninitVar : public TestFixture {
public:
    TestUninitVar() : TestFixture("TestUninitVar") {}

private:
    const Settings settings = settingsBuilder().library("std.cfg").build();

    void run() override {
        mNewTemplate = true;
        TEST_CASE(uninitvar1);
        TEST_CASE(uninitvar_warn_once); // only write 1 warning at a time
        TEST_CASE(uninitvar_decl);      // handling various types in C and C++ files
        TEST_CASE(uninitvar_bitop);     // using uninitialized operand in bit operation
        TEST_CASE(uninitvar_alloc);     // data is allocated but not initialized
        TEST_CASE(uninitvar_arrays);    // arrays
        TEST_CASE(uninitvar_class);     // class/struct
        TEST_CASE(uninitvar_enum);      // enum variables
        TEST_CASE(uninitvar_if);        // handling if
        TEST_CASE(uninitvar_loops);     // handling for/while
        TEST_CASE(uninitvar_switch);    // handling switch
        TEST_CASE(uninitvar_references); // references
        TEST_CASE(uninitvar_return);    // return
        TEST_CASE(uninitvar_assign);    // = {..}
        TEST_CASE(uninitvar_strncpy);   // strncpy doesn't always null-terminate
        TEST_CASE(func_uninit_var);     // analyse function calls for: 'int a(int x) { return x+x; }'
        TEST_CASE(func_uninit_pointer); // analyse function calls for: 'void a(int *p) { *p = 0; }'
        TEST_CASE(uninitvar_typeof);    // typeof
        TEST_CASE(uninitvar_ignore);    // ignore cast, *&x, ..
        TEST_CASE(uninitvar2);
        TEST_CASE(uninitvar3);          // #3844
        TEST_CASE(uninitvar4);          // #3869 (reference)
        TEST_CASE(uninitvar5);          // #3861
        TEST_CASE(uninitvar6);          // #13227
        TEST_CASE(uninitvar2_func);     // function calls
        TEST_CASE(uninitvar2_value);    // value flow
        TEST_CASE(valueFlowUninit2_value);
        TEST_CASE(valueFlowUninit_uninitvar2);
        TEST_CASE(valueFlowUninit_functioncall);
        TEST_CASE(uninitStructMember);  // struct members
        TEST_CASE(uninitvar2_while);
        TEST_CASE(uninitvar2_4494);      // #4494
        TEST_CASE(uninitvar2_malloc);    // malloc returns uninitialized data
        TEST_CASE(uninitvar8); // ticket #6230
        TEST_CASE(uninitvar9); // ticket #6424
        TEST_CASE(uninitvar10); // ticket #9467
        TEST_CASE(uninitvar11); // ticket #9123
        TEST_CASE(uninitvar12); // #10218 - stream read
        TEST_CASE(uninitvar13); // #9772
        TEST_CASE(uninitvar14);
        TEST_CASE(uninitvar15); // #13685
        TEST_CASE(uninitvar_unconditionalTry);
        TEST_CASE(uninitvar_funcptr); // #6404
        TEST_CASE(uninitvar_operator); // #6680
        TEST_CASE(uninitvar_ternaryexpression1); // #4683
        TEST_CASE(uninitvar_ternaryexpression2); // #14729
        TEST_CASE(uninitvar_pointertoarray);
        TEST_CASE(uninitvar_cpp11ArrayInit); // #7010
        TEST_CASE(uninitvar_rangeBasedFor); // #7078
        TEST_CASE(uninitvar_static); // #8734
        TEST_CASE(uninitvar_configuration);
        TEST_CASE(checkExpr);
        TEST_CASE(trac_4871);
        TEST_CASE(syntax_error); // Ticket #5073
        TEST_CASE(trac_5970);
        TEST_CASE(valueFlowUninitTest);
        TEST_CASE(valueFlowUninitBreak);
        TEST_CASE(valueFlowUninitStructMembers);
        TEST_CASE(valueFlowUninitForLoop);
        TEST_CASE(uninitvar_ipa);
        TEST_CASE(uninitvar_memberfunction);
        TEST_CASE(uninitvar_nonmember); // crash in ycmd test
        TEST_CASE(uninitvarDesignatedInitializers);
        TEST_CASE(uninitvarMemberPointer);

        TEST_CASE(isVariableUsageDeref); // *p
        TEST_CASE(isVariableUsageDerefValueflow); // *p

        TEST_CASE(uninitvar_memberaccess); // (&(a))->b  a.b

        // whole program analysis
        TEST_CASE(ctuTest);
    }

    struct CheckUninitVarOptions
    {
        bool cpp = true;
    };

#define checkUninitVar(...) checkUninitVar_(__FILE__, __LINE__, __VA_ARGS__)
    template
    void checkUninitVar_(const char* file, int line, const char (&code)[size], const CheckUninitVarOptions& options = make_default_obj()) {
        checkUninitVar_(file, line, code, settings, options.cpp);
    }

    template
    void checkUninitVar_(const char* file, int line, const char (&code)[size], const Settings& settings1, bool cpp = true) {
        SimpleTokenizer tokenizer(settings1, *this, cpp);
        ASSERT_LOC(tokenizer.tokenize(code), file, line);

        // Check for redundant code..
        CheckUninitVarImpl checkuninitvar(&tokenizer, settings1, *this);
        checkuninitvar.check();
    }

    // TODO: get rid of this
    void checkUninitVar_(const char* file, int line, const std::string& code) {
        SimpleTokenizer tokenizer(settings, *this);
        ASSERT_LOC(tokenizer.tokenize(code), file, line);

        // Check for redundant code..
        CheckUninitVarImpl checkuninitvar(&tokenizer, settings, *this);
        checkuninitvar.check();
    }

    void uninitvar1() {
        // extracttests.start: int b; int c;

        // Ticket #2207 - False negative
        checkUninitVar("void foo() {\n"
                       "    int a;\n"
                       "    b = c - a;\n"
                       "}");
        ASSERT_EQUALS("[test.cpp:3:13]: (error) Uninitialized variable: a [legacyUninitvar]\n", errout_str());

        checkUninitVar("void foo() {\n"
                       "    int a;\n"
                       "    b = a - c;\n"
                       "}");
        ASSERT_EQUALS("[test.cpp:3:9]: (error) Uninitialized variable: a [legacyUninitvar]\n", errout_str());

        // Ticket #6455 - some compilers allow const variables to be uninitialized
        // extracttests.disable
        checkUninitVar("void foo() {\n"
                       "    const int a;\n"
                       "    b = c - a;\n"
                       "}");
        ASSERT_EQUALS("[test.cpp:3:13]: (error) Uninitialized variable: a [legacyUninitvar]\n", errout_str());
        // extracttests.enable

        checkUninitVar("void foo() {\n"
                       "    int *p;\n"
                       "    realloc(p,10);\n"
                       "}");
        ASSERT_EQUALS("[test.cpp:3:13]: (error) Uninitialized variable: p [legacyUninitvar]\n", errout_str());

        checkUninitVar("void foo() {\n" // #5240
                       "    char *p = malloc(100);\n"
                       "    char *tmp = realloc(p,1000);\n"
                       "    if (!tmp) free(p);\n"
                       "}");
        ASSERT_EQUALS("", errout_str());

        checkUninitVar("void foo() {\n"
                       "    int *p = NULL;\n"
                       "    realloc(p,10);\n"
                       "}");
        ASSERT_EQUALS("", errout_str());

        // dereferencing uninitialized pointer..
        // extracttests.start: struct Foo { void abcd(); };
        checkUninitVar("static void foo()\n"
                       "{\n"
                       "    Foo *p;\n"
                       "    p->abcd();\n"
                       "}");
        ASSERT_EQUALS("[test.cpp:4:5]: (error) Uninitialized variable: p [legacyUninitvar]\n", errout_str());

        // extracttests.start: template struct Foo { void abcd(); };
        checkUninitVar("static void foo()\n"
                       "{\n"
                       "    Foo *p;\n"
                       "    p->abcd();\n"
                       "}");
        ASSERT_EQUALS("[test.cpp:4:5]: (error) Uninitialized variable: p [legacyUninitvar]\n", errout_str());

        // extracttests.start: struct Foo { void* a; };
        checkUninitVar("void f(Foo *p)\n"
                       "{\n"
                       "    int a;\n"
                       "    p->a = malloc(4 * a);\n"
                       "}");
        ASSERT_EQUALS("[test.cpp:4:23]: (error) Uninitialized variable: a [legacyUninitvar]\n", errout_str());

        checkUninitVar("static void foo()\n"
                       "{\n"
                       "    int *p;\n"
                       "    delete p;\n"
                       "}");
        ASSERT_EQUALS("[test.cpp:4:12]: (error) Uninitialized variable: p [legacyUninitvar]\n", errout_str());

        checkUninitVar("static void foo()\n"
                       "{\n"
                       "    int *p;\n"
                       "    delete [] p;\n"
                       "}");
        ASSERT_EQUALS("[test.cpp:4:15]: (error) Uninitialized variable: p [legacyUninitvar]\n", errout_str());

        checkUninitVar("static void foo()\n"
                       "{\n"
                       "    int *p;\n"
                       "    *p = 135;\n"
                       "}");
        ASSERT_EQUALS("[test.cpp:4:6]: (error) Uninitialized variable: p [legacyUninitvar]\n", errout_str());

        checkUninitVar("static void foo()\n"
                       "{\n"
                       "    int *p;\n"
                       "    p[0] = 135;\n"
                       "}");
        ASSERT_EQUALS("[test.cpp:4:5]: (error) Uninitialized variable: p [legacyUninitvar]\n", errout_str());

        checkUninitVar("static void foo()\n"
                       "{\n"
                       "    int *x;\n"
                       "    int y = *x;\n"
                       "}");
        ASSERT_EQUALS("[test.cpp:4:14]: (error) Uninitialized variable: x [legacyUninitvar]\n", errout_str());

        checkUninitVar("static void foo()\n"
                       "{\n"
                       "    int *x;\n"
                       "    int &y(*x);\n"
                       "}");
        ASSERT_EQUALS("[test.cpp:4:13]: (error) Uninitialized variable: x [legacyUninitvar]\n", errout_str());

        checkUninitVar("void foo()\n"
                       "{\n"
                       "    int x;\n"
                       "    int *y = &x;\n"
                       "}");
        ASSERT_EQUALS("", errout_str());

        checkUninitVar("void foo()\n"
                       "{\n"
                       "    int *x;\n"
                       "    int *&y = x;\n"
                       "}");
        ASSERT_EQUALS("", errout_str());

        checkUninitVar("void foo()\n"
                       "{\n"
                       "    int x = xyz::x;\n"
                       "}");
        ASSERT_EQUALS("", errout_str());

        checkUninitVar("void f()\n"
                       "{\n"
                       "    int a;\n"
                       "    a = 5 + a;\n"
                       "}");
        ASSERT_EQUALS("[test.cpp:4:13]: (error) Uninitialized variable: a [legacyUninitvar]\n", errout_str());

        checkUninitVar("void f()\n"
                       "{\n"
                       "    int a;\n"
                       "    a++;\n"
                       "}");
        ASSERT_EQUALS("[test.cpp:4:5]: (error) Uninitialized variable: a [legacyUninitvar]\n", errout_str());

        checkUninitVar("void f()\n"
                       "{\n"
                       "    extern int a;\n"
                       "    a++;\n"
                       "}");
        ASSERT_EQUALS("", errout_str());

        // extracttests.start: void bar(int);
        checkUninitVar("void f()\n"
                       "{\n"
                       "    int a;\n"
                       "    bar(4 * a);\n"
                       "}");
        ASSERT_EQUALS("[test.cpp:4:13]: (error) Uninitialized variable: a [legacyUninitvar]\n", errout_str());

        checkUninitVar("static void foo()\n"
                       "{\n"
                       "    int i;\n"
                       "    if (i);\n"
                       "}");
        ASSERT_EQUALS("[test.cpp:4:9]: (error) Uninitialized variable: i [legacyUninitvar]\n", errout_str());

        checkUninitVar("static void foo()\n"
                       "{\n"
                       "    int i;\n"
                       "    for (int x = 0; i < 10; x++);\n"
                       "}");
        ASSERT_EQUALS("[test.cpp:4:21]: (error) Uninitialized variable: i [legacyUninitvar]\n", errout_str());

        checkUninitVar("static void foo()\n"
                       "{\n"
                       "    int i;\n"
                       "    for (int x = 0; x < 10; i++);\n"
                       "}");
        ASSERT_EQUALS("[test.cpp:4:29]: (error) Uninitialized variable: i [legacyUninitvar]\n", errout_str());

        checkUninitVar("static void foo(int x)\n"
                       "{\n"
                       "    int i;\n"
                       "    if (x)\n"
                       "        i = 0;\n"
                       "    i++;\n"
                       "}");
        ASSERT_EQUALS("[test.cpp:6:5]: (error) Uninitialized variable: i [legacyUninitvar]\n", errout_str());

        checkUninitVar("static void foo()\n"
                       "{\n"
                       "    int ar[10];\n"
                       "    int i;\n"
                       "    ar[i] = 0;\n"
                       "}");
        ASSERT_EQUALS("[test.cpp:5:8]: (error) Uninitialized variable: i [legacyUninitvar]\n", errout_str());

        checkUninitVar("static void foo()\n"
                       "{\n"
                       "    int x, y;\n"
                       "    x = (y = 10);\n"
                       "    int z = y * 2;\n"
                       "}");
        ASSERT_EQUALS("", errout_str());

        checkUninitVar("static void foo() {\n"
                       "    int x, y;\n"
                       "    x = ((y) = 10);\n"
                       "}");
        ASSERT_EQUALS("", errout_str());

        // Ticket #3597
        checkUninitVar("void f() {\n"
                       "    int a;\n"
                       "    int b = 1;\n"
                       "    (b += a) = 1;\n"
                       "}");
        ASSERT_EQUALS("[test.cpp:4:11]: (error) Uninitialized variable: a [legacyUninitvar]\n", errout_str());

        checkUninitVar("int f() {\n"
                       "    int a,b,c;\n"
                       "    a = b = c;\n"
                       "}");
        ASSERT_EQUALS("[test.cpp:3:0]: (error) Uninitialized variable: c [legacyUninitvar]\n", errout_str());

        checkUninitVar("static void foo()\n"
                       "{\n"
                       "    Foo p;\n"
                       "    p.abcd();\n"
                       "}");
        ASSERT_EQUALS("", errout_str());

        checkUninitVar("static void foo()\n"
                       "{\n"
                       "    Foo p;\n"
                       "    int x = p.abcd();\n"
                       "}");
        ASSERT_EQUALS("", errout_str());

        // Unknown types
        // extracttests.disable
        {
            checkUninitVar("void a()\n"
                           "{\n"
                           "    A ret;\n"
                           "    return ret;\n"
                           "}");
            ASSERT_EQUALS("", errout_str());

            checkUninitVar("void a()\n"
                           "{\n"
                           "    A ret;\n"
                           "    return ret;\n"
                           "}\n",
                           dinit(CheckUninitVarOptions, $.cpp = false));
            ASSERT_EQUALS("[test.c:4:12]: (error) Uninitialized variable: ret [legacyUninitvar]\n", errout_str());
        }
        // extracttests.enable

        // #3916 - avoid false positive
        checkUninitVar("void f(float x) {\n"
                       "  union lf { long l; float f; } u_lf;\n"
                       "  float hx = (u_lf.f = (x), u_lf.l);\n"
                       "}",
                       dinit(CheckUninitVarOptions, $.cpp = false));
        ASSERT_EQUALS("", errout_str());

        checkUninitVar("void a()\n"
                       "{\n"
                       "    int x[10];\n"
                       "    int *y = x;\n"
                       "}");
        ASSERT_EQUALS("", errout_str());

        checkUninitVar("void a()\n"
                       "{\n"
                       "    int x;\n"
                       "    int *y = &x;\n"
                       "    *y = 0;\n"
                       "    x++;\n"
                       "}");
        ASSERT_EQUALS("", errout_str());

        checkUninitVar("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 

Web Proxy Viewer  |  New URL  |  Original Page