diff --git a/src/test/java/org/apache/commons/xml/AttackTestSupport.java b/src/test/java/org/apache/commons/xml/AttackTestSupport.java index 8e465d53..c9214f0f 100644 --- a/src/test/java/org/apache/commons/xml/AttackTestSupport.java +++ b/src/test/java/org/apache/commons/xml/AttackTestSupport.java @@ -183,6 +183,13 @@ public void warning(final TransformerException exception) { *

Android's {@code KXmlParser} currently fails this test.

*/ static final boolean DOM_RESOLVES_INTERNAL_ENTITIES = probeDomResolvesInternalEntities(); + /** {@code true} when the platform's default DOM factory (and its builders) support parser-attached schemas; Android inherits the throwing JAXP base methods. */ + static final boolean DOM_SUPPORTS_SCHEMA = supportsConfiguration(() -> DocumentBuilderFactory.newInstance().setSchema(null)); + /** {@code true} when the platform's default DOM factory accepts {@link XMLConstants#FEATURE_SECURE_PROCESSING}; Android's factory rejects it. */ + static final boolean DOM_SUPPORTS_SECURE_PROCESSING = + supportsConfiguration(() -> DocumentBuilderFactory.newInstance().setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true)); + /** {@code true} when the platform's default DOM factory (and its builders) support the XInclude switches; Android inherits the throwing JAXP base methods. */ + static final boolean DOM_SUPPORTS_XINCLUDE = supportsConfiguration(() -> DocumentBuilderFactory.newInstance().setXIncludeAware(false)); /** {@code true} when running on Android (Dalvik / ART), {@code false} on any standard JVM. Probed once via {@code Class.forName} on {@code android.os.Build}. */ static final boolean IS_ANDROID = probeAndroid(); /** @@ -199,6 +206,15 @@ public void warning(final TransformerException exception) { * presence is the leak signal.

*/ static final String LEAKED_MARKER = "All your base are belong to us"; + /** {@code true} when the platform's default SAX parser supports {@code reset()}; Android inherits the throwing JAXP base method. */ + static final boolean SAX_SUPPORTS_RESET = supportsConfiguration(() -> SAXParserFactory.newInstance().newSAXParser().reset()); + /** {@code true} when the platform's default SAX factory (and its parsers) support parser-attached schemas; Android inherits the throwing JAXP base methods. */ + static final boolean SAX_SUPPORTS_SCHEMA = supportsConfiguration(() -> SAXParserFactory.newInstance().setSchema(null)); + /** {@code true} when the platform's default SAX factory accepts {@link XMLConstants#FEATURE_SECURE_PROCESSING}; Android's Expat rejects it. */ + static final boolean SAX_SUPPORTS_SECURE_PROCESSING = + supportsConfiguration(() -> SAXParserFactory.newInstance().setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true)); + /** {@code true} when the platform's default SAX factory (and its parsers) support the XInclude switches; Android inherits the throwing JAXP base methods. */ + static final boolean SAX_SUPPORTS_XINCLUDE = supportsConfiguration(() -> SAXParserFactory.newInstance().setXIncludeAware(false)); static final StrictReporter STRICT_REPORTER = new StrictReporter(); /** * Woodstox's entity-count limit property; it ignores the JDK properties above and enforces its own default of {@code 100000}. @@ -1032,6 +1048,16 @@ static XMLReader strictXMLReader(final XMLReader reader) { return reader; } + /** Probes a JAXP configuration call once at class load; {@code false} where the platform default implementation throws (for example Android). */ + private static boolean supportsConfiguration(final Executable action) { + try { + action.execute(); + return true; + } catch (final Throwable t) { + return false; + } + } + /** Runs the action and silently swallows any thrown exception; used to apply best-effort permissive-side flags that may not be supported. */ private static void suppressException(final Executable action) { try { diff --git a/src/test/java/org/apache/commons/xml/SecureDocumentBuilderFactoryTest.java b/src/test/java/org/apache/commons/xml/SecureDocumentBuilderFactoryTest.java index 4d51d9d1..99867236 100644 --- a/src/test/java/org/apache/commons/xml/SecureDocumentBuilderFactoryTest.java +++ b/src/test/java/org/apache/commons/xml/SecureDocumentBuilderFactoryTest.java @@ -27,6 +27,7 @@ import javax.xml.XMLConstants; import javax.xml.parsers.DocumentBuilderFactory; +import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; @@ -35,6 +36,7 @@ class SecureDocumentBuilderFactoryTest { @Test void createsSecureBuildersFromEveryStaticEntryPoint() throws Exception { + Assumptions.assumeTrue(AttackTestSupport.DOM_RESOLVES_INTERNAL_ENTITIES, "the platform DOM is left unwrapped: it does not resolve user-defined entities"); assertInstanceOf(SecureDocumentBuilder.class, SecureDocumentBuilderFactory.newInstance().newDocumentBuilder()); assertInstanceOf(SecureDocumentBuilder.class, SecureDocumentBuilderFactory.newDefaultInstance().newDocumentBuilder()); assertInstanceOf(SecureDocumentBuilder.class, SecureDocumentBuilderFactory.newNSInstance().newDocumentBuilder()); @@ -43,6 +45,7 @@ void createsSecureBuildersFromEveryStaticEntryPoint() throws Exception { @Test void forwardsEverySupportedFactoryConfiguration() throws Exception { + Assumptions.assumeTrue(AttackTestSupport.DOM_RESOLVES_INTERNAL_ENTITIES, "the platform DOM is left unwrapped: it does not resolve user-defined entities"); final DocumentBuilderFactory factory = SecureDocumentBuilderFactory.newInstance(); factory.setCoalescing(true); factory.setExpandEntityReferences(false); diff --git a/src/test/java/org/apache/commons/xml/SecureDocumentBuilderTest.java b/src/test/java/org/apache/commons/xml/SecureDocumentBuilderTest.java index 7f654ece..f7def33c 100644 --- a/src/test/java/org/apache/commons/xml/SecureDocumentBuilderTest.java +++ b/src/test/java/org/apache/commons/xml/SecureDocumentBuilderTest.java @@ -40,13 +40,21 @@ void forwardsDocumentBuilderStateAndDomImplementation() throws Exception { final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); factory.setValidating(false); - factory.setXIncludeAware(false); - factory.setSchema(null); + if (AttackTestSupport.DOM_SUPPORTS_XINCLUDE) { + factory.setXIncludeAware(false); + } + if (AttackTestSupport.DOM_SUPPORTS_SCHEMA) { + factory.setSchema(null); + } final SecureDocumentBuilder builder = new SecureDocumentBuilder(factory.newDocumentBuilder()); assertTrue(builder.isNamespaceAware()); assertFalse(builder.isValidating()); - assertFalse(builder.isXIncludeAware()); - assertNull(builder.getSchema()); + if (AttackTestSupport.DOM_SUPPORTS_XINCLUDE) { + assertFalse(builder.isXIncludeAware()); + } + if (AttackTestSupport.DOM_SUPPORTS_SCHEMA) { + assertNull(builder.getSchema()); + } assertNotNull(builder.getDOMImplementation()); } } diff --git a/src/test/java/org/apache/commons/xml/SecureFactoriesSmokeTest.java b/src/test/java/org/apache/commons/xml/SecureFactoriesSmokeTest.java index 9154afa4..43cf9c52 100644 --- a/src/test/java/org/apache/commons/xml/SecureFactoriesSmokeTest.java +++ b/src/test/java/org/apache/commons/xml/SecureFactoriesSmokeTest.java @@ -19,6 +19,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNotSame; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -32,9 +33,11 @@ import javax.xml.parsers.SAXParserFactory; import javax.xml.stream.XMLInputFactory; import javax.xml.transform.TransformerFactory; +import javax.xml.transform.TransformerFactoryConfigurationError; import javax.xml.validation.SchemaFactory; import javax.xml.xpath.XPathFactory; +import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import org.w3c.dom.Document; @@ -53,6 +56,7 @@ class SecureFactoriesSmokeTest { private static final String BENIGN_XML = "\nhello\n"; @Test + @Tag("dom") void benignDocumentParses() throws Exception { final Document doc = SecureDocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(new StringReader(BENIGN_XML))); assertNotNull(doc); @@ -62,43 +66,56 @@ void benignDocumentParses() throws Exception { // The explicit-class-name tests discover the runtime default implementation through the raw JAXP factory, // so they stay portable across the JAXP implementations of the surefire matrix. @Test + @Tag("dom") void explicitClassNameDocumentBuilderFactoryIsSecure() throws Exception { + Assumptions.assumeTrue(AttackTestSupport.DOM_SUPPORTS_SECURE_PROCESSING, "platform DOM does not support FEATURE_SECURE_PROCESSING"); final Class impl = DocumentBuilderFactory.newInstance().getClass(); final DocumentBuilderFactory factory = SecureDocumentBuilderFactory.newInstance(impl.getName(), impl.getClassLoader()); assertTrue(factory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING)); } @Test + @Tag("dom") void explicitClassNameNSDocumentBuilderFactoryIsNamespaceAware() throws Exception { final Class impl = DocumentBuilderFactory.newInstance().getClass(); final DocumentBuilderFactory factory = SecureDocumentBuilderFactory.newNSInstance(impl.getName(), impl.getClassLoader()); assertTrue(factory.isNamespaceAware()); - assertTrue(factory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING)); + if (AttackTestSupport.DOM_SUPPORTS_SECURE_PROCESSING) { + assertTrue(factory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING)); + } } @Test + @Tag("sax") void explicitClassNameNSSAXParserFactoryIsNamespaceAware() throws Exception { final Class impl = SAXParserFactory.newInstance().getClass(); final SAXParserFactory factory = SecureSAXParserFactory.newNSInstance(impl.getName(), impl.getClassLoader()); assertTrue(factory.isNamespaceAware()); - assertTrue(factory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING)); + if (AttackTestSupport.SAX_SUPPORTS_SECURE_PROCESSING) { + assertTrue(factory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING)); + } } @Test + @Tag("sax") void explicitClassNameSAXParserFactoryIsSecure() throws Exception { + Assumptions.assumeTrue(AttackTestSupport.SAX_SUPPORTS_SECURE_PROCESSING, "platform SAX does not support FEATURE_SECURE_PROCESSING"); final Class impl = SAXParserFactory.newInstance().getClass(); final SAXParserFactory factory = SecureSAXParserFactory.newInstance(impl.getName(), impl.getClassLoader()); assertTrue(factory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING)); } @Test + @Tag("schema") void explicitClassNameSchemaFactoryIsSecure() throws Exception { final Class impl = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI).getClass(); final SchemaFactory factory = SecureSchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI, impl.getName(), impl.getClassLoader()); - assertTrue(factory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING)); + // Schema securing is the resolver floor plus wrapped products; FEATURE_SECURE_PROCESSING stays untouched (the secure sub-parsers carry it). + assertInstanceOf(SecureSchema.class, factory.newSchema()); } @Test + @Tag("trax") void explicitClassNameTransformerFactoryIsSecure() { final Class impl = TransformerFactory.newInstance().getClass(); final TransformerFactory factory = SecureTransformerFactory.newInstance(impl.getName(), impl.getClassLoader()); @@ -106,6 +123,7 @@ void explicitClassNameTransformerFactoryIsSecure() { } @Test + @Tag("xpath") void explicitClassNameXPathFactoryIsSecure() throws Exception { final Class impl = XPathFactory.newInstance().getClass(); final XPathFactory factory = SecureXPathFactory.newInstance(XPathFactory.DEFAULT_OBJECT_MODEL_URI, impl.getName(), impl.getClassLoader()); @@ -113,6 +131,7 @@ void explicitClassNameXPathFactoryIsSecure() throws Exception { } @Test + @Tag("stax") void factoryIdXMLInputFactoryIsSecure() { final String factoryId = "org.apache.commons.xml.test.staxFactory"; // XMLInputFactory.newInstance, not newFactory: Android's StAX API predates newFactory, and this file also compiles against android.jar. @@ -126,51 +145,57 @@ void factoryIdXMLInputFactoryIsSecure() { } @Test + @Tag("stax") void newDefaultFactoryXMLInputFactoryIsSecure() { final XMLInputFactory factory = SecureXMLInputFactory.newDefaultFactory(); assertEquals(Boolean.TRUE, factory.getProperty(XMLInputFactory.SUPPORT_DTD)); } // The newDefault* methods resolve the Java 9 JAXP method at runtime and fall back to the JDK's built-in implementation on Java 8. The dom and sax - // variants also run on Android, whose JAXP predates newDefaultInstance and carries no JDK-internal fallback: the lookup miss surfaces there as the - // factory's own FactoryConfigurationError, like any newInstance miss. + // variants also run on Android, whose JAXP predates newDefaultInstance and carries no JDK-internal fallback: the methods degrade there to the standard + // lookup, which Android pins to the platform implementation. @Test @Tag("dom") void newDefaultInstanceDocumentBuilderFactoryIsUsable() throws Exception { - if (AttackTestSupport.IS_ANDROID) { - assertThrows(FactoryConfigurationError.class, SecureDocumentBuilderFactory::newDefaultInstance); - return; - } final DocumentBuilderFactory factory = SecureDocumentBuilderFactory.newDefaultInstance(); assertNotNull(factory.newDocumentBuilder().parse(new InputSource(new StringReader(BENIGN_XML))).getDocumentElement()); - assertTrue(factory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING)); + if (AttackTestSupport.DOM_SUPPORTS_SECURE_PROCESSING) { + assertTrue(factory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING)); + } } @Test @Tag("sax") void newDefaultInstanceSAXParserFactoryIsUsable() throws Exception { - if (AttackTestSupport.IS_ANDROID) { - assertThrows(FactoryConfigurationError.class, SecureSAXParserFactory::newDefaultInstance); - return; - } final SAXParserFactory factory = SecureSAXParserFactory.newDefaultInstance(); factory.newSAXParser().parse(new InputSource(new StringReader(BENIGN_XML)), new DefaultHandler()); - assertTrue(factory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING)); + if (AttackTestSupport.SAX_SUPPORTS_SECURE_PROCESSING) { + assertTrue(factory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING)); + } } @Test + @Tag("schema") void newDefaultInstanceSchemaFactoryIsSecure() throws Exception { final SchemaFactory factory = SecureSchemaFactory.newDefaultInstance(); - assertTrue(factory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING)); + // Schema securing is the resolver floor plus wrapped products; FEATURE_SECURE_PROCESSING stays untouched (the secure sub-parsers carry it). + assertInstanceOf(SecureSchema.class, factory.newSchema()); } @Test + @Tag("trax") void newDefaultInstanceTransformerFactoryIsSecure() { + // TrAX is outside the Android newDefaultInstance degradation: the platform provides neither the method nor the JDK class, so the miss still throws. + if (AttackTestSupport.IS_ANDROID) { + assertThrows(TransformerFactoryConfigurationError.class, SecureTransformerFactory::newDefaultInstance); + return; + } final TransformerFactory factory = SecureTransformerFactory.newDefaultInstance(); assertTrue(factory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING)); } @Test + @Tag("xpath") void newDefaultInstanceXPathFactoryIsSecure() throws Exception { final XPathFactory factory = SecureXPathFactory.newDefaultInstance(); assertTrue(factory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING)); @@ -179,41 +204,43 @@ void newDefaultInstanceXPathFactoryIsSecure() throws Exception { @Test @Tag("dom") void newDefaultNSInstanceDocumentBuilderFactoryIsNamespaceAware() throws Exception { - if (AttackTestSupport.IS_ANDROID) { - assertThrows(FactoryConfigurationError.class, SecureDocumentBuilderFactory::newDefaultNSInstance); - return; - } final DocumentBuilderFactory factory = SecureDocumentBuilderFactory.newDefaultNSInstance(); assertTrue(factory.isNamespaceAware()); - assertTrue(factory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING)); + if (AttackTestSupport.DOM_SUPPORTS_SECURE_PROCESSING) { + assertTrue(factory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING)); + } } @Test @Tag("sax") void newDefaultNSInstanceSAXParserFactoryIsNamespaceAware() throws Exception { - if (AttackTestSupport.IS_ANDROID) { - assertThrows(FactoryConfigurationError.class, SecureSAXParserFactory::newDefaultNSInstance); - return; - } final SAXParserFactory factory = SecureSAXParserFactory.newDefaultNSInstance(); assertTrue(factory.isNamespaceAware()); - assertTrue(factory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING)); + if (AttackTestSupport.SAX_SUPPORTS_SECURE_PROCESSING) { + assertTrue(factory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING)); + } } @Test + @Tag("dom") void newDocumentBuilderFactoryDisablesXIncludeAndValidation() { final DocumentBuilderFactory factory = SecureDocumentBuilderFactory.newInstance(); - assertFalse(factory.isXIncludeAware(), "XInclude must be off by default"); + if (AttackTestSupport.DOM_SUPPORTS_XINCLUDE) { + assertFalse(factory.isXIncludeAware(), "XInclude must be off by default"); + } assertFalse(factory.isValidating(), "Validation must be off by default"); } @Test + @Tag("dom") void newDocumentBuilderFactoryEnablesSecureProcessing() throws Exception { + Assumptions.assumeTrue(AttackTestSupport.DOM_SUPPORTS_SECURE_PROCESSING, "platform DOM does not support FEATURE_SECURE_PROCESSING"); final DocumentBuilderFactory factory = SecureDocumentBuilderFactory.newInstance(); assertTrue(factory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING), "FEATURE_SECURE_PROCESSING must be on"); } @Test + @Tag("dom") void newDocumentBuilderFactoryReturnsFreshInstance() { final DocumentBuilderFactory a = SecureDocumentBuilderFactory.newInstance(); final DocumentBuilderFactory b = SecureDocumentBuilderFactory.newInstance(); @@ -223,6 +250,7 @@ void newDocumentBuilderFactoryReturnsFreshInstance() { } @Test + @Tag("stax") void newFactoryReturnsFreshInstance() { final XMLInputFactory a = SecureXMLInputFactory.newFactory(); final XMLInputFactory b = SecureXMLInputFactory.newFactory(); @@ -238,7 +266,7 @@ void newNSInstanceDocumentBuilderFactoryIsNamespaceAware() throws Exception { final DocumentBuilderFactory factory = SecureDocumentBuilderFactory.newNSInstance(); assertTrue(factory.isNamespaceAware()); assertNotNull(factory.newDocumentBuilder().parse(new InputSource(new StringReader(BENIGN_XML))).getDocumentElement()); - if (!AttackTestSupport.IS_ANDROID) { + if (AttackTestSupport.DOM_SUPPORTS_SECURE_PROCESSING) { assertTrue(factory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING)); } } @@ -249,29 +277,35 @@ void newNSInstanceSAXParserFactoryIsNamespaceAware() throws Exception { final SAXParserFactory factory = SecureSAXParserFactory.newNSInstance(); assertTrue(factory.isNamespaceAware()); factory.newSAXParser().parse(new InputSource(new StringReader(BENIGN_XML)), new DefaultHandler()); - if (!AttackTestSupport.IS_ANDROID) { + if (AttackTestSupport.SAX_SUPPORTS_SECURE_PROCESSING) { assertTrue(factory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING)); } } @Test + @Tag("sax") void newSAXParserFactoryReturnsFreshInstance() { final SAXParserFactory a = SecureSAXParserFactory.newInstance(); final SAXParserFactory b = SecureSAXParserFactory.newInstance(); assertNotSame(a, b); assertFalse(a.isValidating()); - assertFalse(a.isXIncludeAware()); + if (AttackTestSupport.SAX_SUPPORTS_XINCLUDE) { + assertFalse(a.isXIncludeAware()); + } } @Test + @Tag("schema") void newSchemaFactoryReturnsFreshInstance() throws Exception { final SchemaFactory a = SecureSchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); final SchemaFactory b = SecureSchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); assertNotSame(a, b); - assertTrue(a.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING)); + // Schema securing is the resolver floor plus wrapped products; FEATURE_SECURE_PROCESSING stays untouched (the secure sub-parsers carry it). + assertInstanceOf(SecureSchema.class, a.newSchema()); } @Test + @Tag("trax") void newTransformerFactoryReturnsFreshInstance() { final TransformerFactory a = SecureTransformerFactory.newInstance(); final TransformerFactory b = SecureTransformerFactory.newInstance(); @@ -279,6 +313,7 @@ void newTransformerFactoryReturnsFreshInstance() { } @Test + @Tag("stax") void newXMLInputFactoryReturnsFreshInstance() { final XMLInputFactory a = SecureXMLInputFactory.newInstance(); final XMLInputFactory b = SecureXMLInputFactory.newInstance(); @@ -288,6 +323,7 @@ void newXMLInputFactoryReturnsFreshInstance() { } @Test + @Tag("xpath") void newXPathFactoryReturnsFreshInstance() throws Exception { final XPathFactory a = SecureXPathFactory.newInstance(); final XPathFactory b = SecureXPathFactory.newInstance(); @@ -300,6 +336,12 @@ void newXPathFactoryReturnsFreshInstance() throws Exception { * non-secured factory through an inherited method such as {@code newInstance(String, ClassLoader)} or {@code newDefaultInstance()}. */ @Test + @Tag("dom") + @Tag("sax") + @Tag("stax") + @Tag("trax") + @Tag("xpath") + @Tag("schema") void publicClassesDoNotExtendTheirJaxpFactoryType() { assertFalse(DocumentBuilderFactory.class.isAssignableFrom(SecureDocumentBuilderFactory.class)); assertFalse(SAXParserFactory.class.isAssignableFrom(SecureSAXParserFactory.class)); @@ -310,6 +352,7 @@ void publicClassesDoNotExtendTheirJaxpFactoryType() { } @Test + @Tag("dom") void unknownFactoryClassNameThrows() { assertThrows(FactoryConfigurationError.class, () -> SecureDocumentBuilderFactory.newInstance("no.such.FactoryClass", null)); } diff --git a/src/test/java/org/apache/commons/xml/SecureSAXParserFactoryTest.java b/src/test/java/org/apache/commons/xml/SecureSAXParserFactoryTest.java index cb840d5c..69279386 100644 --- a/src/test/java/org/apache/commons/xml/SecureSAXParserFactoryTest.java +++ b/src/test/java/org/apache/commons/xml/SecureSAXParserFactoryTest.java @@ -54,14 +54,20 @@ void forwardsFactoryConfigurationAndCreatesNamespaceAwareParsers() throws Except final SAXParserFactory factory = SecureSAXParserFactory.newInstance(); factory.setNamespaceAware(true); factory.setValidating(false); - factory.setXIncludeAware(false); - factory.setSchema(null); - factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + if (AttackTestSupport.SAX_SUPPORTS_XINCLUDE) { + factory.setXIncludeAware(false); + assertFalse(factory.isXIncludeAware()); + } + if (AttackTestSupport.SAX_SUPPORTS_SCHEMA) { + factory.setSchema(null); + assertNull(factory.getSchema()); + } + if (AttackTestSupport.SAX_SUPPORTS_SECURE_PROCESSING) { + factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + assertTrue(factory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING)); + } assertTrue(factory.isNamespaceAware()); assertFalse(factory.isValidating()); - assertFalse(factory.isXIncludeAware()); - assertNull(factory.getSchema()); - assertTrue(factory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING)); assertInstanceOf(SecureSAXParser.class, factory.newSAXParser()); } diff --git a/src/test/java/org/apache/commons/xml/SecureSAXParserTest.java b/src/test/java/org/apache/commons/xml/SecureSAXParserTest.java index 1f27c18d..4f24b740 100644 --- a/src/test/java/org/apache/commons/xml/SecureSAXParserTest.java +++ b/src/test/java/org/apache/commons/xml/SecureSAXParserTest.java @@ -126,11 +126,17 @@ void exposesSecureParserViewsAndState() throws Exception { final SecureSAXParser parser = new SecureSAXParser(SAXParserFactory.newInstance().newSAXParser()); assertNotNull(parser.getXMLReader()); assertNotNull(parser.getParser()); - parser.getSchema(); parser.isNamespaceAware(); parser.isValidating(); - parser.isXIncludeAware(); - parser.reset(); + if (AttackTestSupport.SAX_SUPPORTS_SCHEMA) { + parser.getSchema(); + } + if (AttackTestSupport.SAX_SUPPORTS_XINCLUDE) { + parser.isXIncludeAware(); + } + if (AttackTestSupport.SAX_SUPPORTS_RESET) { + parser.reset(); + } } @Test