Fix #11082 FN badBitmaskCheck for binary or with 0 (#4170)

* Fix #11082 FN badBitmaskCheck for binary or with 0

* Add test for #10703
This commit is contained in:
chrchr-github 2022-06-04 17:25:10 +02:00 committed by GitHub
parent 412054e83a
commit f962436826
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 28 additions and 3 deletions

View File

@ -310,13 +310,22 @@ void CheckCondition::checkBadBitmaskCheck()
if (isBoolean && isTrue) if (isBoolean && isTrue)
badBitmaskCheckError(tok); badBitmaskCheckError(tok);
const bool isNoOp = (tok->astOperand1()->hasKnownIntValue() && tok->astOperand1()->values().front().intvalue == 0) ||
(tok->astOperand2()->hasKnownIntValue() && tok->astOperand2()->values().front().intvalue == 0);
if (isNoOp)
badBitmaskCheckError(tok, isNoOp);
} }
} }
} }
void CheckCondition::badBitmaskCheckError(const Token *tok) void CheckCondition::badBitmaskCheckError(const Token *tok, bool isNoOp)
{ {
reportError(tok, Severity::warning, "badBitmaskCheck", "Result of operator '|' is always true if one operand is non-zero. Did you intend to use '&'?", CWE571, Certainty::normal); if (isNoOp)
reportError(tok, Severity::warning, "badBitmaskCheck", "Operator '|' with one operand equal to zero is redundant.", CWE571, Certainty::normal);
else
reportError(tok, Severity::warning, "badBitmaskCheck", "Result of operator '|' is always true if one operand is non-zero. Did you intend to use '&'?", CWE571, Certainty::normal);
} }
void CheckCondition::comparison() void CheckCondition::comparison()

View File

@ -136,7 +136,7 @@ private:
bool isOverlappingCond(const Token * const cond1, const Token * const cond2, bool pure) const; bool isOverlappingCond(const Token * const cond1, const Token * const cond2, bool pure) const;
void assignIfError(const Token *tok1, const Token *tok2, const std::string &condition, bool result); void assignIfError(const Token *tok1, const Token *tok2, const std::string &condition, bool result);
void mismatchingBitAndError(const Token *tok1, const MathLib::bigint num1, const Token *tok2, const MathLib::bigint num2); void mismatchingBitAndError(const Token *tok1, const MathLib::bigint num1, const Token *tok2, const MathLib::bigint num2);
void badBitmaskCheckError(const Token *tok); void badBitmaskCheckError(const Token *tok, bool isNoOp = false);
void comparisonError(const Token *tok, void comparisonError(const Token *tok,
const std::string &bitop, const std::string &bitop,
MathLib::bigint value1, MathLib::bigint value1,

View File

@ -887,6 +887,12 @@ private:
" }\n" " }\n"
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
check("void f(int i) {\n" // #11082
" int j = 0;\n"
" if (i | j) {}\n"
"}\n");
ASSERT_EQUALS("[test.cpp:3]: (warning) Operator '|' with one operand equal to zero is redundant.\n", errout.str());
} }

View File

@ -5918,6 +5918,16 @@ private:
" g();\n" " g();\n"
"}\n"); "}\n");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
functionVariableUsage("int f(int *p) {\n" // #10703
" std::unique_ptr<int> up(p);\n"
" return *p;\n"
"}\n"
"int g(int* p) {\n"
" auto up = std::unique_ptr<int>(p);\n"
" return *p;\n"
"}\n");
ASSERT_EQUALS("", errout.str());
} }
// ticket #3104 - false positive when variable is read with "if (NOT var)" // ticket #3104 - false positive when variable is read with "if (NOT var)"