Fix #11776 (False positive: uninitialized variable, struct array member initialized in function) (#5165)
This commit is contained in:
parent
58dd92dd1b
commit
9a290c959f
|
@ -3105,6 +3105,10 @@ static ExprUsage getFunctionUsage(const Token* tok, int indirect, const Settings
|
||||||
}
|
}
|
||||||
if (!args.empty() && indirect == 0 && !addressOf)
|
if (!args.empty() && indirect == 0 && !addressOf)
|
||||||
return ExprUsage::Used;
|
return ExprUsage::Used;
|
||||||
|
} else if (ftok->isControlFlowKeyword()) {
|
||||||
|
return ExprUsage::Used;
|
||||||
|
} else if (ftok->str() == "{") {
|
||||||
|
return ExprUsage::Used;
|
||||||
} else {
|
} else {
|
||||||
const bool isnullbad = settings->library.isnullargbad(ftok, argnr + 1);
|
const bool isnullbad = settings->library.isnullargbad(ftok, argnr + 1);
|
||||||
if (indirect == 0 && astIsPointer(tok) && !addressOf && isnullbad)
|
if (indirect == 0 && astIsPointer(tok) && !addressOf && isnullbad)
|
||||||
|
|
|
@ -1621,6 +1621,8 @@ void CheckUninitVar::valueFlowUninit()
|
||||||
if (tok->variable()) {
|
if (tok->variable()) {
|
||||||
bool unknown;
|
bool unknown;
|
||||||
const bool isarray = tok->variable()->isArray();
|
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 ispointer = astIsPointer(tok) && !isarray;
|
||||||
const bool deref = CheckNullPointer::isPointerDeRef(tok, unknown, mSettings);
|
const bool deref = CheckNullPointer::isPointerDeRef(tok, unknown, mSettings);
|
||||||
if (ispointer && v->indirect == 1 && !deref)
|
if (ispointer && v->indirect == 1 && !deref)
|
||||||
|
@ -1633,7 +1635,7 @@ void CheckUninitVar::valueFlowUninit()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const ExprUsage usage = getExprUsage(tok, v->indirect, mSettings);
|
const ExprUsage usage = getExprUsage(tok, v->indirect, mSettings);
|
||||||
if (usage == ExprUsage::NotUsed)
|
if (usage == ExprUsage::NotUsed || usage == ExprUsage::Inconclusive)
|
||||||
continue;
|
continue;
|
||||||
if (!v->subexpressions.empty() && usage == ExprUsage::PassedByReference)
|
if (!v->subexpressions.empty() && usage == ExprUsage::PassedByReference)
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -1261,7 +1261,7 @@ void timet_h(struct timespec* ptp1)
|
||||||
clock_settime(clk_id2, ptp1);
|
clock_settime(clk_id2, ptp1);
|
||||||
|
|
||||||
struct timespec tp;
|
struct timespec tp;
|
||||||
// cppcheck-suppress uninitvar
|
// FIXME cppcheck-suppress uninitvar
|
||||||
clock_settime(CLOCK_REALTIME, &tp); // #6577 - false negative
|
clock_settime(CLOCK_REALTIME, &tp); // #6577 - false negative
|
||||||
// cppcheck-suppress uninitvar
|
// cppcheck-suppress uninitvar
|
||||||
clock_settime(clk_id3, &tp);
|
clock_settime(clk_id3, &tp);
|
||||||
|
|
|
@ -5268,7 +5268,7 @@ private:
|
||||||
" s.x = 42;\n"
|
" s.x = 42;\n"
|
||||||
" bar(&s);\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
|
// Ticket #2207 - False negative
|
||||||
valueFlowUninit("void foo() {\n"
|
valueFlowUninit("void foo() {\n"
|
||||||
|
@ -6136,7 +6136,7 @@ private:
|
||||||
" someType_t gVar;\n"
|
" someType_t gVar;\n"
|
||||||
" bar(&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"
|
valueFlowUninit("typedef struct\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
|
@ -6146,7 +6146,8 @@ private:
|
||||||
" someType_t gVar;\n"
|
" someType_t gVar;\n"
|
||||||
" if(gVar.flags[1] == 42){}\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
|
valueFlowUninit("void foo() {\n" // #10293
|
||||||
" union {\n"
|
" union {\n"
|
||||||
|
@ -6667,7 +6668,7 @@ private:
|
||||||
" foo(123, &abc);\n"
|
" foo(123, &abc);\n"
|
||||||
" return abc.b;\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"
|
valueFlowUninit("struct ABC { int a; int b; int c; };\n"
|
||||||
"void foo() {\n"
|
"void foo() {\n"
|
||||||
|
@ -6899,7 +6900,7 @@ private:
|
||||||
" abc.a = 1;\n"
|
" abc.a = 1;\n"
|
||||||
" setabc(123, &abc);\n"
|
" setabc(123, &abc);\n"
|
||||||
"}\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
|
valueFlowUninit("struct S { int* p; };\n" // #10463
|
||||||
"void f(S* in) {\n"
|
"void f(S* in) {\n"
|
||||||
|
@ -6942,6 +6943,41 @@ private:
|
||||||
" if (f < s.offset + sizeof(s)) {}\n"
|
" if (f < s.offset + sizeof(s)) {}\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("", errout.str());
|
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() {
|
void uninitvar_memberfunction() {
|
||||||
|
|
Loading…
Reference in New Issue