feat: add modulo of one check (#9528) (#2650)

This commit is contained in:
miltolstoy 2020-05-21 00:01:32 +03:00 committed by GitHub
parent 9a5e53032d
commit a9d8b3495d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 45 additions and 1 deletions

View File

@ -3105,3 +3105,25 @@ void CheckOther::comparePointersError(const Token *tok, const ValueFlow::Value *
reportError( reportError(
errorPath, Severity::error, "comparePointers", verb + " pointers that point to different objects", CWE570, false); errorPath, Severity::error, "comparePointers", verb + " pointers that point to different objects", CWE570, false);
} }
void CheckOther::checkModuloOfOne()
{
for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) {
if (!tok->astOperand2() || !tok->astOperand1())
continue;
if (tok->str() != "%")
continue;
if (!tok->valueType() || !tok->valueType()->isIntegral())
continue;
// Value flow..
const ValueFlow::Value *value = tok->astOperand2()->getValue(1LL);
if (value && value->isKnown())
checkModuloOfOneError(tok);
}
}
void CheckOther::checkModuloOfOneError(const Token *tok)
{
reportError(tok, Severity::style, "moduloofone", "Modulo of one is always equal to zero");
}

View File

@ -100,6 +100,7 @@ public:
checkOther.checkCastIntToCharAndBack(); checkOther.checkCastIntToCharAndBack();
checkOther.checkMisusedScopedObject(); checkOther.checkMisusedScopedObject();
checkOther.checkAccessOfMovedVariable(); checkOther.checkAccessOfMovedVariable();
checkOther.checkModuloOfOne();
} }
/** @brief Clarify calculation for ".. a * b ? .." */ /** @brief Clarify calculation for ".. a * b ? .." */
@ -215,6 +216,8 @@ public:
void checkComparePointers(); void checkComparePointers();
void checkModuloOfOne();
private: private:
// Error messages.. // Error messages..
void checkComparisonFunctionIsAlwaysTrueOrFalseError(const Token* tok, const std::string &functionName, const std::string &varName, const bool result); void checkComparisonFunctionIsAlwaysTrueOrFalseError(const Token* tok, const std::string &functionName, const std::string &varName, const bool result);
@ -271,6 +274,7 @@ private:
void shadowError(const Token *var, const Token *shadowed, std::string type); void shadowError(const Token *var, const Token *shadowed, std::string type);
void knownArgumentError(const Token *tok, const Token *ftok, const ValueFlow::Value *value); void knownArgumentError(const Token *tok, const Token *ftok, const ValueFlow::Value *value);
void comparePointersError(const Token *tok, const ValueFlow::Value *v1, const ValueFlow::Value *v2); void comparePointersError(const Token *tok, const ValueFlow::Value *v1, const ValueFlow::Value *v2);
void checkModuloOfOneError(const Token *tok);
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const OVERRIDE { void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const OVERRIDE {
CheckOther c(nullptr, settings, errorLogger); CheckOther c(nullptr, settings, errorLogger);
@ -342,6 +346,7 @@ private:
const std::vector<const Token *> nullvec; const std::vector<const Token *> nullvec;
c.funcArgOrderDifferent("function", nullptr, nullptr, nullvec, nullvec); c.funcArgOrderDifferent("function", nullptr, nullptr, nullvec, nullvec);
c.checkModuloOfOneError(nullptr);
} }
static std::string myName() { static std::string myName() {
@ -402,7 +407,8 @@ private:
"- function declaration and definition argument names different.\n" "- function declaration and definition argument names different.\n"
"- function declaration and definition argument order different.\n" "- function declaration and definition argument order different.\n"
"- shadow variable.\n" "- shadow variable.\n"
"- variable can be declared const.\n"; "- variable can be declared const.\n"
"- calculating modulo of one.\n";
} }
}; };
/// @} /// @}

View File

@ -239,6 +239,8 @@ private:
TEST_CASE(checkComparePointers); TEST_CASE(checkComparePointers);
TEST_CASE(unusedVariableValueTemplate); // #8994 TEST_CASE(unusedVariableValueTemplate); // #8994
TEST_CASE(moduloOfOne);
} }
void check(const char code[], const char *filename = nullptr, bool experimental = false, bool inconclusive = true, bool runSimpleChecks=true, bool verbose=false, Settings* settings = nullptr) { void check(const char code[], const char *filename = nullptr, bool experimental = false, bool inconclusive = true, bool runSimpleChecks=true, bool verbose=false, Settings* settings = nullptr) {
@ -8565,6 +8567,20 @@ private:
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void moduloOfOne() {
check("void f(unsigned int x) {\n"
" int y = x % 1;\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (style) Modulo of one is always equal to zero\n", errout.str());
check("void f() {\n"
" for (int x = 1; x < 10; x++) {\n"
" int y = 100 % x;\n"
" }\n"
"}");
ASSERT_EQUALS("", errout.str());
}
}; };
REGISTER_TEST(TestOther) REGISTER_TEST(TestOther)