Correctly implemented this analyzer (hopefully)

Former-commit-id: d65b60ee5212f3a10cc146a7f2aff345fd93695b
This commit is contained in:
Jeremy Long
2013-04-20 13:11:01 -04:00
parent dba1e0b316
commit 62b6bf9105

View File

@@ -19,7 +19,9 @@
package org.owasp.dependencycheck.analyzer; package org.owasp.dependencycheck.analyzer;
import java.io.File; import java.io.File;
import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.ListIterator;
import java.util.Set; import java.util.Set;
import org.owasp.dependencycheck.Engine; import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.dependency.Dependency; import org.owasp.dependencycheck.dependency.Dependency;
@@ -87,42 +89,68 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
public AnalysisPhase getAnalysisPhase() { public AnalysisPhase getAnalysisPhase() {
return ANALYSIS_PHASE; return ANALYSIS_PHASE;
} }
/** /**
* The Post Analysis Action that will be set after analyzing a dependency. * a flag indicating if this analyzer has run. This analyzer only runs once.
*/ */
private PostAnalysisAction action; private boolean analyzed = false;
/** /**
* Analyzes a set of dependencies. If they have been found to have the same * Analyzes a set of dependencies. If they have been found to have the same
* base path and the same set of identifiers they are likely related. The * base path and the same set of identifiers they are likely related. The
* related dependencies are bundled into a single reportable item. * related dependencies are bundled into a single reportable item.
* *
* @param dependency the dependency being analyzed * @param ignore this analyzer ignores the dependency being analyzed
* @param engine the engine that is scanning the dependencies * @param engine the engine that is scanning the dependencies
* @throws AnalysisException is thrown if there is an error reading the JAR * @throws AnalysisException is thrown if there is an error reading the JAR
* file. * file.
*/ */
public void analyze(Dependency dependency, Engine engine) throws AnalysisException { public void analyze(Dependency ignore, Engine engine) throws AnalysisException {
action = PostAnalysisAction.NOTHING; if (!analyzed) {
if (dependency.getIdentifiers().size() > 0) { analyzed = true;
for (Dependency dependencyToCheck : engine.getDependencies()) { Set<Dependency> dependenciesToRemove = new HashSet<Dependency>();
if (dependency.equals(dependencyToCheck)) { ListIterator<Dependency> mainIterator = engine.getDependencies().listIterator();
return; //for (Dependency dependencyToCheck : engine.getDependencies()) {
} while (mainIterator.hasNext()) {
if (identifiersMatch(dependencyToCheck, dependency) final Dependency dependency = mainIterator.next();
&& hasSameBasePath(dependencyToCheck, dependency) System.out.println("START " + dependency.getFileName() + "----------------------");
&& isCore(dependency, dependencyToCheck)) { if (mainIterator.hasNext()) {
//move this dependency to be a related dependency ListIterator<Dependency> subIterator = engine.getDependencies().listIterator(mainIterator.nextIndex());
action = PostAnalysisAction.REMOVE_DEPENDENCY; while (subIterator.hasNext()) {
dependencyToCheck.addRelatedDependency(dependency); final Dependency dependencyToCheck = subIterator.next();
//move any "related dependencies" to the new "parent" dependency if (identifiersMatch(dependency, dependencyToCheck)
final Iterator<Dependency> i = dependency.getRelatedDependencies().iterator(); && hasSameBasePath(dependency, dependencyToCheck)) {
while (i.hasNext()) {
dependencyToCheck.addRelatedDependency(i.next()); if (isCore(dependency, dependencyToCheck)) {
i.remove(); dependency.addRelatedDependency(dependencyToCheck);
//move any "related dependencies" to the new "parent" dependency
final Iterator<Dependency> i = dependencyToCheck.getRelatedDependencies().iterator();
while (i.hasNext()) {
dependency.addRelatedDependency(i.next());
i.remove();
}
dependenciesToRemove.add(dependencyToCheck);
} else {
if (isCore(dependencyToCheck, dependency)) {
dependencyToCheck.addRelatedDependency(dependency);
//move any "related dependencies" to the new "parent" dependency
final Iterator<Dependency> i = dependency.getRelatedDependencies().iterator();
while (i.hasNext()) {
dependencyToCheck.addRelatedDependency(i.next());
i.remove();
}
dependenciesToRemove.add(dependency);
}
}
}
} }
return;
} }
System.out.println("END " + dependency.getFileName() + "----------------------");
}
//removing dependencies here as ensuring correctness and avoiding ConcurrentUpdateExceptions
// was difficult because of the inner iterator.
for (Dependency d : dependenciesToRemove) {
engine.getDependencies().remove(d);
} }
} }
} }
@@ -134,10 +162,13 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
* @return true if the identifiers in the two supplied dependencies are equal * @return true if the identifiers in the two supplied dependencies are equal
*/ */
private boolean identifiersMatch(Dependency dependency1, Dependency dependency2) { private boolean identifiersMatch(Dependency dependency1, Dependency dependency2) {
System.out.println("Checking Identifiers: " + dependency1.getFileName() + " and " + dependency2.getFileName());
if (dependency1 == null || dependency1.getIdentifiers() == null if (dependency1 == null || dependency1.getIdentifiers() == null
|| dependency2 == null || dependency2.getIdentifiers() == null) { || dependency2 == null || dependency2.getIdentifiers() == null) {
return false; return false;
} }
System.out.println("Result = " + (dependency1.getIdentifiers().size() > 0
&& dependency2.getIdentifiers().equals(dependency1.getIdentifiers())));
return dependency1.getIdentifiers().size() > 0 return dependency1.getIdentifiers().size() > 0
&& dependency2.getIdentifiers().equals(dependency1.getIdentifiers()); && dependency2.getIdentifiers().equals(dependency1.getIdentifiers());
} }
@@ -175,31 +206,25 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
* considered the "core" version. * considered the "core" version.
*/ */
private boolean isCore(Dependency left, Dependency right) { private boolean isCore(Dependency left, Dependency right) {
System.out.println("Checking iscore: " + left.getFileName() + " and " + right.getFileName());
final String leftName = left.getFileName().toLowerCase(); final String leftName = left.getFileName().toLowerCase();
final String rightName = right.getFileName().toLowerCase(); final String rightName = right.getFileName().toLowerCase();
if (rightName.contains("core") && !leftName.contains("core")) { if (rightName.contains("core") && !leftName.contains("core")) {
System.out.println("core False 1");
return false; return false;
} else if (!rightName.contains("core") && leftName.contains("core")) { } else if (!rightName.contains("core") && leftName.contains("core")) {
System.out.println("core true 1");
return true; return true;
} else { } else {
//TODO should we be splitting the name on [-_(.\d)+] and seeing if the //TODO should we be splitting the name on [-_(.\d)+] and seeing if the
// parts are contained in the other side? // parts are contained in the other side?
if (leftName.length() > rightName.length()) { if (leftName.length() > rightName.length()) {
System.out.println("core false 2");
return false; return false;
} }
System.out.println("core true 2");
return true; return true;
} }
} }
/**
* Returns whether or not the dependency should be removed from the parent
* list of dependencies.
*
* @return a PostAnalysisAction of REMOVE or NOTHING
*/
@Override
public PostAnalysisAction getPostAnalysisAction() {
return action;
}
} }