Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
86 commits
Select commit Hold shift + click to select a range
14358c8
add description for sarif based on id so github doesnt show same text…
Nettozx Jul 1, 2025
1ae55cf
better description handling and add rule.name to serialize
Nettozx Jul 1, 2025
79ac227
only set severity level for security related sarif findings
Nettozx Jul 1, 2025
69f3660
set problem severity for non security findings
Nettozx Jul 1, 2025
4535112
no prefix string, and always set problem severity
Nettozx Jul 1, 2025
dc43e84
set defaultConfiguration to the same severity level
Nettozx Jul 1, 2025
890d5b1
oops it was already there
Nettozx Jul 2, 2025
b43cca3
guess recommendation is not valid even though the github documentatio…
Nettozx Jul 2, 2025
0b8785f
security-severity needs to be a string
Nettozx Jul 2, 2025
7dd044e
try short message for name
Nettozx Jul 2, 2025
d52efa7
update description functions to fallback to values from finding. add …
Nettozx Jul 2, 2025
f379da1
change name back to short desc, change short desc to shortMessage, up…
Nettozx Jul 2, 2025
0e48504
revert the shortDescription value, that causes the original issue to …
Nettozx Jul 2, 2025
938788d
update comment
Nettozx Jul 2, 2025
706913a
more comment updates
Nettozx Jul 2, 2025
8033d32
add to authors
Nettozx Jul 2, 2025
49c6134
braces
Nettozx Jul 2, 2025
c2c16bd
unit tests
Nettozx Jul 2, 2025
40f36bc
remove duplicate code
Nettozx Jul 2, 2025
dca6a13
match sarifSeverity for security-severity levels
Nettozx Jul 2, 2025
7eedb24
fix misconception about isCriticalErrorId()
Nettozx Jul 2, 2025
76ad903
update unit test
Nettozx Jul 2, 2025
29aaecc
test generic message builder
Nettozx Jul 2, 2025
3023b39
add more regex to handle empty qutoes and extra spaces
Nettozx Jul 2, 2025
17ffc24
formatting
Nettozx Jul 2, 2025
3000f92
add more pattern recognition for generification output. update messag…
Nettozx Jul 2, 2025
433ddde
uncrustify downloaded from link has _f suffix, update DETECTED_VERSIO…
Nettozx Jul 2, 2025
40fcaaa
added unit tests for sarif and ran uncrustify
Nettozx Jul 2, 2025
2109f05
add cwe tags
Nettozx Jul 2, 2025
4d6f508
add tests for cwe tags
Nettozx Jul 2, 2025
cf231bf
fix regex issues for repeated varnames and empty brackets. fix issue …
Nettozx Jul 2, 2025
370c7d6
add more sarif test cases
Nettozx Jul 2, 2025
7f5b4a3
fix issue for invalidScanfArgType_int output not being generic
Nettozx Jul 2, 2025
824e273
fix scanf regex and add unit test for it
Nettozx Jul 2, 2025
c1f6a41
remove ruleID specific pattern matching and define generic regex that…
Nettozx Jul 2, 2025
6f63179
fix column number being 0 issue
Nettozx Jul 3, 2025
9009cc3
allow cwe tags for all rules and not just security related
Nettozx Jul 3, 2025
3934973
more regex patterns to cover more instance specific data coming throu…
Nettozx Jul 3, 2025
e6487ae
make description getters static
Nettozx Jul 3, 2025
fd12bf2
move logic to errorlogger and make generic member
Nettozx Jul 15, 2025
9e7b493
more regex and cleanup duplicate logic
Nettozx Jul 15, 2025
d4d73b2
make it more simpler, remove generic for xml, update tests
Nettozx Jul 15, 2025
ba900cd
run uncrustify
Nettozx Jul 15, 2025
c24fb46
just make everything empty strings because github will then default t…
Nettozx Jul 16, 2025
e51f922
dont need generic message anymore
Nettozx Jul 17, 2025
98f15c1
revert error logger tests
Nettozx Jul 17, 2025
94c7c76
remove irrelevant tests
Nettozx Jul 17, 2025
c03b22e
add test case to check instance specific error messages
Nettozx Jul 17, 2025
1bb8d9c
run uncrustify
Nettozx Jul 17, 2025
91e337f
add description
Nettozx Jul 17, 2025
8d3f483
cross platform approach to running tests copied from cppcheckexecutor
Nettozx Jul 17, 2025
44af45e
run uncrustify
Nettozx Jul 17, 2025
f505636
remove any unneccessary changes
Nettozx Jul 17, 2025
41e75c4
revert formatting changes made by uncrustify. use ss instead of to_st…
Nettozx Jul 17, 2025
f34bea1
fix selfcheck issues
Nettozx Jul 17, 2025
4c140e1
add attempts at other executable paths
Nettozx Jul 17, 2025
b746746
fix clang-tidy issues
Nettozx Jul 17, 2025
92c64d4
few more braces
Nettozx Jul 17, 2025
2e9d793
revert a few more spacing
Nettozx Jul 17, 2025
a02cf35
cmake executable path in test, and clang-tidy fixes
Nettozx Jul 18, 2025
9213093
empty spaces
Nettozx Jul 18, 2025
43af896
fix selfcheck issues
Nettozx Jul 18, 2025
47b62e4
fix clang-tidy issues
Nettozx Jul 18, 2025
dbce578
add helper since selfcheck complains both ways
Nettozx Jul 19, 2025
299d61a
fix formatter complaint
Nettozx Jul 19, 2025
f756552
fix dmake issue
Nettozx Jul 20, 2025
8a59d00
windows executable path changed since last merge
Nettozx Jul 21, 2025
dba1ef9
move sarif reporter to its own class so it can be used for tests, cha…
Nettozx Jul 31, 2025
38e8069
selfcheck and clangtidy fixes
Nettozx Aug 1, 2025
8c7a531
Move SarifReport class to lib directory to fix Windows DLL export issues
Nettozx Aug 1, 2025
bd1b29f
Fix Linux Makefile dependencies for moved sarifreport files
Nettozx Aug 1, 2025
ece5f5a
dmake
Nettozx Aug 1, 2025
07f0fe4
Fix picojson type conflicts in sarifreport - Remove incorrect forward…
Nettozx Aug 1, 2025
71d3991
dmake
Nettozx Aug 1, 2025
976008e
formatting
Nettozx Aug 1, 2025
00247ca
default constructors in header
Nettozx Sep 30, 2025
669dfc3
move system tests to python script
Nettozx Sep 30, 2025
8b1e5ac
unit tests for sarifreport
Nettozx Sep 30, 2025
8619148
undo uncrustify fix
Nettozx Sep 30, 2025
c751918
formatting and python lint issues
Nettozx Sep 30, 2025
68cc214
clang tidy
Nettozx Sep 30, 2025
c0ebf70
fix windows build issue
Nettozx Sep 30, 2025
4de30a0
fix shadow var and format issues
Nettozx Sep 30, 2025
e2a8521
move unique error check above output format check
Nettozx Oct 14, 2025
783eb98
Merge branch 'main' into main
Nettozx Oct 16, 2025
fb42232
Merge branch 'main' into main
Nettozx Oct 23, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,7 @@ Tommy Bergman
Toralf Förster
Troshin V.S.
Tyson Nottingham
Usman Majid
Valentin Batz
Valerii Lashmanov
Vasily Maslyukov
Expand Down
12 changes: 10 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ ifndef INCLUDE_FOR_CLI
endif

ifndef INCLUDE_FOR_TEST
INCLUDE_FOR_TEST=-Ilib -Ifrontend -Icli -isystem externals/simplecpp -isystem externals/tinyxml2
INCLUDE_FOR_TEST=-Ilib -Ifrontend -Icli -isystem externals/picojson -isystem externals/simplecpp -isystem externals/tinyxml2
endif

ifndef CFLAGS_FOR_TEST
Expand Down Expand Up @@ -249,6 +249,7 @@ LIBOBJ = $(libcppdir)/valueflow.o \
$(libcppdir)/programmemory.o \
$(libcppdir)/regex.o \
$(libcppdir)/reverseanalyzer.o \
$(libcppdir)/sarifreport.o \
$(libcppdir)/settings.o \
$(libcppdir)/standards.o \
$(libcppdir)/summaries.o \
Expand Down Expand Up @@ -327,6 +328,7 @@ TESTOBJ = test/fixture.o \
test/testprocessexecutor.o \
test/testprogrammemory.o \
test/testregex.o \
test/testsarifreport.o \
test/testsettings.o \
test/testsimplifytemplate.o \
test/testsimplifytokens.o \
Expand Down Expand Up @@ -638,6 +640,9 @@ $(libcppdir)/regex.o: lib/regex.cpp lib/config.h lib/regex.h
$(libcppdir)/reverseanalyzer.o: lib/reverseanalyzer.cpp lib/addoninfo.h lib/analyzer.h lib/astutils.h lib/checkers.h lib/config.h lib/errortypes.h lib/forwardanalyzer.h lib/library.h lib/mathlib.h lib/platform.h lib/reverseanalyzer.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/utils.h lib/valueptr.h lib/vfvalue.h
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/reverseanalyzer.cpp

$(libcppdir)/sarifreport.o: lib/sarifreport.cpp externals/picojson/picojson.h lib/addoninfo.h lib/check.h lib/checkers.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/json.h lib/library.h lib/mathlib.h lib/platform.h lib/sarifreport.h lib/settings.h lib/standards.h lib/utils.h
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/sarifreport.cpp

$(libcppdir)/settings.o: lib/settings.cpp externals/picojson/picojson.h lib/addoninfo.h lib/checkers.h lib/config.h lib/errortypes.h lib/json.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/summaries.h lib/suppressions.h lib/utils.h lib/vfvalue.h
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/settings.cpp

Expand Down Expand Up @@ -683,7 +688,7 @@ frontend/frontend.o: frontend/frontend.cpp frontend/frontend.h lib/addoninfo.h l
cli/cmdlineparser.o: cli/cmdlineparser.cpp cli/cmdlinelogger.h cli/cmdlineparser.h cli/filelister.h externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/importproject.h lib/library.h lib/mathlib.h lib/path.h lib/pathmatch.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/utils.h lib/xml.h
$(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/cmdlineparser.cpp

cli/cppcheckexecutor.o: cli/cppcheckexecutor.cpp cli/cmdlinelogger.h cli/cmdlineparser.h cli/cppcheckexecutor.h cli/executor.h cli/processexecutor.h cli/sehwrapper.h cli/signalhandler.h cli/singleexecutor.h cli/threadexecutor.h externals/picojson/picojson.h lib/addoninfo.h lib/analyzerinfo.h lib/check.h lib/checkers.h lib/checkersreport.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/json.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h
cli/cppcheckexecutor.o: cli/cppcheckexecutor.cpp cli/cmdlinelogger.h cli/cmdlineparser.h cli/cppcheckexecutor.h cli/executor.h cli/processexecutor.h cli/sehwrapper.h cli/signalhandler.h cli/singleexecutor.h cli/threadexecutor.h externals/picojson/picojson.h lib/addoninfo.h lib/analyzerinfo.h lib/check.h lib/checkers.h lib/checkersreport.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/json.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/sarifreport.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h
$(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/cppcheckexecutor.cpp

cli/executor.o: cli/executor.cpp cli/executor.h lib/addoninfo.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h
Expand Down Expand Up @@ -854,6 +859,9 @@ test/testprogrammemory.o: test/testprogrammemory.cpp lib/addoninfo.h lib/check.h
test/testregex.o: test/testregex.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/utils.h test/fixture.h
$(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testregex.cpp

test/testsarifreport.o: test/testsarifreport.cpp externals/picojson/picojson.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/json.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/sarifreport.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h
$(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testsarifreport.cpp

test/testsettings.o: test/testsettings.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h
$(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testsettings.cpp

Expand Down
161 changes: 7 additions & 154 deletions cli/cppcheckexecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "filesettings.h"
#include "json.h"
#include "path.h"
#include "sarifreport.h"
#include "settings.h"
#include "singleexecutor.h"
#include "suppressions.h"
Expand Down Expand Up @@ -79,156 +80,6 @@
#endif

namespace {
class SarifReport {
public:
void addFinding(ErrorMessage msg) {
mFindings.push_back(std::move(msg));
}

picojson::array serializeRules() const {
picojson::array ret;
std::set<std::string> ruleIds;
for (const auto& finding : mFindings) {
// github only supports findings with locations
if (finding.callStack.empty())
continue;
if (ruleIds.insert(finding.id).second) {
picojson::object rule;
rule["id"] = picojson::value(finding.id);
// rule.shortDescription.text
picojson::object shortDescription;
shortDescription["text"] = picojson::value(finding.shortMessage());
rule["shortDescription"] = picojson::value(shortDescription);
// rule.fullDescription.text
picojson::object fullDescription;
fullDescription["text"] = picojson::value(finding.verboseMessage());
rule["fullDescription"] = picojson::value(fullDescription);
// rule.help.text
picojson::object help;
help["text"] = picojson::value(finding.verboseMessage()); // FIXME provide proper help text
rule["help"] = picojson::value(help);
// rule.properties.precision, rule.properties.problem.severity
picojson::object properties;
properties["precision"] = picojson::value(sarifPrecision(finding));
const char* securitySeverity = nullptr;
if (finding.severity == Severity::error && !ErrorLogger::isCriticalErrorId(finding.id))
securitySeverity = "9.9"; // We see undefined behavior
//else if (finding.severity == Severity::warning)
// securitySeverity = 5.1; // We see potential undefined behavior
if (securitySeverity) {
properties["security-severity"] = picojson::value(securitySeverity);
const picojson::array tags{picojson::value("security")};
properties["tags"] = picojson::value(tags);
}
rule["properties"] = picojson::value(properties);
// rule.defaultConfiguration.level
picojson::object defaultConfiguration;
defaultConfiguration["level"] = picojson::value(sarifSeverity(finding));
rule["defaultConfiguration"] = picojson::value(defaultConfiguration);

ret.emplace_back(rule);
}
}
return ret;
}

static picojson::array serializeLocations(const ErrorMessage& finding) {
picojson::array ret;
for (const auto& location : finding.callStack) {
picojson::object physicalLocation;
picojson::object artifactLocation;
artifactLocation["uri"] = picojson::value(location.getfile(false));
physicalLocation["artifactLocation"] = picojson::value(artifactLocation);
picojson::object region;
region["startLine"] = picojson::value(static_cast<int64_t>(location.line < 1 ? 1 : location.line));
region["startColumn"] = picojson::value(static_cast<int64_t>(location.column < 1 ? 1 : location.column));
region["endLine"] = region["startLine"];
region["endColumn"] = region["startColumn"];
physicalLocation["region"] = picojson::value(region);
picojson::object loc;
loc["physicalLocation"] = picojson::value(physicalLocation);
ret.emplace_back(loc);
}
return ret;
}

picojson::array serializeResults() const {
picojson::array results;
for (const auto& finding : mFindings) {
// github only supports findings with locations
if (finding.callStack.empty())
continue;
picojson::object res;
res["level"] = picojson::value(sarifSeverity(finding));
res["locations"] = picojson::value(serializeLocations(finding));
picojson::object message;
message["text"] = picojson::value(finding.shortMessage());
res["message"] = picojson::value(message);
res["ruleId"] = picojson::value(finding.id);
results.emplace_back(res);
}
return results;
}

picojson::value serializeRuns(const std::string& productName, const std::string& version) const {
picojson::object driver;
driver["name"] = picojson::value(productName);
driver["semanticVersion"] = picojson::value(version);
driver["informationUri"] = picojson::value("https://cppcheck.sourceforge.io");
driver["rules"] = picojson::value(serializeRules());
picojson::object tool;
tool["driver"] = picojson::value(driver);
picojson::object run;
run["tool"] = picojson::value(tool);
run["results"] = picojson::value(serializeResults());
picojson::array runs{picojson::value(run)};
return picojson::value(runs);
}

std::string serialize(std::string productName) const {
const auto nameAndVersion = Settings::getNameAndVersion(productName);
productName = nameAndVersion.first.empty() ? "Cppcheck" : nameAndVersion.first;
std::string version = nameAndVersion.first.empty() ? CppCheck::version() : nameAndVersion.second;
if (version.find(' ') != std::string::npos)
version.erase(version.find(' '), std::string::npos);

picojson::object doc;
doc["version"] = picojson::value("2.1.0");
doc["$schema"] = picojson::value("https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/schemas/sarif-schema-2.1.0.json");
doc["runs"] = serializeRuns(productName, version);

return picojson::value(doc).serialize(true);
}
private:

static std::string sarifSeverity(const ErrorMessage& errmsg) {
if (ErrorLogger::isCriticalErrorId(errmsg.id))
return "error";
switch (errmsg.severity) {
case Severity::error:
case Severity::warning:
case Severity::style:
case Severity::portability:
case Severity::performance:
return "warning";
case Severity::information:
case Severity::internal:
case Severity::debug:
case Severity::none:
return "note";
}
return "note";
}

static std::string sarifPrecision(const ErrorMessage& errmsg) {
if (errmsg.certainty == Certainty::inconclusive)
return "medium";
return "high";
}

std::vector<ErrorMessage> mFindings;
};

class CmdLineLoggerStd : public CmdLineLogger
{
public:
Expand Down Expand Up @@ -712,18 +563,20 @@ void StdLogger::reportErr(const ErrorMessage &msg)
msgCopy.classification = getClassification(msgCopy.guideline, mSettings.reportType);

// TODO: there should be no need for verbose and default messages here
const std::string msgStr = msgCopy.toString(mSettings.verbose, mSettings.templateFormat, mSettings.templateLocation);
const std::string msgStr =
msgCopy.toString(mSettings.verbose, mSettings.templateFormat, mSettings.templateLocation);

// Alert only about unique errors
if (!mSettings.emitDuplicates && !mShownErrors.insert(msgStr).second)
return;

if (mSettings.outputFormat == Settings::OutputFormat::sarif)
if (mSettings.outputFormat == Settings::OutputFormat::sarif) {
mSarifReport.addFinding(std::move(msgCopy));
else if (mSettings.outputFormat == Settings::OutputFormat::xml)
} else if (mSettings.outputFormat == Settings::OutputFormat::xml) {
reportErr(msgCopy.toXML());
else
} else {
reportErr(msgStr);
}
}

/**
Expand Down
2 changes: 2 additions & 0 deletions lib/cppcheck.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
<ClCompile Include="programmemory.cpp" />
<ClCompile Include="regex.cpp" />
<ClCompile Include="reverseanalyzer.cpp" />
<ClCompile Include="sarifreport.cpp" />
<ClCompile Include="settings.cpp" />
<ClCompile Include="standards.cpp" />
<ClCompile Include="summaries.cpp" />
Expand Down Expand Up @@ -158,6 +159,7 @@
<ClInclude Include="programmemory.h" />
<ClInclude Include="regex.h" />
<ClInclude Include="reverseanalyzer.h" />
<ClInclude Include="sarifreport.h" />
<ClInclude Include="settings.h" />
<ClInclude Include="smallvector.h" />
<ClInclude Include="sourcelocation.h" />
Expand Down
Loading