]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-22009 Fix NPE on SARIF import when Extensions don't have Rules
authorantoine.vinot <antoine.vinot@sonarsource.com>
Fri, 5 Apr 2024 09:31:23 +0000 (11:31 +0200)
committersonartech <sonartech@sonarsource.com>
Fri, 5 Apr 2024 20:02:38 +0000 (20:02 +0000)
sonar-core/src/main/java/org/sonar/core/sarif/Extension.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/externalissue/sarif/RunMapper.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/RunMapperTest.java

index d3acedeb88f172c8ac59d395613040bb4fb30d1a..1e7b16c37bfb5efe4f03efda1ace5ea4d09d82ae 100644 (file)
@@ -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<Rule> getRules() {
     return rules;
   }
index 442e2a1703de2333e8a5edd36f1faa512af26c73..f94549c5ade2c634defbdb17af6a04e96acd1258 100644 (file)
@@ -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<NewAdHocRule> toNewAdHocRules(Run run, String driverName, Map<String, String> ruleSeveritiesByRuleId, Map<String, String> ruleSeveritiesByRuleIdForNewCCT) {
     Set<Rule> driverRules = run.getTool().getDriver().getRules();
     Set<Rule> 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<NewExternalIssue> toNewExternalIssues(Run run, String driverName, Map<String, String> ruleSeveritiesByRuleId, Map<String, String> ruleSeveritiesByRuleIdForNewCCT) {
     return run.getResults()
       .stream()
index 67f52b0055684ddaaa3c95f0837924bf3ad61747..8c03e6cd99ae93bc71dae4a8c6d54c4575b3bc21 100644 (file)
@@ -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<RulesSeverityDetector> 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<RulesSeverityDetector> 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());