private final String prKey;
private final BranchType branchType;
private final Date updateDate;
+ private final String cveId;
SiblingIssue(String key, @Nullable Integer line, @Nullable String message, @Nullable String lineHash, RuleKey ruleKey, String status, String prKey, BranchType branchType,
Date updateDate) {
+ this(key, line, message, lineHash, ruleKey, status, prKey, branchType, updateDate, null);
+ }
+
+ SiblingIssue(String key, @Nullable Integer line, @Nullable String message, @Nullable String lineHash, RuleKey ruleKey, String status, String prKey, BranchType branchType,
+ Date updateDate, @Nullable String cveId) {
this.key = key;
this.line = line;
this.message = message;
this.prKey = prKey;
this.branchType = branchType;
this.updateDate = updateDate;
+ this.cveId = cveId;
}
public String getKey() {
return updateDate;
}
+ @CheckForNull
+ @Override
+ public String getCveId() {
+ return cveId;
+ }
+
@Override
public int hashCode() {
return key.hashCode();
}
issue.setIsFromExternalRuleEngine(true);
issue.setLocations(dbLocationsBuilder.build());
- issue.setCveId(reportExternalIssue.getCveId());
+ if (reportExternalIssue.hasCveId()) {
+ issue.setCveId(reportExternalIssue.getCveId());
+ }
return issue;
}
issue.setCodeVariants(getCodeVariants());
issue.setCleanCodeAttribute(cleanCodeAttribute);
impacts.forEach(i -> issue.addImpact(i.getSoftwareQuality(), i.getSeverity()));
+ issue.setCveId(cveId);
return issue;
}
}
i.prioritized_rule as prioritizedRule,
<include refid="issueImpactsColumns"/>
<include refid="ruleDefaultImpactsColumns"/>
+ <include refid="issuesDependencyColumns"/>
<include refid="isNewCodeReferenceIssue"/>
</sql>
ii.software_quality as "ii_softwareQuality",
ii.severity as "ii_severity",
</sql>
+
<sql id="ruleDefaultImpactsColumns">
rdi.software_quality as "rdi_softwareQuality",
rdi.severity as "rdi_severity",
</sql>
+ <sql id="issuesDependencyColumns">
+ cve.id as cveId,
+ </sql>
+
<resultMap id="issueResultMap" type="Issue" autoMapping="true">
<id property="kee" column="kee"/>
left join new_code_reference_issues n on i.kee = n.issue_key
left outer join issues_impacts ii on i.kee = ii.issue_key
left outer join rules_default_impacts rdi on r.uuid = rdi.rule_uuid
+ left join issues_dependency dep on i.kee = dep.issue_uuid
+ left join cves cve on dep.cve_uuid = cve.uuid
where i.kee=#{kee,jdbcType=VARCHAR}
</select>
left join new_code_reference_issues n on i.kee = n.issue_key
left outer join issues_impacts ii on i.kee = ii.issue_key
left outer join rules_default_impacts rdi on r.uuid = rdi.rule_uuid
+ left join issues_dependency dep on i.kee = dep.issue_uuid
+ left join cves cve on dep.cve_uuid = cve.uuid
where
i.component_uuid = #{componentUuid,jdbcType=VARCHAR} and
i.status <> 'CLOSED'
i.kee = ii.issue_key
left outer join rules_default_impacts rdi on
r.uuid = rdi.rule_uuid
+ left join issues_dependency dep on i.kee = dep.issue_uuid
+ left join cves cve on dep.cve_uuid = cve.uuid
where
i.component_uuid = #{componentUuid,jdbcType=VARCHAR}
and i.status = 'CLOSED'
</collection>
</resultMap>
- <select id="scrollIssuesForIndexation" parameterType="map" resultMap="indexedIssueResultMap" fetchSize="${_scrollFetchSize}"
+ <select id="scrollIssuesForIndexation" parameterType="map" resultMap="indexedIssueResultMap" fetchSize="${_scrollFetchSize}"
resultSetType="FORWARD_ONLY" resultOrdered="true">
select
i.kee as issueKey,
i.prioritized_rule as prioritizedRule,
<include refid="issueImpactsColumns"/>
<include refid="ruleDefaultImpactsColumns"/>
+ <include refid="issuesDependencyColumns"/>
<include refid="isNewCodeReferenceIssue"/>
from issues i
inner join rules r on r.uuid = i.rule_uuid
left join new_code_reference_issues n on n.issue_key = i.kee
left outer join issues_impacts ii on i.kee = ii.issue_key
left outer join rules_default_impacts rdi on r.uuid = rdi.rule_uuid
+ left join issues_dependency dep on i.kee = dep.issue_uuid
+ left join cves cve on dep.cve_uuid = cve.uuid
<where>
<if test="branchUuid != null">
and c.branch_uuid = #{branchUuid,jdbcType=VARCHAR} and i.project_uuid = #{branchUuid,jdbcType=VARCHAR}
<select id="selectByKeys" parameterType="map" resultMap="issueResultMap">
select
<include refid="issueColumns"/>,
- u.login as assigneeLogin,
- cve.id as cveId
+ u.login as assigneeLogin
from issues i
inner join rules r on r.uuid=i.rule_uuid
inner join components p on p.uuid=i.component_uuid
left join new_code_reference_issues n on i.kee = n.issue_key
left outer join issues_impacts ii on i.kee = ii.issue_key
left outer join rules_default_impacts rdi on r.uuid = rdi.rule_uuid
+ left join issues_dependency dep on i.kee = dep.issue_uuid
+ left join cves cve on dep.cve_uuid = cve.uuid
where
i.kee in
<foreach collection="keys" open="(" close=")" item="key" separator=",">
i.prioritized_rule as prioritizedRule,
<include refid="issueImpactsColumns"/>
<include refid="ruleDefaultImpactsColumns"/>
+ <include refid="issuesDependencyColumns"/>
i.clean_code_attribute as cleanCodeAttribute,
r.clean_code_attribute as ruleCleanCodeAttribute
</sql>
left join users u on i.assignee = u.uuid
left outer join issues_impacts ii on i.kee = ii.issue_key
left outer join rules_default_impacts rdi on r.uuid = rdi.rule_uuid
+ left join issues_dependency dep on i.kee = dep.issue_uuid
+ left join cves cve on dep.cve_uuid = cve.uuid
where
<if test="keys.size() > 0">
i.kee IN
@Nullable String lineHash,
String transition,
@Nullable String comment) {
+
this.uuid = uuid;
this.projectKey = projectKey;
this.transition = transition;
return Date.from(Instant.now());
}
+ @Nullable
+ @Override
+ public String getCveId() {
+ return null;
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) {
return updateDate;
}
+ @Override
+ @CheckForNull
public String getCveId() {
return cveId;
}
private final RuleKey ruleKey;
private final String lineHash;
private final Integer line;
+ private final String cveId;
protected LineAndLineHashKey(Trackable trackable) {
this.ruleKey = trackable.getRuleKey();
this.line = trackable.getLine();
this.lineHash = Objects.toString(trackable.getLineHash(), "");
+ this.cveId = trackable.getCveId();
}
@Override
}
LineAndLineHashKey that = (LineAndLineHashKey) o;
// start with most discriminant field
- return Objects.equals(line, that.line) && lineHash.equals(that.lineHash) && ruleKey.equals(that.ruleKey);
+ return Objects.equals(line, that.line)
+ && lineHash.equals(that.lineHash)
+ && ruleKey.equals(that.ruleKey)
+ && Objects.equals(cveId, that.cveId);
}
@Override
public int hashCode() {
- return Objects.hash(ruleKey, lineHash, line != null ? line : 0);
+ return Objects.hash(ruleKey, lineHash, line != null ? line : 0, cveId);
}
}
private final String lineHash;
private final String message;
private final Integer line;
+ private final String cveId;
protected LineAndLineHashAndMessage(Trackable trackable) {
this.ruleKey = trackable.getRuleKey();
this.line = trackable.getLine();
this.message = trackable.getMessage();
this.lineHash = Objects.toString(trackable.getLineHash(), "");
+ this.cveId = trackable.getCveId();
}
@Override
}
LineAndLineHashAndMessage that = (LineAndLineHashAndMessage) o;
// start with most discriminant field
- return Objects.equals(line, that.line) && lineHash.equals(that.lineHash) && Objects.equals(message, that.message) && ruleKey.equals(that.ruleKey);
+ return Objects.equals(line, that.line)
+ && lineHash.equals(that.lineHash)
+ && Objects.equals(message, that.message)
+ && ruleKey.equals(that.ruleKey)
+ && Objects.equals(cveId, that.cveId);
}
@Override
public int hashCode() {
- return Objects.hash(ruleKey, lineHash, message, line != null ? line : 0);
+ return Objects.hash(ruleKey, lineHash, message, line != null ? line : 0, cveId);
}
}
private final RuleKey ruleKey;
private final String message;
private final String lineHash;
+ private final String cveId;
LineHashAndMessageKey(Trackable trackable) {
this.ruleKey = trackable.getRuleKey();
this.message = trackable.getMessage();
this.lineHash = Objects.toString(trackable.getLineHash(), "");
+ this.cveId = trackable.getCveId();
}
@Override
}
LineHashAndMessageKey that = (LineHashAndMessageKey) o;
// start with most discriminant field
- return lineHash.equals(that.lineHash) && Objects.equals(message, that.message) && ruleKey.equals(that.ruleKey);
+ return lineHash.equals(that.lineHash)
+ && Objects.equals(message, that.message)
+ && ruleKey.equals(that.ruleKey)
+ && Objects.equals(cveId, that.cveId);
}
@Override
public int hashCode() {
- return Objects.hash(ruleKey, message, lineHash);
+ return Objects.hash(ruleKey, message, lineHash, cveId);
}
}
private final RuleKey ruleKey;
private final String message;
private final Integer line;
+ private final String cveId;
LineAndMessageKey(Trackable trackable) {
this.ruleKey = trackable.getRuleKey();
this.message = trackable.getMessage();
this.line = trackable.getLine();
+ this.cveId = trackable.getCveId();
}
@Override
}
LineAndMessageKey that = (LineAndMessageKey) o;
// start with most discriminant field
- return Objects.equals(line, that.line) && Objects.equals(message, that.message) && ruleKey.equals(that.ruleKey);
+ return Objects.equals(line, that.line)
+ && Objects.equals(message, that.message)
+ && ruleKey.equals(that.ruleKey)
+ && Objects.equals(cveId, that.cveId);
}
@Override
protected static class LineHashKey implements SearchKey {
private final RuleKey ruleKey;
private final String lineHash;
+ private final String cveId;
LineHashKey(Trackable trackable) {
this.ruleKey = trackable.getRuleKey();
this.lineHash = Objects.toString(trackable.getLineHash(), "");
+ this.cveId = trackable.getCveId();
}
@Override
}
LineHashKey that = (LineHashKey) o;
// start with most discriminant field
- return lineHash.equals(that.lineHash) && ruleKey.equals(that.ruleKey);
+ return lineHash.equals(that.lineHash) && ruleKey.equals(that.ruleKey) && Objects.equals(cveId, that.cveId);
}
@Override
public int hashCode() {
- return Objects.hash(ruleKey, lineHash);
+ return Objects.hash(ruleKey, lineHash, cveId);
}
}
* Functional update date for the issue. See {@link DefaultIssue#updateDate()}
*/
Date getUpdateDate();
+
+ @CheckForNull
+ String getCveId();
}
assertThat(tracking.baseFor(raw2)).isEqualTo(base1);
}
+ @Test
+ public void match_issues_with_same_cve_id() {
+ FakeInput baseInput = new FakeInput();
+ Issue base = new Issue(null, "", RuleKey.of("sca", "use-of-vulnerable-dependency"), "Vulnerable", org.sonar.api.issue.Issue.STATUS_OPEN, new Date(), "CVE-1");
+ baseInput.addIssue(base);
+ FakeInput rawInput = new FakeInput();
+ Issue raw = new Issue(null, "", RuleKey.of("sca", "use-of-vulnerable-dependency"), "Vulnerable", org.sonar.api.issue.Issue.STATUS_OPEN, new Date(), "CVE-1");
+ rawInput.addIssue(raw);
+
+ Tracking<Issue, Issue> tracking = tracker.trackNonClosed(rawInput, baseInput);
+
+ assertThat(tracking.getUnmatchedBases()).isEmpty();
+ assertThat(tracking.baseFor(raw)).isEqualTo(base);
+ }
+
+ @Test
+ public void do_not_match_issues_with_different_cve_id() {
+ FakeInput baseInput = new FakeInput();
+ Issue base = new Issue(null, "", RuleKey.of("sca", "use-of-vulnerable-dependency"), "Vulnerable", org.sonar.api.issue.Issue.STATUS_OPEN, new Date(), "CVE-1");
+ baseInput.addIssue(base);
+ FakeInput rawInput = new FakeInput();
+ Issue raw = new Issue(null, "", RuleKey.of("sca", "use-of-vulnerable-dependency"), "Vulnerable", org.sonar.api.issue.Issue.STATUS_OPEN, new Date(), "CVE-2");
+ rawInput.addIssue(raw);
+
+ Tracking<Issue, Issue> tracking = tracker.trackNonClosed(rawInput, baseInput);
+
+ assertThat(tracking.getUnmatchedBases()).contains(base);
+ assertThat(tracking.baseFor(raw)).isNull();
+ }
+
private static class Issue implements Trackable {
private final RuleKey ruleKey;
private final Integer line;
private final String message, lineHash;
private final String status;
private final Date updateDate;
+ private final String cveId;
Issue(@Nullable Integer line, String lineHash, RuleKey ruleKey, @Nullable String message, String status, Date updateDate) {
+ this(line, lineHash, ruleKey, message, status, updateDate, null);
+ }
+
+ Issue(@Nullable Integer line, String lineHash, RuleKey ruleKey, @Nullable String message, String status, Date updateDate, @Nullable String cveId) {
this.line = line;
this.lineHash = lineHash;
this.ruleKey = ruleKey;
this.status = status;
this.updateDate = updateDate;
this.message = trim(message);
+ this.cveId = cveId;
}
@Override
public Date getUpdateDate() {
return updateDate;
}
+
+ @CheckForNull
+ @Override
+ public String getCveId() {
+ return cveId;
+ }
}
private static class FakeInput implements Input<Issue> {