From 118a1b07a78bb95a84defa9535f9999d8f4bd2c5 Mon Sep 17 00:00:00 2001 From: "antoine.vinot" Date: Fri, 5 Apr 2024 11:31:23 +0200 Subject: [PATCH] SONAR-22009 Fix NPE on SARIF import when Extensions don't have Rules --- .../java/org/sonar/core/sarif/Extension.java | 2 ++ .../externalissue/sarif/RunMapper.java | 7 ++++- .../externalissue/sarif/RunMapperTest.java | 31 +++++++++++++++++++ 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/sonar-core/src/main/java/org/sonar/core/sarif/Extension.java b/sonar-core/src/main/java/org/sonar/core/sarif/Extension.java index d3acedeb88f..1e7b16c37bf 100644 --- a/sonar-core/src/main/java/org/sonar/core/sarif/Extension.java +++ b/sonar-core/src/main/java/org/sonar/core/sarif/Extension.java @@ -21,6 +21,7 @@ package org.sonar.core.sarif; import com.google.gson.annotations.SerializedName; import java.util.Set; +import javax.annotation.CheckForNull; public class Extension { @SerializedName("rules") @@ -33,6 +34,7 @@ public class Extension { // http://stackoverflow.com/a/18645370/229031 } + @CheckForNull public Set getRules() { return rules; } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/externalissue/sarif/RunMapper.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/externalissue/sarif/RunMapper.java index 442e2a1703d..f94549c5ade 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/externalissue/sarif/RunMapper.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/externalissue/sarif/RunMapper.java @@ -31,6 +31,7 @@ import org.sonar.api.batch.sensor.issue.NewExternalIssue; import org.sonar.api.batch.sensor.rule.NewAdHocRule; import org.sonar.api.scanner.ScannerSide; import org.sonar.core.sarif.Driver; +import org.sonar.core.sarif.Extension; import org.sonar.core.sarif.Result; import org.sonar.core.sarif.Rule; import org.sonar.core.sarif.Run; @@ -84,7 +85,7 @@ public class RunMapper { private List toNewAdHocRules(Run run, String driverName, Map ruleSeveritiesByRuleId, Map ruleSeveritiesByRuleIdForNewCCT) { Set driverRules = run.getTool().getDriver().getRules(); Set extensionRules = hasExtensions(run.getTool()) - ? run.getTool().getExtensions().stream().flatMap(extension -> extension.getRules().stream()).collect(toSet()) + ? run.getTool().getExtensions().stream().filter(RunMapper::hasRules).flatMap(extension -> extension.getRules().stream()).collect(toSet()) : Set.of(); return Stream.concat(driverRules.stream(), extensionRules.stream()) .distinct() @@ -96,6 +97,10 @@ public class RunMapper { return tool.getExtensions() != null && !tool.getExtensions().isEmpty(); } + private static boolean hasRules(Extension extension) { + return extension.getRules() != null && !extension.getRules().isEmpty(); + } + private List toNewExternalIssues(Run run, String driverName, Map ruleSeveritiesByRuleId, Map ruleSeveritiesByRuleIdForNewCCT) { return run.getResults() .stream() diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/RunMapperTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/RunMapperTest.java index 67f52b00556..8c03e6cd99a 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/RunMapperTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/RunMapperTest.java @@ -42,6 +42,7 @@ import org.sonar.scanner.externalissue.sarif.RunMapper.RunMapperResult; import static java.util.Collections.emptySet; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; +import static org.assertj.core.api.Assertions.assertThatNoException; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mockStatic; import static org.mockito.Mockito.when; @@ -131,6 +132,36 @@ public class RunMapperTest { } } + @Test + public void mapRun_shouldNotFail_whenExtensionsDontHaveRules() { + when(run.getTool().getDriver().getRules()).thenReturn(Set.of(rule)); + Extension extension = mock(Extension.class); + when(extension.getRules()).thenReturn(null); + when(run.getTool().getExtensions()).thenReturn(Set.of(extension)); + + try (MockedStatic detector = mockStatic(RulesSeverityDetector.class)) { + detector.when(() -> RulesSeverityDetector.detectRulesSeverities(run, TEST_DRIVER)).thenReturn(Map.of(RULE_ID, WARNING)); + detector.when(() -> RulesSeverityDetector.detectRulesSeveritiesForNewTaxonomy(run, TEST_DRIVER)).thenReturn(Map.of(RULE_ID, WARNING)); + + assertThatNoException().isThrownBy(() -> runMapper.mapRun(run)); + } + } + + @Test + public void mapRun_shouldNotFail_whenExtensionsHaveEmptyRules() { + when(run.getTool().getDriver().getRules()).thenReturn(Set.of(rule)); + Extension extension = mock(Extension.class); + when(extension.getRules()).thenReturn(Set.of()); + when(run.getTool().getExtensions()).thenReturn(Set.of(extension)); + + try (MockedStatic detector = mockStatic(RulesSeverityDetector.class)) { + detector.when(() -> RulesSeverityDetector.detectRulesSeverities(run, TEST_DRIVER)).thenReturn(Map.of(RULE_ID, WARNING)); + detector.when(() -> RulesSeverityDetector.detectRulesSeveritiesForNewTaxonomy(run, TEST_DRIVER)).thenReturn(Map.of(RULE_ID, WARNING)); + + assertThatNoException().isThrownBy(() -> runMapper.mapRun(run)); + } + } + @Test public void mapRun_ifRunIsEmpty_returnsEmptyList() { when(run.getResults()).thenReturn(emptySet()); -- 2.39.5