Fixed #5126 (new check: missing pointer dereference or pointer overflow 'if (p+1)')
This commit is contained in:
parent
661784a170
commit
a3dd65caee
|
@ -509,3 +509,47 @@ void CheckBool::comparisonOfBoolExpressionWithIntError(const Token *tok, bool n0
|
||||||
reportError(tok, Severity::warning, "compareBoolExpressionWithInt",
|
reportError(tok, Severity::warning, "compareBoolExpressionWithInt",
|
||||||
"Comparison of a boolean expression with an integer.");
|
"Comparison of a boolean expression with an integer.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CheckBool::pointerArithBool()
|
||||||
|
{
|
||||||
|
const SymbolDatabase* symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||||
|
|
||||||
|
const std::size_t functions = symbolDatabase->functionScopes.size();
|
||||||
|
for (std::size_t i = 0; i < functions; ++i) {
|
||||||
|
const Scope * scope = symbolDatabase->functionScopes[i];
|
||||||
|
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
|
||||||
|
if (Token::Match(tok, "if|while (")) {
|
||||||
|
pointerArithBoolCond(tok->next()->astOperand2());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckBool::pointerArithBoolCond(const Token *tok)
|
||||||
|
{
|
||||||
|
if (!tok)
|
||||||
|
return;
|
||||||
|
if (Token::Match(tok, "&&|%oror%")) {
|
||||||
|
pointerArithBoolCond(tok->astOperand1());
|
||||||
|
pointerArithBoolCond(tok->astOperand2());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (tok->str() != "+")
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (tok->astOperand1() &&
|
||||||
|
tok->astOperand1()->isName() &&
|
||||||
|
tok->astOperand1()->variable() &&
|
||||||
|
tok->astOperand1()->variable()->isPointer() &&
|
||||||
|
tok->astOperand2()->isNumber())
|
||||||
|
pointerArithBoolError(tok);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckBool::pointerArithBoolError(const Token *tok)
|
||||||
|
{
|
||||||
|
reportError(tok,
|
||||||
|
Severity::error,
|
||||||
|
"pointerArithBool",
|
||||||
|
"Converting pointer arithmetic result to bool. Either a dereference is forgot, or pointer overflow is required to get a false value");
|
||||||
|
}
|
||||||
|
|
|
@ -54,6 +54,7 @@ public:
|
||||||
// Checks
|
// Checks
|
||||||
checkBool.checkComparisonOfBoolExpressionWithInt();
|
checkBool.checkComparisonOfBoolExpressionWithInt();
|
||||||
checkBool.checkComparisonOfBoolWithInt();
|
checkBool.checkComparisonOfBoolWithInt();
|
||||||
|
checkBool.pointerArithBool();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @brief Run checks against the simplified token list */
|
/** @brief Run checks against the simplified token list */
|
||||||
|
@ -89,6 +90,10 @@ public:
|
||||||
/** @brief %Check for comparing a bool expression with an integer other than 0 or 1 */
|
/** @brief %Check for comparing a bool expression with an integer other than 0 or 1 */
|
||||||
void checkComparisonOfBoolExpressionWithInt();
|
void checkComparisonOfBoolExpressionWithInt();
|
||||||
|
|
||||||
|
/** @brief %Check for 'if (p+1)' etc. either somebody forgot to dereference, or else somebody uses pointer overflow */
|
||||||
|
void pointerArithBool();
|
||||||
|
void pointerArithBoolCond(const Token *tok);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Error messages..
|
// Error messages..
|
||||||
void comparisonOfFuncReturningBoolError(const Token *tok, const std::string &expression);
|
void comparisonOfFuncReturningBoolError(const Token *tok, const std::string &expression);
|
||||||
|
@ -100,6 +105,7 @@ private:
|
||||||
void assignBoolToPointerError(const Token *tok);
|
void assignBoolToPointerError(const Token *tok);
|
||||||
void bitwiseOnBooleanError(const Token *tok, const std::string &varname, const std::string &op);
|
void bitwiseOnBooleanError(const Token *tok, const std::string &varname, const std::string &op);
|
||||||
void comparisonOfBoolExpressionWithIntError(const Token *tok, bool n0o1);
|
void comparisonOfBoolExpressionWithIntError(const Token *tok, bool n0o1);
|
||||||
|
void pointerArithBoolError(const Token *tok);
|
||||||
|
|
||||||
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const {
|
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const {
|
||||||
CheckBool c(0, settings, errorLogger);
|
CheckBool c(0, settings, errorLogger);
|
||||||
|
@ -112,6 +118,7 @@ private:
|
||||||
c.comparisonOfBoolWithIntError(0, "varname", true);
|
c.comparisonOfBoolWithIntError(0, "varname", true);
|
||||||
c.bitwiseOnBooleanError(0, "varname", "&&");
|
c.bitwiseOnBooleanError(0, "varname", "&&");
|
||||||
c.comparisonOfBoolExpressionWithIntError(0, true);
|
c.comparisonOfBoolExpressionWithIntError(0, true);
|
||||||
|
c.pointerArithBoolError(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string myName() {
|
static std::string myName() {
|
||||||
|
@ -126,7 +133,8 @@ private:
|
||||||
"* comparison of a boolean expression with an integer other than 0 or 1\n"
|
"* comparison of a boolean expression with an integer other than 0 or 1\n"
|
||||||
"* comparison of a function returning boolean value using relational operator\n"
|
"* comparison of a function returning boolean value using relational operator\n"
|
||||||
"* comparison of a boolean value with boolean value using relational operator\n"
|
"* comparison of a boolean value with boolean value using relational operator\n"
|
||||||
"* using bool in bitwise expression\n";
|
"* using bool in bitwise expression\n"
|
||||||
|
"* pointer addition in condition (either dereference is forgot or pointer overflow is required to make the condition false)\n";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
/// @}
|
/// @}
|
||||||
|
|
|
@ -56,6 +56,9 @@ private:
|
||||||
TEST_CASE(checkComparisonOfFuncReturningBool4);
|
TEST_CASE(checkComparisonOfFuncReturningBool4);
|
||||||
TEST_CASE(checkComparisonOfFuncReturningBool5);
|
TEST_CASE(checkComparisonOfFuncReturningBool5);
|
||||||
TEST_CASE(checkComparisonOfFuncReturningBool6);
|
TEST_CASE(checkComparisonOfFuncReturningBool6);
|
||||||
|
|
||||||
|
// Converting pointer addition result to bool
|
||||||
|
TEST_CASE(pointerArithBool1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void check(const char code[], bool experimental = false, const char filename[] = "test.cpp") {
|
void check(const char code[], bool experimental = false, const char filename[] = "test.cpp") {
|
||||||
|
@ -869,6 +872,18 @@ private:
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pointerArithBool1() { // #5126
|
||||||
|
check("void f(char *p) {\n"
|
||||||
|
" if (p+1){}\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (error) Converting pointer arithmetic result to bool. Either a dereference is forgot, or pointer overflow is required to get a false value\n", errout.str());
|
||||||
|
|
||||||
|
check("void f(char *p) {\n"
|
||||||
|
" if (p && p+1){}\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (error) Converting pointer arithmetic result to bool. Either a dereference is forgot, or pointer overflow is required to get a false value\n", errout.str());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
REGISTER_TEST(TestBool)
|
REGISTER_TEST(TestBool)
|
||||||
|
|
Loading…
Reference in New Issue