Skip to content

Commit 503c109

Browse files
Fix #11093, #12377 FP mismatchingContainerIterator (#5911)
…r to get reference to container
1 parent 272028c commit 503c109

2 files changed

Lines changed: 69 additions & 6 deletions

File tree

lib/checkstl.cpp

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -686,11 +686,19 @@ void CheckStl::sameIteratorExpressionError(const Token *tok)
686686
reportError(tok, Severity::style, "sameIteratorExpression", "Same iterators expression are used for algorithm.", CWE664, Certainty::normal);
687687
}
688688

689-
static const Token* getAddressContainer(const Token* tok)
689+
static std::vector<const Token*> getAddressContainer(const Token* tok)
690690
{
691691
if (Token::simpleMatch(tok, "[") && tok->astOperand1())
692-
return tok->astOperand1();
693-
return tok;
692+
return { tok->astOperand1() };
693+
std::vector<ValueFlow::Value> values = ValueFlow::getLifetimeObjValues(tok, /*inconclusive*/ false);
694+
std::vector<const Token*> res;
695+
for (const auto& v : values) {
696+
if (v.tokvalue)
697+
res.emplace_back(v.tokvalue);
698+
}
699+
if (res.empty())
700+
res.emplace_back(tok);
701+
return res;
694702
}
695703

696704
static bool isSameIteratorContainerExpression(const Token* tok1,
@@ -701,10 +709,18 @@ static bool isSameIteratorContainerExpression(const Token* tok1,
701709
if (isSameExpression(true, false, tok1, tok2, library, false, false)) {
702710
return !astIsContainerOwned(tok1) || !isTemporary(true, tok1, &library);
703711
}
704-
if (kind == ValueFlow::Value::LifetimeKind::Address) {
705-
return isSameExpression(true, false, getAddressContainer(tok1), getAddressContainer(tok2), library, false, false);
712+
if (astContainerYield(tok2) == Library::Container::Yield::ITEM)
713+
return true;
714+
if (kind == ValueFlow::Value::LifetimeKind::Address || kind == ValueFlow::Value::LifetimeKind::Iterator) {
715+
const auto address1 = getAddressContainer(tok1);
716+
const auto address2 = getAddressContainer(tok2);
717+
return std::any_of(address1.begin(), address1.end(), [&](const Token* tok1) {
718+
return std::any_of(address2.begin(), address2.end(), [&](const Token* tok2) {
719+
return isSameExpression(true, false, tok1, tok2, library, false, false);
720+
});
721+
});
706722
}
707-
return astContainerYield(tok2) == Library::Container::Yield::ITEM;
723+
return false;
708724
}
709725

710726
static ValueFlow::Value getLifetimeIteratorValue(const Token* tok, MathLib::bigint path = 0)
@@ -866,6 +882,8 @@ void CheckStl::mismatchingContainerIterator()
866882
ValueFlow::Value val = getLifetimeIteratorValue(iterTok);
867883
if (!val.tokvalue)
868884
continue;
885+
if (!val.isKnown() && Token::simpleMatch(val.tokvalue->astParent(), ":"))
886+
continue;
869887
if (val.lifetimeKind != ValueFlow::Value::LifetimeKind::Iterator)
870888
continue;
871889
if (iterTok->str() == "*" && iterTok->astOperand1()->valueType() && iterTok->astOperand1()->valueType()->type == ValueType::ITERATOR)

test/teststl.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2134,6 +2134,51 @@ class TestStl : public TestFixture {
21342134
"}\n");
21352135
ASSERT_EQUALS("", errout.str());
21362136

2137+
// #11093
2138+
check("struct S {\n"
2139+
" std::vector<int> v1, v2;\n"
2140+
" void f(bool b) {\n"
2141+
" std::vector<int>& v = b ? v1 : v2;\n"
2142+
" v.erase(v.begin());\n"
2143+
" }\n"
2144+
"};\n");
2145+
ASSERT_EQUALS("", errout.str());
2146+
2147+
// #12377
2148+
check("void f(bool b) {\n"
2149+
" std::vector<int> *pv;\n"
2150+
" if (b) {\n"
2151+
" std::vector<int>& r = get1();\n"
2152+
" pv = &r;\n"
2153+
" }\n"
2154+
" else {\n"
2155+
" std::vector<int>& r = get2();\n"
2156+
" pv = &r;\n"
2157+
" }\n"
2158+
" std::vector<int>::iterator it = pv->begin();\n"
2159+
" it = pv->erase(it, it + 2);\n"
2160+
"}\n");
2161+
ASSERT_EQUALS("", errout.str());
2162+
2163+
check("struct S {\n"
2164+
" std::vector<int> v;\n"
2165+
" void f() {\n"
2166+
" std::vector<int>* p = &v;\n"
2167+
" p->insert(std::find(p->begin(), p->end(), 0), 1);\n"
2168+
" }\n"
2169+
"};\n");
2170+
ASSERT_EQUALS("", errout.str());
2171+
2172+
check("struct S {\n"
2173+
" std::vector<int> v;\n"
2174+
" void f(int i) {\n"
2175+
" std::vector<int>* p = &v;\n"
2176+
" if (p->size() > i)\n"
2177+
" p->erase(p->begin() + i, p->end());\n"
2178+
" }\n"
2179+
"};\n");
2180+
ASSERT_EQUALS("", errout.str());
2181+
21372182
// #11067
21382183
check("struct S {\n"
21392184
" std::vector<int> v;\n"

0 commit comments

Comments
 (0)