From abebecac4a200d10fec4421dc35974849fa89a0e Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Sun, 24 Apr 2016 09:06:00 -0400 Subject: [PATCH] updated parser and tests to revert to old suppression schema if new schema fails --- .../analyzer/AbstractSuppressionAnalyzer.java | 6 ++ .../suppression/SuppressionParser.java | 80 +++++++++++++++++-- .../AbstractSuppressionAnalyzerTest.java | 4 +- .../src/test/resources/suppressions.xml | 5 +- 4 files changed, 86 insertions(+), 9 deletions(-) diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.java index a730acf7e..97c0719d5 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.java @@ -24,6 +24,7 @@ import java.net.MalformedURLException; import java.net.URL; import java.util.List; import java.util.Set; +import java.util.logging.Level; import java.util.regex.Pattern; import org.owasp.dependencycheck.suppression.SuppressionParseException; import org.owasp.dependencycheck.suppression.SuppressionParser; @@ -34,6 +35,7 @@ import org.owasp.dependencycheck.utils.FileUtils; import org.owasp.dependencycheck.utils.Settings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.xml.sax.SAXException; /** * Abstract base suppression analyzer that contains methods for parsing the suppression xml file. @@ -103,6 +105,10 @@ public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer { try { rules = parser.parseSuppressionRules(this.getClass().getClassLoader().getResourceAsStream("dependencycheck-base-suppression.xml")); } catch (SuppressionParseException ex) { + LOGGER.error("Unable to parse the base suppression data file"); + LOGGER.debug("Unable to parse the base suppression data file", ex); + } catch (SAXException ex) { + LOGGER.error("Unable to parse the base suppression data file"); LOGGER.debug("Unable to parse the base suppression data file", ex); } final String suppressionFilePath = Settings.getString(Settings.KEYS.SUPPRESSION_FILE); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/suppression/SuppressionParser.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/suppression/SuppressionParser.java index 9b863c3d0..e4956ed1b 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/suppression/SuppressionParser.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/suppression/SuppressionParser.java @@ -25,6 +25,7 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.util.List; +import java.util.logging.Level; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; @@ -47,20 +48,24 @@ public class SuppressionParser { */ private static final Logger LOGGER = LoggerFactory.getLogger(SuppressionParser.class); /** - * JAXP Schema Language. Source: http://docs.oracle.com/javase/tutorial/jaxp/sax/validation.html + * JAXP Schema Language. Source: + * http://docs.oracle.com/javase/tutorial/jaxp/sax/validation.html */ public static final String JAXP_SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage"; /** - * W3C XML Schema. Source: http://docs.oracle.com/javase/tutorial/jaxp/sax/validation.html + * W3C XML Schema. Source: + * http://docs.oracle.com/javase/tutorial/jaxp/sax/validation.html */ public static final String W3C_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema"; /** - * JAXP Schema Source. Source: http://docs.oracle.com/javase/tutorial/jaxp/sax/validation.html + * JAXP Schema Source. Source: + * http://docs.oracle.com/javase/tutorial/jaxp/sax/validation.html */ public static final String JAXP_SCHEMA_SOURCE = "http://java.sun.com/xml/jaxp/properties/schemaSource"; /** - * Parses the given xml file and returns a list of the suppression rules contained. + * Parses the given xml file and returns a list of the suppression rules + * contained. * * @param file an xml file containing suppression rules * @return a list of suppression rules @@ -74,6 +79,20 @@ public class SuppressionParser { } catch (IOException ex) { LOGGER.debug("", ex); throw new SuppressionParseException(ex); + } catch (SAXException ex) { + try { + if (fis != null) { + try { + fis.close(); + } catch (IOException ex1) { + LOGGER.debug("Unable to close stream", ex1); + } + } + fis = new FileInputStream(file); + } catch (FileNotFoundException ex1) { + throw new SuppressionParseException(ex); + } + return parseOldSuppressionRules(fis); } finally { if (fis != null) { try { @@ -86,13 +105,62 @@ public class SuppressionParser { } /** - * Parses the given xml stream and returns a list of the suppression rules contained. + * Parses the given xml stream and returns a list of the suppression rules + * contained. * * @param inputStream an InputStream containing suppression rues * @return a list of suppression rules * @throws SuppressionParseException if the xml cannot be parsed */ - public List parseSuppressionRules(InputStream inputStream) throws SuppressionParseException { + public List parseSuppressionRules(InputStream inputStream) throws SuppressionParseException, SAXException { + try { + final InputStream schemaStream = this.getClass().getClassLoader().getResourceAsStream("schema/dependency-suppression.1.1.xsd"); + final SuppressionHandler handler = new SuppressionHandler(); + final SAXParserFactory factory = SAXParserFactory.newInstance(); + factory.setNamespaceAware(true); + factory.setValidating(true); + final SAXParser saxParser = factory.newSAXParser(); + saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_LANGUAGE, SuppressionParser.W3C_XML_SCHEMA); + saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_SOURCE, new InputSource(schemaStream)); + final XMLReader xmlReader = saxParser.getXMLReader(); + xmlReader.setErrorHandler(new SuppressionErrorHandler()); + xmlReader.setContentHandler(handler); + + final Reader reader = new InputStreamReader(inputStream, "UTF-8"); + final InputSource in = new InputSource(reader); + //in.setEncoding("UTF-8"); + + xmlReader.parse(in); + + return handler.getSuppressionRules(); + } catch (ParserConfigurationException ex) { + LOGGER.debug("", ex); + throw new SuppressionParseException(ex); + } catch (SAXException ex) { + if (ex.getMessage().contains("Cannot find the declaration of element 'suppressions'.")) { + throw ex; + } else { + LOGGER.debug("", ex); + throw new SuppressionParseException(ex); + } + } catch (FileNotFoundException ex) { + LOGGER.debug("", ex); + throw new SuppressionParseException(ex); + } catch (IOException ex) { + LOGGER.debug("", ex); + throw new SuppressionParseException(ex); + } + } + + /** + * Parses the given xml stream and returns a list of the suppression rules + * contained. + * + * @param inputStream an InputStream containing suppression rues + * @return a list of suppression rules + * @throws SuppressionParseException if the xml cannot be parsed + */ + private List parseOldSuppressionRules(InputStream inputStream) throws SuppressionParseException { try { final InputStream schemaStream = this.getClass().getClassLoader().getResourceAsStream("schema/suppression.xsd"); final SuppressionHandler handler = new SuppressionHandler(); diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzerTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzerTest.java index 19862f09b..27527b2c2 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzerTest.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzerTest.java @@ -77,8 +77,8 @@ public class AbstractSuppressionAnalyzerTest extends BaseTest { Settings.setString(Settings.KEYS.SUPPRESSION_FILE, "suppressions.xml"); instance.initialize(); int expCount = 5; - List result = instance.getRules(); - assertTrue(expCount <= result.size()); + int currentSize = instance.getRules().size(); + assertTrue(expCount <= currentSize); } @Test(expected = SuppressionParseException.class) diff --git a/dependency-check-core/src/test/resources/suppressions.xml b/dependency-check-core/src/test/resources/suppressions.xml index a8670c432..37a449815 100644 --- a/dependency-check-core/src/test/resources/suppressions.xml +++ b/dependency-check-core/src/test/resources/suppressions.xml @@ -1,5 +1,8 @@ - +