foss-vuln-tracker/molerat/src/main/java/it/unitn/molerat/repos/trackers/vuln/SliceVulnerabilityEvidenceT...

140 lines
5.9 KiB
Java

package it.unitn.molerat.repos.trackers.vuln;
import it.unitn.molerat.evidence.Changes;
import it.unitn.molerat.evidence.VulnerabilityEvidence;
import it.unitn.molerat.repos.wrappers.RepoWrapper;
import it.unitn.repoman.core.lang.LanguageFactory;
import it.unitn.repoman.core.slicers.LightweightSlice;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
public class SliceVulnerabilityEvidenceTracker extends VulnerabilityEvidenceTracker {
public SliceVulnerabilityEvidenceTracker(RepoWrapper wrapper, String fixedRev) throws Exception {
super(wrapper, fixedRev);
}
@Override
protected Set<VulnerabilityEvidence> getInitialVulnerabilityEvidence(Changes changes) throws Exception {
// 1. Take the added lines as the slicing criteria and obtain the slice on the fixed revision
Map<Integer, String> slicingCriteria = changes.getAdditions();
String rightFile = this.repoWrapper.doCat(changes.getPath(), changes.getRightRevision());
Map<Integer, String> sliced = this.doSlice(slicingCriteria, rightFile);
Set<VulnerabilityEvidence> slicedEvd = this.recordVulnerabilityEvidenceForRightFile(sliced, changes);
// 2. we need to check which lines from the "fixed" slice are present in the vulnerable revision
// 2.1 we "correlate" the lines from the "fixed" slice to the vulnerable revision
Map<Integer, String> propagated = this.updateChangedLines(changes.getPath(), changes.getLeftRevision(),
changes.getRightRevision(), slicedEvd, changes);
// 2.2 take deleted lines + "correlated" changes from the fixed slice and take a new slice on the vulnerable revision
propagated.putAll(changes.getDeletions());
// 3.1 make the final slice on the vulnerable revision
slicingCriteria = propagated;
String leftFile = this.repoWrapper.doCat(changes.getPath(), changes.getLeftRevision());
sliced = this.doSlice(slicingCriteria, leftFile);
propagated.putAll(sliced);
Set<VulnerabilityEvidence> initialEvidence = this.recordVulnerabilityEvidence(propagated, changes);
return initialEvidence;
}
@Override
protected Set<VulnerabilityEvidence> getVulnerabilityEvidence(String currentEvidenceCommit, String previousEvidenceCommit, Set<Changes> changes) throws Exception {
Set<VulnerabilityEvidence> newEvidences = new HashSet<>();
Set<VulnerabilityEvidence> previousEvidences = getEvidences(previousEvidenceCommit);
Set<VulnerabilityEvidence> changedEvidence = new HashSet<>();
Set<Changes> changesToProcess = new HashSet<>();
Set<VulnerabilityEvidence> stillEvidence = new HashSet<>();
// filter non-Java files
changes = filterNonJavaChanges(changes);
if (previousEvidences == null) {
return newEvidences;
}
for (VulnerabilityEvidence previousEvidence : previousEvidences) {
for (Changes change : changes ) {
// The file has been just renamed
if (change.wasRenamed()) {
if (change.getRenamedTo().equals(previousEvidence.getPath())) {
previousEvidence.setPath(change.getPath());
}
}
// The file has been changed
else if (previousEvidence.getPath().equals(change.getPath())) {
changedEvidence.add(previousEvidence);
changesToProcess.add(change);
}
}
}
stillEvidence.addAll(previousEvidences);
stillEvidence.removeAll(changedEvidence);
// "Refresh" the molerat.evidence when a file was not changed
for (VulnerabilityEvidence e : stillEvidence) {
VulnerabilityEvidence newEvidence = new VulnerabilityEvidence(
e.getPath(),
currentEvidenceCommit,
e.getContainer(),
e.getLineNumber(),
e.getLineContents()
);
newEvidences.add(newEvidence);
}
// "Triage" the molerat.evidence when a file was changed
for (Changes change : changesToProcess) {
// --------------------------------------
Map<Integer, String> slicingCriteria = new TreeMap<>();
for (VulnerabilityEvidence e : changedEvidence) {
if (e.getPath().equals(change.getPath())) {
slicingCriteria.put(e.getLineNumber(), e.getLineContents());
}
}
String rightFile = this.repoWrapper.doCat(change.getPath(), change.getRightRevision());
Map<Integer, String> slice = this.doSlice(slicingCriteria, rightFile);
Set<VulnerabilityEvidence> slicedEvd = this.recordVulnerabilityEvidenceForRightFile(slice, change);
Map<Integer, String> linesToKeep = this.updateChangedLines(
change.getPath(),
change.getLeftRevision(),
change.getRightRevision(),
slicedEvd,
change
);
if (linesToKeep != null) {
String leftFile = this.repoWrapper.doCat(change.getPath(), change.getLeftRevision());
slice = this.doSlice(linesToKeep, leftFile);
newEvidences.addAll(this.recordVulnerabilityEvidence(slice, change));
}
}
return newEvidences;
}
protected Map<Integer, String> doSlice(Map<Integer, String> slicingCriteria, String fileContents) {
Map<Integer, String> sliced = this.repoWrapper.getLineMappings(fileContents);
LanguageFactory.init("Java", fileContents);
LightweightSlice slice;
try {
slice = new LightweightSlice(LanguageFactory.getRoot(), slicingCriteria.keySet());
sliced.keySet().retainAll(slice.getSelectedLines());
} catch (Exception e) {
System.out.println("ERROR: " + e.getMessage());
}
return sliced;
}
}