Skip to content

Commit 7280255

Browse files
committed
Fixed cppcheck-opensource#3593 (New Check: Check for assignment within conditional expression)
1 parent 21b1987 commit 7280255

3 files changed

Lines changed: 61 additions & 1 deletion

File tree

lib/checkcondition.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1698,3 +1698,46 @@ void CheckCondition::duplicateConditionalAssignError(const Token *condTok, const
16981698
reportError(
16991699
errors, Severity::style, "duplicateConditionalAssign", msg, CWE398, Certainty::normal);
17001700
}
1701+
1702+
1703+
void CheckCondition::checkAssignmentInCondition()
1704+
{
1705+
if (!mSettings->severity.isEnabled(Severity::style))
1706+
return;
1707+
1708+
const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase();
1709+
for (const Scope * scope : symbolDatabase->functionScopes) {
1710+
for (const Token* tok = scope->bodyStart; tok != scope->bodyEnd; tok = tok->next()) {
1711+
if (tok->str() != "=")
1712+
continue;
1713+
if (!tok->astParent())
1714+
continue;
1715+
1716+
// Is this assignment of container/iterator?
1717+
if (!tok->valueType())
1718+
continue;
1719+
if (tok->valueType()->type != ValueType::Type::CONTAINER && tok->valueType()->type != ValueType::Type::ITERATOR)
1720+
continue;
1721+
1722+
// warn if this is a conditional expression..
1723+
if (Token::Match(tok->astParent()->previous(), "if|while ("))
1724+
assignmentInCondition(tok);
1725+
else if (Token::Match(tok->astParent(), "%oror%|&&"))
1726+
assignmentInCondition(tok);
1727+
else if (Token::simpleMatch(tok->astParent(), "?") && tok == tok->astParent()->astOperand1())
1728+
assignmentInCondition(tok);
1729+
}
1730+
}
1731+
}
1732+
1733+
void CheckCondition::assignmentInCondition(const Token *eq)
1734+
{
1735+
reportError(
1736+
eq,
1737+
Severity::style,
1738+
"assignmentInCondition",
1739+
"Assignment in condition should probably be comparison.",
1740+
CWE571,
1741+
Certainty::normal);
1742+
}
1743+

lib/checkcondition.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ class CPPCHECKLIB CheckCondition : public Check {
7070
checkCondition.checkBadBitmaskCheck();
7171
checkCondition.comparison();
7272
checkCondition.checkModuloAlwaysTrueFalse();
73+
checkCondition.checkAssignmentInCondition();
7374
}
7475

7576
/** mismatching assignment / comparison */
@@ -122,6 +123,9 @@ class CPPCHECKLIB CheckCondition : public Check {
122123

123124
void checkDuplicateConditionalAssign();
124125

126+
/** @brief Assignment in condition */
127+
void checkAssignmentInCondition();
128+
125129
private:
126130
// The conditions that have been diagnosed
127131
std::set<const Token*> mCondDiags;
@@ -161,6 +165,8 @@ class CPPCHECKLIB CheckCondition : public Check {
161165

162166
void duplicateConditionalAssignError(const Token *condTok, const Token* assignTok);
163167

168+
void assignmentInCondition(const Token *eq);
169+
164170
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const OVERRIDE {
165171
CheckCondition c(nullptr, settings, errorLogger);
166172

@@ -183,6 +189,7 @@ class CPPCHECKLIB CheckCondition : public Check {
183189
c.invalidTestForOverflow(nullptr, nullptr, "false");
184190
c.pointerAdditionResultNotNullError(nullptr, nullptr);
185191
c.duplicateConditionalAssignError(nullptr, nullptr);
192+
c.assignmentInCondition(nullptr);
186193
}
187194

188195
static std::string myName() {
@@ -203,7 +210,8 @@ class CPPCHECKLIB CheckCondition : public Check {
203210
"- Mutual exclusion over || always evaluating to true\n"
204211
"- Comparisons of modulo results that are always true/false.\n"
205212
"- Known variable values => condition is always true/false\n"
206-
"- Invalid test for overflow. Some mainstream compilers remove such overflow tests when optimising code.\n";
213+
"- Invalid test for overflow. Some mainstream compilers remove such overflow tests when optimising code.\n"
214+
"- Assignment of container/iterator in condition should probably be comparison.\n";
207215
}
208216
};
209217
/// @}

test/testcondition.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ class TestCondition : public TestFixture {
120120
TEST_CASE(alwaysTrueFalseInLogicalOperators);
121121
TEST_CASE(pointerAdditionResultNotNull);
122122
TEST_CASE(duplicateConditionalAssign);
123+
124+
TEST_CASE(checkAssignmentInCondition);
123125
}
124126

125127
void check(const char code[], const char* filename = "test.cpp", bool inconclusive = false) {
@@ -4153,6 +4155,13 @@ class TestCondition : public TestFixture {
41534155
"}");
41544156
ASSERT_EQUALS("", errout.str());
41554157
}
4158+
4159+
void checkAssignmentInCondition() {
4160+
check("void f(std::string s) {\n"
4161+
" if (s=\"123\"){}\n"
4162+
"}");
4163+
ASSERT_EQUALS("[test.cpp:2]: (style) Assignment in condition should probably be comparison.\n", errout.str());
4164+
}
41564165
};
41574166

41584167
REGISTER_TEST(TestCondition)

0 commit comments

Comments
 (0)