Skip to content

Commit 6608422

Browse files
committed
fix(SARIF): Correcting reporting descriptor lookup (refs #154)
1 parent d9e0a8d commit 6608422

File tree

2 files changed

+148
-30
lines changed

2 files changed

+148
-30
lines changed

src/main/java/se/bjurr/violations/lib/parsers/SarifParser.java

+147-29
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
import java.util.Optional;
1717
import java.util.Set;
1818
import java.util.TreeSet;
19-
import java.util.function.Function;
2019
import java.util.stream.Collectors;
2120
import se.bjurr.violations.lib.ViolationsLogger;
2221
import se.bjurr.violations.lib.model.SEVERITY;
@@ -31,14 +30,23 @@
3130
import se.bjurr.violations.lib.model.generated.sarif.Region;
3231
import se.bjurr.violations.lib.model.generated.sarif.ReportingConfiguration;
3332
import se.bjurr.violations.lib.model.generated.sarif.ReportingDescriptor;
33+
import se.bjurr.violations.lib.model.generated.sarif.ReportingDescriptorReference;
3434
import se.bjurr.violations.lib.model.generated.sarif.Result;
3535
import se.bjurr.violations.lib.model.generated.sarif.Result.Level;
3636
import se.bjurr.violations.lib.model.generated.sarif.Run;
3737
import se.bjurr.violations.lib.model.generated.sarif.SarifSchema;
38+
import se.bjurr.violations.lib.model.generated.sarif.ToolComponent;
39+
import se.bjurr.violations.lib.model.generated.sarif.ToolComponentReference;
3840
import se.bjurr.violations.lib.reports.Parser;
3941
import se.bjurr.violations.lib.util.Utils;
4042

4143
public class SarifParser implements ViolationsParser {
44+
/** 3.52.3 */
45+
public enum DescriptorElementOf {
46+
RULES,
47+
NOTIFICATIONS
48+
}
49+
4250
public static final String SARIF_RESULTS_CORRELATION_GUID = "correlationGuid";
4351

4452
public class ParsedPhysicalLocation {
@@ -127,7 +135,6 @@ ReportingConfiguration.Level.class, new ReportingConfigurationDeserializer())
127135

128136
private Set<Violation> parseResults(final Run run) {
129137
final Set<Violation> violations = new TreeSet<>();
130-
final Map<String, ReportingDescriptor> rulesById = this.getRulesById(run);
131138
final String reporter = this.getReporter(run);
132139
for (final Result result : run.getResults()) {
133140
final String ruleId = result.getRuleId();
@@ -143,8 +150,8 @@ private Set<Violation> parseResults(final Run run) {
143150
if (!isNullOrEmpty(correlationGuid)) {
144151
specifics.put(SARIF_RESULTS_CORRELATION_GUID, correlationGuid);
145152
}
146-
147-
final ReportingDescriptor reportingDescriptor = rulesById.get(ruleId);
153+
final ReportingDescriptor reportingDescriptor =
154+
this.findReportingDescriptor(run, result, DescriptorElementOf.RULES).orElse(null);
148155
final String category = this.getCategory(reportingDescriptor);
149156

150157
final Optional<String> helpTextOpt = this.findHelpText(reportingDescriptor);
@@ -189,12 +196,18 @@ private Set<Violation> parseResults(final Run run) {
189196

190197
private Set<Violation> parseNotifications(final Run run) {
191198
final Set<Violation> violations = new TreeSet<>();
192-
final List<ReportingDescriptor> notifications = this.getNotifications(run);
199+
this.getNotifications(run);
193200
final String reporter = this.getReporter(run);
194201
for (final Invocation invocation : run.getInvocations()) {
195202
for (final Notification notification : invocation.getToolConfigurationNotifications()) {
203+
final ReportingDescriptorReference ref = notification.getAssociatedRule();
204+
final Integer ruleIndex = this.getRuleIndex(ref);
205+
final String ruleId = null;
196206
final ReportingDescriptor reportingDescriptor =
197-
this.getReportingDescriptor(notifications, notification);
207+
this.findReportingDescriptor(
208+
run, DescriptorElementOf.NOTIFICATIONS, ref, ruleIndex, ruleId)
209+
.orElse(null);
210+
198211
final String reportingDescriptorName = this.getName(reportingDescriptor);
199212
final SEVERITY severity = this.toSeverity(notification.getLevel(), reportingDescriptor);
200213
final List<Location> locations = this.filter(notification.getLocations());
@@ -221,13 +234,18 @@ private Set<Violation> parseNotifications(final Run run) {
221234
.build());
222235
}
223236
} else {
237+
final String message =
238+
this.extractMessage(notification.getMessage(), reportingDescriptor);
239+
if (message.isEmpty()) {
240+
continue;
241+
}
224242
violations.add(
225243
violationBuilder()
226244
.setParser(Parser.SARIF)
227245
.setFile(Violation.NO_FILE)
228246
.setStartLine(Violation.NO_LINE)
229247
.setRule(reportingDescriptorName)
230-
.setMessage(this.extractMessage(notification.getMessage(), reportingDescriptor))
248+
.setMessage(message)
231249
.setSeverity(severity)
232250
.setReporter(reporter)
233251
.build());
@@ -237,6 +255,17 @@ private Set<Violation> parseNotifications(final Run run) {
237255
return violations;
238256
}
239257

258+
private Integer getRuleIndex(final ReportingDescriptorReference ref) {
259+
Integer ruleIndex = null;
260+
if (ref != null) {
261+
ruleIndex = ref.getIndex();
262+
}
263+
if (ruleIndex == null || ruleIndex == -1) {
264+
return null;
265+
}
266+
return ruleIndex;
267+
}
268+
240269
private String getName(final ReportingDescriptor reportingDescriptor) {
241270
if (reportingDescriptor != null) {
242271
return reportingDescriptor.getName();
@@ -295,18 +324,6 @@ private List<Location> filterLocations(final List<Location> locations) {
295324
.collect(Collectors.toList());
296325
}
297326

298-
private ReportingDescriptor getReportingDescriptor(
299-
final List<ReportingDescriptor> notifications, final Notification notification) {
300-
if (notification.getDescriptor() == null) {
301-
return null;
302-
}
303-
final Integer notificationIndex = notification.getDescriptor().getIndex();
304-
if (notificationIndex == null) {
305-
return null;
306-
}
307-
return notifications.get(notificationIndex);
308-
}
309-
310327
private String toMessage(
311328
final Message message,
312329
final Optional<String> helpTextOpt,
@@ -392,16 +409,6 @@ private String extractMessage(
392409
return "";
393410
}
394411

395-
private Map<String, ReportingDescriptor> getRulesById(final Run run) {
396-
if (run.getTool() != null
397-
&& run.getTool().getDriver() != null
398-
&& run.getTool().getDriver().getRules() != null) {
399-
return run.getTool().getDriver().getRules().stream()
400-
.collect(Collectors.toMap(ReportingDescriptor::getId, Function.identity()));
401-
}
402-
return new HashMap<>();
403-
}
404-
405412
private Optional<String> findHelpText(final ReportingDescriptor r) {
406413
if (r == null) {
407414
return Optional.empty();
@@ -461,4 +468,115 @@ private Optional<SEVERITY> toSeverity(final ReportingDescriptor reportingDescrip
461468
}
462469
return Optional.empty();
463470
}
471+
472+
private Optional<ReportingDescriptor> findReportingDescriptor(
473+
final Run run, final Result result, final DescriptorElementOf lookIn) {
474+
final ReportingDescriptorReference ref = result.getRule();
475+
final Integer ruleIndex = this.findRuleIndex(result, ref);
476+
final String ruleId = result.getRuleId();
477+
return this.findReportingDescriptor(run, lookIn, ref, ruleIndex, ruleId);
478+
}
479+
480+
private Optional<ReportingDescriptor> findReportingDescriptor(
481+
final Run run,
482+
final DescriptorElementOf lookIn,
483+
final ReportingDescriptorReference ref,
484+
final Integer ruleIndex,
485+
final String ruleId) {
486+
final ToolComponent tool = this.findToolComponent(run, ref);
487+
if (tool == null) {
488+
return Optional.empty();
489+
}
490+
if (ruleIndex != null) {
491+
return Optional.of(this.getReportingDescriptorByIndex(tool, ruleIndex, lookIn));
492+
}
493+
494+
if (ref != null && ref.getGuid() != null) {
495+
return this.findReportingDescriptorByGui(tool, ref.getGuid(), lookIn);
496+
}
497+
if (ruleId != null) {
498+
return this.findReportingDescriptorByRuleId(tool, ruleId, lookIn);
499+
}
500+
return Optional.empty();
501+
}
502+
503+
private Integer findRuleIndex(final Result result, final ReportingDescriptorReference ref) {
504+
Integer ruleIndex = result.getRuleIndex();
505+
if (ruleIndex == -1) {
506+
ruleIndex = null;
507+
}
508+
if (ruleIndex == null && ref != null) {
509+
ruleIndex = ref.getIndex();
510+
}
511+
return ruleIndex;
512+
}
513+
514+
private ToolComponent findToolComponent(final Run run, final ReportingDescriptorReference ref) {
515+
if (run.getTool() == null) {
516+
return null;
517+
}
518+
if (ref == null) {
519+
return run.getTool().getDriver();
520+
}
521+
final ToolComponentReference toolRef = ref.getToolComponent();
522+
if (toolRef.getGuid() != null) {
523+
return this.getToolComponentByGui(run, toolRef.getGuid());
524+
}
525+
if (toolRef.getIndex() != null) {
526+
return this.getToolComponentByIndex(run, toolRef.getIndex());
527+
}
528+
return run.getTool().getDriver();
529+
}
530+
531+
private ReportingDescriptor getReportingDescriptorByIndex(
532+
final ToolComponent tool, final Integer index, final DescriptorElementOf lookIn) {
533+
if (lookIn == DescriptorElementOf.RULES) {
534+
return new ArrayList<>(tool.getRules()).get(index);
535+
}
536+
if (lookIn == DescriptorElementOf.NOTIFICATIONS) {
537+
return new ArrayList<>(tool.getNotifications()).get(index);
538+
}
539+
throw new IllegalStateException(lookIn + " cannot find ReportingDescriptor");
540+
}
541+
542+
private Optional<ReportingDescriptor> findReportingDescriptorByGui(
543+
final ToolComponent tool, final String guid, final DescriptorElementOf lookIn) {
544+
if (lookIn == DescriptorElementOf.RULES) {
545+
return tool.getRules().stream()
546+
.filter((it) -> it.getGuid() != null && it.getGuid().equals(guid))
547+
.findFirst();
548+
}
549+
if (lookIn == DescriptorElementOf.NOTIFICATIONS) {
550+
return tool.getNotifications().stream()
551+
.filter((it) -> it.getGuid() != null && it.getGuid().equals(guid))
552+
.findFirst();
553+
}
554+
return Optional.empty();
555+
}
556+
557+
private Optional<ReportingDescriptor> findReportingDescriptorByRuleId(
558+
final ToolComponent tool, final String ruleId, final DescriptorElementOf lookIn) {
559+
if (lookIn == DescriptorElementOf.RULES) {
560+
return tool.getRules().stream()
561+
.filter((it) -> it.getId() != null && it.getId().equals(ruleId))
562+
.findFirst();
563+
}
564+
if (lookIn == DescriptorElementOf.NOTIFICATIONS) {
565+
return tool.getNotifications().stream()
566+
.filter((it) -> it.getId() != null && it.getId().equals(ruleId))
567+
.findFirst();
568+
}
569+
throw new IllegalStateException(lookIn + " cannot find ReportingDescriptor");
570+
}
571+
572+
private ToolComponent getToolComponentByIndex(final Run run, final Integer index) {
573+
return new ArrayList<>(run.getTool().getExtensions()).get(index);
574+
}
575+
576+
private ToolComponent getToolComponentByGui(final Run run, final String guid) {
577+
return run.getTool().getExtensions().stream()
578+
.filter((it) -> it.getGuid() != null && it.getGuid().equals(guid))
579+
.findFirst()
580+
.get();
581+
}
464582
}

src/test/java/se/bjurr/violations/lib/SarifParserTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public void testThatViolationsCanBeParsed_smoke() {
2727
.violations();
2828

2929
assertThat(actual) //
30-
.hasSize(54);
30+
.hasSize(53);
3131
}
3232

3333
@Test

0 commit comments

Comments
 (0)