Bug hunting; Add new 'incomplete' flag for error messages. Used when analysis is incomplete.

This commit is contained in:
Daniel Marjamäki 2020-05-03 17:20:38 +02:00
parent 0f6d8546cd
commit b5094f298a
8 changed files with 43 additions and 17 deletions

View File

@ -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()))

View File

@ -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;

View File

@ -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();

View File

@ -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

View File

@ -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();

View File

@ -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)
{ {

View File

@ -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;

View File

@ -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);
} }
}; };