Safe checks: Clarify a warning message

This commit is contained in:
Daniel Marjamäki 2019-07-25 17:19:51 +02:00
parent 2d5f3ae3b4
commit 45d1ca6f7c
6 changed files with 42 additions and 5 deletions

View File

@ -181,6 +181,14 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
else if (std::strcmp(argv[i], "--inconclusive") == 0) else if (std::strcmp(argv[i], "--inconclusive") == 0)
mSettings->inconclusive = true; mSettings->inconclusive = true;
// Experimental: Safe checking
else if (std::strcmp(argv[i], "--safe-classes") == 0)
mSettings->safeChecks.classes = true;
// Experimental: Safe checking
else if (std::strcmp(argv[i], "--safe-functions") == 0)
mSettings->safeChecks.externalFunctions = mSettings->safeChecks.internalFunctions = true;
// Enforce language (--language=, -x) // Enforce language (--language=, -x)
else if (std::strncmp(argv[i], "--language=", 11) == 0 || std::strcmp(argv[i], "-x") == 0) { else if (std::strncmp(argv[i], "--language=", 11) == 0 || std::strcmp(argv[i], "-x") == 0) {
std::string str; std::string str;

View File

@ -66,3 +66,12 @@ std::list<Check *> &Check::instances()
return _instances; return _instances;
#endif #endif
} }
std::string Check::getMessageId(const ValueFlow::Value &value, const char id[])
{
if (value.condition != nullptr)
return id + std::string("Cond");
if (value.safe)
return std::string("safe") + (char)std::toupper(id[0]) + (id + 1);
return id;
}

View File

@ -118,6 +118,8 @@ public:
return false; return false;
} }
static std::string getMessageId(const ValueFlow::Value &value, const char id[]);
protected: protected:
const Tokenizer * const mTokenizer; const Tokenizer * const mTokenizer;
const Settings * const mSettings; const Settings * const mSettings;

View File

@ -200,9 +200,12 @@ void CheckType::integerOverflowError(const Token *tok, const ValueFlow::Value &v
else else
msg = "Signed integer overflow for expression '" + expr + "'."; msg = "Signed integer overflow for expression '" + expr + "'.";
if (value.safe)
msg = "Safe checks: " + msg;
reportError(getErrorPath(tok, &value, "Integer overflow"), reportError(getErrorPath(tok, &value, "Integer overflow"),
value.errorSeverity() ? Severity::error : Severity::warning, value.errorSeverity() ? Severity::error : Severity::warning,
(value.condition == nullptr) ? "integerOverflow" : "integerOverflowCond", getMessageId(value, "integerOverflow").c_str(),
msg, msg,
CWE190, CWE190,
value.isInconclusive()); value.isInconclusive());

View File

@ -374,6 +374,7 @@ static void combineValueProperties(const ValueFlow::Value &value1, const ValueFl
result->varId = (value1.varId != 0U) ? value1.varId : value2.varId; result->varId = (value1.varId != 0U) ? value1.varId : value2.varId;
result->varvalue = (result->varId == value1.varId) ? value1.varvalue : value2.varvalue; result->varvalue = (result->varId == value1.varId) ? value1.varvalue : value2.varvalue;
result->errorPath = (value1.errorPath.empty() ? value2 : value1).errorPath; result->errorPath = (value1.errorPath.empty() ? value2 : value1).errorPath;
result->safe = value1.safe || value2.safe;
} }
@ -5462,9 +5463,11 @@ static void valueFlowSafeFunctions(TokenList *tokenlist, SymbolDatabase *symbold
argValues.emplace_back(0); argValues.emplace_back(0);
argValues.back().valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE; argValues.back().valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
argValues.back().errorPath.emplace_back(arg.nameToken(), "Assuming " + arg.name() + " is empty"); argValues.back().errorPath.emplace_back(arg.nameToken(), "Assuming " + arg.name() + " is empty");
argValues.back().safe = true;
argValues.emplace_back(1000000); argValues.emplace_back(1000000);
argValues.back().valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE; argValues.back().valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
argValues.back().errorPath.emplace_back(arg.nameToken(), "Assuming " + arg.name() + " size is 1000000"); argValues.back().errorPath.emplace_back(arg.nameToken(), "Assuming " + arg.name() + " size is 1000000");
argValues.back().safe = true;
for (const ValueFlow::Value &value : argValues) for (const ValueFlow::Value &value : argValues)
valueFlowContainerForward(const_cast<Token*>(functionScope->bodyStart), arg.declarationId(), value, settings, tokenlist->isCPP()); valueFlowContainerForward(const_cast<Token*>(functionScope->bodyStart), arg.declarationId(), value, settings, tokenlist->isCPP());
continue; continue;
@ -5477,6 +5480,9 @@ static void valueFlowSafeFunctions(TokenList *tokenlist, SymbolDatabase *symbold
if (!isLow && !isHigh && !all) if (!isLow && !isHigh && !all)
continue; continue;
const bool safeLow = !isLow;
const bool safeHigh = !isHigh;
if ((!isLow || !isHigh) && all) { if ((!isLow || !isHigh) && all) {
MathLib::bigint minValue, maxValue; MathLib::bigint minValue, maxValue;
if (getMinMaxValues(arg.valueType(), *settings, &minValue, &maxValue)) { if (getMinMaxValues(arg.valueType(), *settings, &minValue, &maxValue)) {
@ -5490,11 +5496,13 @@ static void valueFlowSafeFunctions(TokenList *tokenlist, SymbolDatabase *symbold
argValues.emplace_back(0); argValues.emplace_back(0);
argValues.back().valueType = ValueFlow::Value::ValueType::FLOAT; argValues.back().valueType = ValueFlow::Value::ValueType::FLOAT;
argValues.back().floatValue = isLow ? low : -1E25f; argValues.back().floatValue = isLow ? low : -1E25f;
argValues.back().errorPath.emplace_back(arg.nameToken(), "Assuming argument has value " + MathLib::toString(argValues.back().floatValue)); argValues.back().errorPath.emplace_back(arg.nameToken(), "Safe checks: Assuming argument has value " + MathLib::toString(argValues.back().floatValue));
argValues.back().safe = true;
argValues.emplace_back(0); argValues.emplace_back(0);
argValues.back().valueType = ValueFlow::Value::ValueType::FLOAT; argValues.back().valueType = ValueFlow::Value::ValueType::FLOAT;
argValues.back().floatValue = isHigh ? high : 1E25f; argValues.back().floatValue = isHigh ? high : 1E25f;
argValues.back().errorPath.emplace_back(arg.nameToken(), "Assuming argument has value " + MathLib::toString(argValues.back().floatValue)); argValues.back().errorPath.emplace_back(arg.nameToken(), "Safe checks: Assuming argument has value " + MathLib::toString(argValues.back().floatValue));
argValues.back().safe = true;
valueFlowForward(const_cast<Token *>(functionScope->bodyStart->next()), valueFlowForward(const_cast<Token *>(functionScope->bodyStart->next()),
functionScope->bodyEnd, functionScope->bodyEnd,
&arg, &arg,
@ -5512,11 +5520,13 @@ static void valueFlowSafeFunctions(TokenList *tokenlist, SymbolDatabase *symbold
std::list<ValueFlow::Value> argValues; std::list<ValueFlow::Value> argValues;
if (isLow) { if (isLow) {
argValues.emplace_back(low); argValues.emplace_back(low);
argValues.back().errorPath.emplace_back(arg.nameToken(), "Assuming argument has value " + MathLib::toString(low)); argValues.back().errorPath.emplace_back(arg.nameToken(), std::string(safeLow ? "Safe checks: " : "") + "Assuming argument has value " + MathLib::toString(low));
argValues.back().safe = safeLow;
} }
if (isHigh) { if (isHigh) {
argValues.emplace_back(high); argValues.emplace_back(high);
argValues.back().errorPath.emplace_back(arg.nameToken(), "Assuming argument has value " + MathLib::toString(high)); argValues.back().errorPath.emplace_back(arg.nameToken(), std::string(safeHigh ? "Safe checks: " : "") + "Assuming argument has value " + MathLib::toString(high));
argValues.back().safe = safeHigh;
} }
if (!argValues.empty()) if (!argValues.empty())
@ -5574,6 +5584,7 @@ ValueFlow::Value::Value(const Token *c, long long val)
varvalue(val), varvalue(val),
condition(c), condition(c),
varId(0U), varId(0U),
safe(false),
conditional(false), conditional(false),
defaultArg(false), defaultArg(false),
lifetimeKind(LifetimeKind::Object), lifetimeKind(LifetimeKind::Object),

View File

@ -50,6 +50,7 @@ namespace ValueFlow {
varvalue(val), varvalue(val),
condition(nullptr), condition(nullptr),
varId(0U), varId(0U),
safe(false),
conditional(false), conditional(false),
defaultArg(false), defaultArg(false),
lifetimeKind(LifetimeKind::Object), lifetimeKind(LifetimeKind::Object),
@ -161,6 +162,9 @@ namespace ValueFlow {
/** For calculated values - varId that calculated value depends on */ /** For calculated values - varId that calculated value depends on */
nonneg int varId; nonneg int varId;
/** value relies on safe checking */
bool safe;
/** Conditional value */ /** Conditional value */
bool conditional; bool conditional;