Bug hunting; Add new 'incomplete' flag for error messages. Used when analysis is incomplete.
This commit is contained in:
parent
0f6d8546cd
commit
b5094f298a
|
@ -34,6 +34,7 @@ bool operator==(const QErrorPathItem &i1, const QErrorPathItem &i2)
|
||||||
|
|
||||||
ErrorItem::ErrorItem()
|
ErrorItem::ErrorItem()
|
||||||
: severity(Severity::none)
|
: severity(Severity::none)
|
||||||
|
, incomplete(false)
|
||||||
, inconclusive(false)
|
, inconclusive(false)
|
||||||
, cwe(-1)
|
, cwe(-1)
|
||||||
{
|
{
|
||||||
|
@ -44,6 +45,7 @@ ErrorItem::ErrorItem(const ErrorLogger::ErrorMessage &errmsg)
|
||||||
, function(QString::fromStdString(errmsg.function))
|
, function(QString::fromStdString(errmsg.function))
|
||||||
, errorId(QString::fromStdString(errmsg.id))
|
, errorId(QString::fromStdString(errmsg.id))
|
||||||
, severity(errmsg.severity)
|
, severity(errmsg.severity)
|
||||||
|
, incomplete(errmsg.incomplete)
|
||||||
, inconclusive(errmsg.inconclusive)
|
, inconclusive(errmsg.inconclusive)
|
||||||
, summary(QString::fromStdString(errmsg.shortMessage()))
|
, summary(QString::fromStdString(errmsg.shortMessage()))
|
||||||
, message(QString::fromStdString(errmsg.verboseMessage()))
|
, message(QString::fromStdString(errmsg.verboseMessage()))
|
||||||
|
|
|
@ -83,6 +83,7 @@ public:
|
||||||
QString function;
|
QString function;
|
||||||
QString errorId;
|
QString errorId;
|
||||||
Severity::SeverityType severity;
|
Severity::SeverityType severity;
|
||||||
|
bool incomplete;
|
||||||
bool inconclusive;
|
bool inconclusive;
|
||||||
QString summary;
|
QString summary;
|
||||||
QString message;
|
QString message;
|
||||||
|
@ -111,6 +112,8 @@ public:
|
||||||
unsigned int line;
|
unsigned int line;
|
||||||
QString file0;
|
QString file0;
|
||||||
QString errorId;
|
QString errorId;
|
||||||
|
bool incomplete;
|
||||||
|
int cwe;
|
||||||
bool inconclusive;
|
bool inconclusive;
|
||||||
Severity::SeverityType severity;
|
Severity::SeverityType severity;
|
||||||
QString summary;
|
QString summary;
|
||||||
|
|
|
@ -166,6 +166,8 @@ bool ResultsTree::addErrorItem(const ErrorItem &item)
|
||||||
line.file = realfile;
|
line.file = realfile;
|
||||||
line.line = loc.line;
|
line.line = loc.line;
|
||||||
line.errorId = item.errorId;
|
line.errorId = item.errorId;
|
||||||
|
line.incomplete = item.incomplete;
|
||||||
|
line.cwe = item.cwe;
|
||||||
line.inconclusive = item.inconclusive;
|
line.inconclusive = item.inconclusive;
|
||||||
line.summary = item.summary;
|
line.summary = item.summary;
|
||||||
line.message = item.message;
|
line.message = item.message;
|
||||||
|
@ -186,7 +188,6 @@ bool ResultsTree::addErrorItem(const ErrorItem &item)
|
||||||
|
|
||||||
//Add user data to that item
|
//Add user data to that item
|
||||||
QMap<QString, QVariant> data;
|
QMap<QString, QVariant> data;
|
||||||
data["hide"] = false;
|
|
||||||
data["severity"] = ShowTypes::SeverityToShowType(item.severity);
|
data["severity"] = ShowTypes::SeverityToShowType(item.severity);
|
||||||
data["summary"] = item.summary;
|
data["summary"] = item.summary;
|
||||||
data["message"] = item.message;
|
data["message"] = item.message;
|
||||||
|
@ -194,6 +195,8 @@ bool ResultsTree::addErrorItem(const ErrorItem &item)
|
||||||
data["line"] = loc.line;
|
data["line"] = loc.line;
|
||||||
data["column"] = loc.column;
|
data["column"] = loc.column;
|
||||||
data["id"] = item.errorId;
|
data["id"] = item.errorId;
|
||||||
|
data["incomplete"] = item.incomplete;
|
||||||
|
data["cwe"] = item.cwe;
|
||||||
data["inconclusive"] = item.inconclusive;
|
data["inconclusive"] = item.inconclusive;
|
||||||
data["file0"] = stripPath(item.file0, true);
|
data["file0"] = stripPath(item.file0, true);
|
||||||
data["function"] = item.function;
|
data["function"] = item.function;
|
||||||
|
@ -227,6 +230,8 @@ bool ResultsTree::addErrorItem(const ErrorItem &item)
|
||||||
child_data["line"] = e.line;
|
child_data["line"] = e.line;
|
||||||
child_data["column"] = e.column;
|
child_data["column"] = e.column;
|
||||||
child_data["id"] = line.errorId;
|
child_data["id"] = line.errorId;
|
||||||
|
child_data["incomplete"] = line.incomplete;
|
||||||
|
child_data["cwe"] = line.cwe;
|
||||||
child_data["inconclusive"] = line.inconclusive;
|
child_data["inconclusive"] = line.inconclusive;
|
||||||
child_item->setData(QVariant(child_data));
|
child_item->setData(QVariant(child_data));
|
||||||
}
|
}
|
||||||
|
@ -1214,6 +1219,8 @@ void ResultsTree::readErrorItem(const QStandardItem *error, ErrorItem *item) con
|
||||||
item->summary = data["summary"].toString();
|
item->summary = data["summary"].toString();
|
||||||
item->message = data["message"].toString();
|
item->message = data["message"].toString();
|
||||||
item->errorId = data["id"].toString();
|
item->errorId = data["id"].toString();
|
||||||
|
item->incomplete = data["incomplete"].toBool();
|
||||||
|
item->cwe = data["cwe"].toInt();
|
||||||
item->inconclusive = data["inconclusive"].toBool();
|
item->inconclusive = data["inconclusive"].toBool();
|
||||||
item->file0 = data["file0"].toString();
|
item->file0 = data["file0"].toString();
|
||||||
item->sinceDate = data["sinceDate"].toString();
|
item->sinceDate = data["sinceDate"].toString();
|
||||||
|
|
|
@ -92,6 +92,12 @@ public:
|
||||||
*/
|
*/
|
||||||
void showHiddenResults();
|
void showHiddenResults();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Refresh tree by checking which of the items should be shown
|
||||||
|
* and which should be hidden
|
||||||
|
*/
|
||||||
|
void refreshTree();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Save results to a text stream
|
* @brief Save results to a text stream
|
||||||
*
|
*
|
||||||
|
@ -384,14 +390,6 @@ protected:
|
||||||
const QString &icon,
|
const QString &icon,
|
||||||
bool childOfMessage);
|
bool childOfMessage);
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Refresh tree by checking which of the items should be shown
|
|
||||||
* and which should be hidden
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void refreshTree();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Convert Severity to translated string for GUI.
|
* @brief Convert Severity to translated string for GUI.
|
||||||
* @param severity Severity to convert
|
* @param severity Severity to convert
|
||||||
|
|
|
@ -286,6 +286,10 @@ void ResultsView::checkingFinished()
|
||||||
mUI.mProgress->setVisible(false);
|
mUI.mProgress->setVisible(false);
|
||||||
mUI.mProgress->setFormat("%p%");
|
mUI.mProgress->setFormat("%p%");
|
||||||
|
|
||||||
|
// TODO: Items can be mysteriously hidden when checking is finished, this function
|
||||||
|
// call should be redundant but it "unhides" the wrongly hidden items.
|
||||||
|
mUI.mTree->refreshTree();
|
||||||
|
|
||||||
//Should we inform user of non visible/not found errors?
|
//Should we inform user of non visible/not found errors?
|
||||||
if (mShowNoErrorsMessage) {
|
if (mShowNoErrorsMessage) {
|
||||||
//Tell user that we found no errors
|
//Tell user that we found no errors
|
||||||
|
@ -415,8 +419,12 @@ void ResultsView::updateDetails(const QModelIndex &index)
|
||||||
if (!file0.isEmpty() && Path::isHeader(data["file"].toString().toStdString()))
|
if (!file0.isEmpty() && Path::isHeader(data["file"].toString().toStdString()))
|
||||||
formattedMsg += QString("\n\n%1: %2").arg(tr("First included by")).arg(QDir::toNativeSeparators(file0));
|
formattedMsg += QString("\n\n%1: %2").arg(tr("First included by")).arg(QDir::toNativeSeparators(file0));
|
||||||
|
|
||||||
|
if (data["cwe"].toInt() > 0)
|
||||||
|
formattedMsg.prepend("CWE: " + QString::number(data["cwe"].toInt()) + "\n");
|
||||||
if (mUI.mTree->showIdColumn())
|
if (mUI.mTree->showIdColumn())
|
||||||
formattedMsg.prepend(tr("Id") + ": " + data["id"].toString() + "\n");
|
formattedMsg.prepend(tr("Id") + ": " + data["id"].toString() + "\n");
|
||||||
|
if (data["incomplete"].toBool())
|
||||||
|
formattedMsg += "\n" + tr("Bug hunting analysis is incomplete");
|
||||||
mUI.mDetails->setText(formattedMsg);
|
mUI.mDetails->setText(formattedMsg);
|
||||||
|
|
||||||
const int lineNumber = data["line"].toInt();
|
const int lineNumber = data["line"].toInt();
|
||||||
|
|
|
@ -59,7 +59,7 @@ InternalError::InternalError(const Token *tok, const std::string &errorMsg, Type
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorLogger::ErrorMessage::ErrorMessage()
|
ErrorLogger::ErrorMessage::ErrorMessage()
|
||||||
: severity(Severity::none), cwe(0U), inconclusive(false)
|
: severity(Severity::none), incomplete(false), cwe(0U), inconclusive(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,6 +68,7 @@ ErrorLogger::ErrorMessage::ErrorMessage(const std::list<FileLocation> &callStack
|
||||||
id(id), // set the message id
|
id(id), // set the message id
|
||||||
file0(file1),
|
file0(file1),
|
||||||
severity(severity), // severity for this error message
|
severity(severity), // severity for this error message
|
||||||
|
incomplete(false),
|
||||||
cwe(0U),
|
cwe(0U),
|
||||||
inconclusive(inconclusive)
|
inconclusive(inconclusive)
|
||||||
{
|
{
|
||||||
|
@ -82,6 +83,7 @@ ErrorLogger::ErrorMessage::ErrorMessage(const std::list<FileLocation> &callStack
|
||||||
id(id), // set the message id
|
id(id), // set the message id
|
||||||
file0(file1),
|
file0(file1),
|
||||||
severity(severity), // severity for this error message
|
severity(severity), // severity for this error message
|
||||||
|
incomplete(false),
|
||||||
cwe(cwe.id),
|
cwe(cwe.id),
|
||||||
inconclusive(inconclusive)
|
inconclusive(inconclusive)
|
||||||
{
|
{
|
||||||
|
@ -90,7 +92,7 @@ ErrorLogger::ErrorMessage::ErrorMessage(const std::list<FileLocation> &callStack
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorLogger::ErrorMessage::ErrorMessage(const std::list<const Token*>& callstack, const TokenList* list, Severity::SeverityType severity, const std::string& id, const std::string& msg, bool inconclusive)
|
ErrorLogger::ErrorMessage::ErrorMessage(const std::list<const Token*>& callstack, const TokenList* list, Severity::SeverityType severity, const std::string& id, const std::string& msg, bool inconclusive)
|
||||||
: id(id), severity(severity), cwe(0U), inconclusive(inconclusive)
|
: id(id), severity(severity), incomplete(false), cwe(0U), inconclusive(inconclusive)
|
||||||
{
|
{
|
||||||
// Format callstack
|
// Format callstack
|
||||||
for (std::list<const Token *>::const_iterator it = callstack.begin(); it != callstack.end(); ++it) {
|
for (std::list<const Token *>::const_iterator it = callstack.begin(); it != callstack.end(); ++it) {
|
||||||
|
@ -109,7 +111,7 @@ ErrorLogger::ErrorMessage::ErrorMessage(const std::list<const Token*>& callstack
|
||||||
|
|
||||||
|
|
||||||
ErrorLogger::ErrorMessage::ErrorMessage(const std::list<const Token*>& callstack, const TokenList* list, Severity::SeverityType severity, const std::string& id, const std::string& msg, const CWE &cwe, bool inconclusive)
|
ErrorLogger::ErrorMessage::ErrorMessage(const std::list<const Token*>& callstack, const TokenList* list, Severity::SeverityType severity, const std::string& id, const std::string& msg, const CWE &cwe, bool inconclusive)
|
||||||
: id(id), severity(severity), cwe(cwe.id), inconclusive(inconclusive)
|
: id(id), severity(severity), incomplete(false), cwe(cwe.id), inconclusive(inconclusive)
|
||||||
{
|
{
|
||||||
// Format callstack
|
// Format callstack
|
||||||
for (const Token *tok: callstack) {
|
for (const Token *tok: callstack) {
|
||||||
|
@ -127,7 +129,7 @@ ErrorLogger::ErrorMessage::ErrorMessage(const std::list<const Token*>& callstack
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorLogger::ErrorMessage::ErrorMessage(const ErrorPath &errorPath, const TokenList *tokenList, Severity::SeverityType severity, const char id[], const std::string &msg, const CWE &cwe, bool inconclusive)
|
ErrorLogger::ErrorMessage::ErrorMessage(const ErrorPath &errorPath, const TokenList *tokenList, Severity::SeverityType severity, const char id[], const std::string &msg, const CWE &cwe, bool inconclusive)
|
||||||
: id(id), severity(severity), cwe(cwe.id), inconclusive(inconclusive)
|
: id(id), severity(severity), incomplete(false), cwe(cwe.id), inconclusive(inconclusive)
|
||||||
{
|
{
|
||||||
// Format callstack
|
// Format callstack
|
||||||
for (ErrorPath::const_iterator it = errorPath.begin(); it != errorPath.end(); ++it) {
|
for (ErrorPath::const_iterator it = errorPath.begin(); it != errorPath.end(); ++it) {
|
||||||
|
@ -147,6 +149,7 @@ ErrorLogger::ErrorMessage::ErrorMessage(const ErrorPath &errorPath, const TokenL
|
||||||
|
|
||||||
ErrorLogger::ErrorMessage::ErrorMessage(const tinyxml2::XMLElement * const errmsg)
|
ErrorLogger::ErrorMessage::ErrorMessage(const tinyxml2::XMLElement * const errmsg)
|
||||||
: severity(Severity::none),
|
: severity(Severity::none),
|
||||||
|
incomplete(false),
|
||||||
cwe(0U),
|
cwe(0U),
|
||||||
inconclusive(false)
|
inconclusive(false)
|
||||||
{
|
{
|
||||||
|
|
|
@ -318,6 +318,8 @@ public:
|
||||||
std::string file0;
|
std::string file0;
|
||||||
/** For GUI bug hunting; function name */
|
/** For GUI bug hunting; function name */
|
||||||
std::string function;
|
std::string function;
|
||||||
|
/** For GUI bug hunting; incomplete analysis */
|
||||||
|
bool incomplete;
|
||||||
|
|
||||||
Severity::SeverityType severity;
|
Severity::SeverityType severity;
|
||||||
CWE cwe;
|
CWE cwe;
|
||||||
|
|
|
@ -1425,8 +1425,8 @@ static void checkContract(Data &data, const Token *tok, const Function *function
|
||||||
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),
|
||||||
bailoutValue);
|
false);
|
||||||
|
errmsg.incomplete = bailoutValue;
|
||||||
errmsg.function = functionName;
|
errmsg.function = functionName;
|
||||||
data.errorLogger->reportErr(errmsg);
|
data.errorLogger->reportErr(errmsg);
|
||||||
}
|
}
|
||||||
|
@ -1443,7 +1443,8 @@ static void checkContract(Data &data, const Token *tok, const Function *function
|
||||||
id,
|
id,
|
||||||
"Function '" + function->name() + "' is called, can not determine that its contract is always met.",
|
"Function '" + function->name() + "' is called, can not determine that its contract is always met.",
|
||||||
CWE(0),
|
CWE(0),
|
||||||
true);
|
false);
|
||||||
|
errmsg.incomplete = true;
|
||||||
data.errorLogger->reportErr(errmsg);
|
data.errorLogger->reportErr(errmsg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2121,9 +2122,11 @@ void ExprEngine::runChecks(ErrorLogger *errorLogger, const Tokenizer *tokenizer,
|
||||||
std::list<const Token*> callstack{settings->clang ? tok : tok->astParent()};
|
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);
|
||||||
ErrorLogger::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), bailout);
|
ErrorLogger::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);
|
||||||
if (!bailout)
|
if (!bailout)
|
||||||
errmsg.function = dataBase->currentFunction;
|
errmsg.function = dataBase->currentFunction;
|
||||||
|
else
|
||||||
|
errmsg.incomplete = bailout;
|
||||||
errorLogger->reportErr(errmsg);
|
errorLogger->reportErr(errmsg);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue