changeset 574:ce16a5aa1507

8022682: Supporting XOM Reviewed-by: alanb, chegar, lancea
author joehw
date Tue, 20 Aug 2013 09:02:25 -0700
parents f952c33ebfdb
children cc3b64366048
files src/com/sun/org/apache/xerces/internal/impl/PropertyManager.java src/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaFactory.java src/com/sun/org/apache/xerces/internal/parsers/DOMParser.java src/com/sun/org/apache/xerces/internal/parsers/DTDConfiguration.java src/com/sun/org/apache/xerces/internal/parsers/NonValidatingConfiguration.java src/com/sun/org/apache/xerces/internal/parsers/SAXParser.java src/com/sun/org/apache/xerces/internal/parsers/XML11Configuration.java src/com/sun/org/apache/xerces/internal/parsers/XMLParser.java src/com/sun/org/apache/xerces/internal/util/SecurityManager.java src/com/sun/org/apache/xerces/internal/utils/XMLLimitAnalyzer.java src/com/sun/org/apache/xerces/internal/utils/XMLSecurityManager.java
diffstat 11 files changed, 395 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/src/com/sun/org/apache/xerces/internal/impl/PropertyManager.java	Thu Aug 15 21:33:52 2013 +0100
+++ b/src/com/sun/org/apache/xerces/internal/impl/PropertyManager.java	Tue Aug 20 09:02:25 2013 -0700
@@ -178,6 +178,25 @@
             supportedProps.put( Constants.XERCES_PROPERTY_PREFIX + Constants.STAX_ENTITY_RESOLVER_PROPERTY , new StaxEntityResolverWrapper((XMLResolver)value)) ;
         }
 
+        /**
+         * It's possible for users to set a security manager through the interface.
+         * If it's the old SecurityManager, convert it to the new XMLSecurityManager
+         */
+        if (property.equals(Constants.SECURITY_MANAGER)) {
+            fSecurityManager = XMLSecurityManager.convert(value, fSecurityManager);
+            supportedProps.put(Constants.SECURITY_MANAGER, fSecurityManager);
+            return;
+        }
+        if (property.equals(Constants.XML_SECURITY_PROPERTY_MANAGER)) {
+            if (value == null) {
+                fSecurityPropertyMgr = new XMLSecurityPropertyManager();
+            } else {
+                fSecurityPropertyMgr = (XMLSecurityPropertyManager)value;
+            }
+            supportedProps.put(Constants.XML_SECURITY_PROPERTY_MANAGER, fSecurityPropertyMgr);
+            return;
+        }
+
         //check if the property is managed by security manager
         if (fSecurityManager == null ||
                 !fSecurityManager.setLimit(property, XMLSecurityManager.State.APIPROPERTY, value)) {
--- a/src/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaFactory.java	Thu Aug 15 21:33:52 2013 +0100
+++ b/src/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaFactory.java	Tue Aug 20 09:02:25 2013 -0700
@@ -408,9 +408,17 @@
                     "ProperyNameNull", null));
         }
         if (name.equals(SECURITY_MANAGER)) {
-            fSecurityManager = (XMLSecurityManager) object;
+            fSecurityManager = XMLSecurityManager.convert(object, fSecurityManager);
             fXMLSchemaLoader.setProperty(SECURITY_MANAGER, fSecurityManager);
             return;
+        } else if (name.equals(Constants.XML_SECURITY_PROPERTY_MANAGER)) {
+            if (object == null) {
+                fSecurityPropertyMgr = new XMLSecurityPropertyManager();
+            } else {
+                fSecurityPropertyMgr = (XMLSecurityPropertyManager)object;
+            }
+            fXMLSchemaLoader.setProperty(Constants.XML_SECURITY_PROPERTY_MANAGER, fSecurityPropertyMgr);
+            return;
         }
         else if (name.equals(XMLGRAMMAR_POOL)) {
             throw new SAXNotSupportedException(
--- a/src/com/sun/org/apache/xerces/internal/parsers/DOMParser.java	Thu Aug 15 21:33:52 2013 +0100
+++ b/src/com/sun/org/apache/xerces/internal/parsers/DOMParser.java	Tue Aug 20 09:02:25 2013 -0700
@@ -29,6 +29,7 @@
 import com.sun.org.apache.xerces.internal.util.SAXMessageFormatter;
 import com.sun.org.apache.xerces.internal.util.Status;
 import com.sun.org.apache.xerces.internal.util.SymbolTable;
+import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager;
 import com.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager;
 import com.sun.org.apache.xerces.internal.xni.XNIException;
 import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarPool;
@@ -531,7 +532,54 @@
      */
     public void setProperty(String propertyId, Object value)
         throws SAXNotRecognizedException, SAXNotSupportedException {
+        /**
+         * It's possible for users to set a security manager through the interface.
+         * If it's the old SecurityManager, convert it to the new XMLSecurityManager
+         */
+        if (propertyId.equals(Constants.SECURITY_MANAGER)) {
+            securityManager = XMLSecurityManager.convert(value, securityManager);
+            setProperty0(Constants.SECURITY_MANAGER, securityManager);
+            return;
+        }
+        if (propertyId.equals(Constants.XML_SECURITY_PROPERTY_MANAGER)) {
+            if (value == null) {
+                securityPropertyManager = new XMLSecurityPropertyManager();
+            } else {
+                securityPropertyManager = (XMLSecurityPropertyManager)value;
+            }
+            setProperty0(Constants.XML_SECURITY_PROPERTY_MANAGER, securityPropertyManager);
+            return;
+        }
 
+        if (securityManager == null) {
+            securityManager = new XMLSecurityManager(true);
+            setProperty0(Constants.SECURITY_MANAGER, securityManager);
+        }
+
+        if (securityPropertyManager == null) {
+            securityPropertyManager = new XMLSecurityPropertyManager();
+            setProperty0(Constants.XML_SECURITY_PROPERTY_MANAGER, securityPropertyManager);
+        }
+        int index = securityPropertyManager.getIndex(propertyId);
+
+        if (index > -1) {
+            /**
+             * this is a direct call to this parser, not a subclass since
+             * internally the support of this property is done through
+             * XMLSecurityPropertyManager
+             */
+            securityPropertyManager.setValue(index, XMLSecurityPropertyManager.State.APIPROPERTY, (String)value);
+        } else {
+            //check if the property is managed by security manager
+            if (!securityManager.setLimit(propertyId, XMLSecurityManager.State.APIPROPERTY, value)) {
+                //fall back to the default configuration to handle the property
+                setProperty0(propertyId, value);
+            }
+        }
+    }
+
+    public void setProperty0(String propertyId, Object value)
+        throws SAXNotRecognizedException, SAXNotSupportedException {
         try {
             fConfiguration.setProperty(propertyId, value);
         }
--- a/src/com/sun/org/apache/xerces/internal/parsers/DTDConfiguration.java	Thu Aug 15 21:33:52 2013 +0100
+++ b/src/com/sun/org/apache/xerces/internal/parsers/DTDConfiguration.java	Tue Aug 20 09:02:25 2013 -0700
@@ -184,6 +184,13 @@
     protected static final String LOCALE =
         Constants.XERCES_PROPERTY_PREFIX + Constants.LOCALE_PROPERTY;
 
+      /** Property identifier: Security property manager. */
+      protected static final String XML_SECURITY_PROPERTY_MANAGER =
+              Constants.XML_SECURITY_PROPERTY_MANAGER;
+
+     /** Property identifier: Security manager. */
+     private static final String SECURITY_MANAGER = Constants.SECURITY_MANAGER;
+
     // debugging
 
     /** Set to true and recompile to print exception stack trace. */
@@ -328,7 +335,9 @@
             VALIDATION_MANAGER,
             JAXP_SCHEMA_SOURCE,
             JAXP_SCHEMA_LANGUAGE,
-            LOCALE
+            LOCALE,
+            SECURITY_MANAGER,
+            XML_SECURITY_PROPERTY_MANAGER
         };
         addRecognizedProperties(recognizedProperties);
 
--- a/src/com/sun/org/apache/xerces/internal/parsers/NonValidatingConfiguration.java	Thu Aug 15 21:33:52 2013 +0100
+++ b/src/com/sun/org/apache/xerces/internal/parsers/NonValidatingConfiguration.java	Tue Aug 20 09:02:25 2013 -0700
@@ -157,6 +157,13 @@
     protected static final String LOCALE =
         Constants.XERCES_PROPERTY_PREFIX + Constants.LOCALE_PROPERTY;
 
+      /** Property identifier: Security property manager. */
+      protected static final String XML_SECURITY_PROPERTY_MANAGER =
+              Constants.XML_SECURITY_PROPERTY_MANAGER;
+
+     /** Property identifier: Security manager. */
+     private static final String SECURITY_MANAGER = Constants.SECURITY_MANAGER;
+
     // debugging
 
     /** Set to true and recompile to print exception stack trace. */
@@ -310,7 +317,9 @@
             XMLGRAMMAR_POOL,
             DATATYPE_VALIDATOR_FACTORY,
             VALIDATION_MANAGER,
-            LOCALE
+            LOCALE,
+            SECURITY_MANAGER,
+            XML_SECURITY_PROPERTY_MANAGER
         };
         addRecognizedProperties(recognizedProperties);
 
--- a/src/com/sun/org/apache/xerces/internal/parsers/SAXParser.java	Thu Aug 15 21:33:52 2013 +0100
+++ b/src/com/sun/org/apache/xerces/internal/parsers/SAXParser.java	Tue Aug 20 09:02:25 2013 -0700
@@ -77,8 +77,7 @@
         XMLGRAMMAR_POOL,
     };
 
-    XMLSecurityManager securityManager;
-    XMLSecurityPropertyManager securityPropertyManager;
+
     //
     // Constructors
     //
@@ -132,9 +131,35 @@
      */
     public void setProperty(String name, Object value)
         throws SAXNotRecognizedException, SAXNotSupportedException {
+        /**
+         * It's possible for users to set a security manager through the interface.
+         * If it's the old SecurityManager, convert it to the new XMLSecurityManager
+         */
+        if (name.equals(Constants.SECURITY_MANAGER)) {
+            securityManager = XMLSecurityManager.convert(value, securityManager);
+            super.setProperty(Constants.SECURITY_MANAGER, securityManager);
+            return;
+        }
+        if (name.equals(Constants.XML_SECURITY_PROPERTY_MANAGER)) {
+            if (value == null) {
+                securityPropertyManager = new XMLSecurityPropertyManager();
+            } else {
+                securityPropertyManager = (XMLSecurityPropertyManager)value;
+            }
+            super.setProperty(Constants.XML_SECURITY_PROPERTY_MANAGER, securityPropertyManager);
+            return;
+        }
+
+        if (securityManager == null) {
+            securityManager = new XMLSecurityManager(true);
+            super.setProperty(Constants.SECURITY_MANAGER, securityManager);
+        }
+
         if (securityPropertyManager == null) {
             securityPropertyManager = new XMLSecurityPropertyManager();
+            super.setProperty(Constants.XML_SECURITY_PROPERTY_MANAGER, securityPropertyManager);
         }
+
         int index = securityPropertyManager.getIndex(name);
         if (index > -1) {
             /**
@@ -143,19 +168,12 @@
              * XMLSecurityPropertyManager
              */
             securityPropertyManager.setValue(index, XMLSecurityPropertyManager.State.APIPROPERTY, (String)value);
-            super.setProperty(Constants.XML_SECURITY_PROPERTY_MANAGER, securityPropertyManager);
         } else {
-            if (securityManager == null) {
-                securityManager = new XMLSecurityManager(true);
-            }
-
             //check if the property is managed by security manager
-            if (securityManager.setLimit(name, XMLSecurityManager.State.APIPROPERTY, value)) {
-                super.setProperty(Constants.SECURITY_MANAGER, securityManager);
-            } else {
+            if (!securityManager.setLimit(name, XMLSecurityManager.State.APIPROPERTY, value)) {
+                //fall back to the default configuration to handle the property
                 super.setProperty(name, value);
             }
-
         }
     }
 } // class SAXParser
--- a/src/com/sun/org/apache/xerces/internal/parsers/XML11Configuration.java	Thu Aug 15 21:33:52 2013 +0100
+++ b/src/com/sun/org/apache/xerces/internal/parsers/XML11Configuration.java	Tue Aug 20 09:02:25 2013 -0700
@@ -583,10 +583,6 @@
 
         fVersionDetector = new XMLVersionDetector();
 
-        fProperties.put(XML_SECURITY_PROPERTY_MANAGER, new XMLSecurityPropertyManager());
-
-        fProperties.put(SECURITY_MANAGER, new XMLSecurityManager(true));
-
         // add message formatters
         if (fErrorReporter.getMessageFormatter(XMLMessageFormatter.XML_DOMAIN) == null) {
             XMLMessageFormatter xmft = new XMLMessageFormatter();
--- a/src/com/sun/org/apache/xerces/internal/parsers/XMLParser.java	Thu Aug 15 21:33:52 2013 +0100
+++ b/src/com/sun/org/apache/xerces/internal/parsers/XMLParser.java	Tue Aug 20 09:02:25 2013 -0700
@@ -23,6 +23,8 @@
 import java.io.IOException;
 
 import com.sun.org.apache.xerces.internal.impl.Constants;
+import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager;
+import com.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager;
 import com.sun.org.apache.xerces.internal.xni.XNIException;
 import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource;
 import com.sun.org.apache.xerces.internal.xni.parser.XMLParserConfiguration;
@@ -78,6 +80,13 @@
     /** The parser configuration. */
     protected XMLParserConfiguration fConfiguration;
 
+    /** The XML Security Manager. */
+    XMLSecurityManager securityManager;
+
+    /** The XML Security Property Manager. */
+    XMLSecurityPropertyManager securityPropertyManager;
+
+
     //
     // Constructors
     //
@@ -118,6 +127,15 @@
      */
     public void parse(XMLInputSource inputSource)
         throws XNIException, IOException {
+        // null indicates that the parser is called directly, initialize them
+        if (securityManager == null) {
+            securityManager = new XMLSecurityManager(true);
+            fConfiguration.setProperty(Constants.SECURITY_MANAGER, securityManager);
+        }
+        if (securityPropertyManager == null) {
+            securityPropertyManager = new XMLSecurityPropertyManager();
+            fConfiguration.setProperty(Constants.XML_SECURITY_PROPERTY_MANAGER, securityPropertyManager);
+        }
 
         reset();
         fConfiguration.parse(inputSource);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/com/sun/org/apache/xerces/internal/util/SecurityManager.java	Tue Aug 20 09:02:25 2013 -0700
@@ -0,0 +1,215 @@
+/*
+ * reserved comment block
+ * DO NOT REMOVE OR ALTER!
+ */
+/*
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 2003 The Apache Software Foundation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ *    if any, must include the following acknowledgment:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgment may appear in the software itself,
+ *    if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Xerces" and "Apache Software Foundation" must
+ *    not be used to endorse or promote products derived from this
+ *    software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ *    nor may "Apache" appear in their name, without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation and was
+ * originally based on software copyright (c) 1999, International
+ * Business Machines, Inc., http://www.apache.org.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+
+package com.sun.org.apache.xerces.internal.util;
+import com.sun.org.apache.xerces.internal.impl.Constants;
+/**
+ * This class is a container for parser settings that relate to
+ * security, or more specifically, it is intended to be used to prevent denial-of-service
+ * attacks from being launched against a system running Xerces.
+ * Any component that is aware of a denial-of-service attack that can arise
+ * from its processing of a certain kind of document may query its Component Manager
+ * for the property (http://apache.org/xml/properties/security-manager)
+ * whose value will be an instance of this class.
+ * If no value has been set for the property, the component should proceed in the "usual" (spec-compliant)
+ * manner.  If a value has been set, then it must be the case that the component in
+ * question needs to know what method of this class to query.  This class
+ * will provide defaults for all known security issues, but will also provide
+ * setters so that those values can be tailored by applications that care.
+ *
+ * @author  Neil Graham, IBM
+ *
+ */
+public final class SecurityManager {
+
+    //
+    // Constants
+    //
+
+    // default value for entity expansion limit
+    private final static int DEFAULT_ENTITY_EXPANSION_LIMIT = 64000;
+
+    /** Default value of number of nodes created. **/
+    private final static int DEFAULT_MAX_OCCUR_NODE_LIMIT = 5000;
+
+    //
+    // Data
+    //
+
+        private final static int DEFAULT_ELEMENT_ATTRIBUTE_LIMIT = 10000;
+
+    /** Entity expansion limit. **/
+    private int entityExpansionLimit;
+
+    /** W3C XML Schema maxOccurs limit. **/
+    private int maxOccurLimit;
+
+        private int fElementAttributeLimit;
+    // default constructor.  Establishes default values for
+    // all known security holes.
+    /**
+     * Default constructor.  Establishes default values
+     * for known security vulnerabilities.
+     */
+    public SecurityManager() {
+        entityExpansionLimit = DEFAULT_ENTITY_EXPANSION_LIMIT;
+        maxOccurLimit = DEFAULT_MAX_OCCUR_NODE_LIMIT ;
+                fElementAttributeLimit = DEFAULT_ELEMENT_ATTRIBUTE_LIMIT;
+                //We are reading system properties only once ,
+                //at the time of creation of this object ,
+                readSystemProperties();
+    }
+
+    /**
+     * <p>Sets the number of entity expansions that the
+     * parser should permit in a document.</p>
+     *
+     * @param limit the number of entity expansions
+     * permitted in a document
+     */
+    public void setEntityExpansionLimit(int limit) {
+        entityExpansionLimit = limit;
+    }
+
+    /**
+     * <p>Returns the number of entity expansions
+     * that the parser permits in a document.</p>
+     *
+     * @return the number of entity expansions
+     * permitted in a document
+     */
+    public int getEntityExpansionLimit() {
+        return entityExpansionLimit;
+    }
+
+    /**
+     * <p>Sets the limit of 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".</p>
+     *
+     * @param limit the maximum value for maxOccurs other
+     * than "unbounded"
+     */
+    public void setMaxOccurNodeLimit(int limit){
+        maxOccurLimit = limit;
+    }
+
+    /**
+     * <p>Returns the limit of 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".</p>
+     *
+     * @return the maximum value for maxOccurs other
+     * than "unbounded"
+     */
+    public int getMaxOccurNodeLimit(){
+        return maxOccurLimit;
+    }
+
+    public int getElementAttrLimit(){
+                return fElementAttributeLimit;
+        }
+
+        public void setElementAttrLimit(int limit){
+                fElementAttributeLimit = limit;
+        }
+
+        private void readSystemProperties(){
+
+                try {
+                        String value = System.getProperty(Constants.ENTITY_EXPANSION_LIMIT);
+                        if(value != null && !value.equals("")){
+                                entityExpansionLimit = Integer.parseInt(value);
+                                if (entityExpansionLimit < 0)
+                                        entityExpansionLimit = DEFAULT_ENTITY_EXPANSION_LIMIT;
+                        }
+                        else
+                                entityExpansionLimit = DEFAULT_ENTITY_EXPANSION_LIMIT;
+                }catch(Exception ex){}
+
+                try {
+                        String value = System.getProperty(Constants.MAX_OCCUR_LIMIT);
+                        if(value != null && !value.equals("")){
+                                maxOccurLimit = Integer.parseInt(value);
+                                if (maxOccurLimit < 0)
+                                        maxOccurLimit = DEFAULT_MAX_OCCUR_NODE_LIMIT;
+                        }
+                        else
+                                maxOccurLimit = DEFAULT_MAX_OCCUR_NODE_LIMIT;
+                }catch(Exception ex){}
+
+                try {
+                        String value = System.getProperty(Constants.ELEMENT_ATTRIBUTE_LIMIT);
+                        if(value != null && !value.equals("")){
+                                fElementAttributeLimit = Integer.parseInt(value);
+                                if ( fElementAttributeLimit < 0)
+                                        fElementAttributeLimit = DEFAULT_ELEMENT_ATTRIBUTE_LIMIT;
+                        }
+                        else
+                                fElementAttributeLimit = DEFAULT_ELEMENT_ATTRIBUTE_LIMIT;
+
+                }catch(Exception ex){}
+
+        }
+
+} // class SecurityManager
--- a/src/com/sun/org/apache/xerces/internal/utils/XMLLimitAnalyzer.java	Thu Aug 15 21:33:52 2013 +0100
+++ b/src/com/sun/org/apache/xerces/internal/utils/XMLLimitAnalyzer.java	Tue Aug 20 09:02:25 2013 -0700
@@ -203,6 +203,9 @@
     }
 
     public boolean isTracking(String name) {
+        if (entityStart == null) {
+            return false;
+        }
         return entityStart.equals(name);
     }
     /**
--- a/src/com/sun/org/apache/xerces/internal/utils/XMLSecurityManager.java	Thu Aug 15 21:33:52 2013 +0100
+++ b/src/com/sun/org/apache/xerces/internal/utils/XMLSecurityManager.java	Tue Aug 20 09:02:25 2013 -0700
@@ -26,6 +26,7 @@
 package com.sun.org.apache.xerces.internal.utils;
 
 import com.sun.org.apache.xerces.internal.impl.Constants;
+import com.sun.org.apache.xerces.internal.util.SecurityManager;
 
 /**
  * This class manages standard and implementation-specific limitations.
@@ -518,4 +519,37 @@
         }
         return false;
     }
+
+
+    /**
+     * Convert a value set through setProperty to XMLSecurityManager.
+     * If the value is an instance of XMLSecurityManager, use it to override the default;
+     * If the value is an old SecurityManager, convert to the new XMLSecurityManager.
+     *
+     * @param value user specified security manager
+     * @param securityManager an instance of XMLSecurityManager
+     * @return an instance of the new security manager XMLSecurityManager
+     */
+    static public XMLSecurityManager convert(Object value, XMLSecurityManager securityManager) {
+        if (value == null) {
+            if (securityManager == null) {
+                securityManager = new XMLSecurityManager(true);
+            }
+            return securityManager;
+        }
+        if (XMLSecurityManager.class.isAssignableFrom(value.getClass())) {
+            return (XMLSecurityManager)value;
+        } else {
+            if (securityManager == null) {
+                securityManager = new XMLSecurityManager(true);
+            }
+            if (SecurityManager.class.isAssignableFrom(value.getClass())) {
+                SecurityManager origSM = (SecurityManager)value;
+                securityManager.setLimit(Limit.MAX_OCCUR_NODE_LIMIT, State.APIPROPERTY, origSM.getMaxOccurNodeLimit());
+                securityManager.setLimit(Limit.ENTITY_EXPANSION_LIMIT, State.APIPROPERTY, origSM.getEntityExpansionLimit());
+                securityManager.setLimit(Limit.ELEMENT_ATTRIBUTE_LIMIT, State.APIPROPERTY, origSM.getElementAttrLimit());
+            }
+            return securityManager;
+        }
+    }
 }