Fixed #2385 (False positive: array index out of bounds)
This commit is contained in:
parent
b04885cd4f
commit
ed6c76ce04
|
@ -186,6 +186,52 @@ private:
|
||||||
const std::string value;
|
const std::string value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* bailout if variable is used inside if/else/switch block or if there is "break"
|
||||||
|
* @param tok token for "if" or "switch"
|
||||||
|
* @param varid variable id
|
||||||
|
* @return is bailout recommended?
|
||||||
|
*/
|
||||||
|
static bool bailoutIfSwitch(const Token *tok, const unsigned int varid)
|
||||||
|
{
|
||||||
|
const std::string str1(tok->str());
|
||||||
|
|
||||||
|
unsigned int indentlevel = 0;
|
||||||
|
for (; tok; tok = tok->next())
|
||||||
|
{
|
||||||
|
if (tok->str() == "{")
|
||||||
|
indentlevel++;
|
||||||
|
else if (tok->str() == "}")
|
||||||
|
{
|
||||||
|
// scan the else-block
|
||||||
|
if (indentlevel == 1 && Token::simpleMatch(tok, "} else {"))
|
||||||
|
{
|
||||||
|
--indentlevel;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (indentlevel <= 1)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
--indentlevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If scanning a "if" block then bailout for "break"
|
||||||
|
else if (str1 == "if" && tok->str() == "break")
|
||||||
|
return true;
|
||||||
|
|
||||||
|
|
||||||
|
// bailout if varid is found
|
||||||
|
else if (tok->varId() == varid)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No bailout stuff found => return false
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse for loop initialization statement. Look for a counter variable
|
* Parse for loop initialization statement. Look for a counter variable
|
||||||
* \param tok [in] first token inside the parentheses
|
* \param tok [in] first token inside the parentheses
|
||||||
|
@ -407,32 +453,7 @@ void CheckBufferOverrun::parse_for_body(const Token *tok2, const ArrayInfo &arra
|
||||||
|
|
||||||
if (Token::Match(tok2, "if|switch"))
|
if (Token::Match(tok2, "if|switch"))
|
||||||
{
|
{
|
||||||
bool bailout = false;
|
if (bailoutIfSwitch(tok2, arrayInfo.varid))
|
||||||
unsigned int indentlevel3 = 0;
|
|
||||||
for (const Token *tok3 = tok2; tok3; tok3 = tok3->next())
|
|
||||||
{
|
|
||||||
if (tok3->str() == "{")
|
|
||||||
indentlevel3++;
|
|
||||||
else if (tok3->str() == "}")
|
|
||||||
{
|
|
||||||
if (indentlevel3 <= 1)
|
|
||||||
break;
|
|
||||||
--indentlevel3;
|
|
||||||
}
|
|
||||||
else if (tok3->str() == "break" && tok2->str() == "if")
|
|
||||||
{
|
|
||||||
bailout = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (tok3->varId() == arrayInfo.varid)
|
|
||||||
{
|
|
||||||
bailout = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bailout
|
|
||||||
if (bailout)
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1338,6 +1338,18 @@ private:
|
||||||
" }\n"
|
" }\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("[test.cpp:6]: (error) Buffer access out-of-bounds: a\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:6]: (error) Buffer access out-of-bounds: a\n", errout.str());
|
||||||
|
|
||||||
|
// Ticket #2385 - No false positive
|
||||||
|
check("void f() {\n"
|
||||||
|
" int a[10];\n"
|
||||||
|
" for (int i = 0; i < 20; ++i) {\n"
|
||||||
|
" if (i<10) {\n"
|
||||||
|
" } else {\n"
|
||||||
|
" a[i-10] = 0;\n"
|
||||||
|
" }\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue