From 91caec07cb2e4d98d4366f5627f55834282caa94 Mon Sep 17 00:00:00 2001 From: Joe Wang Date: Tue, 28 May 2024 19:26:17 +0000 Subject: [PATCH] 8330542: Template for Creating Strict JAXP Configuration File Reviewed-by: lancea, erikj, alanb, ihse, mullan, naoto --- make/modules/java.xml/Copy.gmk | 19 +-- .../conf/jaxp-strict.properties.template | 123 ++++++++++++++++++ src/java.xml/share/conf/jaxp.properties | 31 +++-- .../common/config/ConfigFileTest.java | 114 ++++++++++++++++ .../jaxp/unittest/common/util/TestBase.java | 17 ++- 5 files changed, 280 insertions(+), 24 deletions(-) create mode 100644 src/java.xml/share/conf/jaxp-strict.properties.template create mode 100644 test/jaxp/javax/xml/jaxp/unittest/common/config/ConfigFileTest.java diff --git a/make/modules/java.xml/Copy.gmk b/make/modules/java.xml/Copy.gmk index 3b6c66e42c5..f242cb2ac76 100644 --- a/make/modules/java.xml/Copy.gmk +++ b/make/modules/java.xml/Copy.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -24,14 +24,17 @@ # include CopyCommon.gmk +include Modules.gmk ################################################################################ +# +# Copy property and template files from share/conf to CONF_DST_DIR +# +$(eval $(call SetupCopyFiles, COPY_XML_MODULE_CONF, \ + DEST := $(CONF_DST_DIR), \ + SRC := $(TOPDIR)/src/java.xml/share/conf, \ + FILES := jaxp.properties jaxp-strict.properties.template, \ +)) -XML_LIB_SRC := $(TOPDIR)/src/java.xml/share/conf - -$(CONF_DST_DIR)/jaxp.properties: $(XML_LIB_SRC)/jaxp.properties - $(call install-file) - -TARGETS := $(CONF_DST_DIR)/jaxp.properties - +TARGETS += $(COPY_XML_MODULE_CONF) ################################################################################ diff --git a/src/java.xml/share/conf/jaxp-strict.properties.template b/src/java.xml/share/conf/jaxp-strict.properties.template new file mode 100644 index 00000000000..2d6cbc951e2 --- /dev/null +++ b/src/java.xml/share/conf/jaxp-strict.properties.template @@ -0,0 +1,123 @@ +################################################################################ +# JAXP Strict Configuration Template +# +# This file, jaxp-strict.properties.template, provides a template for creating +# custom configuration files. The settings in this file are more restrictive than +# those in the default configuration, jaxp.properties. In particular: +# - JDKCatalog Resolve is on "strict" setting +# - Extension Functions are disabled +# - JAXP Limits are set to smaller numbers +# +# To create a configuration file, copy the template to a new file with +# the .properties extension, that is: +# +# cp $JAVA_HOME/conf/jaxp-strict.properties.template /path/to/jaxp-strict.properties +# +# The configuration file can then be set up using the system property +# java.xml.config.file to override the default configuration jaxp.properties +# and used to assess the impact of a stricter configuration, for example: +# +# java -Djava.xml.config.file=/path/to/jaxp-strict.properties +# +# The system property java.xml.config.file is defined in the java.xml module +# description. +# +################################################################################ + +# +# ---- Implementation Specific Properties ---- +# For a complete list of properties, refer to the Implementation Specific Properties +# table in the java.xml/module-summary. +# +# Extension Functions: +# +# This property determines whether XSLT and XPath extension functions are allowed. +# The value type is boolean and the default value is true (allowing +# extension functions). The following entry overrides the default value and +# disallows extension functions: +# +jdk.xml.enableExtensionFunctions=false +# +# +# Overriding the default parser: +# +# This property allows a third party implementation to override the default +# parser provided by the JDK. The value type is boolean and the default value is +# false, disallowing overriding the default parser. The setting below reflects +# the default property setting: +# +jdk.xml.overrideDefaultParser=false +# +# Implementation Specific Properties - jdkcatalog.resolve +# +# This property instructs the JDK default CatalogResolver to act in accordance with +# the setting when unable to resolve an external reference with the built-in Catalog. +# The options are: +# continue -- indicates that the processing should continue +# ignore -- indicates that the reference is skipped +# strict -- indicates that the resolver should throw a CatalogException +# +# The following setting causes the default CatalogResolver to throw a CatalogException +# when external references are not resolved by a user-defined resolver or catalog, +# or the built-in Catalog: +jdk.xml.jdkcatalog.resolve=strict +# +# Implementation Specific Properties - DTD +# +# This property instructs the parsers to deny, ignore or allow DTD processing. +# The following setting causes the parser to reject DTDs by throwing an exception. +# jdk.xml.dtd.support=deny +# +# The following setting permits the processor to continue processing DTDs. Note +# that while DTDs are allowed in this configuration, external references are +# restricted, and limits on DTD entities are tightened: +jdk.xml.dtd.support=allow +# +# Implementation Specific Properties - Limits +# +# Limits have a value type Integer. The values must be positive integers. Zero +# means no limit. +# +# Limits the number of entity expansions +jdk.xml.entityExpansionLimit=2500 +# +# Limits the total size of all entities that include general and parameter entities. +# The size is calculated as an aggregation of all entities. +jdk.xml.totalEntitySizeLimit=100000 +# +# Limits the maximum size of any general entities. +jdk.xml.maxGeneralEntitySizeLimit=100000 +# +# Limits the maximum size of any parameter entities, including the result of +# nesting multiple parameter entities. +jdk.xml.maxParameterEntitySizeLimit=15000 +# +# Limits the total number of nodes in all entity references. +jdk.xml.entityReplacementLimit=100000 +# +# Limits the number of attributes an element can have. The default value is 10000. +jdk.xml.elementAttributeLimit=10000 +# +# Limits the number of content model nodes that may be created when building a +# grammar for a W3C XML Schema that contains maxOccurs attributes with values +# other than "unbounded". The default value is 5000. +jdk.xml.maxOccurLimit=5000 +# +# Limits the maximum element depth. The default value is 0. +jdk.xml.maxElementDepth=0 +# +# Limits the maximum size of XML names, including element name, attribute name +# and namespace prefix and URI. The default value is 1000. +jdk.xml.maxXMLNameLimit=1000 +# +# +# XPath Limits +# +# Limits the number of groups an XPath expression can contain. The default value is 10. +jdk.xml.xpathExprGrpLimit=10 +# +# Limits the number of operators an XPath expression can contain. The default value is 100. +jdk.xml.xpathExprOpLimit=100 +# +# Limits the total number of XPath operators in an XSL Stylesheet. The default value is 10000. +jdk.xml.xpathTotalOpLimit=10000 diff --git a/src/java.xml/share/conf/jaxp.properties b/src/java.xml/share/conf/jaxp.properties index 53074816cb9..53835f63743 100644 --- a/src/java.xml/share/conf/jaxp.properties +++ b/src/java.xml/share/conf/jaxp.properties @@ -31,7 +31,7 @@ # # The format of an entry is key=value where the key is the fully qualified name # of the factory and value that of the implementation class. The following entry -# set a DocumentBuilderFactory implementation class: +# sets a DocumentBuilderFactory implementation class: # # javax.xml.parsers.DocumentBuilderFactory=com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl # @@ -49,7 +49,7 @@ # # For example, the RESOLVE property in CatalogFeatures has an associated system # property called javax.xml.catalog.resolve. An entry for the RESOLVE property in the -# configuration file would therefore use javax.xml.catalog.resolve as the key, that +# configuration file therefore uses javax.xml.catalog.resolve as the key, that # is: # javax.xml.catalog.resolve=strict # @@ -58,15 +58,15 @@ # # This property determines whether XSLT and XPath extension functions are allowed. # The value type is boolean and the default value is true (allowing -# extension functions). The following entry would override the default value and -# disallow extension functions: +# extension functions). The following entry overrides the default value and +# disallows extension functions: # # jdk.xml.enableExtensionFunctions=false # # # Overriding the default parser: # -# This property allows using a third party implementation to override the default +# This property allows a third party implementation to override the default # parser provided by the JDK. The value type is boolean and the default value is # false, disallowing overriding the default parser. The setting below reflects # the default property setting: @@ -137,16 +137,20 @@ jdk.xml.overrideDefaultParser=false # ignore -- indicates that the reference is skipped # strict -- indicates that the resolver should throw a CatalogException # -# The following setting would cause the resolve to throw a CatalogException when -# unable to resolve an external reference: -# jdk.xml.jdkcatalog.resolve=strict +# The following setting allows the resolution to continue in cases where +# external references are not resolved by a user-defined resolver or catalog if +# any, and the built-in Catalog: +jdk.xml.jdkcatalog.resolve=continue # # Implementation Specific Properties - DTD # -# This property instructs the parsers to: deny, ignore or allow DTD processing. -# The following setting would cause the parser to reject DTD by throwing an exception. +# This property instructs the parsers to deny, ignore or allow DTD processing. +# The following setting causes the parser to reject DTDs by throwing an exception. # jdk.xml.dtd.support=deny # +# The following setting permits the processor to continue processing DTDs +jdk.xml.dtd.support=allow +# # Implementation Specific Properties - Limits # # Limits have a value type Integer. The values must be positive integers. Zero @@ -157,17 +161,17 @@ jdk.xml.overrideDefaultParser=false # # Limits the total size of all entities that include general and parameter entities. # The size is calculated as an aggregation of all entities. The default value is 5x10^7. -# jdk.xml.totalEntitySizeLimit=5E7 +# jdk.xml.totalEntitySizeLimit=50000000 # # Limits the maximum size of any general entities. The default value is 0. # jdk.xml.maxGeneralEntitySizeLimit=0 # # Limits the maximum size of any parameter entities, including the result of # nesting multiple parameter entities. The default value is 10^6. -# jdk.xml.maxParameterEntitySizeLimit=1E6 +# jdk.xml.maxParameterEntitySizeLimit=1000000 # # Limits the total number of nodes in all entity references. The default value is 3x10^6. -# jdk.xml.entityReplacementLimit=3E6 +# jdk.xml.entityReplacementLimit=3000000 # # Limits the number of attributes an element can have. The default value is 10000. # jdk.xml.elementAttributeLimit=10000 @@ -195,4 +199,3 @@ jdk.xml.xpathExprOpLimit=100 # # Limits the total number of XPath operators in an XSL Stylesheet. The default value is 10000. jdk.xml.xpathTotalOpLimit=10000 - diff --git a/test/jaxp/javax/xml/jaxp/unittest/common/config/ConfigFileTest.java b/test/jaxp/javax/xml/jaxp/unittest/common/config/ConfigFileTest.java new file mode 100644 index 00000000000..fd5b8b36fa3 --- /dev/null +++ b/test/jaxp/javax/xml/jaxp/unittest/common/config/ConfigFileTest.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package common.config; + +import common.util.TestBase; +import static common.util.TestBase.CONFIG_DEFAULT; +import static common.util.TestBase.CONFIG_STRICT; +import static common.util.TestBase.CONFIG_TEMPLATE_STRICT; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.stream.IntStream; +import javax.xml.transform.TransformerFactory; + +/** + * @test @bug 8330542 + * @summary verifies the default JAXP configuration file jaxp.properties and + * strict template jaxp-strict.properties.template. + * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest + * @modules java.xml/jdk.xml.internal + * @run driver common.config.ConfigFileTest 0 // verifies jaxp.properties + * @run driver common.config.ConfigFileTest 1 // verifies jaxp-strict.properties.template + */ +public class ConfigFileTest { + // system property for custom configuration file + static final String SP_CONFIG = "java.xml.config.file"; + // target directory + static String TEST_DIR = System.getProperty("test.classes"); + + // properties in the configuration file + String[] keys = { + "jdk.xml.enableExtensionFunctions", + "jdk.xml.overrideDefaultParser", + "jdk.xml.jdkcatalog.resolve", + "jdk.xml.dtd.support", + "jdk.xml.entityExpansionLimit", + "jdk.xml.totalEntitySizeLimit", + "jdk.xml.maxGeneralEntitySizeLimit", + "jdk.xml.maxParameterEntitySizeLimit", + "jdk.xml.entityReplacementLimit", + "jdk.xml.elementAttributeLimit", + "jdk.xml.maxOccurLimit", + "jdk.xml.maxElementDepth", + "jdk.xml.maxXMLNameLimit", + "jdk.xml.xpathExprGrpLimit", + "jdk.xml.xpathExprOpLimit", + "jdk.xml.xpathTotalOpLimit"}; + + // type of properties + boolean[] propertyIsFeature ={true, true, false, false, false, false, + false, false, false, false, false, false, false, false, false, false}; + + // values from jaxp-strict.properties.template + String[] strictValues ={"false", "false", "strict", "allow", "2500", "100000", + "100000", "15000", "100000", "10000", "5000", "0", "1000", "10", "100", "10000"}; + + // values from jaxp.properties, as of JDK 23 + String[] defaultValues ={"true", "false", "continue", "allow", "64000", "50000000", + "0", "1000000", "3000000", "10000", "5000", "0", "1000", "10", "100", "10000"}; + + public static void main(String args[]) throws Exception { + new ConfigFileTest().run(args[0]); + } + + public void run(String index) throws Exception { + String conf = System.getProperty("java.home") + "/conf/"; + if (index.equals("0")) { + verifyConfig(conf + CONFIG_DEFAULT, defaultValues); + } else { + Path config = Paths.get(TEST_DIR, CONFIG_STRICT); + Files.copy(Paths.get(conf, CONFIG_TEMPLATE_STRICT), config); + verifyConfig(config.toString(), strictValues); + } + } + + /** + * Verifies a configuration file by iterating through its property settings. + * @param filename the configuration file + * @param values expected values in the configuration file + */ + private void verifyConfig(String filename, String[] values) { + System.setProperty(SP_CONFIG, filename); + + TransformerFactory tf = TransformerFactory.newInstance(); + IntStream.range(0, keys.length).forEach(i -> { + if (propertyIsFeature[i]) { + TestBase.Assert.assertEquals(tf.getFeature(keys[i]), Boolean.parseBoolean(values[i])); + } else { + TestBase.Assert.assertEquals(tf.getAttribute(keys[i]), values[i]); + } + }); + System.clearProperty(SP_CONFIG); + } +} diff --git a/test/jaxp/javax/xml/jaxp/unittest/common/util/TestBase.java b/test/jaxp/javax/xml/jaxp/unittest/common/util/TestBase.java index 6be967d8dd5..77672609147 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/common/util/TestBase.java +++ b/test/jaxp/javax/xml/jaxp/unittest/common/util/TestBase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ import java.io.FileNotFoundException; import java.io.InputStream; import java.io.StringReader; import java.io.StringWriter; +import java.util.Objects; import java.util.regex.Pattern; import javax.xml.XMLConstants; import javax.xml.catalog.CatalogFeatures; @@ -121,6 +122,11 @@ public class TestBase { // CATALOG=strict public static final String CONFIG_CATALOG_STRICT = "catalog2.properties"; + // JAXP Configuration Files to be added to $JAVA_HOME/conf/ + public static final String CONFIG_DEFAULT = "jaxp.properties"; + public static final String CONFIG_STRICT = "jaxp-strict.properties"; + public static final String CONFIG_TEMPLATE_STRICT = "jaxp-strict.properties.template"; + public static final String UNKNOWN_HOST = "invalid.site.com"; String xmlExternalEntity, xmlExternalEntityId; @@ -133,6 +139,7 @@ public class TestBase { // config file: CATALOG = strict CONFIG_FILE_CATALOG_STRICT(null, CONFIG_FILE, Type.FEATURE, getPath(CONFIG_FILE_PATH, CONFIG_CATALOG_STRICT)), CONFIG_FILE_DTD2(null, CONFIG_FILE, Type.FEATURE, getPath(CONFIG_FILE_PATH, JCF_DTD2)), + FSP(XMLConstants.FEATURE_SECURE_PROCESSING, null, Type.FEATURE, "true"), FSP_FALSE(XMLConstants.FEATURE_SECURE_PROCESSING, null, Type.FEATURE, "false"), @@ -715,7 +722,7 @@ public class TestBase { return temp; } - static class Assert { + public static class Assert { public static void assertTrue(boolean condition) { assertTrue(condition, null); } @@ -733,5 +740,11 @@ public class TestBase { public static void fail(String message) { throw new RuntimeException("Test failed. " + message); } + + public static void assertEquals(Object actual, Object expected) { + if (!Objects.equals(actual, expected)) { + throw new RuntimeException("Expected: " + expected + " but actual result was " + actual); + } + } } }