-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Add SARIF output support. #4651
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
2e352ed
to
3395a1b
Compare
Thanks for your contribution. Without actually looking at what it does - please add some unit and/or system tests for it. |
I haven't looked into your implementation but I really like this. 👍 |
c75210c
to
8c84999
Compare
@firewave, any idea how to include certain .cpp files into the Visual Studio build? I don't have any experience with Windows development.
|
8ce527a
to
8fdaa05
Compare
Currently, for XML output, the XML generation is tightly-coupled with the `ErrorMessage` class, which makes it harder to implement other formats (e.g. SARIF) that may need to see all of the errors/findings at once. Furthermore, implementing the serialization in the `ErrorMessage` class as individual methods (e.g. `toXML`) does not scale very well when using multiple formats. This approach uses the `AnalysisReport` abstract class to sub-class the different serialization formats.
This treats the CLI output as just another format (default) for the findings/report.
This should look and feel like the rest of the CppCheck code.
This is a good start, but it still needs some work. In particular, I need to fix the startLine/endLine/startColumn/endColumn part. Right now, I am using placeholder values ("1") instead of the real line/column numbers.
This matches the other AnalysisReport classes, and it's what clang-tidy recommends.
SARIF's precision property maps to Cppcheck's certainty, which is essentially the confidence level.
Sorry for the late reply but I currently out sick. So still no code review...
If #4652 is merged (could happen any day), |
Since GitHub actions apparently support SARIF output could also also adjust the selfcheck workflow to use SARIF output instead of relying on the exitcode? Also if SARIF is used should the exitcode be forced to 0? I have no idea how other tools implement this. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also run dmake
to actually update the Makefile
.
#ifndef ANALYSIS_REPORT_H | ||
#define ANALYSIS_REPORT_H | ||
|
||
#include "errorlogger.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for the include. Just forward declare ErrorMessage
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you sure? I tried forward-declaring ErrorMessage
as such:
class ErrorMessage;
But it then failed to build.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes because you pass ErrorMessage by value to addFinding. It should be passed by const reference.. then I believe a forward declaration will be enough.
@@ -19,6 +19,7 @@ | |||
#ifndef CPPCHECKEXECUTOR_H | |||
#define CPPCHECKEXECUTOR_H | |||
|
|||
#include "analysisreport.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I always forgot if std::unique_ptr
can work with incomplete types...could be forward decl then.
cli/sarifanalysisreport.cpp
Outdated
|
||
// https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/sarif-v2.1.0-os.html#_Toc34317507 | ||
run["results"] = picojson::value(results); | ||
runs.emplace_back(run); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
std::move()
? same for the other emplace_back()
calls above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
} | ||
|
||
static std::map<std::string, picojson::value> text(const std::string& s) { | ||
std::map<std::string, picojson::value> m = {{ "text", picojson::value(s) }}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could enable PICOJSON_USE_RVALUE_REFERENCE
(or is it enabled via compile-time detection?) and pass byval and move into picojson::value()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That define is based on preprocessor checks. It should be available in all compiler although I am not 100% sure if the Visual Studio check already covers VS2012.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, I think I've got it, but you should probably double-check my work.
@firewave, unfortunately
See https://github.com/mario-campos/cppcheck/actions/runs/3887481113/jobs/6633822871. Which means that, without tampering with the Makefile, |
…lue. We will only pass std::string by value if it can be std::move()d. Otherwise, it will get passed as a constant reference.
#ifndef ANALYSIS_REPORT_H | ||
#define ANALYSIS_REPORT_H | ||
|
||
#include "errorlogger.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes because you pass ErrorMessage by value to addFinding. It should be passed by const reference.. then I believe a forward declaration will be enough.
std::string serialize() override; | ||
|
||
private: | ||
bool mVerbose; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have the feeling these members can be const.
@@ -941,8 +941,10 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) | |||
} | |||
|
|||
// Write results in results.xml | |||
else if (std::strcmp(argv[i], "--xml") == 0) | |||
else if (std::strcmp(argv[i], "--xml") == 0) { | |||
printMessage("option --xml is deprecated; use --output-format=xml instead."); | |||
mSettings->xml = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest we remove variable xml in the Settings. And create enum outputFormat instead.
/** | ||
* Submit a CppCheck result for inclusion into the report. | ||
*/ | ||
virtual void addFinding(ErrorMessage msg) = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change parameter type to const ErrorMessage& msg
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe it used to be const ErrorMessage&
, but @firewave suggested passing by value so it could be std::move
d.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm.. ok but then I think you can't use the forward declaration.. maybe firewave did not see that. Could you double check if the forward declaration is possible if a const reference is used instead.
* by others classes that will contain the results of a CppCheck analysis, and | ||
* output those results in a particular format. | ||
*/ | ||
class AnalysisReport { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe the constructor for AnalysisReport could take a output stream argument:
std::ostream *outputStream
Then you pass the ofstream/std::cout/std::cerr as argument to the report.
I think this looks really interesting. There are some refactorings I would like to see.. but maybe instead of writing lots of nits it's quicker to just take over the finishing touches.. |
I have the feeling that you can adjust dmake.cpp here: I guess it should say something like:
|
I have made some fixes in this branch: https://github.com/danmar/cppcheck/tree/4651 The fixes I made are here: https://github.com/danmar/cppcheck/commit/acca98d8f33e8f1f4bb5e06c4fb88277970830a2.diff There are still some tests that fail. You can run those tests with these commands:
If the tests are fixed I have the feeling that we can merge this PR. |
That would be helpful. Unfortunately, now that the holiday season is over, I don't have as much time for this PR as I did before. But, I will still continue to address the remaining problems as much as I can. |
FYI there's already an PR which adds that output format command-line switch: #3365. |
This has been on my TODO list for a while! I've been wanting to integrate CppCheck's results into GitHub since Code Scanning came out. To do that, however, the tool needs to spit out SARIF.
To test it out, run
cppcheck --output-format=sarif --quiet foo.c
Now, this is only an initial stab, and it's probably a bit ugly. I'm not quite done just yet (hence why it's a draft PR). For one, it's not truly outputting the correct line/column numbers. So, if you have any suggestions or comments, please let me know.
Also, I initially tried to work SARIF output into the original design by adding a
ErrorMessage::toSARIF
method (alaErrorMessage::toXML
), but I quickly realized that this wouldn't work very well, since the SARIF document has to be "constructed", not "streamed" the way the XML document is. Which meant that I had to rework the way that findings ("errors") were collected and aggregated, since the SARIF document kinda needs to see everything all at once.