]> source.dussan.org Git - sonarqube.git/blob
e6531e9164e1e0c8624cfa87cc1e01780d7d5993
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2022 SonarSource SA
4  * mailto:info AT sonarsource DOT com
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 3 of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19  */
20 package org.sonar.ce.task.projectanalysis.pushevent;
21
22 import java.util.LinkedList;
23 import java.util.List;
24 import java.util.Set;
25 import org.jetbrains.annotations.NotNull;
26 import org.sonar.api.rules.RuleType;
27 import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolder;
28 import org.sonar.ce.task.projectanalysis.component.Component;
29 import org.sonar.ce.task.projectanalysis.component.TreeRootHolder;
30 import org.sonar.ce.task.projectanalysis.issue.IssueVisitor;
31 import org.sonar.core.issue.DefaultIssue;
32 import org.sonar.db.protobuf.DbCommons;
33 import org.sonar.db.protobuf.DbIssues;
34
35 import static java.util.Objects.requireNonNull;
36 import static java.util.Objects.requireNonNullElse;
37
38 public class TaintVulnerabilityVisitor extends IssueVisitor {
39   private static final Set<String> TAINT_REPOSITORIES = Set.of("roslyn.sonaranalyzer.security.cs", "javasecurity", "jssecurity", "tssecurity", "phpsecurity", "pythonsecurity");
40
41   private final PushEventRepository pushEventRepository;
42   private final AnalysisMetadataHolder analysisMetadataHolder;
43   private final TreeRootHolder treeRootHolder;
44
45   public TaintVulnerabilityVisitor(PushEventRepository pushEventRepository,
46     AnalysisMetadataHolder analysisMetadataHolder, TreeRootHolder treeRootHolder) {
47     this.pushEventRepository = pushEventRepository;
48     this.analysisMetadataHolder = analysisMetadataHolder;
49     this.treeRootHolder = treeRootHolder;
50   }
51
52   @Override
53   public void onIssue(Component component, DefaultIssue issue) {
54     if ((issue.isNew() || issue.isCopied()) && isTaintVulnerability(issue)) {
55       PushEvent<?> pushEvent = raiseTaintVulnerabilityRaisedEvent(component, issue);
56       pushEventRepository.add(pushEvent);
57     }
58   }
59
60   public PushEvent<TaintVulnerabilityRaised> raiseTaintVulnerabilityRaisedEvent(Component component, DefaultIssue issue) {
61     TaintVulnerabilityRaised event = prepareEvent(component, issue);
62     return new PushEvent<TaintVulnerabilityRaised>().setName("TaintVulnerabilityRaised").setData(event);
63   }
64
65   private TaintVulnerabilityRaised prepareEvent(Component component, DefaultIssue issue) {
66     TaintVulnerabilityRaised event = new TaintVulnerabilityRaised();
67     event.setProjectKey(issue.projectKey());
68     event.setCreationDate(issue.creationDate().getTime());
69     event.setKey(issue.key());
70     event.setSeverity(issue.severity());
71     event.setRuleKey(issue.getRuleKey().toString());
72     event.setType(issue.type().name());
73
74     event.setBranch(analysisMetadataHolder.getBranch().getName());
75
76     DbIssues.Locations issueLocations = requireNonNull(issue.getLocations());
77
78     Location mainLocation = new Location();
79     mainLocation.setMessage(issue.getMessage());
80
81     mainLocation.setFilePath(component.getName());
82
83     TextRange mainLocationTextRange = getTextRange(issueLocations.getTextRange(), issueLocations.getChecksum());
84     mainLocation.setTextRange(mainLocationTextRange);
85     event.setMainLocation(mainLocation);
86
87     List<Flow> flows = new LinkedList<>();
88     for (DbIssues.Flow sourceFlow : issueLocations.getFlowList()) {
89       Flow flow = new Flow();
90       List<Location> locations = new LinkedList<>();
91       for (DbIssues.Location sourceLocation : sourceFlow.getLocationList()) {
92         Location location = new Location();
93         var locationComponent = treeRootHolder.getComponentByUuid(sourceLocation.getComponentId());
94         location.setFilePath(requireNonNullElse(locationComponent, component).getName());
95         location.setMessage(sourceLocation.getMsg());
96
97         TextRange textRange = getTextRange(sourceLocation.getTextRange(), sourceLocation.getChecksum());
98         location.setTextRange(textRange);
99
100         locations.add(location);
101       }
102       flow.setLocations(locations);
103       flows.add(flow);
104     }
105     event.setFlows(flows);
106     return event;
107   }
108
109   @NotNull
110   private static TextRange getTextRange(DbCommons.TextRange source, String checksum) {
111     TextRange textRange = new TextRange();
112     textRange.setStartLine(source.getStartLine());
113     textRange.setStartLineOffset(source.getStartOffset());
114     textRange.setEndLine(source.getEndLine());
115     textRange.setEndLineOffset(source.getEndOffset());
116     textRange.setHash(checksum);
117     return textRange;
118   }
119
120   private static boolean isTaintVulnerability(DefaultIssue issue) {
121     return TAINT_REPOSITORIES.contains(issue.getRuleKey().repository())
122       && issue.getLocations() != null
123       && !RuleType.SECURITY_HOTSPOT.equals(issue.type());
124   }
125 }