Skip to content

Commit e7093ff

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

File tree

2 files changed

+143
-29
lines changed

2 files changed

+143
-29
lines changed

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

+142-28
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,19 @@ 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+
notification.getAssociatedRule();
204+
final ReportingDescriptorReference ref = notification.getAssociatedRule();
205+
final Integer ruleIndex = this.getRuleIndex(ref);
206+
final String ruleId = null;
196207
final ReportingDescriptor reportingDescriptor =
197-
this.getReportingDescriptor(notifications, notification);
208+
this.findReportingDescriptor(
209+
run, DescriptorElementOf.NOTIFICATIONS, ref, ruleIndex, ruleId)
210+
.orElse(null);
211+
198212
final String reportingDescriptorName = this.getName(reportingDescriptor);
199213
final SEVERITY severity = this.toSeverity(notification.getLevel(), reportingDescriptor);
200214
final List<Location> locations = this.filter(notification.getLocations());
@@ -237,6 +251,17 @@ private Set<Violation> parseNotifications(final Run run) {
237251
return violations;
238252
}
239253

254+
private Integer getRuleIndex(final ReportingDescriptorReference ref) {
255+
Integer ruleIndex = null;
256+
if (ref != null) {
257+
ruleIndex = ref.getIndex();
258+
}
259+
if (ruleIndex == null || ruleIndex == -1) {
260+
return null;
261+
}
262+
return ruleIndex;
263+
}
264+
240265
private String getName(final ReportingDescriptor reportingDescriptor) {
241266
if (reportingDescriptor != null) {
242267
return reportingDescriptor.getName();
@@ -295,18 +320,6 @@ private List<Location> filterLocations(final List<Location> locations) {
295320
.collect(Collectors.toList());
296321
}
297322

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-
310323
private String toMessage(
311324
final Message message,
312325
final Optional<String> helpTextOpt,
@@ -392,16 +405,6 @@ private String extractMessage(
392405
return "";
393406
}
394407

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

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)