diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.java index 4857e8f5d..6f6ee4291 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.java @@ -17,20 +17,24 @@ */ package org.owasp.dependencycheck.analyzer; +import java.io.BufferedReader; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; + import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; + import org.owasp.dependencycheck.Engine; import org.owasp.dependencycheck.analyzer.exception.AnalysisException; import org.owasp.dependencycheck.dependency.Confidence; @@ -71,7 +75,7 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer { /** * Logger */ - private static final Logger LOG = Logger.getLogger(AbstractAnalyzer.class.getName()); + private static final Logger LOG = Logger.getLogger(AssemblyAnalyzer.class.getName()); /** * Builds the beginnings of a List for ProcessBuilder @@ -113,6 +117,13 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer { final ProcessBuilder pb = new ProcessBuilder(args); try { final Process proc = pb.start(); + // Try evacuating the error stream + final BufferedReader rdr = new BufferedReader(new InputStreamReader(proc.getErrorStream())); + String line = null; + while ((line = rdr.readLine()) != null) { + LOG.warning("Error from GrokAssembly: " + line); + } + int rc = 0; final Document doc = builder.parse(proc.getInputStream()); final XPath xpath = XPathFactory.newInstance().newXPath(); @@ -140,6 +151,19 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer { product, Confidence.HIGH)); } + try { + rc = proc.waitFor(); + } catch (InterruptedException ie) { + return; + } + if (rc == 3) { + LOG.info(dependency.getActualFilePath() + " is not a valid assembly"); + return; + } else if (rc != 0) { + LOG.warning("Return code " + rc + " from GrokAssembly"); + } + + } catch (IOException ioe) { throw new AnalysisException(ioe); } catch (SAXException saxe) { @@ -195,7 +219,14 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer { // Now, need to see if GrokAssembly actually runs from this location. final List args = buildArgumentList(); try { - final Process p = new ProcessBuilder(args).start(); + final ProcessBuilder pb = new ProcessBuilder(args); + final Process p = pb.start(); + // Try evacuating the error stream + final BufferedReader rdr = new BufferedReader(new InputStreamReader(p.getErrorStream())); + String line = null; + while ((line = rdr.readLine()) != null) { + // We expect this to complain + } final Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(p.getInputStream()); final XPath xpath = XPathFactory.newInstance().newXPath(); final String error = xpath.evaluate("/assembly/error", doc); diff --git a/dependency-check-core/src/main/resources/GrokAssembly.exe b/dependency-check-core/src/main/resources/GrokAssembly.exe index 9c395259e..0cea03759 100755 Binary files a/dependency-check-core/src/main/resources/GrokAssembly.exe and b/dependency-check-core/src/main/resources/GrokAssembly.exe differ diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/AssemblyAnalyzerTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/AssemblyAnalyzerTest.java index 19c1f57ed..0aa96abd3 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/AssemblyAnalyzerTest.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/AssemblyAnalyzerTest.java @@ -17,14 +17,17 @@ */ package org.owasp.dependencycheck.analyzer; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.junit.Assume.assumeFalse; + import java.io.File; import java.util.logging.Level; import java.util.logging.Logger; + import org.junit.After; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; import org.junit.Assume; -import static org.junit.Assume.assumeFalse; import org.junit.Before; import org.junit.Test; import org.owasp.dependencycheck.analyzer.exception.AnalysisException; @@ -75,7 +78,21 @@ public class AssemblyAnalyzerTest { File f = new File(AssemblyAnalyzerTest.class.getClassLoader().getResource("GrokAssembly.exe").getPath()); Dependency d = new Dependency(f); analyzer.analyze(d, null); - assertTrue(d.getVersionEvidence().getEvidence().contains(new Evidence("grokassembly", "version", "1.0.5176.23901", Confidence.HIGHEST))); + boolean foundVendor = false; + for (Evidence e : d.getVendorEvidence().getEvidence("grokassembly", "vendor")) { + if ("OWASP".equals(e.getValue())) { + foundVendor = true; + } + } + assertTrue(foundVendor); + + boolean foundProduct = false; + for (Evidence e : d.getProductEvidence().getEvidence("grokassembly", "product")) { + if ("GrokAssembly".equals(e.getValue())) { + foundProduct = true; + } + } + assertTrue(foundProduct); } @Test @@ -88,15 +105,29 @@ public class AssemblyAnalyzerTest { assertTrue(d.getProductEvidence().getEvidence().contains(new Evidence("grokassembly", "product", "log4net", Confidence.HIGH))); } - @Test(expected = AnalysisException.class) - public void testNonexistent() throws Exception { + @Test + public void testNonexistent() { + Level oldLevel = Logger.getLogger(AssemblyAnalyzer.class.getName()).getLevel(); + Level oldDependency = Logger.getLogger(Dependency.class.getName()).getLevel(); + // Tweak the log level so the warning doesn't show in the console + Logger.getLogger(AssemblyAnalyzer.class.getName()).setLevel(Level.OFF); + Logger.getLogger(Dependency.class.getName()).setLevel(Level.OFF); File f = new File(AssemblyAnalyzerTest.class.getClassLoader().getResource("log4net.dll").getPath()); File test = new File(f.getParent(), "nonexistent.dll"); Dependency d = new Dependency(test); - analyzer.analyze(d, null); + + try { + analyzer.analyze(d, null); + fail("Expected an AnalysisException"); + } catch (AnalysisException ae) { + assertEquals("File does not exist", ae.getMessage()); + } finally { + Logger.getLogger(AssemblyAnalyzer.class.getName()).setLevel(oldLevel); + Logger.getLogger(Dependency.class.getName()).setLevel(oldDependency); + } } - @Test(expected = AnalysisException.class) + @Test public void testWithSettingMono() throws Exception { //This test doesn't work on Windows. @@ -113,12 +144,20 @@ public class AssemblyAnalyzerTest { Settings.setString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, "/yooser/bine/mono"); } + Level oldLevel = Logger.getLogger(AssemblyAnalyzer.class.getName()).getLevel(); try { + // Tweak the logging to swallow the warning when testing + Logger.getLogger(AssemblyAnalyzer.class.getName()).setLevel(Level.OFF); // Have to make a NEW analyzer because during setUp, it would have gotten the correct one AssemblyAnalyzer aanalyzer = new AssemblyAnalyzer(); aanalyzer.supportsExtension("dll"); aanalyzer.initialize(); + fail("Expected an AnalysisException"); + } catch (AnalysisException ae) { + assertEquals("An error occured with the .NET AssemblyAnalyzer", ae.getMessage()); } finally { + // Recover the logger + Logger.getLogger(AssemblyAnalyzer.class.getName()).setLevel(oldLevel); // Now recover the way we came in. If we had to set a System property, delete it. Otherwise, // reset the old value if (oldValue == null) {