1 /* 2 * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 package parsers; 25 26 import java.io.File; 27 import java.io.FilePermission; 28 import java.io.InputStream; 29 30 import javax.xml.XMLConstants; 31 import javax.xml.parsers.DocumentBuilder; 32 import javax.xml.parsers.DocumentBuilderFactory; 33 import javax.xml.parsers.SAXParser; 34 import javax.xml.parsers.SAXParserFactory; 35 36 import jaxp.library.JAXPTestUtilities; 37 38 import org.testng.Assert; 39 import org.testng.annotations.Test; 40 import org.w3c.dom.Document; 41 import org.xml.sax.SAXParseException; 42 43 /* 44 * @bug 6309988 45 * @summary Test elementAttributeLimit, maxOccurLimit, entityExpansionLimit. 46 */ 47 @Test(singleThreaded = true) 48 public class Bug6309988 { 49 50 DocumentBuilderFactory dbf = null; 51 52 public void runWithSecurityManager() throws Exception { 53 JAXPTestUtilities.tryRunWithPolicyManager(() -> test(), 54 new FilePermission(System.getProperty("test.src") + "/-", "read")); 55 } 56 57 public void runWithoutSecurityManager() throws Exception { 58 test(); 59 } 60 61 private void test() { 62 testDOMParserElementAttributeLimit(); 63 testDOMNSParserElementAttributeLimit(); 64 testDOMNSParserElementAttributeLimitWithoutSecureProcessing(); 65 testSystemElementAttributeLimitWithoutSecureProcessing(); 66 testSystemElementAttributeLimitWithSecureProcessing(); 67 testDOMSecureProcessingDefaultValue(); 68 testSAXSecureProcessingDefaultValue(); 69 testSystemMaxOccurLimitWithoutSecureProcessing(); 70 testValidMaxOccurLimitWithOutSecureProcessing(); 71 testSystemEntityExpansionLimitWithOutSecureProcessing(); 72 testSystemEntityExpansionLimitWithSecureProcessing(); 73 testEntityExpansionLimitWithSecureProcessing(); 74 testEntityExpansionLimitWithOutSecureProcessing(); 75 } 76 77 /* 78 * Given XML document has more than 10000 attributes. Exception is expected 79 */ 80 private void testDOMParserElementAttributeLimit() { 81 try { 82 dbf = DocumentBuilderFactory.newInstance(); 83 DocumentBuilder parser = dbf.newDocumentBuilder(); 84 Document doc = parser.parse(this.getClass().getResourceAsStream("DosTest.xml")); 85 Assert.fail("SAXParserException is expected, as given XML document contains more than 10000 attributes"); 86 } catch (SAXParseException e) { 87 System.out.println(e.getMessage()); 88 } catch (Exception e) { 89 Assert.fail("Exception " + e.getMessage()); 90 } 91 } 92 93 /* 94 * Given XML document has more than 10000 attributes. It should report an 95 * error. 96 */ 97 private void testDOMNSParserElementAttributeLimit() { 98 try { 99 dbf = DocumentBuilderFactory.newInstance(); 100 dbf.setNamespaceAware(true); 101 DocumentBuilder parser = dbf.newDocumentBuilder(); 102 Document doc = parser.parse(this.getClass().getResourceAsStream("DosTest.xml")); 103 Assert.fail("SAXParserException is expected, as given XML document contains more than 10000 attributes"); 104 } catch (SAXParseException e) { 105 System.out.println(e.getMessage()); 106 } catch (Exception e) { 107 Assert.fail("Exception " + e.getMessage()); 108 } 109 } 110 111 /* 112 * Given XML document has more than 10000 attributes. Parsing this XML 113 * document in non-secure mode, should not report any error. 114 */ 115 private void testDOMNSParserElementAttributeLimitWithoutSecureProcessing() { 116 if (isSecureMode()) 117 return; // jaxp secure feature can not be turned off when security 118 // manager is present 119 try { 120 dbf = DocumentBuilderFactory.newInstance(); 121 dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, false); 122 dbf.setNamespaceAware(true); 123 DocumentBuilder parser = dbf.newDocumentBuilder(); 124 Document doc = parser.parse(this.getClass().getResourceAsStream("DosTest.xml")); 125 126 } catch (SAXParseException e) { 127 Assert.fail(e.getMessage()); 128 } catch (Exception e) { 129 Assert.fail("Exception " + e.getMessage()); 130 } 131 } 132 133 /* 134 * Before 8014530: Given XML document has 3 attributes and System property 135 * is set to 2. Parsing this XML document in non-secure mode, should not 136 * report an error. 137 * After 8014530: System properties will override FSP, the result of this 138 * test should be the same as 139 * testSystemElementAttributeLimitWithSecureProcessing 140 */ 141 private void testSystemElementAttributeLimitWithoutSecureProcessing() { 142 if (isSecureMode()) 143 return; // jaxp secure feature can not be turned off when security 144 // manager is present 145 try { 146 dbf = DocumentBuilderFactory.newInstance(); 147 dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, false); 148 dbf.setNamespaceAware(true); 149 System.setProperty("elementAttributeLimit", "2"); 150 DocumentBuilder parser = dbf.newDocumentBuilder(); 151 Document doc = parser.parse(this.getClass().getResourceAsStream("DosTest3.xml")); 152 153 Assert.fail("SAXParserException is expected, as given XML document contains more than 2 attributes"); 154 } catch (Exception e) { 155 String errMsg = e.getMessage(); 156 Throwable cause = e.getCause(); 157 if (cause != null) { 158 errMsg += cause.getMessage(); 159 } 160 if (errMsg.contains("JAXP0001")) { 161 // expected 162 } else { 163 Assert.fail("Unexpected error: " + e.getMessage()); 164 } 165 } finally { 166 System.clearProperty("elementAttributeLimit"); 167 } 168 } 169 170 /* 171 * Given XML document has 3 attributes and System property is set to 2. 172 * Parsing this XML document in secure mode, should report an error. 173 */ 174 private void testSystemElementAttributeLimitWithSecureProcessing() { 175 try { 176 dbf = DocumentBuilderFactory.newInstance(); 177 dbf.setNamespaceAware(true); 178 System.setProperty("elementAttributeLimit", "2"); 179 DocumentBuilder parser = dbf.newDocumentBuilder(); 180 Document doc = parser.parse(this.getClass().getResourceAsStream("DosTest3.xml")); 181 Assert.fail("SAXParserException is expected, as given XML document contains more than 2 attributes"); 182 } catch (SAXParseException e) { 183 System.out.println(e.getMessage()); 184 } catch (Exception e) { 185 Assert.fail("Exception " + e.getMessage()); 186 } finally { 187 System.setProperty("elementAttributeLimit", ""); 188 } 189 } 190 191 /* 192 * Default value for secure processing feature should be true. 193 */ 194 private void testDOMSecureProcessingDefaultValue() { 195 try { 196 dbf = DocumentBuilderFactory.newInstance(); 197 Assert.assertTrue(dbf.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING), "Default value for secureProcessing feature should be true"); 198 199 } catch (Exception e) { 200 Assert.fail("Exception " + e.getMessage()); 201 } 202 } 203 204 /* 205 * Default value for secure processing feature should be true. 206 */ 207 private void testSAXSecureProcessingDefaultValue() { 208 try { 209 SAXParserFactory spf = SAXParserFactory.newInstance(); 210 Assert.assertTrue(spf.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING), "Default value for secureProcessing feature should be true"); 211 212 } catch (Exception e) { 213 Assert.fail("Exception " + e.getMessage()); 214 } 215 } 216 217 /* 218 * This method sets system property for maxOccurLimit=2 and secure process 219 * feature is off. Given doument contains more than 2 elements and hence an 220 * error should be reported. 221 */ 222 private void testSystemMaxOccurLimitWithoutSecureProcessing() { 223 if (isSecureMode()) 224 return; // jaxp secure feature can not be turned off when security 225 // manager is present 226 try { 227 SAXParserFactory spf = SAXParserFactory.newInstance(); 228 spf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, false); 229 spf.setValidating(true); 230 System.setProperty("maxOccurLimit", "2"); 231 // Set the properties for Schema Validation 232 String SCHEMA_LANG = "http://java.sun.com/xml/jaxp/properties/schemaLanguage"; 233 String SCHEMA_TYPE = "http://www.w3.org/2001/XMLSchema"; 234 // Get the Schema location as a File object 235 File schemaFile = new File(this.getClass().getResource("toys.xsd").toURI()); 236 // Get the parser 237 SAXParser parser = spf.newSAXParser(); 238 parser.setProperty(SCHEMA_LANG, SCHEMA_TYPE); 239 parser.setProperty("http://java.sun.com/xml/jaxp/properties/schemaSource", schemaFile); 240 241 InputStream is = this.getClass().getResourceAsStream("toys.xml"); 242 MyErrorHandler eh = new MyErrorHandler(); 243 parser.parse(is, eh); 244 Assert.assertFalse(eh.errorOccured, "Not Expected Error"); 245 System.setProperty("maxOccurLimit", ""); 246 } catch (Exception e) { 247 Assert.fail("Exception occured: " + e.getMessage()); 248 } 249 } 250 251 /* 252 * This test will take longer time to execute( abt 120sec). This method 253 * tries to validate a document. This document contains an element whose 254 * maxOccur is '3002'. Since secure processing feature is off, document 255 * should be parsed without any errors. 256 */ 257 private void testValidMaxOccurLimitWithOutSecureProcessing() { 258 if (isSecureMode()) 259 return; // jaxp secure feature can not be turned off when security 260 // manager is present 261 try { 262 SAXParserFactory spf = SAXParserFactory.newInstance(); 263 spf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, false); 264 spf.setValidating(true); 265 // Set the properties for Schema Validation 266 String SCHEMA_LANG = "http://java.sun.com/xml/jaxp/properties/schemaLanguage"; 267 String SCHEMA_TYPE = "http://www.w3.org/2001/XMLSchema"; 268 // Get the Schema location as a File object 269 File schemaFile = new File(this.getClass().getResource("toys3002.xsd").toURI()); 270 // Get the parser 271 SAXParser parser = spf.newSAXParser(); 272 parser.setProperty(SCHEMA_LANG, SCHEMA_TYPE); 273 parser.setProperty("http://java.sun.com/xml/jaxp/properties/schemaSource", schemaFile); 274 275 InputStream is = this.getClass().getResourceAsStream("toys.xml"); 276 MyErrorHandler eh = new MyErrorHandler(); 277 parser.parse(is, eh); 278 Assert.assertFalse(eh.errorOccured, "Expected Error as maxOccurLimit is exceeded"); 279 280 } catch (Exception e) { 281 Assert.fail("Exception occured: " + e.getMessage()); 282 } 283 } 284 285 /* 286 * Before 8014530: System property is set to 2. Given XML document has more 287 * than 2 entity references. Parsing this document in non-secure mode, 288 * should *not* report an error. 289 * After 8014530: System properties will override FSP, the result of this 290 * test should be the same as 291 * testSystemElementAttributeLimitWithSecureProcessing 292 */ 293 private void testSystemEntityExpansionLimitWithOutSecureProcessing() { 294 if (isSecureMode()) 295 return; // jaxp secure feature can not be turned off when security 296 // manager is present 297 try { 298 System.setProperty("entityExpansionLimit", "2"); 299 dbf = DocumentBuilderFactory.newInstance(); 300 dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, false); 301 dbf.setValidating(true); 302 DocumentBuilder parser = dbf.newDocumentBuilder(); 303 Document doc = parser.parse(this.getClass().getResourceAsStream("entity.xml")); 304 Assert.fail("SAXParserException is expected, as given XML document contains more 2 entity references"); 305 } catch (Exception e) { 306 String errMsg = e.getMessage(); 307 Throwable cause = e.getCause(); 308 if (cause != null) { 309 errMsg += cause.getMessage(); 310 } 311 if (errMsg.contains("JAXP0001")) { 312 // expected 313 } else { 314 Assert.fail("Unexpected error: " + e.getMessage()); 315 } 316 } finally { 317 System.clearProperty("entityExpansionLimit"); 318 } 319 } 320 321 /* 322 * System property is set to 2. Given XML document has more than 2 entity 323 * references. Parsing this document in secure mode, should report an error. 324 */ 325 private void testSystemEntityExpansionLimitWithSecureProcessing() { 326 try { 327 dbf = DocumentBuilderFactory.newInstance(); 328 dbf.setValidating(true); 329 System.setProperty("entityExpansionLimit", "2"); 330 DocumentBuilder parser = dbf.newDocumentBuilder(); 331 Document doc = parser.parse(this.getClass().getResourceAsStream("entity.xml")); 332 Assert.fail("SAXParserException is expected, as given XML document contains more 2 entity references"); 333 334 } catch (SAXParseException e) { 335 System.out.println(e.getMessage()); 336 } catch (Exception e) { 337 Assert.fail("Exception " + e.getMessage()); 338 } finally { 339 System.setProperty("entityExpansionLimit", ""); 340 } 341 } 342 343 /* 344 * Given XML document has more than 64000 entity references. Parsing this 345 * document in secure mode, should report an error. 346 */ 347 private void testEntityExpansionLimitWithSecureProcessing() { 348 try { 349 dbf = DocumentBuilderFactory.newInstance(); 350 dbf.setValidating(true); 351 DocumentBuilder parser = dbf.newDocumentBuilder(); 352 Document doc = parser.parse(this.getClass().getResourceAsStream("entity64K.xml")); 353 Assert.fail("SAXParserException is expected, as given XML document contains more 2 entity references"); 354 355 } catch (SAXParseException e) { 356 System.out.println(e.getMessage()); 357 } catch (Exception e) { 358 Assert.fail("Exception " + e.getMessage()); 359 } finally { 360 System.setProperty("entityExpansionLimit", ""); 361 } 362 } 363 364 /* 365 * Given XML document has more than 64000 entity references. Parsing this 366 * document in non-secure mode, should not report any error. 367 */ 368 private void testEntityExpansionLimitWithOutSecureProcessing() { 369 if (isSecureMode()) 370 return; // jaxp secure feature can not be turned off when security 371 // manager is present 372 try { 373 dbf = DocumentBuilderFactory.newInstance(); 374 dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, false); 375 dbf.setValidating(true); 376 DocumentBuilder parser = dbf.newDocumentBuilder(); 377 Document doc = parser.parse(this.getClass().getResourceAsStream("entity64K.xml")); 378 379 } catch (SAXParseException e) { 380 Assert.fail("Exception " + e.getMessage()); 381 } catch (Exception e) { 382 Assert.fail("Exception " + e.getMessage()); 383 } finally { 384 System.setProperty("entityExpansionLimit", ""); 385 } 386 } 387 388 private boolean isSecureMode() { 389 return System.getSecurityManager() != null; 390 } 391 }