ExprEngine: execute functions in same TU
This commit is contained in:
parent
4acc63ac48
commit
cbe038e694
|
@ -293,6 +293,7 @@ namespace {
|
||||||
, errorLogger(errorLogger)
|
, errorLogger(errorLogger)
|
||||||
, tokenizer(tokenizer)
|
, tokenizer(tokenizer)
|
||||||
, callbacks(callbacks)
|
, callbacks(callbacks)
|
||||||
|
, recursion(0)
|
||||||
, mTrackExecution(trackExecution)
|
, mTrackExecution(trackExecution)
|
||||||
, mDataIndex(trackExecution->getNewDataIndex()) {}
|
, mDataIndex(trackExecution->getNewDataIndex()) {}
|
||||||
typedef std::map<nonneg int, ExprEngine::ValuePtr> Memory;
|
typedef std::map<nonneg int, ExprEngine::ValuePtr> Memory;
|
||||||
|
@ -302,6 +303,7 @@ namespace {
|
||||||
const Tokenizer * const tokenizer;
|
const Tokenizer * const tokenizer;
|
||||||
const std::vector<ExprEngine::Callback> &callbacks;
|
const std::vector<ExprEngine::Callback> &callbacks;
|
||||||
std::vector<ExprEngine::ValuePtr> constraints;
|
std::vector<ExprEngine::ValuePtr> constraints;
|
||||||
|
int recursion;
|
||||||
|
|
||||||
ExprEngine::ValuePtr executeContract(const Function *function, ExprEngine::ValuePtr(*executeExpression)(const Token*, Data&)) {
|
ExprEngine::ValuePtr executeContract(const Function *function, ExprEngine::ValuePtr(*executeExpression)(const Token*, Data&)) {
|
||||||
const auto it = settings->functionContracts.find(function->fullName());
|
const auto it = settings->functionContracts.find(function->fullName());
|
||||||
|
@ -331,10 +333,6 @@ namespace {
|
||||||
constraints.push_back(value);
|
constraints.push_back(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addError(int linenr) OVERRIDE {
|
|
||||||
mTrackExecution->addError(linenr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void assignValue(const Token *tok, unsigned int varId, ExprEngine::ValuePtr value) {
|
void assignValue(const Token *tok, unsigned int varId, ExprEngine::ValuePtr value) {
|
||||||
if (varId == 0)
|
if (varId == 0)
|
||||||
return;
|
return;
|
||||||
|
@ -494,6 +492,27 @@ namespace {
|
||||||
addConstraint(std::make_shared<ExprEngine::BinOpResult>("<=", value, std::make_shared<ExprEngine::IntRange>(std::to_string(high), high, high)), true);
|
addConstraint(std::make_shared<ExprEngine::BinOpResult>("<=", value, std::make_shared<ExprEngine::IntRange>(std::to_string(high), high, high)), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void reportError(const Token *tok,
|
||||||
|
Severity::SeverityType severity,
|
||||||
|
const char id[],
|
||||||
|
const std::string &text,
|
||||||
|
CWE cwe,
|
||||||
|
bool inconclusive,
|
||||||
|
bool incomplete,
|
||||||
|
const std::string functionName) OVERRIDE
|
||||||
|
|
||||||
|
{
|
||||||
|
if (errorPath.empty())
|
||||||
|
mTrackExecution->addError(tok->linenr());
|
||||||
|
|
||||||
|
ErrorPath e = errorPath;
|
||||||
|
e.push_back(ErrorPathItem(tok, text));
|
||||||
|
ErrorMessage errmsg(e, &tokenizer->list, severity, id, text, cwe, inconclusive);
|
||||||
|
errmsg.incomplete = incomplete;
|
||||||
|
errmsg.function = functionName.empty() ? currentFunction : functionName;
|
||||||
|
errorLogger->reportErr(errmsg);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TrackExecution * const mTrackExecution;
|
TrackExecution * const mTrackExecution;
|
||||||
const int mDataIndex;
|
const int mDataIndex;
|
||||||
|
@ -1255,6 +1274,7 @@ static void call(const std::vector<ExprEngine::Callback> &callbacks, const Token
|
||||||
|
|
||||||
static ExprEngine::ValuePtr executeExpression(const Token *tok, Data &data);
|
static ExprEngine::ValuePtr executeExpression(const Token *tok, Data &data);
|
||||||
static ExprEngine::ValuePtr executeExpression1(const Token *tok, Data &data);
|
static ExprEngine::ValuePtr executeExpression1(const Token *tok, Data &data);
|
||||||
|
static void execute(const Token *start, const Token *end, Data &data);
|
||||||
|
|
||||||
static ExprEngine::ValuePtr calculateArrayIndex(const Token *tok, Data &data, const ExprEngine::ArrayValue &arrayValue)
|
static ExprEngine::ValuePtr calculateArrayIndex(const Token *tok, Data &data, const ExprEngine::ArrayValue &arrayValue)
|
||||||
{
|
{
|
||||||
|
@ -1465,39 +1485,34 @@ static void checkContract(Data &data, const Token *tok, const Function *function
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bailoutValue || solver.check() == z3::sat) {
|
if (bailoutValue || solver.check() == z3::sat) {
|
||||||
data.addError(tok->linenr());
|
const char id[] = "bughuntingFunctionCall";
|
||||||
std::list<const Token*> callstack{tok};
|
|
||||||
const char * const id = "bughuntingFunctionCall";
|
|
||||||
const auto contractIt = data.settings->functionContracts.find(function->fullName());
|
const auto contractIt = data.settings->functionContracts.find(function->fullName());
|
||||||
const std::string functionName = contractIt->first;
|
const std::string functionName = contractIt->first;
|
||||||
const std::string functionExpects = contractIt->second;
|
const std::string functionExpects = contractIt->second;
|
||||||
ErrorMessage errmsg(callstack,
|
data.reportError(tok,
|
||||||
&data.tokenizer->list,
|
Severity::SeverityType::error,
|
||||||
Severity::SeverityType::error,
|
id,
|
||||||
id,
|
"Function '" + function->name() + "' is called, can not determine that its contract '" + functionExpects + "' is always met.",
|
||||||
"Function '" + function->name() + "' is called, can not determine that its contract '" + functionExpects + "' is always met.",
|
CWE(0),
|
||||||
CWE(0),
|
false,
|
||||||
false);
|
bailoutValue,
|
||||||
errmsg.incomplete = bailoutValue;
|
functionName);
|
||||||
errmsg.function = functionName;
|
|
||||||
data.errorLogger->reportErr(errmsg);
|
|
||||||
}
|
}
|
||||||
} catch (const z3::exception &exception) {
|
} catch (const z3::exception &exception) {
|
||||||
std::cerr << "z3: " << exception << std::endl;
|
std::cerr << "z3: " << exception << std::endl;
|
||||||
} catch (const BugHuntingException &e) {
|
} catch (const BugHuntingException &e) {
|
||||||
std::list<const Token*> callstack{tok};
|
const char id[] = "internalErrorInExprEngine";
|
||||||
const char * const id = "internalErrorInExprEngine";
|
|
||||||
const auto contractIt = data.settings->functionContracts.find(function->fullName());
|
const auto contractIt = data.settings->functionContracts.find(function->fullName());
|
||||||
|
const std::string functionName = contractIt->first;
|
||||||
const std::string functionExpects = contractIt->second;
|
const std::string functionExpects = contractIt->second;
|
||||||
ErrorMessage errmsg(callstack,
|
data.reportError(tok,
|
||||||
&data.tokenizer->list,
|
Severity::SeverityType::error,
|
||||||
Severity::SeverityType::error,
|
id,
|
||||||
id,
|
"Function '" + function->name() + "' is called, can not determine that its contract '" + functionExpects + "' is always met.",
|
||||||
"Function '" + function->name() + "' is called, can not determine that its contract is always met.",
|
CWE(0),
|
||||||
CWE(0),
|
false,
|
||||||
false);
|
true,
|
||||||
errmsg.incomplete = true;
|
functionName);
|
||||||
data.errorLogger->reportErr(errmsg);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1518,7 +1533,7 @@ static ExprEngine::ValuePtr executeFunctionCall(const Token *tok, Data &data)
|
||||||
|
|
||||||
std::vector<ExprEngine::ValuePtr> argValues;
|
std::vector<ExprEngine::ValuePtr> argValues;
|
||||||
for (const Token *argtok : getArguments(tok)) {
|
for (const Token *argtok : getArguments(tok)) {
|
||||||
auto val = executeExpression(argtok, data);
|
auto val = executeExpression1(argtok, data);
|
||||||
argValues.push_back(val);
|
argValues.push_back(val);
|
||||||
if (!argtok->valueType() || (argtok->valueType()->constness & 1) == 1)
|
if (!argtok->valueType() || (argtok->valueType()->constness & 1) == 1)
|
||||||
continue;
|
continue;
|
||||||
|
@ -1536,11 +1551,12 @@ static ExprEngine::ValuePtr executeFunctionCall(const Token *tok, Data &data)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tok->astOperand1()->function()) {
|
if (tok->astOperand1()->function()) {
|
||||||
const std::string &functionName = tok->astOperand1()->function()->fullName();
|
const Function *function = tok->astOperand1()->function();
|
||||||
|
const std::string &functionName = function->fullName();
|
||||||
const auto contractIt = data.settings->functionContracts.find(functionName);
|
const auto contractIt = data.settings->functionContracts.find(functionName);
|
||||||
if (contractIt != data.settings->functionContracts.end()) {
|
if (contractIt != data.settings->functionContracts.end()) {
|
||||||
#ifdef USE_Z3
|
#ifdef USE_Z3
|
||||||
checkContract(data, tok, tok->astOperand1()->function(), argValues);
|
checkContract(data, tok, function, argValues);
|
||||||
#endif
|
#endif
|
||||||
} else if (!argValues.empty()) {
|
} else if (!argValues.empty()) {
|
||||||
bool bailout = false;
|
bool bailout = false;
|
||||||
|
@ -1549,6 +1565,22 @@ static ExprEngine::ValuePtr executeFunctionCall(const Token *tok, Data &data)
|
||||||
if (!bailout)
|
if (!bailout)
|
||||||
data.addMissingContract(functionName);
|
data.addMissingContract(functionName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Execute subfunction..
|
||||||
|
if (function->hasBody()) {
|
||||||
|
const Scope *functionScope = function->functionScope;
|
||||||
|
int argnr = 0;
|
||||||
|
for (const Variable &arg: function->argumentList) {
|
||||||
|
if (argnr < argValues.size())
|
||||||
|
data.assignValue(function->functionScope->bodyStart, arg.declarationId(), argValues[argnr]);
|
||||||
|
// TODO default values!
|
||||||
|
argnr++;
|
||||||
|
}
|
||||||
|
data.contractConstraints(function, executeExpression1);
|
||||||
|
data.errorPath.push_back(ErrorPathItem(tok, "Calling " + function->name()));
|
||||||
|
execute(functionScope->bodyStart, functionScope->bodyEnd, data);
|
||||||
|
data.errorPath.pop_back();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto val = getValueRangeFromValueType(data.getNewSymbolName(), tok->valueType(), *data.settings);
|
auto val = getValueRangeFromValueType(data.getNewSymbolName(), tok->valueType(), *data.settings);
|
||||||
|
@ -1838,12 +1870,25 @@ static ExprEngine::ValuePtr executeExpression(const Token *tok, Data &data)
|
||||||
|
|
||||||
static ExprEngine::ValuePtr createVariableValue(const Variable &var, Data &data);
|
static ExprEngine::ValuePtr createVariableValue(const Variable &var, Data &data);
|
||||||
|
|
||||||
static void execute(const Token *start, const Token *end, Data &data, int recursion=0)
|
static void execute(const Token *start, const Token *end, Data &data)
|
||||||
{
|
{
|
||||||
if (++recursion > 20)
|
if (data.recursion > 20)
|
||||||
// FIXME
|
// FIXME
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Update data.recursion
|
||||||
|
struct Recursion {
|
||||||
|
Recursion(int *var, int value) : var(var), value(value) {
|
||||||
|
*var = value + 1;
|
||||||
|
}
|
||||||
|
~Recursion() {
|
||||||
|
if (*var >= value) *var = value;
|
||||||
|
}
|
||||||
|
int *var;
|
||||||
|
int value;
|
||||||
|
};
|
||||||
|
Recursion updateRecursion(&data.recursion, data.recursion);
|
||||||
|
|
||||||
for (const Token *tok = start; tok != end; tok = tok->next()) {
|
for (const Token *tok = start; tok != end; tok = tok->next()) {
|
||||||
if (Token::Match(tok, "[;{}]"))
|
if (Token::Match(tok, "[;{}]"))
|
||||||
data.trackProgramState(tok);
|
data.trackProgramState(tok);
|
||||||
|
@ -1909,7 +1954,7 @@ static void execute(const Token *start, const Token *end, Data &data, int recurs
|
||||||
std::string exceptionMessage;
|
std::string exceptionMessage;
|
||||||
auto exec = [&](const Token *tok1, const Token *tok2, Data& data) {
|
auto exec = [&](const Token *tok1, const Token *tok2, Data& data) {
|
||||||
try {
|
try {
|
||||||
execute(tok1, tok2, data, recursion);
|
execute(tok1, tok2, data);
|
||||||
} catch (BugHuntingException &e) {
|
} catch (BugHuntingException &e) {
|
||||||
if (!exceptionToken || (e.tok && precedes(e.tok, exceptionToken))) {
|
if (!exceptionToken || (e.tok && precedes(e.tok, exceptionToken))) {
|
||||||
exceptionToken = e.tok;
|
exceptionToken = e.tok;
|
||||||
|
@ -1942,7 +1987,7 @@ static void execute(const Token *start, const Token *end, Data &data, int recurs
|
||||||
std::string exceptionMessage;
|
std::string exceptionMessage;
|
||||||
auto exec = [&](const Token *tok1, const Token *tok2, Data& data) {
|
auto exec = [&](const Token *tok1, const Token *tok2, Data& data) {
|
||||||
try {
|
try {
|
||||||
execute(tok1, tok2, data, recursion);
|
execute(tok1, tok2, data);
|
||||||
} catch (BugHuntingException &e) {
|
} catch (BugHuntingException &e) {
|
||||||
if (!exceptionToken || (e.tok && precedes(e.tok, exceptionToken))) {
|
if (!exceptionToken || (e.tok && precedes(e.tok, exceptionToken))) {
|
||||||
exceptionToken = e.tok;
|
exceptionToken = e.tok;
|
||||||
|
@ -2271,14 +2316,14 @@ void ExprEngine::runChecks(ErrorLogger *errorLogger, const Tokenizer *tokenizer,
|
||||||
if (!overflowArgument)
|
if (!overflowArgument)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
dataBase->addError(tok->linenr());
|
const bool bailout = (value.type == ExprEngine::ValueType::BailoutValue);
|
||||||
std::list<const Token*> callstack{tok};
|
dataBase->reportError(tok,
|
||||||
ErrorMessage errmsg(callstack, &tokenizer->list, Severity::SeverityType::error, "bughuntingBufferOverflow", "Buffer read/write, when calling '" + ftok->str() + "' it cannot be determined that " + std::to_string(overflowArgument) + getOrdinalText(overflowArgument) + " argument is not overflowed", CWE(120), false);
|
Severity::SeverityType::error,
|
||||||
if (value.type == ExprEngine::ValueType::BailoutValue)
|
"bughuntingBufferOverflow",
|
||||||
errmsg.incomplete = true;
|
"Buffer read/write, when calling '" + ftok->str() + "' it cannot be determined that " + std::to_string(overflowArgument) + getOrdinalText(overflowArgument) + " argument is not overflowed",
|
||||||
else
|
CWE(120),
|
||||||
errmsg.function = dataBase->currentFunction;
|
false,
|
||||||
errorLogger->reportErr(errmsg);
|
bailout);
|
||||||
};
|
};
|
||||||
|
|
||||||
std::function<void(const Token *, const ExprEngine::Value &, ExprEngine::DataBase *)> divByZero = [=](const Token *tok, const ExprEngine::Value &value, ExprEngine::DataBase *dataBase) {
|
std::function<void(const Token *, const ExprEngine::Value &, ExprEngine::DataBase *)> divByZero = [=](const Token *tok, const ExprEngine::Value &value, ExprEngine::DataBase *dataBase) {
|
||||||
|
@ -2298,16 +2343,15 @@ void ExprEngine::runChecks(ErrorLogger *errorLogger, const Tokenizer *tokenizer,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (tok->astParent()->astOperand2() == tok && value.isEqual(dataBase, 0)) {
|
if (tok->astParent()->astOperand2() == tok && value.isEqual(dataBase, 0)) {
|
||||||
dataBase->addError(tok->linenr());
|
|
||||||
std::list<const Token*> callstack{settings->clang ? tok : tok->astParent()};
|
|
||||||
const char * const id = (tok->valueType() && tok->valueType()->isFloat()) ? "bughuntingDivByZeroFloat" : "bughuntingDivByZero";
|
const char * const id = (tok->valueType() && tok->valueType()->isFloat()) ? "bughuntingDivByZeroFloat" : "bughuntingDivByZero";
|
||||||
const bool bailout = (value.type == ExprEngine::ValueType::BailoutValue);
|
const bool bailout = (value.type == ExprEngine::ValueType::BailoutValue);
|
||||||
ErrorMessage errmsg(callstack, &tokenizer->list, Severity::SeverityType::error, id, "There is division, cannot determine that there can't be a division by zero.", CWE(369), false);
|
dataBase->reportError(settings->clang ? tok : tok->astParent(),
|
||||||
if (!bailout)
|
Severity::SeverityType::error,
|
||||||
errmsg.function = dataBase->currentFunction;
|
id,
|
||||||
else
|
"There is division, cannot determine that there can't be a division by zero.",
|
||||||
errmsg.incomplete = bailout;
|
CWE(369),
|
||||||
errorLogger->reportErr(errmsg);
|
false,
|
||||||
|
bailout);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2354,9 +2398,7 @@ void ExprEngine::runChecks(ErrorLogger *errorLogger, const Tokenizer *tokenizer,
|
||||||
if (tok->valueType()->sign == ::ValueType::Sign::UNSIGNED)
|
if (tok->valueType()->sign == ::ValueType::Sign::UNSIGNED)
|
||||||
errorMessage += " Note that unsigned integer overflow is defined and will wrap around.";
|
errorMessage += " Note that unsigned integer overflow is defined and will wrap around.";
|
||||||
|
|
||||||
std::list<const Token*> callstack{tok};
|
dataBase->reportError(tok, Severity::SeverityType::error, "bughuntingIntegerOverflow", errorMessage, false, value.type == ExprEngine::ValueType::BailoutValue);
|
||||||
ErrorMessage errmsg(callstack, &tokenizer->list, Severity::SeverityType::error, "bughuntingIntegerOverflow", errorMessage, false);
|
|
||||||
errorLogger->reportErr(errmsg);
|
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -2423,6 +2465,27 @@ void ExprEngine::runChecks(ErrorLogger *errorLogger, const Tokenizer *tokenizer,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Uninitialized function argument
|
||||||
|
if (Token::Match(tok->astParent(), "[,(]")) {
|
||||||
|
const Token *parent = tok->astParent();
|
||||||
|
int count = 0;
|
||||||
|
if (Token::simpleMatch(parent, ",")) {
|
||||||
|
if (tok == parent->astOperand2())
|
||||||
|
++count;
|
||||||
|
while (Token::simpleMatch(parent, ",")) {
|
||||||
|
count++;
|
||||||
|
parent = parent->astParent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Token::simpleMatch(parent, "(") && parent->astOperand1() != tok) {
|
||||||
|
if (parent->astOperand1()->function()) {
|
||||||
|
const Variable *argvar = parent->astOperand1()->function()->getArgumentVar(count);
|
||||||
|
if (argvar && argvar->isReference() && !argvar->isConst())
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Avoid FP for array declaration
|
// Avoid FP for array declaration
|
||||||
const Token *parent = tok->astParent();
|
const Token *parent = tok->astParent();
|
||||||
while (parent && parent->str() == "[")
|
while (parent && parent->str() == "[")
|
||||||
|
@ -2430,15 +2493,23 @@ void ExprEngine::runChecks(ErrorLogger *errorLogger, const Tokenizer *tokenizer,
|
||||||
if (!parent)
|
if (!parent)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
dataBase->addError(tok->linenr());
|
|
||||||
std::list<const Token*> callstack{tok};
|
|
||||||
if (!uninitStructMember.empty()) {
|
if (!uninitStructMember.empty()) {
|
||||||
ErrorMessage errmsg(callstack, &tokenizer->list, Severity::SeverityType::error, "bughuntingUninitStructMember", "Cannot determine that '" + tok->expressionString() + "." + uninitStructMember + "' is initialized", CWE_USE_OF_UNINITIALIZED_VARIABLE, false);
|
dataBase->reportError(tok,
|
||||||
errorLogger->reportErr(errmsg);
|
Severity::SeverityType::error,
|
||||||
|
"bughuntingUninitStructMember",
|
||||||
|
"Cannot determine that '" + tok->expressionString() + "." + uninitStructMember + "' is initialized",
|
||||||
|
CWE_USE_OF_UNINITIALIZED_VARIABLE,
|
||||||
|
false,
|
||||||
|
value.type == ExprEngine::ValueType::BailoutValue);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ErrorMessage errmsg(callstack, &tokenizer->list, Severity::SeverityType::error, "bughuntingUninit", "Cannot determine that '" + tok->expressionString() + "' is initialized", CWE_USE_OF_UNINITIALIZED_VARIABLE, false);
|
dataBase->reportError(tok,
|
||||||
errorLogger->reportErr(errmsg);
|
Severity::SeverityType::error,
|
||||||
|
"bughuntingUninit",
|
||||||
|
"Cannot determine that '" + tok->expressionString() + "' is initialized",
|
||||||
|
CWE_USE_OF_UNINITIALIZED_VARIABLE,
|
||||||
|
false,
|
||||||
|
value.type == ExprEngine::ValueType::BailoutValue);
|
||||||
};
|
};
|
||||||
|
|
||||||
std::function<void(const Token *, const ExprEngine::Value &, ExprEngine::DataBase *)> checkFunctionCall = [=](const Token *tok, const ExprEngine::Value &value, ExprEngine::DataBase *dataBase) {
|
std::function<void(const Token *, const ExprEngine::Value &, ExprEngine::DataBase *)> checkFunctionCall = [=](const Token *tok, const ExprEngine::Value &value, ExprEngine::DataBase *dataBase) {
|
||||||
|
@ -2479,14 +2550,12 @@ void ExprEngine::runChecks(ErrorLogger *errorLogger, const Tokenizer *tokenizer,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!bad.empty()) {
|
if (!bad.empty()) {
|
||||||
dataBase->addError(tok->linenr());
|
dataBase->reportError(tok,
|
||||||
std::list<const Token*> callstack{tok};
|
Severity::SeverityType::error,
|
||||||
ErrorMessage errmsg(callstack,
|
"bughuntingInvalidArgValue",
|
||||||
&tokenizer->list,
|
"There is function call, cannot determine that " + std::to_string(num) + getOrdinalText(num) + " argument value meets the attribute " + bad,
|
||||||
Severity::SeverityType::error,
|
CWE(0),
|
||||||
"bughuntingInvalidArgValue",
|
false);
|
||||||
"There is function call, cannot determine that " + std::to_string(num) + getOrdinalText(num) + " argument value meets the attribute " + bad, CWE(0), false);
|
|
||||||
errorLogger->reportErr(errmsg);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2531,10 +2600,7 @@ void ExprEngine::runChecks(ErrorLogger *errorLogger, const Tokenizer *tokenizer,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
dataBase->addError(tok->linenr());
|
dataBase->reportError(tok, Severity::SeverityType::error, "bughuntingInvalidArgValue", "There is function call, cannot determine that " + std::to_string(num) + getOrdinalText(num) + " argument value is valid. Bad value: " + bad, CWE(0), false);
|
||||||
std::list<const Token*> callstack{tok};
|
|
||||||
ErrorMessage errmsg(callstack, &tokenizer->list, Severity::SeverityType::error, "bughuntingInvalidArgValue", "There is function call, cannot determine that " + std::to_string(num) + getOrdinalText(num) + " argument value is valid. Bad value: " + bad, CWE(0), false);
|
|
||||||
errorLogger->reportErr(errmsg);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2545,10 +2611,7 @@ void ExprEngine::runChecks(ErrorLogger *errorLogger, const Tokenizer *tokenizer,
|
||||||
auto index0 = std::make_shared<ExprEngine::IntRange>("0", 0, 0);
|
auto index0 = std::make_shared<ExprEngine::IntRange>("0", 0, 0);
|
||||||
for (const auto &v: arrayValue.read(index0)) {
|
for (const auto &v: arrayValue.read(index0)) {
|
||||||
if (v.second->isUninit()) {
|
if (v.second->isUninit()) {
|
||||||
dataBase->addError(tok->linenr());
|
dataBase->reportError(tok, Severity::SeverityType::error, "bughuntingUninitArg", "There is function call, cannot determine that " + std::to_string(num) + getOrdinalText(num) + " argument is initialized.", CWE_USE_OF_UNINITIALIZED_VARIABLE, false);
|
||||||
std::list<const Token*> callstack{tok};
|
|
||||||
ErrorMessage errmsg(callstack, &tokenizer->list, Severity::SeverityType::error, "bughuntingUninitArg", "There is function call, cannot determine that " + std::to_string(num) + getOrdinalText(num) + " argument is initialized.", CWE_USE_OF_UNINITIALIZED_VARIABLE, false);
|
|
||||||
errorLogger->reportErr(errmsg);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2568,22 +2631,14 @@ void ExprEngine::runChecks(ErrorLogger *errorLogger, const Tokenizer *tokenizer,
|
||||||
|
|
||||||
MathLib::bigint low;
|
MathLib::bigint low;
|
||||||
if (vartok->getCppcheckAttribute(TokenImpl::CppcheckAttributes::Type::LOW, &low)) {
|
if (vartok->getCppcheckAttribute(TokenImpl::CppcheckAttributes::Type::LOW, &low)) {
|
||||||
if (value.isLessThan(dataBase, low)) {
|
if (value.isLessThan(dataBase, low))
|
||||||
dataBase->addError(tok->linenr());
|
dataBase->reportError(tok, Severity::SeverityType::error, "bughuntingAssign", "There is assignment, cannot determine that value is greater or equal with " + std::to_string(low), CWE_INCORRECT_CALCULATION, false);
|
||||||
std::list<const Token*> callstack{tok};
|
|
||||||
ErrorMessage errmsg(callstack, &tokenizer->list, Severity::SeverityType::error, "bughuntingAssign", "There is assignment, cannot determine that value is greater or equal with " + std::to_string(low), CWE_INCORRECT_CALCULATION, false);
|
|
||||||
errorLogger->reportErr(errmsg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MathLib::bigint high;
|
MathLib::bigint high;
|
||||||
if (vartok->getCppcheckAttribute(TokenImpl::CppcheckAttributes::Type::HIGH, &high)) {
|
if (vartok->getCppcheckAttribute(TokenImpl::CppcheckAttributes::Type::HIGH, &high)) {
|
||||||
if (value.isGreaterThan(dataBase, high)) {
|
if (value.isGreaterThan(dataBase, high))
|
||||||
dataBase->addError(tok->linenr());
|
dataBase->reportError(tok, Severity::SeverityType::error, "bughuntingAssign", "There is assignment, cannot determine that value is lower or equal with " + std::to_string(high), CWE_INCORRECT_CALCULATION, false);
|
||||||
std::list<const Token*> callstack{tok};
|
|
||||||
ErrorMessage errmsg(callstack, &tokenizer->list, Severity::SeverityType::error, "bughuntingAssign", "There is assignment, cannot determine that value is lower or equal with " + std::to_string(high), CWE_INCORRECT_CALCULATION, false);
|
|
||||||
errorLogger->reportErr(errmsg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "errortypes.h"
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
@ -78,9 +79,15 @@ namespace ExprEngine {
|
||||||
virtual std::string getNewSymbolName() = 0;
|
virtual std::string getNewSymbolName() = 0;
|
||||||
const std::string currentFunction;
|
const std::string currentFunction;
|
||||||
const Settings * const settings;
|
const Settings * const settings;
|
||||||
virtual void addError(int linenr) {
|
virtual void reportError(const Token *tok,
|
||||||
(void)linenr;
|
Severity::SeverityType severity,
|
||||||
}
|
const char id[],
|
||||||
|
const std::string &text,
|
||||||
|
CWE cwe,
|
||||||
|
bool inconclusive,
|
||||||
|
bool incomplete=false,
|
||||||
|
const std::string functionName = std::string()) = 0;
|
||||||
|
ErrorPath errorPath;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Value {
|
class Value {
|
||||||
|
|
Loading…
Reference in New Issue