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