value flow: inconclusive handling of unknown functions
This commit is contained in:
parent
5d2a39b580
commit
8b6f001f94
|
@ -785,7 +785,7 @@ void CheckNullPointer::nullPointerByDeRefAndChec()
|
||||||
if (value->condition == NULL)
|
if (value->condition == NULL)
|
||||||
nullPointerError(tok);
|
nullPointerError(tok);
|
||||||
else if (_settings->isEnabled("warning"))
|
else if (_settings->isEnabled("warning"))
|
||||||
nullPointerError(tok, tok->str(), value->condition, false);
|
nullPointerError(tok, tok->str(), value->condition, value->inconclusive);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -797,7 +797,7 @@ void CheckNullPointer::nullPointerByDeRefAndChec()
|
||||||
if (value->condition == NULL)
|
if (value->condition == NULL)
|
||||||
nullPointerError(tok);
|
nullPointerError(tok);
|
||||||
else if (_settings->isEnabled("warning"))
|
else if (_settings->isEnabled("warning"))
|
||||||
nullPointerError(tok, tok->str(), value->condition, false);
|
nullPointerError(tok, tok->str(), value->condition, value->inconclusive);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ static void bailout(TokenList *tokenlist, ErrorLogger *errorLogger, const Token
|
||||||
errorLogger->reportErr(errmsg);
|
errorLogger->reportErr(errmsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool bailoutFunctionPar(const Token *tok, const ValueFlow::Value &value, const Settings *settings)
|
static bool bailoutFunctionPar(const Token *tok, const ValueFlow::Value &value, const Settings *settings, bool *inconclusive)
|
||||||
{
|
{
|
||||||
// passing variable to subfunction?
|
// passing variable to subfunction?
|
||||||
const bool addr = tok && Token::Match(tok->previous(), "&");
|
const bool addr = tok && Token::Match(tok->previous(), "&");
|
||||||
|
@ -65,9 +65,15 @@ static bool bailoutFunctionPar(const Token *tok, const ValueFlow::Value &value,
|
||||||
return false; // not a function => dont bailout
|
return false; // not a function => dont bailout
|
||||||
|
|
||||||
if (!tok->function()) {
|
if (!tok->function()) {
|
||||||
// unknown function.. bailout unless value is 0 and the library
|
// if value is 0 and the library says 0 is invalid => dont bailout
|
||||||
// says 0 is invalid
|
if (value.intvalue==0 && settings->library.isnullargbad(tok->str(), 1+argnr))
|
||||||
return (value.intvalue!=0 || !settings->library.isnullargbad(tok->str(), 1+argnr));
|
return false;
|
||||||
|
// inconclusive => don't bailout
|
||||||
|
if (inconclusive && !addr && settings->inconclusive) {
|
||||||
|
*inconclusive = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Variable *arg = tok->function()->getArgumentVar(argnr);
|
const Variable *arg = tok->function()->getArgumentVar(argnr);
|
||||||
|
@ -186,6 +192,7 @@ static void valueFlowBeforeCondition(TokenList *tokenlist, ErrorLogger *errorLog
|
||||||
val2 = ValueFlow::Value(tok,0);
|
val2 = ValueFlow::Value(tok,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool inconclusive = false;
|
||||||
for (Token *tok2 = tok->previous(); ; tok2 = tok2->previous()) {
|
for (Token *tok2 = tok->previous(); ; tok2 = tok2->previous()) {
|
||||||
if (!tok2) {
|
if (!tok2) {
|
||||||
if (settings->debugwarnings) {
|
if (settings->debugwarnings) {
|
||||||
|
@ -213,11 +220,14 @@ static void valueFlowBeforeCondition(TokenList *tokenlist, ErrorLogger *errorLog
|
||||||
}
|
}
|
||||||
|
|
||||||
// assigned by subfunction?
|
// assigned by subfunction?
|
||||||
if (bailoutFunctionPar(tok2,val2.condition ? val2 : val,settings)) {
|
bool inconclusive2 = false;
|
||||||
|
if (bailoutFunctionPar(tok2,val2.condition ? val2 : val, settings, &inconclusive2)) {
|
||||||
if (settings->debugwarnings)
|
if (settings->debugwarnings)
|
||||||
bailout(tokenlist, errorLogger, tok2, "possible assignment of " + tok2->str() + " by subfunction");
|
bailout(tokenlist, errorLogger, tok2, "possible assignment of " + tok2->str() + " by subfunction");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
inconclusive |= inconclusive2;
|
||||||
|
val2.inconclusive |= inconclusive2;
|
||||||
|
|
||||||
// skip if variable is conditionally used in ?: expression
|
// skip if variable is conditionally used in ?: expression
|
||||||
if (const Token *parent = skipValueInConditionalExpression(tok2)) {
|
if (const Token *parent = skipValueInConditionalExpression(tok2)) {
|
||||||
|
@ -230,6 +240,7 @@ static void valueFlowBeforeCondition(TokenList *tokenlist, ErrorLogger *errorLog
|
||||||
}
|
}
|
||||||
|
|
||||||
tok2->values.push_back(val);
|
tok2->values.push_back(val);
|
||||||
|
tok2->values.back().inconclusive = inconclusive;
|
||||||
if (val2.condition)
|
if (val2.condition)
|
||||||
tok2->values.push_back(val2);
|
tok2->values.push_back(val2);
|
||||||
if (var && tok2 == var->nameToken())
|
if (var && tok2 == var->nameToken())
|
||||||
|
|
|
@ -29,11 +29,12 @@ class Settings;
|
||||||
namespace ValueFlow {
|
namespace ValueFlow {
|
||||||
class Value {
|
class Value {
|
||||||
public:
|
public:
|
||||||
Value() : condition(0), intvalue(0) {}
|
Value() : condition(0), intvalue(0), inconclusive(false) {}
|
||||||
Value(long long val) : condition(0), intvalue(val) {}
|
Value(long long val) : condition(0), intvalue(val), inconclusive(false) {}
|
||||||
Value(const Token *c, long long val) : condition(c), intvalue(val) {}
|
Value(const Token *c, long long val) : condition(c), intvalue(val), inconclusive(false) {}
|
||||||
const Token *condition;
|
const Token *condition;
|
||||||
long long intvalue;
|
long long intvalue;
|
||||||
|
bool inconclusive;
|
||||||
};
|
};
|
||||||
|
|
||||||
void setValues(TokenList *tokenlist, ErrorLogger *errorLogger, const Settings *settings);
|
void setValues(TokenList *tokenlist, ErrorLogger *errorLogger, const Settings *settings);
|
||||||
|
|
Loading…
Reference in New Issue