Fix #11776 (False positive: uninitialized variable, struct array member initialized in function) (#5165)

This commit is contained in:
Daniel Marjamäki 2023-06-17 10:20:20 +02:00 committed by GitHub
parent 58dd92dd1b
commit 9a290c959f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 49 additions and 7 deletions

View File

@ -3105,6 +3105,10 @@ static ExprUsage getFunctionUsage(const Token* tok, int indirect, const Settings
}
if (!args.empty() && indirect == 0 && !addressOf)
return ExprUsage::Used;
} else if (ftok->isControlFlowKeyword()) {
return ExprUsage::Used;
} else if (ftok->str() == "{") {
return ExprUsage::Used;
} else {
const bool isnullbad = settings->library.isnullargbad(ftok, argnr + 1);
if (indirect == 0 && astIsPointer(tok) && !addressOf && isnullbad)

View File

@ -1621,6 +1621,8 @@ void CheckUninitVar::valueFlowUninit()
if (tok->variable()) {
bool unknown;
const bool isarray = tok->variable()->isArray();
if (isarray && tok->variable()->isMember())
continue; // Todo: this is a bailout
const bool ispointer = astIsPointer(tok) && !isarray;
const bool deref = CheckNullPointer::isPointerDeRef(tok, unknown, mSettings);
if (ispointer && v->indirect == 1 && !deref)
@ -1633,7 +1635,7 @@ void CheckUninitVar::valueFlowUninit()
continue;
}
const ExprUsage usage = getExprUsage(tok, v->indirect, mSettings);
if (usage == ExprUsage::NotUsed)
if (usage == ExprUsage::NotUsed || usage == ExprUsage::Inconclusive)
continue;
if (!v->subexpressions.empty() && usage == ExprUsage::PassedByReference)
continue;

View File

@ -1261,7 +1261,7 @@ void timet_h(struct timespec* ptp1)
clock_settime(clk_id2, ptp1);
struct timespec tp;
// cppcheck-suppress uninitvar
// FIXME cppcheck-suppress uninitvar
clock_settime(CLOCK_REALTIME, &tp); // #6577 - false negative
// cppcheck-suppress uninitvar
clock_settime(clk_id3, &tp);

View File

@ -5268,7 +5268,7 @@ private:
" s.x = 42;\n"
" bar(&s);\n"
"}");
ASSERT_EQUALS("[test.cpp:18]: (error) Uninitialized variable: &s.flag\n", errout.str());
ASSERT_EQUALS("[test.cpp:18] -> [test.cpp:12] -> [test.cpp:8]: (warning) Uninitialized variable: s->flag\n", errout.str());
// Ticket #2207 - False negative
valueFlowUninit("void foo() {\n"
@ -6136,7 +6136,7 @@ private:
" someType_t gVar;\n"
" bar(&gVar);\n"
"}");
ASSERT_EQUALS("[test.cpp:9]: (error) Uninitialized variable: &gVar\n", errout.str());
ASSERT_EQUALS("[test.cpp:9] -> [test.cpp:5]: (warning) Uninitialized variable: p->flags\n", errout.str());
valueFlowUninit("typedef struct\n"
"{\n"
@ -6146,7 +6146,8 @@ private:
" someType_t gVar;\n"
" if(gVar.flags[1] == 42){}\n"
"}");
ASSERT_EQUALS("[test.cpp:7]: (error) Uninitialized variable: gVar.flags\n", errout.str());
// TODO : find bugs for member arrays
TODO_ASSERT_EQUALS("[test.cpp:7]: (error) Uninitialized variable: gVar.flags\n", "", errout.str());
valueFlowUninit("void foo() {\n" // #10293
" union {\n"
@ -6667,7 +6668,7 @@ private:
" foo(123, &abc);\n"
" return abc.b;\n"
"}");
ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: &abc\n", errout.str());
ASSERT_EQUALS("[test.cpp:6]: (error) Uninitialized variable: abc.b\n", errout.str());
valueFlowUninit("struct ABC { int a; int b; int c; };\n"
"void foo() {\n"
@ -6899,7 +6900,7 @@ private:
" abc.a = 1;\n"
" setabc(123, &abc);\n"
"}\n");
ASSERT_EQUALS("[test.cpp:8]: (error) Uninitialized variables: &abc.b, &abc.c\n", errout.str());
ASSERT_EQUALS("[test.cpp:8] -> [test.cpp:3]: (warning) Uninitialized variable: abc->b\n", errout.str());
valueFlowUninit("struct S { int* p; };\n" // #10463
"void f(S* in) {\n"
@ -6942,6 +6943,41 @@ private:
" if (f < s.offset + sizeof(s)) {}\n"
"}\n");
ASSERT_EQUALS("", errout.str());
// #11776 - function call initialises struct array member
valueFlowUninit("typedef struct {\n"
" int arr[1];\n"
" int count;\n"
"} arr_struct;\n"
"\n"
"void init(int *a, int b);\n"
"\n"
"void foo(arr_struct const *var);\n" // <- inconclusive if var->count is used
"\n"
"void uninitvar_FP7() {\n"
" arr_struct my_st;\n"
" init(my_st.arr, 12);\n" // <- assume that my_st.arr is written
" foo(&my_st);\n"
"}\n");
ASSERT_EQUALS("", errout.str());
valueFlowUninit("typedef struct {\n"
" int arr[1];\n"
" int count;\n"
"} arr_struct;\n"
"\n"
"void init(int *a, int b);\n"
"\n"
"void foo(arr_struct const *var) {\n"
" x = var->arr[0];\n"
"}\n"
"\n"
"void uninitvar_FP7() {\n"
" arr_struct my_st;\n"
" init(my_st.arr, 12);\n" // <- assume that my_st.arr is written
" foo(&my_st);\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}
void uninitvar_memberfunction() {