mirror of
https://github.com/openjdk/jdk7u.git
synced 2025-12-10 10:13:47 -06:00
8270504: Better Xpath expression handling
Reviewed-by: bae Backport-of: b61a2ca626b1da5e555c50e548b643a2daa396c6
This commit is contained in:
parent
f7b710fcb3
commit
0bbcf1a956
@ -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
|
||||
|
||||
@ -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" ;
|
||||
|
||||
@ -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));
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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};
|
||||
}
|
||||
|
||||
@ -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}''."},
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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.
|
||||
*
|
||||
|
||||
@ -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 = "";
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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...
|
||||
|
||||
@ -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;
|
||||
|
||||
249
jaxp/src/jdk/xml/internal/XMLLimitAnalyzer.java
Normal file
249
jaxp/src/jdk/xml/internal/XMLLimitAnalyzer.java
Normal 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()]));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user