8270504: Better Xpath expression handling

Reviewed-by: bae
Backport-of: b61a2ca626b1da5e555c50e548b643a2daa396c6
This commit is contained in:
Yuri Nesterenko 2022-03-03 16:47:07 +03:00 committed by Andrew Brygin
parent f7b710fcb3
commit 0bbcf1a956
22 changed files with 1055 additions and 321 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2022, 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
@ -26,6 +26,8 @@
package com.sun.java_cup.internal.runtime;
import com.sun.org.apache.xalan.internal.xsltc.compiler.sym;
import java.util.Arrays;
import java.util.Stack;
/** This class implements a skeleton table driven LR parser. In general,
@ -134,9 +136,19 @@ import java.util.Stack;
* @see com.sun.java_cup.internal.runtime.Symbol
* @see com.sun.java_cup.internal.runtime.virtual_parse_stack
* @author Frank Flannery
*
* @LastModified: Jan 2022
*/
public abstract class lr_parser {
public static final int ID_GROUP = 1;
public static final int ID_OPERATOR = 2;
public static final int ID_TOTAL_OPERATOR = 3;
private boolean isLiteral = false;
private int grpCount = 0;
private int opCount = 0;
private int totalOpCount = 0;
/*-----------------------------------------------------------*/
/*--- Constructor(s) ----------------------------------------*/
@ -355,8 +367,34 @@ public abstract class lr_parser {
* the "scan with" clause. Do not recycle objects; every call to
* scan() should return a fresh object.
*/
public Symbol scan() throws java.lang.Exception {
return getScanner().next_token();
public Symbol scan() throws Exception {
Symbol s = getScanner().next_token();
if (s.sym == sym.LPAREN) {
if (!isLiteral) {
grpCount++;
}
opCount++; // function
isLiteral = false;
} else if (contains(sym.OPERATORS, s.sym)) {
opCount++;
isLiteral = false;
}
if (s.sym == sym.Literal || s.sym == sym.QNAME) {
isLiteral = true;
}
return s;
}
private boolean contains(final int[] arr, final int key) {
for(int i: arr) {
if (i == key) {
return true;
}
}
return false;
}
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
@ -552,6 +590,9 @@ public abstract class lr_parser {
/* do user initialization */
user_init();
isLiteral = false;
grpCount = 0;
opCount = 0;
/* get the first token */
cur_token = scan();
@ -630,9 +671,29 @@ public abstract class lr_parser {
}
}
}
totalOpCount += opCount;
return lhs_sym;
}
/**
* Returns the count of operators in XPath expressions.
*
* @param id the ID of the count
* @return the count associated with the ID
*/
public int getCount(int id) {
switch (id) {
case ID_GROUP:
return grpCount;
case ID_OPERATOR:
return opCount;
case ID_TOTAL_OPERATOR:
return totalOpCount;
}
return 0;
}
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** Write a debugging message to System.err for the debugging version

View File

@ -176,6 +176,21 @@ public final class XalanConstants {
*/
public static final String JDK_EXTENSION_CLASSLOADER = "jdk.xml.transform.extensionClassLoader";
/**
* JDK XPath Expression group limit
*/
public static final String XPATH_GROUP_LIMIT = "jdk.xml.xpathExprGrpLimit";
/**
* JDK XPath Expression operators limit
*/
public static final String XPATH_OP_LIMIT = "jdk.xml.xpathExprOpLimit";
/**
* JDK XSL XPath limit or Total Number of Operators Permitted in an XSL Stylesheet
*/
public static final String XPATH_TOTALOP_LIMIT = "jdk.xml.xpathTotalOpLimit";
//legacy System Properties
public final static String ENTITY_EXPANSION_LIMIT = "entityExpansionLimit";
public static final String ELEMENT_ATTRIBUTE_LIMIT = "elementAttributeLimit" ;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@ -27,7 +27,7 @@ import com.sun.java_cup.internal.runtime.Symbol;
import com.sun.org.apache.xalan.internal.XalanConstants;
import com.sun.org.apache.xalan.internal.utils.ObjectFactory;
import com.sun.org.apache.xalan.internal.utils.SecuritySupport;
import com.sun.org.apache.xalan.internal.utils.XMLSecurityManager;
import jdk.xml.internal.XMLSecurityManager;
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodType;
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type;
@ -467,8 +467,10 @@ public class Parser implements Constants, ContentHandler {
XMLSecurityManager securityManager =
(XMLSecurityManager) _xsltc.getProperty(XalanConstants.SECURITY_MANAGER);
for (XMLSecurityManager.Limit limit : XMLSecurityManager.Limit.values()) {
lastProperty = limit.apiProperty();
reader.setProperty(lastProperty, securityManager.getLimitValueAsString(limit));
if (limit.isSupported(XMLSecurityManager.Processor.PARSER)) {
lastProperty = limit.apiProperty();
reader.setProperty(lastProperty, securityManager.getLimitValueAsString(limit));
}
}
if (securityManager.printEntityCountInfo()) {
lastProperty = XalanConstants.JDK_ENTITY_COUNT_INFO;
@ -1125,6 +1127,9 @@ public class Parser implements Constants, ContentHandler {
expression, parent));
}
catch (Exception e) {
if (ErrorMsg.XPATH_LIMIT.equals(e.getMessage())) {
throw new RuntimeException(ErrorMsg.XPATH_LIMIT);
}
if (_xsltc.debug()) e.printStackTrace();
reportError(ERROR, new ErrorMsg(ErrorMsg.XPATH_PARSER_ERR,
expression, parent));

View File

@ -9,6 +9,10 @@ package com.sun.org.apache.xalan.internal.xsltc.compiler;
import java.util.Stack;
import java.util.Vector;
import java.io.StringReader;
import com.sun.org.apache.xalan.internal.XalanConstants;
import jdk.xml.internal.XMLLimitAnalyzer;
import jdk.xml.internal.XMLSecurityManager;
import jdk.xml.internal.XMLSecurityManager.Limit;
import com.sun.java_cup.internal.runtime.*;
import com.sun.org.apache.xml.internal.dtm.DTM;
import com.sun.org.apache.xalan.internal.xsltc.DOM;
@ -19,6 +23,9 @@ import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
/** CUP v0.10j generated parser.
*/
public class XPathParser extends com.sun.java_cup.internal.runtime.lr_parser {
private int grpLimit = 0;
private int opLimit = 0;
private int totalOpLimit = 0;
/** Default constructor. */
public XPathParser() {super();}
@ -885,10 +892,19 @@ public class XPathParser extends com.sun.java_cup.internal.runtime.lr_parser {
*/
public SymbolTable _symbolTable;
private XMLSecurityManager _xmlSM;
private XMLLimitAnalyzer _limitAnalyzer = null;
public XPathParser(Parser parser) {
_parser = parser;
_xsltc = parser.getXSLTC();
_symbolTable = parser.getSymbolTable();
_xmlSM = (XMLSecurityManager)_xsltc.getProperty(XalanConstants.SECURITY_MANAGER);
_limitAnalyzer = new XMLLimitAnalyzer();
// no limits if _xmlSM is null
grpLimit = (_xmlSM != null) ? _xmlSM.getLimit(Limit.XPATH_GROUP_LIMIT) : 0;
opLimit = (_xmlSM != null) ? _xmlSM.getLimit(Limit.XPATH_OP_LIMIT) : 0;
totalOpLimit = (_xmlSM != null) ? _xmlSM.getLimit(Limit.XPATH_TOTALOP_LIMIT) : 0;
}
public int getLineNumber() {
@ -1043,7 +1059,32 @@ public class XPathParser extends com.sun.java_cup.internal.runtime.lr_parser {
try {
_expression = expression;
_lineNumber = lineNumber;
return super.parse();
Symbol s = super.parse();
int grpCount = getCount(ID_GROUP);
int opCount = getCount(ID_OPERATOR);
int totalOpCount = getCount(ID_TOTAL_OPERATOR);
String errCode = null;
Object[] params = null;
if (grpLimit > 0 && grpCount > grpLimit) {
errCode = ErrorMsg.XPATH_GROUP_LIMIT;
params = new Object[]{grpCount, grpLimit,
_xmlSM.getStateLiteral(Limit.XPATH_GROUP_LIMIT)};
} else if (opLimit > 0 && opCount > opLimit) {
errCode = ErrorMsg.XPATH_OPERATOR_LIMIT;
params = new Object[]{opCount, opLimit,
_xmlSM.getStateLiteral(Limit.XPATH_OP_LIMIT)};
} else if (totalOpLimit > 0 && totalOpCount > totalOpLimit) {
errCode = ErrorMsg.XPATH_TOTAL_OPERATOR_LIMIT;
params = new Object[]{totalOpCount, totalOpLimit,
_xmlSM.getStateLiteral(Limit.XPATH_TOTALOP_LIMIT)};
}
if (errCode != null) {
_parser.reportError(Constants.FATAL,
new ErrorMsg(errCode, lineNumber, params));
throw new RuntimeException(ErrorMsg.XPATH_LIMIT);
}
return s;
}
catch (IllegalCharException e) {
ErrorMsg err = new ErrorMsg(ErrorMsg.ILLEGAL_CHAR_ERR,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@ -26,7 +26,6 @@ package com.sun.org.apache.xalan.internal.xsltc.compiler;
import com.sun.org.apache.bcel.internal.classfile.JavaClass;
import com.sun.org.apache.xalan.internal.XalanConstants;
import com.sun.org.apache.xalan.internal.utils.SecuritySupport;
import com.sun.org.apache.xalan.internal.utils.XMLSecurityManager;
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util;
import com.sun.org.apache.xml.internal.dtm.DTM;
@ -49,6 +48,7 @@ import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import javax.xml.XMLConstants;
import jdk.xml.internal.JdkXmlFeatures;
import jdk.xml.internal.XMLSecurityManager;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
@ -483,7 +483,10 @@ public final class XSLTC {
}
}
catch (Exception e) {
/*if (_debug)*/ e.printStackTrace();
if (_debug) e.printStackTrace();
if (ErrorMsg.XPATH_LIMIT.equals(e.getMessage())) {
return !_parser.errorsFound();
}
_parser.reportError(Constants.FATAL, new ErrorMsg(ErrorMsg.JAXP_COMPILE_ERR, e));
}
catch (Error e) {

View File

@ -6,6 +6,8 @@
package com.sun.org.apache.xalan.internal.xsltc.compiler;
import java.util.Arrays;
/** CUP generated class containing symbol constants. */
public class sym {
/* terminals */
@ -63,4 +65,12 @@ public class sym {
public static final int ATTRIBUTE = 41;
public static final int GT = 19;
public static final int NODE = 31;
/*
AXES: count once at DCOLON,
these axes names are therefore not counted:
NAMESPACE, FOLLOWINGSIBLING, CHILD, DESCENDANTORSELF, DESCENDANT
, PRECEDINGSIBLING, SELF, ANCESTORORSELF, PRECEDING, ANCESTOROR, PARENT, FOLLOWING, ATTRIBUTE
*/
public static final int[] OPERATORS = {GE, SLASH, ATSIGN, LPAREN, DCOLON,
MINUS, STAR, LT, OR, DIV, PLUS, LE, VBAR, MOD, EQ, LBRACK, DOLLAR, NE, GT};
}

View File

@ -27,6 +27,7 @@ import java.util.ListResourceBundle;
/**
* @author Morten Jorgensen
* @LastModified: Jan 2022
*/
public class ErrorMessages extends ListResourceBundle {
@ -1014,12 +1015,22 @@ public class ErrorMessages extends ListResourceBundle {
"smaller templates."
},
{ErrorMsg.DESERIALIZE_TRANSLET_ERR, "When Java security is enabled, " +
"support for deserializing TemplatesImpl is disabled." +
"This can be overridden by setting the jdk.xml.enableTemplatesImplDeserialization" +
" system property to true."}
{ErrorMsg.DESERIALIZE_TRANSLET_ERR, "When Java security is enabled, "
+ "support for deserializing TemplatesImpl is disabled. This can be "
+ "overridden by setting the jdk.xml.enableTemplatesImplDeserialization"
+ " system property to true."},
};
{ErrorMsg.XPATH_GROUP_LIMIT,
"JAXP0801001: the compiler encountered an XPath expression containing "
+ "''{0}'' groups that exceeds the ''{1}'' limit set by ''{2}''."},
{ErrorMsg.XPATH_OPERATOR_LIMIT,
"JAXP0801002: the compiler encountered an XPath expression containing "
+ "''{0}'' operators that exceeds the ''{1}'' limit set by ''{2}''."},
{ErrorMsg.XPATH_TOTAL_OPERATOR_LIMIT,
"JAXP0801003: the compiler encountered XPath expressions with an accumulated "
+ "''{0}'' operators that exceeds the ''{1}'' limit set by ''{2}''."},
};
}
}

View File

@ -172,6 +172,11 @@ public final class ErrorMsg {
public static final String DESERIALIZE_TRANSLET_ERR = "DESERIALIZE_TEMPLATES_ERR";
public static final String XPATH_LIMIT = "XPATH_LIMIT";
public static final String XPATH_GROUP_LIMIT = "XPATH_GROUP_LIMIT";
public static final String XPATH_OPERATOR_LIMIT = "XPATH_OPERATOR_LIMIT";
public static final String XPATH_TOTAL_OPERATOR_LIMIT = "XPATH_TOTAL_OPERATOR_LIMIT";
// All error messages are localized and are stored in resource bundles.
// This array and the following 4 strings are read from that bundle.
private static ResourceBundle _bundle;
@ -208,7 +213,11 @@ public final class ErrorMsg {
public ErrorMsg(String code, int line, Object param) {
_code = code;
_line = line;
_params = new Object[] { param };
if (param instanceof Object[]) {
_params = (Object[])param;
} else {
_params = new Object[] { param };
}
}
public ErrorMsg(String code, Object param) {

View File

@ -27,7 +27,7 @@ import com.sun.org.apache.xalan.internal.XalanConstants;
import com.sun.org.apache.xalan.internal.utils.FeaturePropertyBase.State;
import com.sun.org.apache.xalan.internal.utils.ObjectFactory;
import com.sun.org.apache.xalan.internal.utils.SecuritySupport;
import com.sun.org.apache.xalan.internal.utils.XMLSecurityManager;
import jdk.xml.internal.XMLSecurityManager;
import com.sun.org.apache.xalan.internal.utils.XMLSecurityPropertyManager;
import com.sun.org.apache.xalan.internal.utils.XMLSecurityPropertyManager.Property;
import com.sun.org.apache.xalan.internal.xsltc.compiler.Constants;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2022, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@ -24,7 +24,6 @@
package com.sun.org.apache.xalan.internal.xsltc.trax;
import com.sun.org.apache.xalan.internal.XalanConstants;
import com.sun.org.apache.xalan.internal.utils.XMLSecurityManager;
import com.sun.org.apache.xalan.internal.utils.SecuritySupport;
import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.DOMCache;
@ -80,6 +79,7 @@ import javax.xml.transform.stax.StAXResult;
import javax.xml.transform.stax.StAXSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import jdk.xml.internal.XMLSecurityManager;
import jdk.xml.internal.JdkXmlUtils;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Copyright 2001-2004 The Apache Software Foundation.
@ -39,7 +39,7 @@ import javax.xml.transform.stax.StAXSource;
import javax.xml.transform.stream.StreamSource;
import jdk.xml.internal.JdkXmlFeatures;
import jdk.xml.internal.JdkXmlUtils;
import com.sun.org.apache.xalan.internal.utils.XMLSecurityManager;
import jdk.xml.internal.XMLSecurityManager;
import com.sun.org.apache.xalan.internal.xsltc.compiler.XSLTC;
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
@ -118,9 +118,11 @@ public final class Util {
(XMLSecurityManager)xsltc.getProperty(XalanConstants.SECURITY_MANAGER);
if (securityManager != null) {
for (XMLSecurityManager.Limit limit : XMLSecurityManager.Limit.values()) {
lastProperty = limit.apiProperty();
reader.setProperty(lastProperty,
securityManager.getLimitValueAsString(limit));
if (limit.isSupported(XMLSecurityManager.Processor.PARSER)) {
lastProperty = limit.apiProperty();
reader.setProperty(lastProperty,
securityManager.getLimitValueAsString(limit));
}
}
if (securityManager.printEntityCountInfo()) {
lastProperty = XalanConstants.JDK_ENTITY_COUNT_INFO;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2022, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Copyright 1999-2004 The Apache Software Foundation.
@ -23,11 +23,11 @@ package com.sun.org.apache.xml.internal.utils;
import com.sun.org.apache.xalan.internal.XalanConstants;
import com.sun.org.apache.xalan.internal.utils.SecuritySupport;
import com.sun.org.apache.xalan.internal.utils.XMLSecurityManager;
import java.util.HashMap;
import javax.xml.XMLConstants;
import jdk.xml.internal.JdkXmlUtils;
import jdk.xml.internal.XMLSecurityManager;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
@ -133,9 +133,11 @@ public class XMLReaderManager {
try {
if (_xmlSecurityManager != null) {
for (XMLSecurityManager.Limit limit : XMLSecurityManager.Limit.values()) {
lastProperty = limit.apiProperty();
reader.setProperty(lastProperty,
_xmlSecurityManager.getLimitValueAsString(limit));
if (limit.isSupported(XMLSecurityManager.Processor.PARSER)) {
lastProperty = limit.apiProperty();
reader.setProperty(lastProperty,
_xmlSecurityManager.getLimitValueAsString(limit));
}
}
if (_xmlSecurityManager.printEntityCountInfo()) {
lastProperty = XalanConstants.JDK_ENTITY_COUNT_INFO;

View File

@ -30,6 +30,7 @@ import javax.xml.transform.TransformerException;
import com.sun.org.apache.xalan.internal.res.XSLMessages;
import com.sun.org.apache.xml.internal.dtm.DTM;
import com.sun.org.apache.xml.internal.utils.DefaultErrorHandler;
import com.sun.org.apache.xml.internal.utils.PrefixResolver;
import com.sun.org.apache.xml.internal.utils.SAXSourceLocator;
import com.sun.org.apache.xpath.internal.compiler.Compiler;
@ -38,6 +39,7 @@ import com.sun.org.apache.xpath.internal.compiler.XPathParser;
import com.sun.org.apache.xpath.internal.functions.Function;
import com.sun.org.apache.xpath.internal.objects.XObject;
import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
import jdk.xml.internal.XMLSecurityManager;
/**
* The XPath class wraps an expression object and provides general services
@ -162,40 +164,11 @@ public class XPath implements Serializable, ExpressionOwner
*
* @throws javax.xml.transform.TransformerException if syntax or other error.
*/
public XPath(
String exprString, SourceLocator locator, PrefixResolver prefixResolver, int type,
ErrorListener errorListener)
throws javax.xml.transform.TransformerException
public XPath(String exprString, SourceLocator locator, PrefixResolver prefixResolver,
int type, ErrorListener errorListener)
throws TransformerException
{
initFunctionTable();
if(null == errorListener)
errorListener = new com.sun.org.apache.xml.internal.utils.DefaultErrorHandler();
m_patternString = exprString;
XPathParser parser = new XPathParser(errorListener, locator);
Compiler compiler = new Compiler(errorListener, locator, m_funcTable);
if (SELECT == type)
parser.initXPath(compiler, exprString, prefixResolver);
else if (MATCH == type)
parser.initMatchPattern(compiler, exprString, prefixResolver);
else
throw new RuntimeException(XSLMessages.createXPATHMessage(
XPATHErrorResources.ER_CANNOT_DEAL_XPATH_TYPE,
new Object[]{Integer.toString(type)}));
// System.out.println("----------------");
Expression expr = compiler.compileExpression(0);
// System.out.println("expr: "+expr);
this.setExpression(expr);
if((null != locator) && locator instanceof ExpressionNode)
{
expr.exprSetParent((ExpressionNode)locator);
}
this(exprString, locator, prefixResolver, type, errorListener, null);
}
/**
@ -209,22 +182,27 @@ public class XPath implements Serializable, ExpressionOwner
* namespace URIs.
* @param type one of {@link #SELECT} or {@link #MATCH}.
* @param errorListener The error listener, or null if default should be used.
* @param funcTable the function table
* @param xmlSecMgr the XML security manager
*
* @throws javax.xml.transform.TransformerException if syntax or other error.
*/
public XPath(
String exprString, SourceLocator locator,
PrefixResolver prefixResolver, int type,
ErrorListener errorListener, FunctionTable aTable)
throws javax.xml.transform.TransformerException
public XPath(String exprString, SourceLocator locator, PrefixResolver prefixResolver,
int type, ErrorListener errorListener, FunctionTable funcTable,
XMLSecurityManager xmlSecMgr)
throws TransformerException
{
m_funcTable = aTable;
if (funcTable == null) {
initFunctionTable();
} else {
m_funcTable = funcTable;
}
if(null == errorListener)
errorListener = new com.sun.org.apache.xml.internal.utils.DefaultErrorHandler();
errorListener = new DefaultErrorHandler();
m_patternString = exprString;
XPathParser parser = new XPathParser(errorListener, locator);
XPathParser parser = new XPathParser(errorListener, locator, xmlSecMgr);
Compiler compiler = new Compiler(errorListener, locator, m_funcTable);
if (SELECT == type)
@ -263,13 +241,32 @@ public class XPath implements Serializable, ExpressionOwner
*
* @throws javax.xml.transform.TransformerException if syntax or other error.
*/
public XPath(
String exprString, SourceLocator locator, PrefixResolver prefixResolver, int type)
throws javax.xml.transform.TransformerException
public XPath(String exprString, SourceLocator locator, PrefixResolver prefixResolver,
int type)
throws TransformerException
{
this(exprString, locator, prefixResolver, type, null);
}
/**
* Constructs an XPath object.
*
* @param exprString The XPath expression.
* @param locator The location of the expression, may be null.
* @param prefixResolver A prefix resolver to use to resolve prefixes to
* namespace URIs.
* @param type one of {@link #SELECT} or {@link #MATCH}.
* @param errorListener The error listener, or null if default should be used.
* @param funcTable the function table
* @throws TransformerException
*/
public XPath(String exprString, SourceLocator locator, PrefixResolver prefixResolver,
int type, ErrorListener errorListener, FunctionTable funcTable)
throws TransformerException
{
this(exprString, locator, prefixResolver, type, errorListener, funcTable, null);
}
/**
* Construct an XPath object.
*

View File

@ -24,8 +24,13 @@ package com.sun.org.apache.xpath.internal.compiler;
import java.util.Vector;
import com.sun.org.apache.xalan.internal.res.XSLMessages;
import com.sun.org.apache.xml.internal.utils.PrefixResolver;
import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
import java.util.Objects;
import javax.xml.transform.TransformerException;
import jdk.xml.internal.XMLSecurityManager;
import jdk.xml.internal.XMLSecurityManager.Limit;
/**
* This class is in charge of lexical processing of the XPath
@ -71,6 +76,24 @@ class Lexer
*/
private int m_patternMapSize;
// XML security manager
XMLSecurityManager m_xmlSecMgr;
// operator limit
private int m_opCountLimit;
// group limit
private int m_grpCountLimit;
// count of operators
private int m_opCount;
// count of groups
private int m_grpCount;
// indicate whether the current token is a literal
private boolean isLiteral = false;
/**
* Create a Lexer object.
*
@ -78,14 +101,22 @@ class Lexer
* @param resolver The prefix resolver for mapping qualified name prefixes
* to namespace URIs.
* @param xpathProcessor The parser that is processing strings to opcodes.
* @param xmlSecMgr the XML security manager
*/
Lexer(Compiler compiler, PrefixResolver resolver,
XPathParser xpathProcessor)
XPathParser xpathProcessor, XMLSecurityManager xmlSecMgr)
{
m_compiler = compiler;
m_namespaceContext = resolver;
m_processor = xpathProcessor;
m_xmlSecMgr = xmlSecMgr;
/**
* No limits if XML Security Manager is null. Applications using XPath through
* the public API always have a XMLSecurityManager. Applications invoking
* the internal XPath API shall consider using the public API instead.
*/
m_opCountLimit = (xmlSecMgr != null) ? xmlSecMgr.getLimit(Limit.XPATH_OP_LIMIT) : 0;
m_grpCountLimit = (xmlSecMgr != null) ? xmlSecMgr.getLimit(Limit.XPATH_GROUP_LIMIT) : 0;
}
/**
@ -136,7 +167,7 @@ class Lexer
switch (c)
{
case '\"' :
case Token.DQ :
{
if (startSubstring != -1)
{
@ -171,7 +202,7 @@ class Lexer
}
}
break;
case '\'' :
case Token.SQ :
if (startSubstring != -1)
{
isNum = false;
@ -190,9 +221,9 @@ class Lexer
startSubstring = i;
for (i++; (i < nChars) && ((c = pat.charAt(i)) != '\''); i++);
for (i++; (i < nChars) && ((c = pat.charAt(i)) != Token.SQ); i++);
if (c == '\'' && i < nChars)
if (c == Token.SQ && i < nChars)
{
addToTokenQueue(pat.substring(startSubstring, i + 1));
@ -220,18 +251,24 @@ class Lexer
}
else
{
addToTokenQueue(pat.substring(startSubstring, i));
// check operator symbol
String s = pat.substring(startSubstring, i);
if (Token.contains(s)) {
m_opCount++;
isLiteral = false;
}
addToTokenQueue(s);
}
startSubstring = -1;
}
break;
case '@' :
case Token.AT :
isAttrName = true;
// fall-through on purpose
case '-' :
if ('-' == c)
case Token.MINUS :
if (Token.MINUS == c)
{
if (!(isNum || (startSubstring == -1)))
{
@ -242,22 +279,22 @@ class Lexer
}
// fall-through on purpose
case '(' :
case '[' :
case ')' :
case ']' :
case '|' :
case '/' :
case '*' :
case '+' :
case '=' :
case ',' :
case Token.LPAREN :
case Token.LBRACK :
case Token.RPAREN :
case Token.RBRACK :
case Token.VBAR :
case Token.SLASH :
case Token.STAR :
case Token.PLUS :
case Token.EQ :
case Token.COMMA :
case '\\' : // Unused at the moment
case '^' : // Unused at the moment
case '!' : // Unused at the moment
case '$' :
case '<' :
case '>' :
case Token.EM : // Unused at the moment
case Token.DOLLAR :
case Token.LT :
case Token.GT :
if (startSubstring != -1)
{
isNum = false;
@ -275,11 +312,11 @@ class Lexer
startSubstring = -1;
}
else if (('/' == c) && isStartOfPat)
else if ((Token.SLASH == c) && isStartOfPat)
{
isStartOfPat = mapPatternElemPos(nesting, isStartOfPat, isAttrName);
}
else if ('*' == c)
else if (Token.STAR == c)
{
isStartOfPat = mapPatternElemPos(nesting, isStartOfPat, isAttrName);
isAttrName = false;
@ -287,7 +324,7 @@ class Lexer
if (0 == nesting)
{
if ('|' == c)
if (Token.VBAR == c)
{
if (null != targetStrings)
{
@ -298,18 +335,32 @@ class Lexer
}
}
if ((')' == c) || (']' == c))
if ((Token.RPAREN == c) || (Token.RBRACK == c))
{
nesting--;
}
else if (('(' == c) || ('[' == c))
else if ((Token.LPAREN == c) || (Token.LBRACK == c))
{
nesting++;
if (!isLiteral && (Token.LPAREN == c)) {
m_grpCount++;
m_opCount++;
isLiteral = false;
}
}
if ((Token.GT == c || Token.LT == c || Token.EQ == c) && Token.EQ != peekNext(pat, i)) {
m_opCount++;
isLiteral = false;
}
else if ((Token.LPAREN != c) && (Token.RPAREN != c) && (Token.RBRACK != c)) {
m_opCount++;
isLiteral = false;
}
addToTokenQueue(pat.substring(i, i + 1));
break;
case ':' :
case Token.COLON :
if (i>0)
{
if (posOfNSSep == (i - 1))
@ -324,7 +375,7 @@ class Lexer
isAttrName = false;
startSubstring = -1;
posOfNSSep = -1;
m_opCount++;
addToTokenQueue(pat.substring(i - 1, i + 1));
break;
@ -337,6 +388,7 @@ class Lexer
// fall through on purpose
default :
isLiteral = true;
if (-1 == startSubstring)
{
startSubstring = i;
@ -347,6 +399,20 @@ class Lexer
isNum = Character.isDigit(c);
}
}
if (m_grpCountLimit > 0 && m_grpCount > m_grpCountLimit) {
throw new TransformerException(XSLMessages.createXPATHMessage(
XPATHErrorResources.ER_XPATH_GROUP_LIMIT,
new Object[]{Integer.toString(m_grpCount),
Integer.toString(m_grpCountLimit),
m_xmlSecMgr.getStateLiteral(Limit.XPATH_GROUP_LIMIT)}));
}
if (m_opCountLimit > 0 && m_opCount > m_opCountLimit) {
throw new TransformerException(XSLMessages.createXPATHMessage(
XPATHErrorResources.ER_XPATH_OPERATOR_LIMIT,
new Object[]{Integer.toString(m_opCount),
Integer.toString(m_opCountLimit),
m_xmlSecMgr.getStateLiteral(Limit.XPATH_OP_LIMIT)}));
}
}
if (startSubstring != -1)
@ -377,6 +443,19 @@ class Lexer
m_processor.m_queueMark = 0;
}
/**
* Peeks at the next character without advancing the index.
* @param s the input string
* @param index the current index
* @return the next char
*/
private char peekNext(String s, int index) {
if (index >= 0 && s.length() > index) {
return s.charAt(index + 1);
}
return 0;
}
/**
* Record the current position on the token queue as long as
* this is a top-level element. Must be called before the
@ -499,7 +578,7 @@ class Lexer
resetTokenMark(tokPos + 1);
if (m_processor.lookahead('(', 1))
if (m_processor.lookahead(Token.LPAREN, 1))
{
int tok = getKeywordToken(m_processor.m_token);
@ -529,14 +608,14 @@ class Lexer
}
else
{
if (m_processor.tokenIs('@'))
if (m_processor.tokenIs(Token.AT))
{
tokPos++;
resetTokenMark(tokPos + 1);
}
if (m_processor.lookahead(':', 1))
if (m_processor.lookahead(Token.COLON, 1))
{
tokPos += 2;
}
@ -565,13 +644,13 @@ class Lexer
* @param posOfNSSep The position of the namespace seperator (':').
* @param posOfScan The end of the name index.
*
* @throws javax.xml.transform.TransformerException
* @throws TransformerException
*
* @return -1 always.
*/
private int mapNSTokens(String pat, int startSubstring, int posOfNSSep,
int posOfScan)
throws javax.xml.transform.TransformerException
throws TransformerException
{
String prefix = "";

View File

@ -0,0 +1,81 @@
/*
* Copyright (c) 2022, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 com.sun.org.apache.xpath.internal.compiler;
import java.util.Arrays;
/**
* XPath tokens
*/
public final class Token {
static final char EM = '!';
static final char EQ = '=';
static final char LT = '<';
static final char GT = '>';
static final char PLUS = '+';
static final char MINUS = '-';
static final char STAR = '*';
static final char VBAR = '|';
static final char SLASH = '/';
static final char LBRACK = '[';
static final char RBRACK = ']';
static final char LPAREN = '(';
static final char RPAREN = ')';
static final char COMMA = ',';
static final char DOT = '.';
static final char AT = '@';
static final char US = '_';
static final char COLON = ':';
static final char SQ = '\'';
static final char DQ = '"';
static final char DOLLAR = '$';
static final String OR = "or";
static final String AND = "and";
static final String DIV = "div";
static final String MOD = "mod";
static final String QUO = "quo";
static final String DDOT = "..";
static final String DCOLON = "::";
static final String ATTR = "attribute";
static final String CHILD = "child";
static final String[] OPERATORS = {OR, AND, DIV, MOD, QUO,
DDOT, DCOLON, ATTR, CHILD};
public static boolean contains(String str) {
for(String op: OPERATORS) {
if (str.equals(op)) {
return true;
}
}
return false;
}
private Token() {
//to prevent instantiation
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Copyright 1999-2004 The Apache Software Foundation.
@ -21,9 +21,6 @@
*/
package com.sun.org.apache.xpath.internal.compiler;
import javax.xml.transform.ErrorListener;
import javax.xml.transform.TransformerException;
import com.sun.org.apache.xalan.internal.res.XSLMessages;
import com.sun.org.apache.xml.internal.utils.PrefixResolver;
import com.sun.org.apache.xpath.internal.XPathProcessorException;
@ -31,12 +28,17 @@ import com.sun.org.apache.xpath.internal.domapi.XPathStylesheetDOM3Exception;
import com.sun.org.apache.xpath.internal.objects.XNumber;
import com.sun.org.apache.xpath.internal.objects.XString;
import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
import javax.xml.transform.ErrorListener;
import javax.xml.transform.SourceLocator;
import javax.xml.transform.TransformerException;
import jdk.xml.internal.XMLSecurityManager;
import jdk.xml.internal.XMLSecurityManager.Limit;
/**
* Tokenizes and parses XPath expressions. This should really be named
* XPathParserImpl, and may be renamed in the future.
* @xsl.usage general
* @LastModified: May 2019
* @LastModified: Jan 2022
*/
public class XPathParser
{
@ -77,13 +79,18 @@ public class XPathParser
// counts open predicates
private int countPredicate;
// XML security manager
XMLSecurityManager m_xmlSecMgr;
/**
* The parser constructor.
*/
public XPathParser(ErrorListener errorListener, javax.xml.transform.SourceLocator sourceLocator)
public XPathParser(ErrorListener errorListener, SourceLocator sourceLocator,
XMLSecurityManager xmlSecMgr)
{
m_errorListener = errorListener;
m_sourceLocator = sourceLocator;
m_xmlSecMgr = xmlSecMgr;
}
/**
@ -101,18 +108,18 @@ public class XPathParser
* @param namespaceContext An object that is able to resolve prefixes in
* the XPath to namespaces.
*
* @throws javax.xml.transform.TransformerException
* @throws TransformerException
*/
public void initXPath(
Compiler compiler, String expression, PrefixResolver namespaceContext)
throws javax.xml.transform.TransformerException
throws TransformerException
{
m_ops = compiler;
m_namespaceContext = namespaceContext;
m_functionTable = compiler.getFunctionTable();
Lexer lexer = new Lexer(compiler, namespaceContext, this);
Lexer lexer = new Lexer(compiler, namespaceContext, this, m_xmlSecMgr);
lexer.tokenize(expression);
@ -180,18 +187,18 @@ public class XPathParser
* @param namespaceContext An object that is able to resolve prefixes in
* the XPath to namespaces.
*
* @throws javax.xml.transform.TransformerException
* @throws TransformerException
*/
public void initMatchPattern(
Compiler compiler, String expression, PrefixResolver namespaceContext)
throws javax.xml.transform.TransformerException
throws TransformerException
{
m_ops = compiler;
m_namespaceContext = namespaceContext;
m_functionTable = compiler.getFunctionTable();
Lexer lexer = new Lexer(compiler, namespaceContext, this);
Lexer lexer = new Lexer(compiler, namespaceContext, this, m_xmlSecMgr);
lexer.tokenize(expression);
@ -384,9 +391,9 @@ public class XPathParser
if ((m_queueMark - n) > 0)
{
String lookbehind = (String) m_ops.m_tokenQueue.elementAt(m_queueMark - (n - 1));
char c0 = (lookbehind == null) ? '|' : lookbehind.charAt(0);
char c0 = (lookbehind == null) ? Token.VBAR : lookbehind.charAt(0);
hasToken = (c0 == '|') ? false : true;
hasToken = (c0 == Token.VBAR) ? false : true;
}
else
{
@ -498,10 +505,10 @@ public class XPathParser
*
* @param expected The string to be expected.
*
* @throws javax.xml.transform.TransformerException
* @throws TransformerException
*/
private final void consumeExpected(String expected)
throws javax.xml.transform.TransformerException
throws TransformerException
{
if (tokenIs(expected))
@ -526,10 +533,10 @@ public class XPathParser
*
* @param expected the character to be expected.
*
* @throws javax.xml.transform.TransformerException
* @throws TransformerException
*/
private final void consumeExpected(char expected)
throws javax.xml.transform.TransformerException
throws TransformerException
{
if (tokenIs(expected))
@ -796,9 +803,9 @@ public class XPathParser
* Expr ::= OrExpr
*
*
* @throws javax.xml.transform.TransformerException
* @throws TransformerException
*/
protected void Expr() throws javax.xml.transform.TransformerException
protected void Expr() throws TransformerException
{
OrExpr();
}
@ -810,16 +817,16 @@ public class XPathParser
* | OrExpr 'or' AndExpr
*
*
* @throws javax.xml.transform.TransformerException
* @throws TransformerException
*/
protected void OrExpr() throws javax.xml.transform.TransformerException
protected void OrExpr() throws TransformerException
{
int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
AndExpr();
if ((null != m_token) && tokenIs("or"))
if ((null != m_token) && tokenIs(Token.OR))
{
nextToken();
insertOp(opPos, 2, OpCodes.OP_OR);
@ -837,16 +844,16 @@ public class XPathParser
* | AndExpr 'and' EqualityExpr
*
*
* @throws javax.xml.transform.TransformerException
* @throws TransformerException
*/
protected void AndExpr() throws javax.xml.transform.TransformerException
protected void AndExpr() throws TransformerException
{
int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
EqualityExpr(-1);
if ((null != m_token) && tokenIs("and"))
if ((null != m_token) && tokenIs(Token.AND))
{
nextToken();
insertOp(opPos, 2, OpCodes.OP_AND);
@ -870,9 +877,9 @@ public class XPathParser
*
* @return the position at the end of the equality expression.
*
* @throws javax.xml.transform.TransformerException
* @throws TransformerException
*/
protected int EqualityExpr(int addPos) throws javax.xml.transform.TransformerException
protected int EqualityExpr(int addPos) throws TransformerException
{
int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
@ -884,7 +891,7 @@ public class XPathParser
if (null != m_token)
{
if (tokenIs('!') && lookahead('=', 1))
if (tokenIs(Token.EM) && lookahead(Token.EQ, 1))
{
nextToken();
nextToken();
@ -897,7 +904,7 @@ public class XPathParser
m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen);
addPos += 2;
}
else if (tokenIs('='))
else if (tokenIs(Token.EQ))
{
nextToken();
insertOp(addPos, 2, OpCodes.OP_EQUALS);
@ -930,9 +937,9 @@ public class XPathParser
*
* @return the position at the end of the relational expression.
*
* @throws javax.xml.transform.TransformerException
* @throws TransformerException
*/
protected int RelationalExpr(int addPos) throws javax.xml.transform.TransformerException
protected int RelationalExpr(int addPos) throws TransformerException
{
int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
@ -944,11 +951,11 @@ public class XPathParser
if (null != m_token)
{
if (tokenIs('<'))
if (tokenIs(Token.LT))
{
nextToken();
if (tokenIs('='))
if (tokenIs(Token.EQ))
{
nextToken();
insertOp(addPos, 2, OpCodes.OP_LTE);
@ -965,11 +972,11 @@ public class XPathParser
m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen);
addPos += 2;
}
else if (tokenIs('>'))
else if (tokenIs(Token.GT))
{
nextToken();
if (tokenIs('='))
if (tokenIs(Token.EQ))
{
nextToken();
insertOp(addPos, 2, OpCodes.OP_GTE);
@ -1005,9 +1012,9 @@ public class XPathParser
*
* @return the position at the end of the equality expression.
*
* @throws javax.xml.transform.TransformerException
* @throws TransformerException
*/
protected int AdditiveExpr(int addPos) throws javax.xml.transform.TransformerException
protected int AdditiveExpr(int addPos) throws TransformerException
{
int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
@ -1019,7 +1026,7 @@ public class XPathParser
if (null != m_token)
{
if (tokenIs('+'))
if (tokenIs(Token.PLUS))
{
nextToken();
insertOp(addPos, 2, OpCodes.OP_PLUS);
@ -1031,7 +1038,7 @@ public class XPathParser
m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen);
addPos += 2;
}
else if (tokenIs('-'))
else if (tokenIs(Token.MINUS))
{
nextToken();
insertOp(addPos, 2, OpCodes.OP_MINUS);
@ -1063,9 +1070,9 @@ public class XPathParser
*
* @return the position at the end of the equality expression.
*
* @throws javax.xml.transform.TransformerException
* @throws TransformerException
*/
protected int MultiplicativeExpr(int addPos) throws javax.xml.transform.TransformerException
protected int MultiplicativeExpr(int addPos) throws TransformerException
{
int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
@ -1077,7 +1084,7 @@ public class XPathParser
if (null != m_token)
{
if (tokenIs('*'))
if (tokenIs(Token.STAR))
{
nextToken();
insertOp(addPos, 2, OpCodes.OP_MULT);
@ -1089,7 +1096,7 @@ public class XPathParser
m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen);
addPos += 2;
}
else if (tokenIs("div"))
else if (tokenIs(Token.DIV))
{
nextToken();
insertOp(addPos, 2, OpCodes.OP_DIV);
@ -1101,7 +1108,7 @@ public class XPathParser
m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen);
addPos += 2;
}
else if (tokenIs("mod"))
else if (tokenIs(Token.MOD))
{
nextToken();
insertOp(addPos, 2, OpCodes.OP_MOD);
@ -1113,7 +1120,7 @@ public class XPathParser
m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen);
addPos += 2;
}
else if (tokenIs("quo"))
else if (tokenIs(Token.QUO))
{
nextToken();
insertOp(addPos, 2, OpCodes.OP_QUO);
@ -1136,15 +1143,15 @@ public class XPathParser
* | '-' UnaryExpr
*
*
* @throws javax.xml.transform.TransformerException
* @throws TransformerException
*/
protected void UnaryExpr() throws javax.xml.transform.TransformerException
protected void UnaryExpr() throws TransformerException
{
int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
boolean isNeg = false;
if (m_tokenChar == '-')
if (m_tokenChar == Token.MINUS)
{
nextToken();
appendOp(2, OpCodes.OP_NEG);
@ -1164,9 +1171,9 @@ public class XPathParser
* StringExpr ::= Expr
*
*
* @throws javax.xml.transform.TransformerException
* @throws TransformerException
*/
protected void StringExpr() throws javax.xml.transform.TransformerException
protected void StringExpr() throws TransformerException
{
int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
@ -1184,9 +1191,9 @@ public class XPathParser
* StringExpr ::= Expr
*
*
* @throws javax.xml.transform.TransformerException
* @throws TransformerException
*/
protected void BooleanExpr() throws javax.xml.transform.TransformerException
protected void BooleanExpr() throws TransformerException
{
int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
@ -1210,9 +1217,9 @@ public class XPathParser
* NumberExpr ::= Expr
*
*
* @throws javax.xml.transform.TransformerException
* @throws TransformerException
*/
protected void NumberExpr() throws javax.xml.transform.TransformerException
protected void NumberExpr() throws TransformerException
{
int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
@ -1235,9 +1242,9 @@ public class XPathParser
* | UnionExpr '|' PathExpr
*
*
* @throws javax.xml.transform.TransformerException
* @throws TransformerException
*/
protected void UnionExpr() throws javax.xml.transform.TransformerException
protected void UnionExpr() throws TransformerException
{
int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
@ -1248,7 +1255,7 @@ public class XPathParser
{
PathExpr();
if (tokenIs('|'))
if (tokenIs(Token.VBAR))
{
if (false == foundUnion)
{
@ -1281,9 +1288,9 @@ public class XPathParser
* @throws XSLProcessorException thrown if the active ProblemListener and XPathContext decide
* the error condition is severe enough to halt processing.
*
* @throws javax.xml.transform.TransformerException
* @throws TransformerException
*/
protected void PathExpr() throws javax.xml.transform.TransformerException
protected void PathExpr() throws TransformerException
{
int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
@ -1296,7 +1303,7 @@ public class XPathParser
// have been inserted.
boolean locationPathStarted = (filterExprMatch==FILTER_MATCH_PREDICATES);
if (tokenIs('/'))
if (tokenIs(Token.SLASH))
{
nextToken();
@ -1346,9 +1353,9 @@ public class XPathParser
* FilterExpr that was just a PrimaryExpr; or
* FILTER_MATCH_FAILED, if this method did not match a FilterExpr
*
* @throws javax.xml.transform.TransformerException
* @throws TransformerException
*/
protected int FilterExpr() throws javax.xml.transform.TransformerException
protected int FilterExpr() throws TransformerException
{
int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
@ -1357,13 +1364,13 @@ public class XPathParser
if (PrimaryExpr())
{
if (tokenIs('['))
if (tokenIs(Token.LBRACK))
{
// int locationPathOpPos = opPos;
insertOp(opPos, 2, OpCodes.OP_LOCATIONPATH);
while (tokenIs('['))
while (tokenIs(Token.LBRACK))
{
Predicate();
}
@ -1401,16 +1408,16 @@ public class XPathParser
*
* @return true if this method successfully matched a PrimaryExpr
*
* @throws javax.xml.transform.TransformerException
* @throws TransformerException
*
*/
protected boolean PrimaryExpr() throws javax.xml.transform.TransformerException
protected boolean PrimaryExpr() throws TransformerException
{
boolean matchFound;
int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
if ((m_tokenChar == '\'') || (m_tokenChar == '"'))
if ((m_tokenChar == Token.SQ) || (m_tokenChar == Token.DQ))
{
appendOp(2, OpCodes.OP_LITERAL);
Literal();
@ -1420,7 +1427,7 @@ public class XPathParser
matchFound = true;
}
else if (m_tokenChar == '$')
else if (m_tokenChar == Token.DOLLAR)
{
nextToken(); // consume '$'
appendOp(2, OpCodes.OP_VARIABLE);
@ -1431,12 +1438,12 @@ public class XPathParser
matchFound = true;
}
else if (m_tokenChar == '(')
else if (m_tokenChar == Token.LPAREN)
{
nextToken();
appendOp(2, OpCodes.OP_GROUP);
Expr();
consumeExpected(')');
consumeExpected(Token.RPAREN);
m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH,
m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
@ -1454,7 +1461,7 @@ public class XPathParser
matchFound = true;
}
else if (lookahead('(', 1) || (lookahead(':', 1) && lookahead('(', 3)))
else if (lookahead(Token.LPAREN, 1) || (lookahead(Token.COLON, 1) && lookahead(Token.LPAREN, 3)))
{
matchFound = FunctionCall();
}
@ -1471,9 +1478,9 @@ public class XPathParser
* Argument ::= Expr
*
*
* @throws javax.xml.transform.TransformerException
* @throws TransformerException
*/
protected void Argument() throws javax.xml.transform.TransformerException
protected void Argument() throws TransformerException
{
int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
@ -1491,14 +1498,14 @@ public class XPathParser
*
* @return true if, and only if, a FunctionCall was matched
*
* @throws javax.xml.transform.TransformerException
* @throws TransformerException
*/
protected boolean FunctionCall() throws javax.xml.transform.TransformerException
protected boolean FunctionCall() throws TransformerException
{
int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
if (lookahead(':', 1))
if (lookahead(Token.COLON, 1))
{
appendOp(4, OpCodes.OP_EXTFUNCTION);
@ -1538,22 +1545,23 @@ public class XPathParser
nextToken();
}
consumeExpected('(');
consumeExpected(Token.LPAREN);
while (!tokenIs(')') && m_token != null)
while (!tokenIs(Token.RPAREN) && m_token != null)
{
if (tokenIs(','))
if (tokenIs(Token.COMMA))
{
error(XPATHErrorResources.ER_FOUND_COMMA_BUT_NO_PRECEDING_ARG, null); //"Found ',' but no preceding argument!");
//"Found ',' but no preceding argument!");
error(XPATHErrorResources.ER_FOUND_COMMA_BUT_NO_PRECEDING_ARG, null);
}
Argument();
if (!tokenIs(')'))
if (!tokenIs(Token.RPAREN))
{
consumeExpected(',');
consumeExpected(Token.COMMA);
if (tokenIs(')'))
if (tokenIs(Token.RPAREN))
{
error(XPATHErrorResources.ER_FOUND_COMMA_BUT_NO_FOLLOWING_ARG,
null); //"Found ',' but no following argument!");
@ -1561,7 +1569,7 @@ public class XPathParser
}
}
consumeExpected(')');
consumeExpected(Token.RPAREN);
// Terminate for safety.
m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), OpCodes.ENDOP);
@ -1580,9 +1588,9 @@ public class XPathParser
* | AbsoluteLocationPath
*
*
* @throws javax.xml.transform.TransformerException
* @throws TransformerException
*/
protected void LocationPath() throws javax.xml.transform.TransformerException
protected void LocationPath() throws TransformerException
{
int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
@ -1590,7 +1598,7 @@ public class XPathParser
// int locationPathOpPos = opPos;
appendOp(2, OpCodes.OP_LOCATIONPATH);
boolean seenSlash = tokenIs('/');
boolean seenSlash = tokenIs(Token.SLASH);
if (seenSlash)
{
@ -1631,17 +1639,17 @@ public class XPathParser
*
* @returns true if, and only if, a RelativeLocationPath was matched
*
* @throws javax.xml.transform.TransformerException
* @throws TransformerException
*/
protected boolean RelativeLocationPath()
throws javax.xml.transform.TransformerException
throws TransformerException
{
if (!Step())
{
return false;
}
while (tokenIs('/'))
while (tokenIs(Token.SLASH))
{
nextToken();
@ -1663,13 +1671,13 @@ public class XPathParser
*
* @returns false if step was empty (or only a '/'); true, otherwise
*
* @throws javax.xml.transform.TransformerException
* @throws TransformerException
*/
protected boolean Step() throws javax.xml.transform.TransformerException
protected boolean Step() throws TransformerException
{
int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
boolean doubleSlash = tokenIs('/');
boolean doubleSlash = tokenIs(Token.SLASH);
// At most a single '/' before each Step is consumed by caller; if the
// first thing is a '/', that means we had '//' and the Step must not
@ -1701,11 +1709,11 @@ public class XPathParser
opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
}
if (tokenIs("."))
if (tokenIs(Token.DOT))
{
nextToken();
if (tokenIs('['))
if (tokenIs(Token.LBRACK))
{
error(XPATHErrorResources.ER_PREDICATE_ILLEGAL_SYNTAX, null); //"'..[predicate]' or '.[predicate]' is illegal syntax. Use 'self::node()[predicate]' instead.");
}
@ -1716,7 +1724,7 @@ public class XPathParser
m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH) - 2,4);
m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH) - 1, OpCodes.NODETYPE_NODE);
}
else if (tokenIs(".."))
else if (tokenIs(Token.DDOT))
{
nextToken();
appendOp(4, OpCodes.FROM_PARENT);
@ -1729,12 +1737,12 @@ public class XPathParser
// There is probably a better way to test for this
// transition... but it gets real hairy if you try
// to do it in basis().
else if (tokenIs('*') || tokenIs('@') || tokenIs('_')
else if (tokenIs(Token.STAR) || tokenIs(Token.AT) || tokenIs(Token.US)
|| (m_token!= null && Character.isLetter(m_token.charAt(0))))
{
Basis();
while (tokenIs('['))
while (tokenIs(Token.LBRACK))
{
Predicate();
}
@ -1763,23 +1771,23 @@ public class XPathParser
* Basis ::= AxisName '::' NodeTest
* | AbbreviatedBasis
*
* @throws javax.xml.transform.TransformerException
* @throws TransformerException
*/
protected void Basis() throws javax.xml.transform.TransformerException
protected void Basis() throws TransformerException
{
int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
int axesType;
// The next blocks guarantee that a FROM_XXX will be added.
if (lookahead("::", 1))
if (lookahead(Token.DCOLON, 1))
{
axesType = AxisName();
nextToken();
nextToken();
}
else if (tokenIs('@'))
else if (tokenIs(Token.AT))
{
axesType = OpCodes.FROM_ATTRIBUTES;
@ -1810,9 +1818,9 @@ public class XPathParser
*
* @return FROM_XXX axes type, found in {@link com.sun.org.apache.xpath.internal.compiler.Keywords}.
*
* @throws javax.xml.transform.TransformerException
* @throws TransformerException
*/
protected int AxisName() throws javax.xml.transform.TransformerException
protected int AxisName() throws TransformerException
{
Object val = Keywords.getAxisName(m_token);
@ -1838,12 +1846,12 @@ public class XPathParser
*
* @param axesType FROM_XXX axes type, found in {@link com.sun.org.apache.xpath.internal.compiler.Keywords}.
*
* @throws javax.xml.transform.TransformerException
* @throws TransformerException
*/
protected void NodeTest(int axesType) throws javax.xml.transform.TransformerException
protected void NodeTest(int axesType) throws TransformerException
{
if (lookahead('(', 1))
if (lookahead(Token.LPAREN, 1))
{
Object nodeTestOp = Keywords.getNodeType(m_token);
@ -1861,17 +1869,17 @@ public class XPathParser
m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), nt);
m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1);
consumeExpected('(');
consumeExpected(Token.LPAREN);
if (OpCodes.NODETYPE_PI == nt)
{
if (!tokenIs(')'))
if (!tokenIs(Token.RPAREN))
{
Literal();
}
}
consumeExpected(')');
consumeExpected(Token.RPAREN);
}
}
else
@ -1881,9 +1889,9 @@ public class XPathParser
m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), OpCodes.NODENAME);
m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1);
if (lookahead(':', 1))
if (lookahead(Token.COLON, 1))
{
if (tokenIs('*'))
if (tokenIs(Token.STAR))
{
m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), OpCodes.ELEMWILDCARD);
}
@ -1893,7 +1901,7 @@ public class XPathParser
// Minimalist check for an NCName - just check first character
// to distinguish from other possible tokens
if (!Character.isLetter(m_tokenChar) && !tokenIs('_'))
if (!Character.isLetter(m_tokenChar) && !tokenIs(Token.US))
{
// "Node test that matches either NCName:* or QName was expected."
error(XPATHErrorResources.ER_EXPECTED_NODE_TEST, null);
@ -1910,7 +1918,7 @@ public class XPathParser
m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1);
if (tokenIs('*'))
if (tokenIs(Token.STAR))
{
m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), OpCodes.ELEMWILDCARD);
}
@ -1920,7 +1928,7 @@ public class XPathParser
// Minimalist check for an NCName - just check first character
// to distinguish from other possible tokens
if (!Character.isLetter(m_tokenChar) && !tokenIs('_'))
if (!Character.isLetter(m_tokenChar) && !tokenIs(Token.US))
{
// "Node test that matches either NCName:* or QName was expected."
error(XPATHErrorResources.ER_EXPECTED_NODE_TEST, null);
@ -1938,11 +1946,11 @@ public class XPathParser
* Predicate ::= '[' PredicateExpr ']'
*
*
* @throws javax.xml.transform.TransformerException
* @throws TransformerException
*/
protected void Predicate() throws javax.xml.transform.TransformerException
protected void Predicate() throws TransformerException
{
if (tokenIs('['))
if (tokenIs(Token.LBRACK))
{
countPredicate++;
nextToken();
@ -1957,9 +1965,9 @@ public class XPathParser
* PredicateExpr ::= Expr
*
*
* @throws javax.xml.transform.TransformerException
* @throws TransformerException
*/
protected void PredicateExpr() throws javax.xml.transform.TransformerException
protected void PredicateExpr() throws TransformerException
{
int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
@ -1979,12 +1987,12 @@ public class XPathParser
* Prefix ::= NCName
* LocalPart ::= NCName
*
* @throws javax.xml.transform.TransformerException
* @throws TransformerException
*/
protected void QName() throws javax.xml.transform.TransformerException
protected void QName() throws TransformerException
{
// Namespace
if(lookahead(':', 1))
if(lookahead(Token.COLON, 1))
{
m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), m_queueMark - 1);
m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1);
@ -2026,16 +2034,16 @@ public class XPathParser
* | "'" [^']* "'"
*
*
* @throws javax.xml.transform.TransformerException
* @throws TransformerException
*/
protected void Literal() throws javax.xml.transform.TransformerException
protected void Literal() throws TransformerException
{
int last = m_token.length() - 1;
char c0 = m_tokenChar;
char cX = m_token.charAt(last);
if (((c0 == '\"') && (cX == '\"')) || ((c0 == '\'') && (cX == '\'')))
if (((c0 == Token.DQ) && (cX == Token.DQ)) || ((c0 == Token.SQ) && (cX == Token.SQ)))
{
// Mutate the token to remove the quotes and have the XString object
@ -2066,9 +2074,9 @@ public class XPathParser
* Number ::= [0-9]+('.'[0-9]+)? | '.'[0-9]+
*
*
* @throws javax.xml.transform.TransformerException
* @throws TransformerException
*/
protected void Number() throws javax.xml.transform.TransformerException
protected void Number() throws TransformerException
{
if (null != m_token)
@ -2109,16 +2117,16 @@ public class XPathParser
* | Pattern '|' LocationPathPattern
*
*
* @throws javax.xml.transform.TransformerException
* @throws TransformerException
*/
protected void Pattern() throws javax.xml.transform.TransformerException
protected void Pattern() throws TransformerException
{
while (true)
{
LocationPathPattern();
if (tokenIs('|'))
if (tokenIs(Token.VBAR))
{
nextToken();
}
@ -2137,9 +2145,9 @@ public class XPathParser
* | '//'? RelativePathPattern
*
*
* @throws javax.xml.transform.TransformerException
* @throws TransformerException
*/
protected void LocationPathPattern() throws javax.xml.transform.TransformerException
protected void LocationPathPattern() throws TransformerException
{
int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
@ -2152,17 +2160,17 @@ public class XPathParser
appendOp(2, OpCodes.OP_LOCATIONPATHPATTERN);
if (lookahead('(', 1)
if (lookahead(Token.LPAREN, 1)
&& (tokenIs(Keywords.FUNC_ID_STRING)
|| tokenIs(Keywords.FUNC_KEY_STRING)))
{
IdKeyPattern();
if (tokenIs('/'))
if (tokenIs(Token.SLASH))
{
nextToken();
if (tokenIs('/'))
if (tokenIs(Token.SLASH))
{
appendOp(4, OpCodes.MATCH_ANY_ANCESTOR);
@ -2180,9 +2188,9 @@ public class XPathParser
relativePathStatus = RELATIVE_PATH_REQUIRED;
}
}
else if (tokenIs('/'))
else if (tokenIs(Token.SLASH))
{
if (lookahead('/', 1))
if (lookahead(Token.SLASH, 1))
{
appendOp(4, OpCodes.MATCH_ANY_ANCESTOR);
@ -2215,7 +2223,7 @@ public class XPathParser
if (relativePathStatus != RELATIVE_PATH_NOT_PERMITTED)
{
if (!tokenIs('|') && (null != m_token))
if (!tokenIs(Token.VBAR) && (null != m_token))
{
RelativePathPattern();
}
@ -2240,9 +2248,9 @@ public class XPathParser
* (Also handle doc())
*
*
* @throws javax.xml.transform.TransformerException
* @throws TransformerException
*/
protected void IdKeyPattern() throws javax.xml.transform.TransformerException
protected void IdKeyPattern() throws TransformerException
{
FunctionCall();
}
@ -2253,17 +2261,17 @@ public class XPathParser
* | RelativePathPattern '/' StepPattern
* | RelativePathPattern '//' StepPattern
*
* @throws javax.xml.transform.TransformerException
* @throws TransformerException
*/
protected void RelativePathPattern()
throws javax.xml.transform.TransformerException
throws TransformerException
{
// Caller will have consumed any '/' or '//' preceding the
// RelativePathPattern, so let StepPattern know it can't begin with a '/'
boolean trailingSlashConsumed = StepPattern(false);
while (tokenIs('/'))
while (tokenIs(Token.SLASH))
{
nextToken();
@ -2283,10 +2291,10 @@ public class XPathParser
*
* @return boolean indicating whether a slash following the step was consumed
*
* @throws javax.xml.transform.TransformerException
* @throws TransformerException
*/
protected boolean StepPattern(boolean isLeadingSlashPermitted)
throws javax.xml.transform.TransformerException
throws TransformerException
{
return AbbreviatedNodeTestStep(isLeadingSlashPermitted);
}
@ -2300,10 +2308,10 @@ public class XPathParser
*
* @return boolean indicating whether a slash following the step was consumed
*
* @throws javax.xml.transform.TransformerException
* @throws TransformerException
*/
protected boolean AbbreviatedNodeTestStep(boolean isLeadingSlashPermitted)
throws javax.xml.transform.TransformerException
throws TransformerException
{
int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
@ -2312,22 +2320,22 @@ public class XPathParser
// The next blocks guarantee that a MATCH_XXX will be added.
int matchTypePos = -1;
if (tokenIs('@'))
if (tokenIs(Token.AT))
{
axesType = OpCodes.MATCH_ATTRIBUTE;
appendOp(2, axesType);
nextToken();
}
else if (this.lookahead("::", 1))
else if (this.lookahead(Token.DCOLON, 1))
{
if (tokenIs("attribute"))
if (tokenIs(Token.ATTR))
{
axesType = OpCodes.MATCH_ATTRIBUTE;
appendOp(2, axesType);
}
else if (tokenIs("child"))
else if (tokenIs(Token.CHILD))
{
matchTypePos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
axesType = OpCodes.MATCH_IMMEDIATE_ANCESTOR;
@ -2345,7 +2353,7 @@ public class XPathParser
nextToken();
nextToken();
}
else if (tokenIs('/'))
else if (tokenIs(Token.SLASH))
{
if (!isLeadingSlashPermitted)
{
@ -2374,7 +2382,7 @@ public class XPathParser
m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH + 1,
m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
while (tokenIs('['))
while (tokenIs(Token.LBRACK))
{
Predicate();
}
@ -2393,7 +2401,7 @@ public class XPathParser
// If current step is on the attribute axis (e.g., "@x//b"), we won't
// change the current step, and let following step be marked as
// MATCH_ANY_ANCESTOR on next call instead.
if ((matchTypePos > -1) && tokenIs('/') && lookahead('/', 1))
if ((matchTypePos > -1) && tokenIs(Token.SLASH) && lookahead(Token.SLASH, 1))
{
m_ops.setOp(matchTypePos, OpCodes.MATCH_ANY_ANCESTOR);

View File

@ -30,6 +30,7 @@ import javax.xml.xpath.XPathFactoryConfigurationException;
import javax.xml.xpath.XPathFunctionResolver;
import javax.xml.xpath.XPathVariableResolver;
import jdk.xml.internal.JdkXmlFeatures;
import jdk.xml.internal.XMLSecurityManager;
/**
* The XPathFactory builds XPaths.
@ -68,6 +69,12 @@ public class XPathFactoryImpl extends XPathFactory {
*/
private final JdkXmlFeatures _featureManager;
/**
* The XML security manager
*/
private XMLSecurityManager _xmlSecMgr;
/**
* javax.xml.xpath.XPathFactory implementation.
*/
@ -78,6 +85,7 @@ public class XPathFactoryImpl extends XPathFactory {
_isNotSecureProcessing = false;
}
_featureManager = new JdkXmlFeatures(!_isNotSecureProcessing);
_xmlSecMgr = new XMLSecurityManager(true);
}
/**
* <p>Is specified object model supported by this
@ -127,7 +135,7 @@ public class XPathFactoryImpl extends XPathFactory {
public javax.xml.xpath.XPath newXPath() {
return new com.sun.org.apache.xpath.internal.jaxp.XPathImpl(
xPathVariableResolver, xPathFunctionResolver,
!_isNotSecureProcessing, _featureManager );
!_isNotSecureProcessing, _featureManager, _xmlSecMgr);
}
/**

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Copyright 1999-2004 The Apache Software Foundation.
@ -46,6 +46,7 @@ import javax.xml.parsers.*;
import java.io.IOException;
import jdk.xml.internal.JdkXmlFeatures;
import jdk.xml.internal.XMLSecurityManager;
import jdk.xml.internal.JdkXmlUtils;
/**
@ -72,19 +73,23 @@ public class XPathImpl implements javax.xml.xpath.XPath {
private boolean featureSecureProcessing = false;
private boolean overrideDefaultParser = true;
private final JdkXmlFeatures featureManager;
XMLSecurityManager xmlSecMgr;
XPathImpl( XPathVariableResolver vr, XPathFunctionResolver fr ) {
this(vr, fr, false, new JdkXmlFeatures(false));
XPathImpl(XPathVariableResolver vr, XPathFunctionResolver fr) {
this(vr, fr, false, new JdkXmlFeatures(false), new XMLSecurityManager(true));
}
XPathImpl( XPathVariableResolver vr, XPathFunctionResolver fr,
boolean featureSecureProcessing, JdkXmlFeatures featureManager) {
XPathImpl(XPathVariableResolver vr, XPathFunctionResolver fr,
boolean featureSecureProcessing, JdkXmlFeatures featureManager,
XMLSecurityManager xmlSecMgr) {
this.origVariableResolver = this.variableResolver = vr;
this.origFunctionResolver = this.functionResolver = fr;
this.featureSecureProcessing = featureSecureProcessing;
this.featureManager = featureManager;
this.overrideDefaultParser = featureManager.getFeature(
JdkXmlFeatures.XmlFeature.JDK_OVERRIDE_PARSER);
this.xmlSecMgr = xmlSecMgr;
}
/**
@ -187,7 +192,7 @@ public class XPathImpl implements javax.xml.xpath.XPath {
private XObject eval(String expression, Object contextItem)
throws javax.xml.transform.TransformerException {
com.sun.org.apache.xpath.internal.XPath xpath = new com.sun.org.apache.xpath.internal.XPath( expression,
null, prefixResolver, com.sun.org.apache.xpath.internal.XPath.SELECT );
null, prefixResolver, com.sun.org.apache.xpath.internal.XPath.SELECT, null, null, xmlSecMgr);
com.sun.org.apache.xpath.internal.XPathContext xpathSupport = null;
if ( functionResolver != null ) {
JAXPExtensionsProvider jep = new JAXPExtensionsProvider(
@ -388,7 +393,7 @@ public class XPathImpl implements javax.xml.xpath.XPath {
}
try {
com.sun.org.apache.xpath.internal.XPath xpath = new XPath (expression, null,
prefixResolver, com.sun.org.apache.xpath.internal.XPath.SELECT );
prefixResolver, com.sun.org.apache.xpath.internal.XPath.SELECT, null, null, xmlSecMgr);
// Can have errorListener
XPathExpressionImpl ximpl = new XPathExpressionImpl(xpath,
prefixResolver, functionResolver, variableResolver,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Copyright 1999-2005 The Apache Software Foundation.
@ -32,7 +32,7 @@ import java.util.ListResourceBundle;
* Also you need to update the count of messages(MAX_CODE)or
* the count of warnings(MAX_WARNING) [ Information purpose only]
* @xsl.usage advanced
* @LastModified: May 2019
* @LastModified: Jan 2022
*/
public class XPATHErrorResources extends ListResourceBundle
{
@ -322,6 +322,9 @@ public static final String ER_IGNORABLE_WHITESPACE_NOT_HANDLED =
public static final String ER_SECUREPROCESSING_FEATURE = "ER_SECUREPROCESSING_FEATURE";
public static final String ER_NULL_XPATH_FUNCTION_RESOLVER = "ER_NULL_XPATH_FUNCTION_RESOLVER";
public static final String ER_NULL_XPATH_VARIABLE_RESOLVER = "ER_NULL_XPATH_VARIABLE_RESOLVER";
public static final String ER_XPATH_GROUP_LIMIT = "XPATH_GROUP_LIMIT";
public static final String ER_XPATH_OPERATOR_LIMIT = "XPATH_OPERATOR_LIMIT";
//END: Keys needed for exception messages of JAXP 1.3 XPath API implementation
public static final String WG_LOCALE_NAME_NOT_HANDLED =
@ -833,6 +836,14 @@ public static final String ER_IGNORABLE_WHITESPACE_NOT_HANDLED =
{ ER_NULL_XPATH_VARIABLE_RESOLVER,
"Attempting to set a null XPathVariableResolver:{0}#setXPathVariableResolver(null)"},
{ ER_XPATH_GROUP_LIMIT,
"JAXP0801001: the compiler encountered an XPath expression containing "
+ "''{0}'' groups that exceeds the ''{1}'' limit set by ''{2}''."},
{ ER_XPATH_OPERATOR_LIMIT,
"JAXP0801002: the compiler encountered an XPath expression containing "
+ "''{0}'' operators that exceeds the ''{1}'' limit set by ''{2}''."},
//END: Definitions of error keys used in exception messages of JAXP 1.3 XPath API implementation
// Warnings...

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2022, 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
@ -25,7 +25,6 @@
package jdk.xml.internal;
import com.sun.org.apache.xalan.internal.utils.XMLSecurityManager;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import com.sun.org.apache.xerces.internal.impl.Constants;
import com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl;

View File

@ -0,0 +1,249 @@
/*
* Copyright (c) 2013, 2022, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 jdk.xml.internal;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Map;
import jdk.xml.internal.XMLSecurityManager.Limit;
import com.sun.org.apache.xalan.internal.XalanConstants;
/**
* A helper for analyzing entity expansion limits
*
*/
public final class XMLLimitAnalyzer {
/**
* Map old property names with the new ones
*/
public static enum NameMap {
ENTITY_EXPANSION_LIMIT(XalanConstants.SP_ENTITY_EXPANSION_LIMIT, XalanConstants.ENTITY_EXPANSION_LIMIT),
MAX_OCCUR_NODE_LIMIT(XalanConstants.SP_MAX_OCCUR_LIMIT, XalanConstants.MAX_OCCUR_LIMIT),
ELEMENT_ATTRIBUTE_LIMIT(XalanConstants.SP_ELEMENT_ATTRIBUTE_LIMIT, XalanConstants.ELEMENT_ATTRIBUTE_LIMIT);
final String newName;
final String oldName;
NameMap(String newName, String oldName) {
this.newName = newName;
this.oldName = oldName;
}
String getOldName(String newName) {
if (newName.equals(this.newName)) {
return oldName;
}
return null;
}
}
/**
* Max value accumulated for each property
*/
private final int[] values;
/**
* Names of the entities corresponding to their max values
*/
private final String[] names;
/**
* Total value of accumulated entities
*/
private final int[] totalValue;
/**
* Maintain values of the top 10 elements in the process of parsing
*/
private final Map<String, Integer>[] caches;
private String entityStart, entityEnd;
/**
* Default constructor. Establishes default values for known security
* vulnerabilities.
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public XMLLimitAnalyzer() {
values = new int[Limit.values().length];
totalValue = new int[Limit.values().length];
names = new String[Limit.values().length];
caches = new Map[Limit.values().length];
}
/**
* Add the value to the current max count for the specified property
* To find the max value of all entities, set no limit
*
* @param limit the type of the property
* @param entityName the name of the entity
* @param value the value of the entity
*/
public void addValue(Limit limit, String entityName, int value) {
addValue(limit.ordinal(), entityName, value);
}
/**
* Add the value to the current count by the index of the property
* @param index the index of the property
* @param entityName the name of the entity
* @param value the value of the entity
*/
public void addValue(int index, String entityName, int value) {
if (index == Limit.ENTITY_EXPANSION_LIMIT.ordinal() ||
index == Limit.MAX_OCCUR_NODE_LIMIT.ordinal() ||
index == Limit.ELEMENT_ATTRIBUTE_LIMIT.ordinal() ||
index == Limit.TOTAL_ENTITY_SIZE_LIMIT.ordinal() ||
index == Limit.ENTITY_REPLACEMENT_LIMIT.ordinal()
) {
totalValue[index] += value;
return;
}
if (index == Limit.MAX_ELEMENT_DEPTH_LIMIT.ordinal() ||
index == Limit.MAX_NAME_LIMIT.ordinal()) {
values[index] = value;
totalValue[index] = value;
return;
}
Map<String, Integer> cache;
if (caches[index] == null) {
cache = new HashMap<>(10);
caches[index] = cache;
} else {
cache = caches[index];
}
int accumulatedValue = value;
if (cache.containsKey(entityName)) {
accumulatedValue += cache.get(entityName);
cache.put(entityName, accumulatedValue);
} else {
cache.put(entityName, value);
}
if (accumulatedValue > values[index]) {
values[index] = accumulatedValue;
names[index] = entityName;
}
if (index == Limit.GENEAL_ENTITY_SIZE_LIMIT.ordinal() ||
index == Limit.PARAMETER_ENTITY_SIZE_LIMIT.ordinal()) {
totalValue[Limit.TOTAL_ENTITY_SIZE_LIMIT.ordinal()] += value;
}
}
/**
* Return the value of the current max count for the specified property
*
* @param limit the property
* @return the value of the property
*/
public int getValue(Limit limit) {
return getValue(limit.ordinal());
}
public int getValue(int index) {
if (index == Limit.ENTITY_REPLACEMENT_LIMIT.ordinal()) {
return totalValue[index];
}
return values[index];
}
/**
* Return the total value accumulated so far
*
* @param limit the property
* @return the accumulated value of the property
*/
public int getTotalValue(Limit limit) {
return totalValue[limit.ordinal()];
}
public int getTotalValue(int index) {
return totalValue[index];
}
/**
* Return the current max value (count or length) by the index of a property
* @param index the index of a property
* @return count of a property
*/
public int getValueByIndex(int index) {
return values[index];
}
public void startEntity(String name) {
entityStart = name;
}
public boolean isTracking(String name) {
if (entityStart == null) {
return false;
}
return entityStart.equals(name);
}
/**
* Stop tracking the entity
* @param limit the limit property
* @param name the name of an entity
*/
public void endEntity(Limit limit, String name) {
entityStart = "";
Map<String, Integer> cache = caches[limit.ordinal()];
if (cache != null) {
cache.remove(name);
}
}
/**
* Resets the current value of the specified limit.
* @param limit The limit to be reset.
*/
public void reset(Limit limit) {
if (limit.ordinal() == Limit.TOTAL_ENTITY_SIZE_LIMIT.ordinal()) {
totalValue[limit.ordinal()] = 0;
} else if (limit.ordinal() == Limit.GENEAL_ENTITY_SIZE_LIMIT.ordinal()) {
names[limit.ordinal()] = null;
values[limit.ordinal()] = 0;
caches[limit.ordinal()] = null;
totalValue[limit.ordinal()] = 0;
}
}
public void debugPrint(XMLSecurityManager securityManager) {
Formatter formatter = new Formatter();
System.out.println(formatter.format("%30s %15s %15s %15s %30s",
"Property","Limit","Total size","Size","Entity Name"));
for (Limit limit : Limit.values()) {
formatter = new Formatter();
System.out.println(formatter.format("%30s %15d %15d %15d %30s",
limit.name(),
securityManager.getLimit(limit),
totalValue[limit.ordinal()],
values[limit.ordinal()],
names[limit.ordinal()]));
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2022, 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
@ -23,19 +23,17 @@
* questions.
*/
package com.sun.org.apache.xalan.internal.utils;
package jdk.xml.internal;
import com.sun.org.apache.xalan.internal.XalanConstants;
import com.sun.org.apache.xerces.internal.util.SecurityManager;
import java.util.concurrent.CopyOnWriteArrayList;
import com.sun.org.apache.xalan.internal.XalanConstants;
import org.xml.sax.SAXException;
/**
* This class is not the same as that in Xerces. It is used to manage the
* state of corresponding Xerces properties and pass the values over to
* the Xerces Security Manager.
*
* @author Joe Wang Oracle Corp.
* This class manages standard and implementation-specific limitations.
*
*/
public final class XMLSecurityManager {
@ -66,38 +64,47 @@ public final class XMLSecurityManager {
* Limits managed by the security manager
*/
public static enum Limit {
ENTITY_EXPANSION_LIMIT("EntityExpansionLimit", XalanConstants.JDK_ENTITY_EXPANSION_LIMIT,
XalanConstants.SP_ENTITY_EXPANSION_LIMIT, 0, 64000),
XalanConstants.SP_ENTITY_EXPANSION_LIMIT, 0, 64000, Processor.PARSER),
MAX_OCCUR_NODE_LIMIT("MaxOccurLimit", XalanConstants.JDK_MAX_OCCUR_LIMIT,
XalanConstants.SP_MAX_OCCUR_LIMIT, 0, 5000),
XalanConstants.SP_MAX_OCCUR_LIMIT, 0, 5000, Processor.PARSER),
ELEMENT_ATTRIBUTE_LIMIT("ElementAttributeLimit", XalanConstants.JDK_ELEMENT_ATTRIBUTE_LIMIT,
XalanConstants.SP_ELEMENT_ATTRIBUTE_LIMIT, 0, 10000),
XalanConstants.SP_ELEMENT_ATTRIBUTE_LIMIT, 0, 10000, Processor.PARSER),
TOTAL_ENTITY_SIZE_LIMIT("TotalEntitySizeLimit", XalanConstants.JDK_TOTAL_ENTITY_SIZE_LIMIT,
XalanConstants.SP_TOTAL_ENTITY_SIZE_LIMIT, 0, 50000000),
XalanConstants.SP_TOTAL_ENTITY_SIZE_LIMIT, 0, 50000000, Processor.PARSER),
GENEAL_ENTITY_SIZE_LIMIT("MaxEntitySizeLimit", XalanConstants.JDK_GENEAL_ENTITY_SIZE_LIMIT,
XalanConstants.SP_GENEAL_ENTITY_SIZE_LIMIT, 0, 0),
XalanConstants.SP_GENEAL_ENTITY_SIZE_LIMIT, 0, 0, Processor.PARSER),
PARAMETER_ENTITY_SIZE_LIMIT("MaxEntitySizeLimit", XalanConstants.JDK_PARAMETER_ENTITY_SIZE_LIMIT,
XalanConstants.SP_PARAMETER_ENTITY_SIZE_LIMIT, 0, 1000000),
XalanConstants.SP_PARAMETER_ENTITY_SIZE_LIMIT, 0, 1000000, Processor.PARSER),
MAX_ELEMENT_DEPTH_LIMIT("MaxElementDepthLimit", XalanConstants.JDK_MAX_ELEMENT_DEPTH,
XalanConstants.SP_MAX_ELEMENT_DEPTH, 0, 0),
XalanConstants.SP_MAX_ELEMENT_DEPTH, 0, 0, Processor.PARSER),
MAX_NAME_LIMIT("MaxXMLNameLimit", XalanConstants.JDK_XML_NAME_LIMIT,
XalanConstants.SP_XML_NAME_LIMIT, 1000, 1000),
XalanConstants.SP_XML_NAME_LIMIT, 1000, 1000, Processor.PARSER),
ENTITY_REPLACEMENT_LIMIT("EntityReplacementLimit", XalanConstants.JDK_ENTITY_REPLACEMENT_LIMIT,
XalanConstants.SP_ENTITY_REPLACEMENT_LIMIT, 0, 3000000);
XalanConstants.SP_ENTITY_REPLACEMENT_LIMIT, 0, 3000000, Processor.PARSER),
XPATH_GROUP_LIMIT("XPathGroupLimit", XalanConstants.XPATH_GROUP_LIMIT,
XalanConstants.XPATH_GROUP_LIMIT, 10, 10, Processor.XPATH),
XPATH_OP_LIMIT("XPathExprOpLimit", XalanConstants.XPATH_OP_LIMIT,
XalanConstants.XPATH_OP_LIMIT, 100, 100, Processor.XPATH),
XPATH_TOTALOP_LIMIT("XPathTotalOpLimit", XalanConstants.XPATH_TOTALOP_LIMIT,
XalanConstants.XPATH_TOTALOP_LIMIT, 10000, 10000, Processor.XPATH)
;
final String key;
final String apiProperty;
final String systemProperty;
final int defaultValue;
final int secureValue;
final Processor processor;
Limit(String key, String apiProperty, String systemProperty, int value, int secureValue) {
Limit(String key, String apiProperty, String systemProperty, int value,
int secureValue, Processor processor) {
this.key = key;
this.apiProperty = apiProperty;
this.systemProperty = systemProperty;
this.defaultValue = value;
this.secureValue = secureValue;
this.processor = processor;
}
public boolean equalsAPIPropertyName(String propertyName) {
@ -124,6 +131,10 @@ public final class XMLSecurityManager {
return defaultValue;
}
public boolean isSupported(Processor p) {
return processor == p;
}
int secureValue() {
return secureValue;
}
@ -134,12 +145,9 @@ public final class XMLSecurityManager {
*/
public static enum NameMap {
ENTITY_EXPANSION_LIMIT(XalanConstants.SP_ENTITY_EXPANSION_LIMIT,
XalanConstants.ENTITY_EXPANSION_LIMIT),
MAX_OCCUR_NODE_LIMIT(XalanConstants.SP_MAX_OCCUR_LIMIT,
XalanConstants.MAX_OCCUR_LIMIT),
ELEMENT_ATTRIBUTE_LIMIT(XalanConstants.SP_ELEMENT_ATTRIBUTE_LIMIT,
XalanConstants.ELEMENT_ATTRIBUTE_LIMIT);
ENTITY_EXPANSION_LIMIT(XalanConstants.SP_ENTITY_EXPANSION_LIMIT, XalanConstants.ENTITY_EXPANSION_LIMIT),
MAX_OCCUR_NODE_LIMIT(XalanConstants.SP_MAX_OCCUR_LIMIT, XalanConstants.MAX_OCCUR_LIMIT),
ELEMENT_ATTRIBUTE_LIMIT(XalanConstants.SP_ELEMENT_ATTRIBUTE_LIMIT, XalanConstants.ELEMENT_ATTRIBUTE_LIMIT);
final String newName;
final String oldName;
@ -155,14 +163,32 @@ public final class XMLSecurityManager {
return null;
}
}
/**
* Supported processors
*/
public static enum Processor {
PARSER,
XPATH,
}
private static final int NO_LIMIT = 0;
/**
* Values of the properties
*/
private final int[] values;
/**
* States of the settings for each property
*/
private State[] states;
/**
* Flag indicating if secure processing is set
*/
boolean secureProcessing;
/**
* States that determine if properties are set explicitly
*/
@ -192,9 +218,10 @@ public final class XMLSecurityManager {
values = new int[Limit.values().length];
states = new State[Limit.values().length];
isSet = new boolean[Limit.values().length];
this.secureProcessing = secureProcessing;
for (Limit limit : Limit.values()) {
if (secureProcessing) {
values[limit.ordinal()] = limit.secureValue();
values[limit.ordinal()] = limit.secureValue;
states[limit.ordinal()] = State.FSP;
} else {
values[limit.ordinal()] = limit.defaultValue();
@ -209,6 +236,7 @@ public final class XMLSecurityManager {
* Setting FEATURE_SECURE_PROCESSING explicitly
*/
public void setSecureProcessing(boolean secure) {
secureProcessing = secure;
for (Limit limit : Limit.values()) {
if (secure) {
setLimit(limit.ordinal(), State.FSP, limit.secureValue());
@ -218,6 +246,14 @@ public final class XMLSecurityManager {
}
}
/**
* Return the state of secure processing
* @return the state of secure processing
*/
public boolean isSecureProcessing() {
return secureProcessing;
}
/**
* Set limit by property name and state
* @param propertyName property name
@ -255,7 +291,6 @@ public final class XMLSecurityManager {
*/
public void setLimit(int index, State state, Object value) {
if (index == indexEntityCountInfo) {
//if it's explicitly set, it's treated as yes no matter the value
printEntityCountInfo = (String)value;
} else {
int temp = 0;
@ -289,9 +324,8 @@ public final class XMLSecurityManager {
}
}
/**
* Return the value of the specified property.
* Return the value of the specified property
*
* @param propertyName the property name
* @return the value of the property as a string. If a property is managed
@ -305,17 +339,6 @@ public final class XMLSecurityManager {
return null;
}
/**
* Return the value of a property by its ordinal
*
* @param limit the property
* @return value of a property
*/
public String getLimitValueAsString(Limit limit) {
return Integer.toString(values[limit.ordinal()]);
}
/**
* Return the value of the specified property
*
@ -329,14 +352,15 @@ public final class XMLSecurityManager {
/**
* Return the value of a property by its ordinal
*
* @param index the index of a property
* @param limit the property
* @return value of a property
*/
public int getLimitByIndex(int index) {
return values[index];
public String getLimitValueAsString(Limit limit) {
return Integer.toString(values[limit.ordinal()]);
}
/**
* Return the value of a property by its index
* Return the value of a property by its ordinal
*
* @param index the index of a property
* @return limit of a property as a string
@ -348,6 +372,7 @@ public final class XMLSecurityManager {
return Integer.toString(values[index]);
}
/**
* Return the state of the limit property
*
@ -388,6 +413,85 @@ public final class XMLSecurityManager {
return -1;
}
/**
* Check if there's no limit defined by the Security Manager
* @param limit
* @return
*/
public boolean isNoLimit(int limit) {
return limit == NO_LIMIT;
}
/**
* Check if the size (length or count) of the specified limit property is
* over the limit
*
* @param limit the type of the limit property
* @param entityName the name of the entity
* @param size the size (count or length) of the entity
* @return true if the size is over the limit, false otherwise
*/
public boolean isOverLimit(Limit limit, String entityName, int size,
XMLLimitAnalyzer limitAnalyzer) {
return isOverLimit(limit.ordinal(), entityName, size, limitAnalyzer);
}
/**
* Check if the value (length or count) of the specified limit property is
* over the limit
*
* @param index the index of the limit property
* @param entityName the name of the entity
* @param size the size (count or length) of the entity
* @return true if the size is over the limit, false otherwise
*/
public boolean isOverLimit(int index, String entityName, int size,
XMLLimitAnalyzer limitAnalyzer) {
if (values[index] == NO_LIMIT) {
return false;
}
if (size > values[index]) {
limitAnalyzer.addValue(index, entityName, size);
return true;
}
return false;
}
/**
* Check against cumulated value
*
* @param limit the type of the limit property
* @param size the size (count or length) of the entity
* @return true if the size is over the limit, false otherwise
*/
public boolean isOverLimit(Limit limit, XMLLimitAnalyzer limitAnalyzer) {
return isOverLimit(limit.ordinal(), limitAnalyzer);
}
public boolean isOverLimit(int index, XMLLimitAnalyzer limitAnalyzer) {
if (values[index] == NO_LIMIT) {
return false;
}
if (index == Limit.ELEMENT_ATTRIBUTE_LIMIT.ordinal() ||
index == Limit.ENTITY_EXPANSION_LIMIT.ordinal() ||
index == Limit.TOTAL_ENTITY_SIZE_LIMIT.ordinal() ||
index == Limit.ENTITY_REPLACEMENT_LIMIT.ordinal() ||
index == Limit.MAX_ELEMENT_DEPTH_LIMIT.ordinal() ||
index == Limit.MAX_NAME_LIMIT.ordinal()
) {
return (limitAnalyzer.getTotalValue(index) > values[index]);
} else {
return (limitAnalyzer.getValue(index) > values[index]);
}
}
public void debugPrint(XMLLimitAnalyzer limitAnalyzer) {
if (printEntityCountInfo.equals(XalanConstants.JDK_YES)) {
limitAnalyzer.debugPrint(this);
}
}
/**
* Indicate if a property is set explicitly
* @param index
@ -400,6 +504,7 @@ public final class XMLSecurityManager {
public boolean printEntityCountInfo() {
return printEntityCountInfo.equals(XalanConstants.JDK_YES);
}
/**
* Read from system properties, or those in jaxp.properties
*/
@ -463,4 +568,37 @@ public final class XMLSecurityManager {
}
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
*/
public static XMLSecurityManager convert(Object value, XMLSecurityManager securityManager) {
if (value == null) {
if (securityManager == null) {
securityManager = new XMLSecurityManager(true);
}
return securityManager;
}
if (value instanceof XMLSecurityManager) {
return (XMLSecurityManager)value;
} else {
if (securityManager == null) {
securityManager = new XMLSecurityManager(true);
}
if (value instanceof SecurityManager) {
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;
}
}
}