package it.unitn.molerat.repos.trackers.vuln; import it.unitn.molerat.evidence.Changes; import it.unitn.molerat.evidence.VulnerabilityEvidence; import it.unitn.molerat.repos.utils.SignatureExtractor; import it.unitn.molerat.repos.wrappers.RepoWrapper; import java.util.HashSet; import java.util.Map; import java.util.Set; public class PatchedMethodBodyTracker extends VulnerabilityEvidenceTracker { public PatchedMethodBodyTracker(RepoWrapper wrapper, String fixedRev) throws Exception { super(wrapper, fixedRev); } @Override protected Set getInitialVulnerabilityEvidence(Changes changes) throws Exception { SignatureExtractor se = new SignatureExtractor(repoWrapper.doCat(changes.getPath(), changes.getRightRevision())); Map> rightSignatures = se.getSignaturesWithLines(); Set relevantSignatures = new HashSet<>(); for (int line : changes.getAdditions().keySet()) { for (Map.Entry> entry : rightSignatures.entrySet()) { if (entry.getValue().contains(line)) { relevantSignatures.add(entry.getKey()); } } } String leftFile = repoWrapper.doCat(changes.getPath(), changes.getLeftRevision()); Map lineMappings = repoWrapper.getLineMappings(leftFile); se = new SignatureExtractor(leftFile); Map> leftSignatures = se.getSignaturesWithLines(); for (int line : changes.getDeletions().keySet()) { for (Map.Entry> entry : leftSignatures.entrySet()) { if (entry.getValue().contains(line)) { relevantSignatures.add(entry.getKey()); } } } Set initialEvidence = new HashSet<>(); for (String signature : relevantSignatures) { for (Map.Entry> entry : leftSignatures.entrySet()) { if (signature.equals(entry.getKey())) { for (int line : entry.getValue()) { VulnerabilityEvidence evd = new VulnerabilityEvidence( changes.getPath(), changes.getLeftRevision(), signature, line, lineMappings.get(line) ); initialEvidence.add(evd); } } } } return initialEvidence; } @Override protected Set getVulnerabilityEvidence(String currentEvidenceCommit, String previousEvidenceCommit, Set changes) throws Exception { Set newEvidences = new HashSet<>(); Set previousEvidences = getEvidences(previousEvidenceCommit); Set changedEvidence = new HashSet<>(); Set changesToProcess = new HashSet<>(); Set 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) { Set relevantSignatures = new HashSet<>(); for (VulnerabilityEvidence e : changedEvidence) { relevantSignatures.add(e.getContainer()); } String leftFile = repoWrapper.doCat(change.getPath(), change.getLeftRevision()); Map lineMappings = repoWrapper.getLineMappings(leftFile); SignatureExtractor se = new SignatureExtractor(leftFile); Map> leftSignatures = se.getSignaturesWithLines(); for (String signature : relevantSignatures) { for (Map.Entry> entry : leftSignatures.entrySet()) { if (signature.equals(entry.getKey())) { for (int line : entry.getValue()) { VulnerabilityEvidence evd = new VulnerabilityEvidence( change.getPath(), change.getLeftRevision(), signature, line, lineMappings.get(line) ); newEvidences.add(evd); } } } } } return newEvidences; } }