diff --git a/lib/checkuninitvar.cpp b/lib/checkuninitvar.cpp index d05ea3fbd28..446a645c341 100644 --- a/lib/checkuninitvar.cpp +++ b/lib/checkuninitvar.cpp @@ -834,7 +834,7 @@ bool CheckUninitVarImpl::checkScopeForVariable(const Token *tok, const Variable& } } } - if (Token::simpleMatch(parent->astParent(), "=") && astIsLHS(parent)) { + if (parent->astParent() && parent->astParent()->isAssignmentOp() && astIsLHS(parent)) { const Token *eq = parent->astParent(); if (const Token *errorToken = checkExpr(eq->astOperand2(), var, *alloc, number_of_if==0)) { if (!suppressErrors) @@ -1295,6 +1295,19 @@ const Token* CheckUninitVarImpl::isVariableUsage(const Token *vartok, const Libr } if (alloc != NO_ALLOC && astIsRhs(valueExpr)) return nullptr; + } else if (tok->astParent() && (tok->astParent()->isAssignmentOp() || tok->astParent()->isIncDecOp())) { + // NO_ALLOC -> no matter what we read the uninitialized memory. + // pointer/array -> safe, as long as we don't dereference + bool isPtr = pointer; + bool isArr = alloc == ARRAY; + // "pointer" and "alloc" get set for non-ptr non-array var + if (vartok && vartok->variable()) { + isPtr = vartok->variable()->isPointer(); + isArr = vartok->variable()->isArray(); + } + if ((alloc != NO_ALLOC) && ((isPtr || isArr) && !derefValue)) { + return nullptr; + } } } diff --git a/test/testuninitvar.cpp b/test/testuninitvar.cpp index 1874e020fa8..8c17316c9e2 100644 --- a/test/testuninitvar.cpp +++ b/test/testuninitvar.cpp @@ -2202,6 +2202,37 @@ class TestUninitVar : public TestFixture { " return i;\n" "}\n"); ASSERT_EQUALS("", errout_str()); + + + checkUninitVar("void f() {\n" + " char *p = new char;\n" + " p += 1;\n" + " delete (p - 1);\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); + + checkUninitVar("void f() {\n" + " char *buf = (char *)malloc(1);\n" + " if (!buf)\n" + " return NULL;\n" + " buf += buf[0];\n" + " free(buf);\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:5:15]: (error) Memory is allocated but not initialized: buf[0] [uninitdata]\n", errout_str()); + + checkUninitVar("void g() {\n" + " int* p = new int;\n" + " p++;\n" + " delete (p - 1);\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); + + checkUninitVar("void g() {\n" + " int* p = new int;\n" + " ++p; // FP\n" + " delete (p - 1);\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); } // class / struct..