1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.xml.secure;
19
20 import static org.junit.jupiter.api.Assertions.assertEquals;
21 import static org.junit.jupiter.api.Assertions.assertFalse;
22 import static org.junit.jupiter.api.Assertions.assertNotEquals;
23 import static org.junit.jupiter.api.Assertions.assertTrue;
24 import static org.junit.jupiter.api.Assumptions.assumeFalse;
25 import static org.junit.jupiter.api.Assumptions.assumeTrue;
26
27 import java.io.StringWriter;
28
29 import javax.xml.transform.Transformer;
30 import javax.xml.transform.TransformerFactory;
31 import javax.xml.transform.stream.StreamResult;
32 import javax.xml.validation.SchemaFactory;
33 import javax.xml.xpath.XPathFactory;
34
35 import org.junit.jupiter.api.Tag;
36 import org.junit.jupiter.api.Test;
37 import org.junit.jupiter.api.condition.DisabledInNativeImage;
38 import org.xml.sax.XMLReader;
39
40
41
42
43
44
45
46
47
48
49
50 @Tag("trax")
51 @Tag("xpath")
52 @Tag("schema")
53 class OverrideDefaultParserTest {
54
55 private static final String FEATURE = SecureSAXParserFactory.OVERRIDE_DEFAULT_PARSER;
56
57
58
59
60 private static final String JDK_INTERNAL_PREFIX = "com.sun.org.apache.xerces.internal.";
61
62
63
64
65 private static final boolean SUPPORTS_FEATURE = probeFeature();
66
67
68
69
70 private static void assumeFeatureSupported() {
71 assumeTrue(SUPPORTS_FEATURE, "runtime does not recognize " + FEATURE);
72 }
73
74 private static boolean probeFeature() {
75 try {
76 TransformerFactory.newInstance().setFeature(FEATURE, true);
77 return true;
78 } catch (final Exception e) {
79 return false;
80 }
81 }
82
83 private static String transform(final TransformerFactory factory, final String text) throws Exception {
84 final Transformer transformer = factory.newTransformer(AttackTestSupport.streamSource(AttackTestSupport.xsltBody(text)));
85 final StringWriter out = new StringWriter();
86 transformer.transform(AttackTestSupport.streamSource(AttackTestSupport.xmlBody("ignored")), new StreamResult(out));
87 return out.toString();
88 }
89
90 private static boolean xercesOnClasspath() {
91 try {
92 Class.forName("org.apache.xerces.jaxp.SAXParserFactoryImpl");
93 return true;
94 } catch (final ClassNotFoundException e) {
95 return false;
96 }
97 }
98
99 @Test
100 void schemaFactoryReadsFeatureAtCreation() throws Exception {
101 assumeFalse(AttackTestSupport.IS_ANDROID);
102 assumeFeatureSupported();
103 final SchemaFactory factory = SecureSchemaFactory.newDefaultInstance();
104 assertFalse(factory.getFeature(FEATURE));
105 assertFalse(((SecureSchema) factory.newSchema(AttackTestSupport.streamSource(AttackTestSupport.BENIGN_SCHEMA))).overrideDefaultParser);
106 factory.setFeature(FEATURE, true);
107 assertTrue(((SecureSchema) factory.newSchema(AttackTestSupport.streamSource(AttackTestSupport.BENIGN_SCHEMA))).overrideDefaultParser);
108 }
109
110 @Test
111 void secureReaderFollowsFlag() throws Exception {
112 assumeFalse(AttackTestSupport.IS_ANDROID);
113 final XMLReader pinned = ((SecureXMLReader) SecureSAXParserFactory.newXMLReader(false)).getDelegate();
114 assertTrue(pinned.getClass().getName().startsWith(JDK_INTERNAL_PREFIX), pinned.getClass().getName());
115 final XMLReader pluggable = ((SecureXMLReader) SecureSAXParserFactory.newXMLReader(true)).getDelegate();
116 final XMLReader lookedUp = ((SecureXMLReader) SecureSAXParserFactory.newNSInstance().newSAXParser().getXMLReader()).getDelegate();
117 assertEquals(lookedUp.getClass(), pluggable.getClass());
118 if (xercesOnClasspath()) {
119
120 assertNotEquals(pinned.getClass(), pluggable.getClass());
121 }
122 }
123
124 @Test
125 void transformerFactoryReadsFeatureAtCreation() throws Exception {
126 assumeFalse(AttackTestSupport.IS_ANDROID);
127 assumeFeatureSupported();
128 final TransformerFactory factory = SecureTransformerFactory.newDefaultInstance();
129 assertFalse(factory.getFeature(FEATURE));
130 assertFalse(((SecureTemplates) factory.newTemplates(AttackTestSupport.streamSource(AttackTestSupport.xsltBody("probe")))).overrideDefaultParser);
131 factory.setFeature(FEATURE, true);
132 assertTrue(((SecureTemplates) factory.newTemplates(AttackTestSupport.streamSource(AttackTestSupport.xsltBody("probe")))).overrideDefaultParser);
133 }
134
135 @Test
136
137
138 @DisabledInNativeImage
139 void transformSucceedsUnderBothParserFamilies() throws Exception {
140 assumeFalse(AttackTestSupport.IS_ANDROID);
141 assumeFeatureSupported();
142 final TransformerFactory factory = SecureTransformerFactory.newDefaultInstance();
143
144 assertTrue(transform(factory, "pinned").contains("pinned"));
145 factory.setFeature(FEATURE, true);
146
147 assertTrue(transform(factory, "pluggable").contains("pluggable"));
148 }
149
150 @Test
151 void xPathFactoryReadsFeatureAtCreation() throws Exception {
152 assumeFalse(AttackTestSupport.IS_ANDROID);
153 assumeFeatureSupported();
154 final XPathFactory factory = SecureXPathFactory.newDefaultInstance();
155 assertFalse(factory.getFeature(FEATURE));
156 assertFalse(((SecureXPath) factory.newXPath()).overrideDefaultParser);
157 factory.setFeature(FEATURE, true);
158 assertTrue(((SecureXPath) factory.newXPath()).overrideDefaultParser);
159 }
160 }