Fix 11194: FN: knownConditionTrueFalse (#4452)
* Fix 11194: FN: knownConditionTrueFalse * Format
This commit is contained in:
parent
92845295b8
commit
f83b8dd385
|
@ -5088,13 +5088,58 @@ static void valueFlowSymbolic(TokenList* tokenlist, SymbolDatabase* symboldataba
|
|||
}
|
||||
}
|
||||
|
||||
static void valueFlowSymbolicIdentity(TokenList* tokenlist)
|
||||
static const Token* isStrlenOf(const Token* tok, const Token* expr, int depth = 10)
|
||||
{
|
||||
for (Token* tok = tokenlist->front(); tok; tok = tok->next()) {
|
||||
if (depth < 0)
|
||||
return nullptr;
|
||||
if (!tok)
|
||||
return nullptr;
|
||||
if (!expr)
|
||||
return nullptr;
|
||||
if (expr->exprId() == 0)
|
||||
return nullptr;
|
||||
if (Token::simpleMatch(tok->previous(), "strlen (")) {
|
||||
if (tok->astOperand2()->exprId() == expr->exprId())
|
||||
return tok;
|
||||
} else {
|
||||
for (const ValueFlow::Value& v : tok->values()) {
|
||||
if (!v.isSymbolicValue())
|
||||
continue;
|
||||
if (!v.isKnown())
|
||||
continue;
|
||||
if (v.intvalue != 0)
|
||||
continue;
|
||||
if (const Token* next = isStrlenOf(v.tokvalue, expr, depth - 1))
|
||||
return next;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void valueFlowSymbolicOperators(TokenList* tokenlist, SymbolDatabase* symboldatabase)
|
||||
{
|
||||
for (const Scope* scope : symboldatabase->functionScopes) {
|
||||
for (Token* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
|
||||
if (tok->hasKnownIntValue())
|
||||
continue;
|
||||
if (!Token::Match(tok, "*|/|<<|>>|^|+|-|%or%"))
|
||||
|
||||
if (Token::Match(tok, "abs|labs|llabs|fabs|fabsf|fabsl (")) {
|
||||
const Token* arg = tok->next()->astOperand2();
|
||||
if (!arg)
|
||||
continue;
|
||||
ValueFlow::Value c = inferCondition(">=", arg, 0);
|
||||
if (!c.isKnown())
|
||||
continue;
|
||||
|
||||
ValueFlow::Value v = makeSymbolic(arg);
|
||||
v.errorPath = c.errorPath;
|
||||
v.errorPath.emplace_back(tok, "Passed to " + tok->str());
|
||||
if (c.intvalue == 0)
|
||||
v.setImpossible();
|
||||
else
|
||||
v.setKnown();
|
||||
setTokenValue(tok->next(), v, tokenlist->getSettings());
|
||||
} else if (Token::Match(tok, "*|/|<<|>>|^|+|-|%or%")) {
|
||||
if (!tok->astOperand1())
|
||||
continue;
|
||||
if (!tok->astOperand2())
|
||||
|
@ -5125,8 +5170,10 @@ static void valueFlowSymbolicIdentity(TokenList* tokenlist)
|
|||
continue;
|
||||
std::vector<ValueFlow::Value> values = {makeSymbolic(vartok)};
|
||||
std::unordered_set<nonneg int> ids = {vartok->exprId()};
|
||||
std::copy_if(
|
||||
vartok->values().begin(), vartok->values().end(), std::back_inserter(values), [&](const ValueFlow::Value& v) {
|
||||
std::copy_if(vartok->values().begin(),
|
||||
vartok->values().end(),
|
||||
std::back_inserter(values),
|
||||
[&](const ValueFlow::Value& v) {
|
||||
if (!v.isSymbolicValue())
|
||||
return false;
|
||||
if (!v.tokvalue)
|
||||
|
@ -5135,33 +5182,33 @@ static void valueFlowSymbolicIdentity(TokenList* tokenlist)
|
|||
});
|
||||
for (const ValueFlow::Value& v : values)
|
||||
setTokenValue(tok, v, tokenlist->getSettings());
|
||||
} else if (Token::simpleMatch(tok, "[")) {
|
||||
const Token* arrayTok = tok->astOperand1();
|
||||
const Token* indexTok = tok->astOperand2();
|
||||
if (!arrayTok)
|
||||
continue;
|
||||
if (!indexTok)
|
||||
continue;
|
||||
for (const ValueFlow::Value& value : indexTok->values()) {
|
||||
if (!value.isSymbolicValue())
|
||||
continue;
|
||||
if (value.intvalue != 0)
|
||||
continue;
|
||||
if (value.bound == ValueFlow::Value::Bound::Upper)
|
||||
continue;
|
||||
if (value.isImpossible() && value.bound != ValueFlow::Value::Bound::Lower)
|
||||
continue;
|
||||
if (value.isKnown() && value.bound != ValueFlow::Value::Bound::Point)
|
||||
continue;
|
||||
const Token* strlenTok = isStrlenOf(value.tokvalue, arrayTok);
|
||||
if (!strlenTok)
|
||||
continue;
|
||||
ValueFlow::Value v = value;
|
||||
v.valueType = ValueFlow::Value::ValueType::INT;
|
||||
v.errorPath.emplace_back(strlenTok, "Return index of string to the first element that is 0");
|
||||
setTokenValue(tok, v, tokenlist->getSettings());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void valueFlowSymbolicAbs(TokenList* tokenlist, SymbolDatabase* symboldatabase)
|
||||
{
|
||||
for (const Scope* scope : symboldatabase->functionScopes) {
|
||||
for (Token* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
|
||||
if (!Token::Match(tok, "abs|labs|llabs|fabs|fabsf|fabsl ("))
|
||||
continue;
|
||||
if (tok->hasKnownIntValue())
|
||||
continue;
|
||||
|
||||
const Token* arg = tok->next()->astOperand2();
|
||||
if (!arg)
|
||||
continue;
|
||||
ValueFlow::Value c = inferCondition(">=", arg, 0);
|
||||
if (!c.isKnown())
|
||||
continue;
|
||||
|
||||
ValueFlow::Value v = makeSymbolic(arg);
|
||||
v.errorPath = c.errorPath;
|
||||
v.errorPath.emplace_back(tok, "Passed to " + tok->str());
|
||||
if (c.intvalue == 0)
|
||||
v.setImpossible();
|
||||
else
|
||||
v.setKnown();
|
||||
setTokenValue(tok->next(), v, tokenlist->getSettings());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8764,8 +8811,7 @@ void ValueFlow::setValues(TokenList *tokenlist, SymbolDatabase* symboldatabase,
|
|||
while (n > 0 && values < getTotalValues(tokenlist)) {
|
||||
values = getTotalValues(tokenlist);
|
||||
valueFlowImpossibleValues(tokenlist, settings);
|
||||
valueFlowSymbolicIdentity(tokenlist);
|
||||
valueFlowSymbolicAbs(tokenlist, symboldatabase);
|
||||
valueFlowSymbolicOperators(tokenlist, symboldatabase);
|
||||
valueFlowCondition(SymbolicConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings);
|
||||
valueFlowSymbolicInfer(tokenlist, symboldatabase);
|
||||
valueFlowArrayBool(tokenlist);
|
||||
|
|
|
@ -158,6 +158,7 @@ private:
|
|||
TEST_CASE(valueFlowNotNull);
|
||||
TEST_CASE(valueFlowSymbolic);
|
||||
TEST_CASE(valueFlowSymbolicIdentity);
|
||||
TEST_CASE(valueFlowSymbolicStrlen);
|
||||
TEST_CASE(valueFlowSmartPointer);
|
||||
}
|
||||
|
||||
|
@ -7522,6 +7523,27 @@ private:
|
|||
ASSERT_EQUALS(false, testValueOfXKnown(code, 3U, "a", 0));
|
||||
}
|
||||
|
||||
void valueFlowSymbolicStrlen()
|
||||
{
|
||||
const char* code;
|
||||
|
||||
code = "int f(char *s) {\n"
|
||||
" size_t len = strlen(s);\n"
|
||||
" int x = s[len];\n"
|
||||
" return x;\n"
|
||||
"}\n";
|
||||
ASSERT_EQUALS(true, testValueOfXKnown(code, 4U, 0));
|
||||
|
||||
code = "int f(char *s, size_t i) {\n"
|
||||
" if (i < strlen(s)) {\n"
|
||||
" int x = s[i];\n"
|
||||
" return x;\n"
|
||||
" }\n"
|
||||
" return 0;\n"
|
||||
"}\n";
|
||||
ASSERT_EQUALS(true, testValueOfXImpossible(code, 4U, 0));
|
||||
}
|
||||
|
||||
void valueFlowSmartPointer()
|
||||
{
|
||||
const char* code;
|
||||
|
|
Loading…
Reference in New Issue