diff --git a/gui/erroritem.cpp b/gui/erroritem.cpp index b0ef6a1e2..6037dcacd 100644 --- a/gui/erroritem.cpp +++ b/gui/erroritem.cpp @@ -34,6 +34,7 @@ bool operator==(const QErrorPathItem &i1, const QErrorPathItem &i2) ErrorItem::ErrorItem() : severity(Severity::none) + , incomplete(false) , inconclusive(false) , cwe(-1) { @@ -44,6 +45,7 @@ ErrorItem::ErrorItem(const ErrorLogger::ErrorMessage &errmsg) , function(QString::fromStdString(errmsg.function)) , errorId(QString::fromStdString(errmsg.id)) , severity(errmsg.severity) + , incomplete(errmsg.incomplete) , inconclusive(errmsg.inconclusive) , summary(QString::fromStdString(errmsg.shortMessage())) , message(QString::fromStdString(errmsg.verboseMessage())) diff --git a/gui/erroritem.h b/gui/erroritem.h index 35dbc1f64..6adb49a90 100644 --- a/gui/erroritem.h +++ b/gui/erroritem.h @@ -83,6 +83,7 @@ public: QString function; QString errorId; Severity::SeverityType severity; + bool incomplete; bool inconclusive; QString summary; QString message; @@ -111,6 +112,8 @@ public: unsigned int line; QString file0; QString errorId; + bool incomplete; + int cwe; bool inconclusive; Severity::SeverityType severity; QString summary; diff --git a/gui/resultstree.cpp b/gui/resultstree.cpp index bf99b4501..7ae34a0a0 100644 --- a/gui/resultstree.cpp +++ b/gui/resultstree.cpp @@ -166,6 +166,8 @@ bool ResultsTree::addErrorItem(const ErrorItem &item) line.file = realfile; line.line = loc.line; line.errorId = item.errorId; + line.incomplete = item.incomplete; + line.cwe = item.cwe; line.inconclusive = item.inconclusive; line.summary = item.summary; line.message = item.message; @@ -186,7 +188,6 @@ bool ResultsTree::addErrorItem(const ErrorItem &item) //Add user data to that item QMap data; - data["hide"] = false; data["severity"] = ShowTypes::SeverityToShowType(item.severity); data["summary"] = item.summary; data["message"] = item.message; @@ -194,6 +195,8 @@ bool ResultsTree::addErrorItem(const ErrorItem &item) data["line"] = loc.line; data["column"] = loc.column; data["id"] = item.errorId; + data["incomplete"] = item.incomplete; + data["cwe"] = item.cwe; data["inconclusive"] = item.inconclusive; data["file0"] = stripPath(item.file0, true); data["function"] = item.function; @@ -227,6 +230,8 @@ bool ResultsTree::addErrorItem(const ErrorItem &item) child_data["line"] = e.line; child_data["column"] = e.column; child_data["id"] = line.errorId; + child_data["incomplete"] = line.incomplete; + child_data["cwe"] = line.cwe; child_data["inconclusive"] = line.inconclusive; 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->message = data["message"].toString(); item->errorId = data["id"].toString(); + item->incomplete = data["incomplete"].toBool(); + item->cwe = data["cwe"].toInt(); item->inconclusive = data["inconclusive"].toBool(); item->file0 = data["file0"].toString(); item->sinceDate = data["sinceDate"].toString(); diff --git a/gui/resultstree.h b/gui/resultstree.h index 0b7ce8e4b..55303cc6d 100644 --- a/gui/resultstree.h +++ b/gui/resultstree.h @@ -92,6 +92,12 @@ public: */ 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 * @@ -384,14 +390,6 @@ protected: const QString &icon, 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. * @param severity Severity to convert diff --git a/gui/resultsview.cpp b/gui/resultsview.cpp index 117f8af89..5eb214bcb 100644 --- a/gui/resultsview.cpp +++ b/gui/resultsview.cpp @@ -286,6 +286,10 @@ void ResultsView::checkingFinished() mUI.mProgress->setVisible(false); 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? if (mShowNoErrorsMessage) { //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())) 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()) formattedMsg.prepend(tr("Id") + ": " + data["id"].toString() + "\n"); + if (data["incomplete"].toBool()) + formattedMsg += "\n" + tr("Bug hunting analysis is incomplete"); mUI.mDetails->setText(formattedMsg); const int lineNumber = data["line"].toInt(); diff --git a/lib/errorlogger.cpp b/lib/errorlogger.cpp index b03c5d388..d7f790a09 100644 --- a/lib/errorlogger.cpp +++ b/lib/errorlogger.cpp @@ -59,7 +59,7 @@ InternalError::InternalError(const Token *tok, const std::string &errorMsg, Type } 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 &callStack id(id), // set the message id file0(file1), severity(severity), // severity for this error message + incomplete(false), cwe(0U), inconclusive(inconclusive) { @@ -82,6 +83,7 @@ ErrorLogger::ErrorMessage::ErrorMessage(const std::list &callStack id(id), // set the message id file0(file1), severity(severity), // severity for this error message + incomplete(false), cwe(cwe.id), inconclusive(inconclusive) { @@ -90,7 +92,7 @@ ErrorLogger::ErrorMessage::ErrorMessage(const std::list &callStack } ErrorLogger::ErrorMessage::ErrorMessage(const std::list& 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 for (std::list::const_iterator it = callstack.begin(); it != callstack.end(); ++it) { @@ -109,7 +111,7 @@ ErrorLogger::ErrorMessage::ErrorMessage(const std::list& callstack ErrorLogger::ErrorMessage::ErrorMessage(const std::list& 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 for (const Token *tok: callstack) { @@ -127,7 +129,7 @@ ErrorLogger::ErrorMessage::ErrorMessage(const std::list& 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) - : id(id), severity(severity), cwe(cwe.id), inconclusive(inconclusive) + : id(id), severity(severity), incomplete(false), cwe(cwe.id), inconclusive(inconclusive) { // Format callstack 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) : severity(Severity::none), + incomplete(false), cwe(0U), inconclusive(false) { diff --git a/lib/errorlogger.h b/lib/errorlogger.h index d91cb35b0..86eb41bca 100644 --- a/lib/errorlogger.h +++ b/lib/errorlogger.h @@ -318,6 +318,8 @@ public: std::string file0; /** For GUI bug hunting; function name */ std::string function; + /** For GUI bug hunting; incomplete analysis */ + bool incomplete; Severity::SeverityType severity; CWE cwe; diff --git a/lib/exprengine.cpp b/lib/exprengine.cpp index 65aff465c..8536d0437 100644 --- a/lib/exprengine.cpp +++ b/lib/exprengine.cpp @@ -1425,8 +1425,8 @@ static void checkContract(Data &data, const Token *tok, const Function *function id, "Function '" + function->name() + "' is called, can not determine that its contract '" + functionExpects + "' is always met.", CWE(0), - bailoutValue); - + false); + errmsg.incomplete = bailoutValue; errmsg.function = functionName; data.errorLogger->reportErr(errmsg); } @@ -1443,7 +1443,8 @@ static void checkContract(Data &data, const Token *tok, const Function *function id, "Function '" + function->name() + "' is called, can not determine that its contract is always met.", CWE(0), - true); + false); + errmsg.incomplete = true; data.errorLogger->reportErr(errmsg); } } @@ -2121,9 +2122,11 @@ void ExprEngine::runChecks(ErrorLogger *errorLogger, const Tokenizer *tokenizer, std::list callstack{settings->clang ? tok : tok->astParent()}; const char * const id = (tok->valueType() && tok->valueType()->isFloat()) ? "bughuntingDivByZeroFloat" : "bughuntingDivByZero"; 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) errmsg.function = dataBase->currentFunction; + else + errmsg.incomplete = bailout; errorLogger->reportErr(errmsg); } };