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