Skip to content
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

Add valgrind parser #738

Merged
merged 7 commits into from
Sep 20, 2023
Merged

Conversation

bitrunner
Copy link
Contributor

@bitrunner bitrunner commented Dec 10, 2021

This is the beginning of a valgrind report parser. It is a work-in-progress based on the recent addition of a valgrind parser to violations-lib so it depends upon #735 and will fail CI until that is merged because I didn't want to conflict the pom.xml changes for that here. The eventual goal of this pull request is to provide valgrind support in warnings-ng as a replacement for the broken, vulnerable, and unmaintained jenkins valgrind-plugin.

There are a few known problems/open questions with this that I could use some advice/help with to move this forward. I'm willing to work this through whatever needs to be done to achieve the goal of providing a warnings-ng alternative to the valgrind-plugin.

  1. Valgrind analyzes running programs for memory related problems so it provides a lot of important details about findings in the form of stack traces. I tried to capture these details in the description field of issues as HTML tables similar to how they were reported by the existing valgrind-plugin. I haven't been able to wire this up successfully through warnings-ng to see what this looks like on the warnings-ng Jenkins UI, so this might be a terrible strategy or otherwise need to be revised to fit existing design paradigms.
  2. It's difficult to get a parser to identify the right file where the issue root cause is because there are often multiple files to choose from in the stack trace and simple rules would not always identify the correct one. Is there an established pattern for dealing with this kind of ambiguity? Right now, the violations-lib valgrind parser uses the file that is closest to the top of the stack that isn't valgrind's replacement for malloc. That behavior is echoed in analysis-model in this initial pull request. That might not be ideal.
  3. There's some text in the suppression part of the description HTML that contains a special character, <, that needs to be escaped. A simple String.replace("<","&lt;") would suffice, but is there a more robust way to escape such strings that may contain special HTML characters? Will this escaping be handled in warnings-ng or further downstream of analysis-model for the description field?
  4. Both the origin and category fields are set to "valgrind:[tool]" where [tool] is the actual valgrind tool that detected the problem (ex. memcheck). It seems important to identify these problems as coming from valgrind and its subtool, but I couldn't find a reference elsewhere in the code for similar handling so this may need some refinement.
  5. IntelliJ reports static analysis findings that seem in conflict with javac. For example, IntelliJ wants "final" keywords on method parameters but javac complains that is unnecessary and discouraged since Java 8. Is there a preference for what to make happy for these types of things? I've been going with the compiler, but it seems like IntelliJ cleanliness might be preferred.
  6. There is some embedded JSON in the Violation structure that can generate some exceptions when parsed in the convertToReport function of the ValgrindAdapter in analysis-model. I resorted to catching and ignoring them because an alternative was unclear to me. Is there a better way to deal with that?
  7. Is it best to work on analysis-model in isolation or should it be worked in conjunction with whatever needs to be done to warnings-ng to support this new valgrind tool? I've found it difficult to align all the moving parts to get this to work end-to-end coming at this from a place of complete ignorance. Is there some guidance on adding new tools somewhere?
  • Make sure you are opening from a topic/feature/bugfix branch (right side) and not your main branch!
  • Ensure that the pull request title represents the desired changelog entry
  • Please describe what you did
  • Link to relevant issues in GitHub or Jira
  • Link to relevant pull requests, esp. upstream and downstream changes
  • Ensure you have provided tests - that demonstrates feature works or fixes the issue

@uhafner
Copy link
Member

uhafner commented Dec 11, 2021

Thanks for providing this PR! I merged the violations lib PR #735 so you can update your PR with the new pom.xml version.

@uhafner
Copy link
Member

uhafner commented Dec 16, 2021

  1. Valgrind analyzes running programs for memory related problems so it provides a lot of important details about findings in the form of stack traces. I tried to capture these details in the description field of issues as HTML tables similar to how they were reported by the existing valgrind-plugin. I haven't been able to wire this up successfully through warnings-ng to see what this looks like on the warnings-ng Jenkins UI, so this might be a terrible strategy or otherwise need to be revised to fit existing design paradigms.

It is hard to decide without an example. Do you have an HTML snippet that shows such a description?

  1. It's difficult to get a parser to identify the right file where the issue root cause is because there are often multiple files to choose from in the stack trace and simple rules would not always identify the correct one. Is there an established pattern for dealing with this kind of ambiguity? Right now, the violations-lib valgrind parser uses the file that is closest to the top of the stack that isn't valgrind's replacement for malloc. That behavior is echoed in analysis-model in this initial pull request. That might not be ideal.

I think this is a good starting point. There is currently no strategy, each parser author decides on his own how to map issues to files.

  1. There's some text in the suppression part of the description HTML that contains a special character, <, that needs to be escaped. A simple String.replace("<","<") would suffice, but is there a more robust way to escape such strings that may contain special HTML characters? Will this escaping be handled in warnings-ng or further downstream of analysis-model for the description field?

Currently, the description field is used by a few parsers only: these parsers return an HTML string. I think I need to improve the documentation for this field. Currently no escaping is done, so if you have non-HTML content you need to escape on your own by using StringEscapeUtils.escapeHtml4 (https://issues.jenkins.io/browse/JENKINS-62036). I'm not sure if I can or should add something in the analysis-model. Maybe can you elaborate your problem with an example?

The HTML string is later processed in the warnings plugin. The whole description is piped through an HTML processor (https://github.com/jenkinsci/antisamy-markup-formatter-plugin) to ensure that the created HTML contains no evil tags.

  1. Both the origin and category fields are set to "valgrind:[tool]" where [tool] is the actual valgrind tool that detected the problem (ex. memcheck). It seems important to identify these problems as coming from valgrind and its subtool, but I couldn't find a reference elsewhere in the code for similar handling so this may need some refinement.

Do not use the origin, this field should be set from outside. I should make that clear in the JavaDoc as well.

  1. IntelliJ reports static analysis findings that seem in conflict with javac. For example, IntelliJ wants "final" keywords on method parameters but javac complains that is unnecessary and discouraged since Java 8.

This was a bug in my configuration. final still should be used. I fixed the ErrorProne analysis configuration.

Is there a preference for what to make happy for these types of things? I've been going with the compiler, but it seems like IntelliJ cleanliness might be preferred.

Actually, the PR checks should be all Green 😄

  1. There is some embedded JSON in the Violation structure that can generate some exceptions when parsed in the convertToReport function of the ValgrindAdapter in analysis-model. I resorted to catching and ignoring them because an alternative was unclear to me. Is there a better way to deal with that?

If the exceptions indicate a problem in the source code of the parser, then they should be thrown so we can fix the parser (fail fast). If the exception may occur more often due to a problem in the tool that writes the reports then we should catch and ignore them. I'll look at the code and comment there.

  1. Is it best to work on analysis-model in isolation or should it be worked in conjunction with whatever needs to be done to warnings-ng to support this new valgrind tool? I've found it difficult to align all the moving parts to get this to work end-to-end coming at this from a place of complete ignorance. Is there some guidance on adding new tools somewhere?

Normally, it is not required anymore to make any changes in the warnings plugin. A new parser should work out of the box. In order to test your changes you need to wrap your changes into a new https://github.com/jenkinsci/analysis-model-api-plugin Jenkins plugin and deploy it to your Jenkins. When you are using my devenv then the deploy script does that automatically for you. You can then use the analysisModelId (https://github.com/jenkinsci/warnings-ng-plugin/blob/master/doc/Documentation.md#pipeline-step-with-a-generic-symbol)

@uhafner uhafner added the feature New features label Dec 17, 2021
@uhafner uhafner changed the title add valgrind parser Add valgrind parser Dec 17, 2021
@bitrunner
Copy link
Contributor Author

Thanks for the helpful feedback and advice. I think this is sorted out except for the description format and styling.

Here's an example of what it's currently generating (with extra newlines and formatting for readability):

<table>
  <tr><td class="pane-header">Executable</td><td class="pane">./terrible_program</td></tr>
  <tr><td class="pane-header">Unique Id</td><td class="pane">0x1</td></tr>
  <tr><td class="pane-header">Thread Id</td><td class="pane">1</td></tr>
  <tr><td class="pane-header">Auxiliary</td><td class="pane">Address 0x4dd0c90 is 0 bytes after a block of size 16 alloc'd</td></tr>
</table>
<h2>Primary Stack Trace</h2>
<h3>Invalid write of size 4</h3>
<table>
  <tr><td class="pane-header">Object</td><td class="pane">/home/some_user/terrible_program/terrible_program</td></tr>
  <tr><td class="pane-header">Function</td><td class="pane">main</td></tr>
  <tr><td class="pane-header">File</td><td class="pane">/home/some_user/terrible_program/terrible_program.cpp:10</td></tr>
</table>
<h2>Auxiliary Stack Trace</h2>
<h3>Address 0x4dd0c90 is 0 bytes after a block of size 16 alloc'd</h3>
<table>
  <tr><td class="pane-header">Object</td><td class="pane">/usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so</td></tr>
  <tr><td class="pane-header">Function</td><td class="pane">operator new[](unsigned long)</td></tr>
  <tr><td class="pane-header">File</td><td class="pane">./coregrind/m_replacemalloc/vg_replace_malloc.c:640</td></tr>
</table>
<br>
<table>
  <tr><td class="pane-header">Object</td><td class="pane">/home/some_user/terrible_program/terrible_program</td></tr>
  <tr><td class="pane-header">Function</td><td class="pane">main</td></tr>
  <tr><td class="pane-header">File</td><td class="pane">/home/some_user/terrible_program/terrible_program.cpp:3</td></tr>
</table>
<h2>Suppression</h2>
<table>
  <tr><td class="pane"><pre>{
   &lt;insert_a_suppression_name_here&gt;
   Memcheck:Addr4
   fun:main
}</pre></td></tr>
</table>

Here's what that looks like (without warnings-ng CSS):

Executable./terrible_program
Unique Id0x1
Thread Id1
AuxiliaryAddress 0x4dd0c90 is 0 bytes after a block of size 16 alloc'd

Primary Stack Trace

Invalid write of size 4

Object/home/some_user/terrible_program/terrible_program
Functionmain
File/home/some_user/terrible_program/terrible_program.cpp:10

Auxiliary Stack Trace

Address 0x4dd0c90 is 0 bytes after a block of size 16 alloc'd

Object/usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so
Functionoperator new[](unsigned long)
File./coregrind/m_replacemalloc/vg_replace_malloc.c:640

Object/home/some_user/terrible_program/terrible_program
Functionmain
File/home/some_user/terrible_program/terrible_program.cpp:3

Suppression

{
   <insert_a_suppression_name_here>
   Memcheck:Addr4
   fun:main
}

@codecov
Copy link

codecov bot commented Jan 2, 2022

Codecov Report

Merging #738 (943e039) into master (565bacf) will increase coverage by 0.02%.
Report is 13 commits behind head on master.
The diff coverage is 94.50%.

@@             Coverage Diff              @@
##             master     #738      +/-   ##
============================================
+ Coverage     92.92%   92.94%   +0.02%     
- Complexity     2338     2368      +30     
============================================
  Files           345      347       +2     
  Lines          6499     6592      +93     
  Branches        672      686      +14     
============================================
+ Hits           6039     6127      +88     
- Misses          262      263       +1     
- Partials        198      202       +4     
Files Changed Coverage Δ
...du/hm/hafner/analysis/registry/ParserRegistry.java 100.00% <ø> (ø)
...er/analysis/parser/violations/ValgrindAdapter.java 93.82% <93.82%> (ø)
...m/hafner/analysis/registry/ValgrindDescriptor.java 100.00% <100.00%> (ø)

... and 1 file with indirect coverage changes

📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more

@bitrunner
Copy link
Contributor Author

I finally got this to work end-to-end through warnings-ng after manually updating analysis-model-api's pom.xml to use the analysis-model SNAPSHOT (you might consider noting this probably obvious required step in your guide somewhere to keep idiots like me from staring open mouthed at it not working for an embarrassingly long time) using the analysisModelId trick you pointed me at. I moved the big blob of HTML into the message from the description because I couldn't find the description anywhere on the warnings-ng UI. It looks like this horrible mess:
image

I obviously have no UI skills, so advice on how to make this look less ridiculous is welcome. strong tags seem to be automatically inserted into the supplied HTML and those aren't helping make it look less terrible. Maybe this whole idea is dumb because it's so far outside the norm for warnings-ng. At this point, I'm not sure. Without all the stack information, it will be impossible for anyone to figure out what needs fixing so it seems like it has to be available to the user somehow if this is going to be useful.

Thoughts?

@uhafner
Copy link
Member

uhafner commented Jan 5, 2022

Yes, I need to update the documentation and my development environment (https://github.com/uhafner/warnings-ng-plugin-devenv) description. Since I switched to incremental builds the procedure has been changed and now the version is not a SNAPSHOT version anymore. (That helps to use Dependabot creating automatic PRs when a new release appears.).

Currently the description is used by a few parsers only (and there the description is obtained from external files). But normally only the message is wrapped into the <strong> tags, the description should be shown as such (HTML). Note that some tags might get removed by our sanitizer to avoid security problems.

I think I need to install your PR in my local instance and play around with it a little bit. I'm also not a UI designer but during the development of the plugin I improved my skills 😁

Are there other tools that produce nice Valgrind reports where we can get an inspiration?

@uhafner
Copy link
Member

uhafner commented Jan 10, 2022

I just installed it and started with some experiments. I think it does not make sense to use fonts larger than the content. I activated some styling using the predefined Bootstrap CSS table styling but I am not sure if that is enough. Maybe we need to provide some new CSS classes for such use cases.

Bildschirmfoto 2022-01-10 um 19 50 36

@uhafner
Copy link
Member

uhafner commented Jan 10, 2022

You can use basically anything from https://getbootstrap.com/ if that helps? (Collapsible sections, etc.)

@mchatt
Copy link

mchatt commented Feb 4, 2022

Hello @bitrunner,
I am looking forward using your new valgrind parser. Any idea when this PR can be merged ?
Thank you

@uhafner
Copy link
Member

uhafner commented Feb 4, 2022

Maybe we can use the current styling in improve it later in another PR? I haven't yet looked at the code because there where these open UI design questions but I can add a review this weekend if it makes sense.

@mchatt
Copy link

mchatt commented Feb 7, 2022

Maybe we can use the current styling in improve it later in another PR? I haven't yet looked at the code because there where these open UI design questions but I can add a review this weekend if it makes sense.

I have almost zero knowledge about UI development. I can't be of much help to you. But as a potential user of this parser, I would say yes, let merge it as it is, and improve the design in a different PR.

@bitrunner
Copy link
Contributor Author

bitrunner commented Sep 15, 2023

It seems like it might be time to finally finish this up. I like your bootstrap suggestions, style hints, and think your example screenshot is plenty good enough @uhafner. I tried to add some CSS to make it look nicer, but all the CSS seems to get stripped from the message and description fields so no CSS classes can be applied. Were you able to get some through to make that screenshot or were you just adding the styling in the browser? I can make it look nice by editing stuff in my browser, but I can't seem to get enough wizardry through the plugin to make it look reasonable.

@uhafner
Copy link
Member

uhafner commented Sep 15, 2023

Good to see that you have some time to finish it. I also have some time to help right now!

Actually I forgot whether I changed the HTML output in the browser or in the code 🙈

You can use HTML in the description but not in the message. If that does not work it might get stripped somewhere by accident.

@bitrunner
Copy link
Contributor Author

bitrunner commented Sep 15, 2023

It doesn't seem to work in the description either. Here's the best I've been able to make it look without any CSS.
vg_wng_output
It seems usable like that, but it's not great. Only the first line is the message, everything else is in the description.

I rebased and pushed the latest formatting stuff so what's currently in the pull request should make output like the screenshot.

@uhafner
Copy link
Member

uhafner commented Sep 15, 2023

Sorry, seems that I forced pushed to your repository :-(

Can you please force push your chagnes again? I wasn't aware that my branch is not set to track my repository. Sorry about that...

@bitrunner
Copy link
Contributor Author

No problem. Done. Feel free to add whatever you like.

@uhafner
Copy link
Member

uhafner commented Sep 15, 2023

Actually I just wanted to see the results in my Jenkins instance. From your code it also looks that HTML Is working in the description, doesn't it?

@uhafner
Copy link
Member

uhafner commented Sep 15, 2023

Currently, your headers are smaller than the text, maybe you need to tweak these a little bit.

@uhafner
Copy link
Member

uhafner commented Sep 15, 2023

BTW: in Java it might make more sense to use j2html to generate the HTML output (and not a StringBuilder).

Example:

private String formatDescription(final String fileName, final JSONObject finding) {

@KalleOlaviNiemitalo
Copy link

If you use j2html, be aware that its TagCreator.join method "removes spaces before periods and commas", which may be an undesirable change on text coming from a tool such as valgrind.

@bitrunner
Copy link
Contributor Author

The HTML tags I've tried seem to go through fine, but the CSS is stripped. For example, trying to add striping to the tables like this results in a bare table tag (the class="..." part is stripped) in the output HTML:

<table class="table table-striped">

As for j2html, if you'd prefer it be done that way, I'll switch to it. I'm too clueless to have a preference. @KalleOlaviNiemitalo's comment causes some concern but I can't think of anything specific potentially losing some spaces would mess up that HTML doesn't already do anyway.

@bitrunner
Copy link
Contributor Author

Another problem I noticed is that the suppression part of the Violation's specifics is getting lost somehow. It works in the ValgrindAdapter unit test, but Violation.getSpecifics().get("suppression") always returns null when running in Jenkins. Some debugging indicates there does not appear to ever be a suppression key/value pair in the specifics Map. The stack traces are also stored in the specifics Map and they are working fine. Processing the same valgrind output XML in the unit test and on Jenkins shows the suppression part in the unit test but not on Jenkins. The suppression uses CDATA in XML and has \n newlines, curly braces {}, and angle brackets <> in its text so it might have something funky that is making something upset. I don't see anything of interest in the jenkins log. Any idea how this might be possible?

@KalleOlaviNiemitalo
Copy link

@bitrunner the j2html behaviour did previously cause JENKINS-64051. I don't remember whether valgrind output can include any application-specified text that j2html could corrupt in a similar fashion.

@bitrunner
Copy link
Contributor Author

I updated this to use j2html and thanks to @KalleOlaviNiemitalo, avoided problems like JENKINS-64051 by borrowing @uhafner's strategy. In the process, I changed from h5 to h4 to make the headers bigger than the text per @uhafner's note above.

I also managed to trick the very strict static analysis into accepting some methods that return null using a somewhat ridiculous obfuscation. null returns appears to be a common idiom in j2html to handle optional things. If my trickery is not acceptable, I'll refactor yet again to find some other middle ground between j2html and the static analysis rules or just go back to StringBuilder where null returns aren't helpful.

I also put the CSS in to show the problem of it being stripped.

It seems like this might be good enough as is although it has not-so-pretty HTML output and missing suppressions which doesn't seem critical.

Shall we squash and merge or pursue further enhancements?

@uhafner
Copy link
Member

uhafner commented Sep 18, 2023

The HTML tags I've tried seem to go through fine, but the CSS is stripped. For example, trying to add striping to the tables like this results in a bare table tag (the class="..." part is stripped) in the output HTML:

You are right, the https://github.com/jenkinsci/antisamy-markup-formatter-plugin actually removes potentially unsafe HTML tags and classes. I have no idea why classes are considered a security problem.

@uhafner
Copy link
Member

uhafner commented Sep 18, 2023

Another problem I noticed is that the suppression part of the Violation's specifics is getting lost somehow. It works in the ValgrindAdapter unit test, but Violation.getSpecifics().get("suppression") always returns null when running in Jenkins. Some debugging indicates there does not appear to ever be a suppression key/value pair in the specifics Map. The stack traces are also stored in the specifics Map and they are working fine. Processing the same valgrind output XML in the unit test and on Jenkins shows the suppression part in the unit test but not on Jenkins. The suppression uses CDATA in XML and has \n newlines, curly braces {}, and angle brackets <> in its text so it might have something funky that is making something upset. I don't see anything of interest in the jenkins log. Any idea how this might be possible?

The only thing what you need to be aware: Jenkins might read those values (you will seem them in the serialized XML reports in Jenkins build folder) but will not render them due to the OWASP markup formatter. All tags will be checked against a whitelist to see whether only safe elements are contained.

Copy link
Member

@uhafner uhafner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks much better with j2html! Just some small adjustments required. Maybe we then can make a release and postpone additional UI refactorings.

issue -> {
final String description = issue.getDescription();
if (Violation.NO_FILE.equals(issue.getFileName())) {
assertThat(!description.contains("Primary Stack Trace"));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AssertJ does not work in this way. You do not verify anything!

Suggested change
assertThat(!description.contains("Primary Stack Trace"));
softly.assertThat(description).doesNotContain("Primary Stack Trace");

Comment on lines 68 to 69
assertThat(description.contains("Primary Stack Trace"));
assertThat(description.contains("&lt;insert_a_suppression_name_here&gt;"));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
assertThat(description.contains("Primary Stack Trace"));
assertThat(description.contains("&lt;insert_a_suppression_name_here&gt;"));
softly.assertThat(description).contains("Primary Stack Trace",
"&lt;insert_a_suppression_name_here&gt;");

/**
* A descriptor for Valgrind.
*/
public class ValgrindDescriptor extends ParserDescriptor {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you also have a URL?

).render();
}

private Tag generateGeneralTableHtml(final String executable, final String uniqueId, @CheckForNull final String threadId, @CheckForNull final String threadName, @CheckForNull final JSONArray auxWhats) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
private Tag generateGeneralTableHtml(final String executable, final String uniqueId, @CheckForNull final String threadId, @CheckForNull final String threadName, @CheckForNull final JSONArray auxWhats) {
private ContainerTag generateGeneralTableHtml(final String executable, final String uniqueId, @CheckForNull final String threadId, @CheckForNull final String threadName, @CheckForNull final JSONArray auxWhats) {

return generalTable;
}

private Tag maybeGenerateStackTracesHtml(@CheckForNull final String stacksJson, final String message, @CheckForNull final JSONArray auxWhats) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
private Tag maybeGenerateStackTracesHtml(@CheckForNull final String stacksJson, final String message, @CheckForNull final JSONArray auxWhats) {
private ContainerTag maybeGenerateStackTracesHtml(@CheckForNull final String stacksJson, final String message, @CheckForNull final JSONArray auxWhats) {


private Tag maybeGenerateStackTracesHtml(@CheckForNull final String stacksJson, final String message, @CheckForNull final JSONArray auxWhats) {
if (StringUtils.isBlank(stacksJson)) {
return iff(false, null);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there is no null object (empty container) simply return null. If required use a SuppressWarnings directive.

Suggested change
return iff(false, null);
return null;

return stackTraces;
}

return iff(false, null);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return iff(false, null);
return null;

return iff(false, null);
}

private Tag generateStackTraceHtml(final String title, @CheckForNull final String message, final JSONArray frames) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
private Tag generateStackTraceHtml(final String title, @CheckForNull final String message, final JSONArray frames) {
private ContainerTag generateStackTraceHtml(final String title, @CheckForNull final String message, final JSONArray frames) {

return stackTraceContainer;
}

private Tag generateStackFrameHtml(final JSONObject frame) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
private Tag generateStackFrameHtml(final JSONObject frame) {
private ContainerTag generateStackFrameHtml(final JSONObject frame) {

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All other usages of raw type Tag as well

private Tag generateStackFrameHtml(final JSONObject frame) {
return
table(
attrs(".table.table-striped"),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can remove the classes since they are stripped away

@bitrunner
Copy link
Contributor Author

bitrunner commented Sep 18, 2023

You are right, the https://github.com/jenkinsci/antisamy-markup-formatter-plugin actually removes potentially unsafe HTML tags and classes. I have no idea why classes are considered a security problem.

Can the stuff that is produced by the plugin be separated from the stuff that comes from the tool report file for the purpose of sanitization? That is, can we allow the plugin to generate HTML that is not subject to the user safety checks and only run the stuff that comes directly from the report files/valgrind tool through the safety check?

This is not possible yet (and I don't know if its worth the effort, currently we simply filter everything). This would also imply that we need to sanitize the HTML already here.

The only thing what you need to be aware: Jenkins might read those values (you will seem them in the serialized XML reports in Jenkins build folder) but will not render them due to the OWASP markup formatter. All tags will be checked against a whitelist to see whether only safe elements are contained.

From what I can tell from debugging, the suppression content from the valgrind.xml report is not being read into the Violation when running in Jenkins but it is read when running the unit test. It might be dropped by the XML reader, I'm not sure. I am sure this is not a problem where the tags are stripped on the output. This information is lost on the input side.

Do you have an example in the unit test? Then I can try to debug locally.

Copy link
Member

@uhafner uhafner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you like, you can add links to the icon and URL to the descriptor as well:

https://valgrind.org/gallery/artwork.html

@bitrunner
Copy link
Contributor Author

Do you have an example in the unit test? Then I can try to debug locally.

Yes. 4 of the 5 test errors in the test valgrind.xml have suppressions. In valgrind.xml, the suppression is stored in CDATA sections within the <rawtext> tags like this one:

<rawtext>
<![CDATA[
{
<insert_a_suppression_name_here>
Memcheck:Cond
fun:main
}
]]>
</rawtext>

The insert_a_suppression_name_here part of this line verifies that the suppressions are in the output within the unit test:

softly.assertThat(description).contains("Primary Stack Trace", "&lt;insert_a_suppression_name_here&gt;");

While running in Jenkins, specifics.get("suppression") is always null here:

maybeGenerateSuppressionHtml(specifics.get("suppression"))

If you like, you can add links to the icon and URL to the descriptor as well:

Sorry, I misunderstood what you wanted me to do. I think I manged to do it right in the latest push.

@uhafner
Copy link
Member

uhafner commented Sep 20, 2023

Do you have an example in the unit test? Then I can try to debug locally.

Yes. 4 of the 5 test errors in the test valgrind.xml have suppressions. In valgrind.xml, the suppression is stored in CDATA sections within the <rawtext> tags like this one:

<rawtext>
<![CDATA[
{
<insert_a_suppression_name_here>
Memcheck:Cond
fun:main
}
]]>
</rawtext>

The insert_a_suppression_name_here part of this line verifies that the suppressions are in the output within the unit test:

softly.assertThat(description).contains("Primary Stack Trace", "&lt;insert_a_suppression_name_here&gt;");

While running in Jenkins, specifics.get("suppression") is always null here:

maybeGenerateSuppressionHtml(specifics.get("suppression"))

I found the problem. In my unit tests the default XML input stream parser of Xerces XMLStreamReaderImpl is used while during runtime a ValidatingStreamReader of the Jackson library is used. This parsers seems to replace the standard parser in Jenkins. I have no idea if we can (or should) remove that association.

@uhafner uhafner merged commit 1655139 into jenkinsci:master Sep 20, 2023
25 checks passed
@uhafner
Copy link
Member

uhafner commented Sep 20, 2023

I think we can postpone the problem with the parser and create a new release right now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature New features
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants