1 /*
   2  * Copyright (c) 2014, 2015, 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.InputStream;
  28 
  29 import javax.xml.XMLConstants;
  30 import javax.xml.parsers.DocumentBuilder;
  31 import javax.xml.parsers.DocumentBuilderFactory;
  32 import javax.xml.parsers.SAXParser;
  33 import javax.xml.parsers.SAXParserFactory;
  34 
  35 import org.testng.Assert;
  36 import org.testng.annotations.Test;
  37 import org.w3c.dom.Document;
  38 import org.xml.sax.SAXParseException;
  39 
  40 /*
  41  * @bug 6309988
  42  * @summary Test elementAttributeLimit, maxOccurLimit, entityExpansionLimit.
  43  */
  44 public class Bug6309988 {
  45 
  46     DocumentBuilderFactory dbf = null;
  47     static boolean _isSecureMode = false;
  48     static {
  49         if (System.getSecurityManager() != null) {
  50             _isSecureMode = true;
  51             System.out.println("Security Manager is present");
  52         } else {
  53             System.out.println("Security Manager is NOT present");
  54         }
  55     }
  56 
  57     /*
  58      * Given XML document has more than 10000 attributes. Exception is expected
  59      */
  60     @Test
  61     public void testDOMParserElementAttributeLimit() {
  62         try {
  63             dbf = DocumentBuilderFactory.newInstance();
  64             DocumentBuilder parser = dbf.newDocumentBuilder();
  65             Document doc = parser.parse(this.getClass().getResourceAsStream("DosTest.xml"));
  66             Assert.fail("SAXParserException is expected, as given XML document contains more than 10000 attributes");
  67         } catch (SAXParseException e) {
  68             System.out.println(e.getMessage());
  69         } catch (Exception e) {
  70             Assert.fail("Exception " + e.getMessage());
  71         }
  72     }
  73 
  74     /*
  75      * Given XML document has more than 10000 attributes. It should report an
  76      * error.
  77      */
  78     @Test
  79     public void testDOMNSParserElementAttributeLimit() {
  80         try {
  81             dbf = DocumentBuilderFactory.newInstance();
  82             dbf.setNamespaceAware(true);
  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. Parsing this XML
  95      * document in non-secure mode, should not report any error.
  96      */
  97     @Test
  98     public void testDOMNSParserElementAttributeLimitWithoutSecureProcessing() {
  99         if (_isSecureMode)
 100             return; // jaxp secure feature can not be turned off when security
 101                     // manager is present
 102         try {
 103             dbf = DocumentBuilderFactory.newInstance();
 104             dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, false);
 105             dbf.setNamespaceAware(true);
 106             DocumentBuilder parser = dbf.newDocumentBuilder();
 107             Document doc = parser.parse(this.getClass().getResourceAsStream("DosTest.xml"));
 108 
 109         } catch (SAXParseException e) {
 110             Assert.fail(e.getMessage());
 111         } catch (Exception e) {
 112             Assert.fail("Exception " + e.getMessage());
 113         }
 114     }
 115 
 116     /*
 117      * Before 8014530: Given XML document has 3 attributes and System property
 118      * is set to 2. Parsing this XML document in non-secure mode, should not
 119      * report an error.
 120      * After 8014530: System properties will override FSP, the result of this
 121      * test should be the same as
 122      * testSystemElementAttributeLimitWithSecureProcessing
 123      */
 124     @Test
 125     public void testSystemElementAttributeLimitWithoutSecureProcessing() {
 126         if (_isSecureMode)
 127             return; // jaxp secure feature can not be turned off when security
 128                     // manager is present
 129         try {
 130             dbf = DocumentBuilderFactory.newInstance();
 131             dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, false);
 132             dbf.setNamespaceAware(true);
 133             System.setProperty("elementAttributeLimit", "2");
 134             DocumentBuilder parser = dbf.newDocumentBuilder();
 135             Document doc = parser.parse(this.getClass().getResourceAsStream("DosTest3.xml"));
 136 
 137             Assert.fail("SAXParserException is expected, as given XML document contains more than 2 attributes");
 138         } catch (Exception e) {
 139             String errMsg = e.getMessage();
 140             Throwable cause = e.getCause();
 141             if (cause != null) {
 142                 errMsg += cause.getMessage();
 143             }
 144             if (errMsg.contains("JAXP0001")) {
 145                 // expected
 146             } else {
 147                 Assert.fail("Unexpected error: " + e.getMessage());
 148             }
 149         } finally {
 150             System.clearProperty("elementAttributeLimit");
 151         }
 152     }
 153 
 154     /*
 155      * Given XML document has 3 attributes and System property is set to 2.
 156      * Parsing this XML document in secure mode, should report an error.
 157      */
 158     @Test
 159     public void testSystemElementAttributeLimitWithSecureProcessing() {
 160         try {
 161             dbf = DocumentBuilderFactory.newInstance();
 162             dbf.setNamespaceAware(true);
 163             System.setProperty("elementAttributeLimit", "2");
 164             DocumentBuilder parser = dbf.newDocumentBuilder();
 165             Document doc = parser.parse(this.getClass().getResourceAsStream("DosTest3.xml"));
 166             Assert.fail("SAXParserException is expected, as given XML document contains more than 2 attributes");
 167         } catch (SAXParseException e) {
 168             System.out.println(e.getMessage());
 169         } catch (Exception e) {
 170             Assert.fail("Exception " + e.getMessage());
 171         } finally {
 172             System.setProperty("elementAttributeLimit", "");
 173         }
 174     }
 175 
 176     /*
 177      * Default value for secure processing feature should be true.
 178      */
 179     @Test
 180     public void testDOMSecureProcessingDefaultValue() {
 181         try {
 182             dbf = DocumentBuilderFactory.newInstance();
 183             Assert.assertTrue(dbf.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING), "Default value for secureProcessing feature should be true");
 184 
 185         } catch (Exception e) {
 186             Assert.fail("Exception " + e.getMessage());
 187         }
 188     }
 189 
 190     /*
 191      * Default value for secure processing feature should be true.
 192      */
 193     @Test
 194     public void testSAXSecureProcessingDefaultValue() {
 195         try {
 196             SAXParserFactory spf = SAXParserFactory.newInstance();
 197             Assert.assertTrue(spf.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      * This method sets system property for maxOccurLimit=2 and secure process
 206      * feature is off. Given doument contains more than 2 elements and hence an
 207      * error should be reported.
 208      */
 209     @Test
 210     public void testSystemMaxOccurLimitWithoutSecureProcessing() {
 211         if (_isSecureMode)
 212             return; // jaxp secure feature can not be turned off when security
 213                     // manager is present
 214         try {
 215             SAXParserFactory spf = SAXParserFactory.newInstance();
 216             spf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, false);
 217             spf.setValidating(true);
 218             System.setProperty("maxOccurLimit", "2");
 219             // Set the properties for Schema Validation
 220             String SCHEMA_LANG = "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
 221             String SCHEMA_TYPE = "http://www.w3.org/2001/XMLSchema";
 222             // Get the Schema location as a File object
 223             File schemaFile = new File(this.getClass().getResource("toys.xsd").toURI());
 224             // Get the parser
 225             SAXParser parser = spf.newSAXParser();
 226             parser.setProperty(SCHEMA_LANG, SCHEMA_TYPE);
 227             parser.setProperty("http://java.sun.com/xml/jaxp/properties/schemaSource", schemaFile);
 228 
 229             InputStream is = this.getClass().getResourceAsStream("toys.xml");
 230             MyErrorHandler eh = new MyErrorHandler();
 231             parser.parse(is, eh);
 232             Assert.assertFalse(eh.errorOccured, "Not Expected Error");
 233             System.setProperty("maxOccurLimit", "");
 234         } catch (Exception e) {
 235             Assert.fail("Exception occured: " + e.getMessage());
 236         }
 237     }
 238 
 239     /*
 240      * This test will take longer time to execute( abt 120sec). This method
 241      * tries to validate a document. This document contains an element whose
 242      * maxOccur is '3002'. Since secure processing feature is off, document
 243      * should be parsed without any errors.
 244      */
 245     @Test
 246     public void testValidMaxOccurLimitWithOutSecureProcessing() {
 247         if (_isSecureMode)
 248             return; // jaxp secure feature can not be turned off when security
 249                     // manager is present
 250         try {
 251             SAXParserFactory spf = SAXParserFactory.newInstance();
 252             spf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, false);
 253             spf.setValidating(true);
 254             // Set the properties for Schema Validation
 255             String SCHEMA_LANG = "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
 256             String SCHEMA_TYPE = "http://www.w3.org/2001/XMLSchema";
 257             // Get the Schema location as a File object
 258             File schemaFile = new File(this.getClass().getResource("toys3002.xsd").toURI());
 259             // Get the parser
 260             SAXParser parser = spf.newSAXParser();
 261             parser.setProperty(SCHEMA_LANG, SCHEMA_TYPE);
 262             parser.setProperty("http://java.sun.com/xml/jaxp/properties/schemaSource", schemaFile);
 263 
 264             InputStream is = this.getClass().getResourceAsStream("toys.xml");
 265             MyErrorHandler eh = new MyErrorHandler();
 266             parser.parse(is, eh);
 267             Assert.assertFalse(eh.errorOccured, "Expected Error as maxOccurLimit is exceeded");
 268 
 269         } catch (Exception e) {
 270             Assert.fail("Exception occured: " + e.getMessage());
 271         }
 272     }
 273 
 274     /*
 275      * Before 8014530: System property is set to 2. Given XML document has more
 276      * than 2 entity references. Parsing this document in non-secure mode,
 277      * should *not* report an error.
 278      * After 8014530: System properties will override FSP, the result of this
 279      * test should be the same as
 280      * testSystemElementAttributeLimitWithSecureProcessing
 281      */
 282     @Test
 283     public void testSystemEntityExpansionLimitWithOutSecureProcessing() {
 284         if (_isSecureMode)
 285             return; // jaxp secure feature can not be turned off when security
 286                     // manager is present
 287         try {
 288             System.setProperty("entityExpansionLimit", "2");
 289             dbf = DocumentBuilderFactory.newInstance();
 290             dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, false);
 291             dbf.setValidating(true);
 292             DocumentBuilder parser = dbf.newDocumentBuilder();
 293             Document doc = parser.parse(this.getClass().getResourceAsStream("entity.xml"));
 294             Assert.fail("SAXParserException is expected, as given XML document contains more 2 entity references");
 295         } catch (Exception e) {
 296             String errMsg = e.getMessage();
 297             Throwable cause = e.getCause();
 298             if (cause != null) {
 299                 errMsg += cause.getMessage();
 300             }
 301             if (errMsg.contains("JAXP0001")) {
 302                 // expected
 303             } else {
 304                 Assert.fail("Unexpected error: " + e.getMessage());
 305             }
 306         } finally {
 307             System.clearProperty("entityExpansionLimit");
 308         }
 309     }
 310 
 311     /*
 312      * System property is set to 2. Given XML document has more than 2 entity
 313      * references. Parsing this document in secure mode, should report an error.
 314      */
 315     @Test
 316     public void testSystemEntityExpansionLimitWithSecureProcessing() {
 317         try {
 318             dbf = DocumentBuilderFactory.newInstance();
 319             dbf.setValidating(true);
 320             System.setProperty("entityExpansionLimit", "2");
 321             DocumentBuilder parser = dbf.newDocumentBuilder();
 322             Document doc = parser.parse(this.getClass().getResourceAsStream("entity.xml"));
 323             Assert.fail("SAXParserException is expected, as given XML document contains more 2 entity references");
 324 
 325         } catch (SAXParseException e) {
 326             System.out.println(e.getMessage());
 327         } catch (Exception e) {
 328             Assert.fail("Exception " + e.getMessage());
 329         } finally {
 330             System.setProperty("entityExpansionLimit", "");
 331         }
 332     }
 333 
 334     /*
 335      * Given XML document has more than 64000 entity references. Parsing this
 336      * document in secure mode, should report an error.
 337      */
 338     @Test
 339     public void testEntityExpansionLimitWithSecureProcessing() {
 340         try {
 341             dbf = DocumentBuilderFactory.newInstance();
 342             dbf.setValidating(true);
 343             DocumentBuilder parser = dbf.newDocumentBuilder();
 344             Document doc = parser.parse(this.getClass().getResourceAsStream("entity64K.xml"));
 345             Assert.fail("SAXParserException is expected, as given XML document contains more 2 entity references");
 346 
 347         } catch (SAXParseException e) {
 348             System.out.println(e.getMessage());
 349         } catch (Exception e) {
 350             Assert.fail("Exception " + e.getMessage());
 351         } finally {
 352             System.setProperty("entityExpansionLimit", "");
 353         }
 354     }
 355 
 356     /*
 357      * Given XML document has more than 64000 entity references. Parsing this
 358      * document in non-secure mode, should not report any error.
 359      */
 360     @Test
 361     public void testEntityExpansionLimitWithOutSecureProcessing() {
 362         if (_isSecureMode)
 363             return; // jaxp secure feature can not be turned off when security
 364                     // manager is present
 365         try {
 366             dbf = DocumentBuilderFactory.newInstance();
 367             dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, false);
 368             dbf.setValidating(true);
 369             DocumentBuilder parser = dbf.newDocumentBuilder();
 370             Document doc = parser.parse(this.getClass().getResourceAsStream("entity64K.xml"));
 371 
 372         } catch (SAXParseException e) {
 373             Assert.fail("Exception " + e.getMessage());
 374         } catch (Exception e) {
 375             Assert.fail("Exception " + e.getMessage());
 376         } finally {
 377             System.setProperty("entityExpansionLimit", "");
 378         }
 379     }
 380 }