diff --git a/jaxp/src/com/sun/java_cup/internal/runtime/lr_parser.java b/jaxp/src/com/sun/java_cup/internal/runtime/lr_parser.java index a94dff8892..27e78af076 100644 --- a/jaxp/src/com/sun/java_cup/internal/runtime/lr_parser.java +++ b/jaxp/src/com/sun/java_cup/internal/runtime/lr_parser.java @@ -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 diff --git a/jaxp/src/com/sun/org/apache/xalan/internal/XalanConstants.java b/jaxp/src/com/sun/org/apache/xalan/internal/XalanConstants.java index b792c34aa0..d097013a0c 100644 --- a/jaxp/src/com/sun/org/apache/xalan/internal/XalanConstants.java +++ b/jaxp/src/com/sun/org/apache/xalan/internal/XalanConstants.java @@ -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" ; diff --git a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Parser.java b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Parser.java index 38ce8aec91..8e0e2ee614 100644 --- a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Parser.java +++ b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Parser.java @@ -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)); diff --git a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/XPathParser.java b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/XPathParser.java index f33b34b29c..da5f8a316b 100644 --- a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/XPathParser.java +++ b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/XPathParser.java @@ -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, diff --git a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java index e9cca2f743..89cc1460e4 100644 --- a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java +++ b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java @@ -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) { diff --git a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/sym.java b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/sym.java index d64dc3fd04..88244a31ab 100644 --- a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/sym.java +++ b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/sym.java @@ -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}; } diff --git a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages.java b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages.java index cf83580147..bb1a6e8f56 100644 --- a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages.java +++ b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages.java @@ -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}''."}, + }; } } diff --git a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMsg.java b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMsg.java index 4192cf2d7e..365f6c747e 100644 --- a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMsg.java +++ b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMsg.java @@ -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) { diff --git a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java index af487f04e5..7a4350d544 100644 --- a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java +++ b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java @@ -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; diff --git a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerImpl.java b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerImpl.java index 019fcbbfc7..0e2b7424ca 100644 --- a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerImpl.java +++ b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerImpl.java @@ -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; diff --git a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/Util.java b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/Util.java index 91d8491798..a54208573f 100644 --- a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/Util.java +++ b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/Util.java @@ -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; diff --git a/jaxp/src/com/sun/org/apache/xml/internal/utils/XMLReaderManager.java b/jaxp/src/com/sun/org/apache/xml/internal/utils/XMLReaderManager.java index 39a5e88981..71a9cf14d6 100644 --- a/jaxp/src/com/sun/org/apache/xml/internal/utils/XMLReaderManager.java +++ b/jaxp/src/com/sun/org/apache/xml/internal/utils/XMLReaderManager.java @@ -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; diff --git a/jaxp/src/com/sun/org/apache/xpath/internal/XPath.java b/jaxp/src/com/sun/org/apache/xpath/internal/XPath.java index 2734cc46ec..628ac7c91e 100644 --- a/jaxp/src/com/sun/org/apache/xpath/internal/XPath.java +++ b/jaxp/src/com/sun/org/apache/xpath/internal/XPath.java @@ -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. * diff --git a/jaxp/src/com/sun/org/apache/xpath/internal/compiler/Lexer.java b/jaxp/src/com/sun/org/apache/xpath/internal/compiler/Lexer.java index 5af6f188f6..fa42d1a4a6 100644 --- a/jaxp/src/com/sun/org/apache/xpath/internal/compiler/Lexer.java +++ b/jaxp/src/com/sun/org/apache/xpath/internal/compiler/Lexer.java @@ -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 = ""; diff --git a/jaxp/src/com/sun/org/apache/xpath/internal/compiler/Token.java b/jaxp/src/com/sun/org/apache/xpath/internal/compiler/Token.java new file mode 100644 index 0000000000..40d84035f7 --- /dev/null +++ b/jaxp/src/com/sun/org/apache/xpath/internal/compiler/Token.java @@ -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 + } +} diff --git a/jaxp/src/com/sun/org/apache/xpath/internal/compiler/XPathParser.java b/jaxp/src/com/sun/org/apache/xpath/internal/compiler/XPathParser.java index bd19dffdd7..91404306a7 100644 --- a/jaxp/src/com/sun/org/apache/xpath/internal/compiler/XPathParser.java +++ b/jaxp/src/com/sun/org/apache/xpath/internal/compiler/XPathParser.java @@ -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); diff --git a/jaxp/src/com/sun/org/apache/xpath/internal/jaxp/XPathFactoryImpl.java b/jaxp/src/com/sun/org/apache/xpath/internal/jaxp/XPathFactoryImpl.java index af9ef866e3..04606a073e 100644 --- a/jaxp/src/com/sun/org/apache/xpath/internal/jaxp/XPathFactoryImpl.java +++ b/jaxp/src/com/sun/org/apache/xpath/internal/jaxp/XPathFactoryImpl.java @@ -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); } /** *
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);
}
/**
diff --git a/jaxp/src/com/sun/org/apache/xpath/internal/jaxp/XPathImpl.java b/jaxp/src/com/sun/org/apache/xpath/internal/jaxp/XPathImpl.java
index ebf9083ed9..29775c9983 100644
--- a/jaxp/src/com/sun/org/apache/xpath/internal/jaxp/XPathImpl.java
+++ b/jaxp/src/com/sun/org/apache/xpath/internal/jaxp/XPathImpl.java
@@ -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,
diff --git a/jaxp/src/com/sun/org/apache/xpath/internal/res/XPATHErrorResources.java b/jaxp/src/com/sun/org/apache/xpath/internal/res/XPATHErrorResources.java
index 9b29d10c5b..69046c5048 100644
--- a/jaxp/src/com/sun/org/apache/xpath/internal/res/XPATHErrorResources.java
+++ b/jaxp/src/com/sun/org/apache/xpath/internal/res/XPATHErrorResources.java
@@ -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...
diff --git a/jaxp/src/jdk/xml/internal/JdkXmlUtils.java b/jaxp/src/jdk/xml/internal/JdkXmlUtils.java
index 012fa7711a..6f747c2d56 100644
--- a/jaxp/src/jdk/xml/internal/JdkXmlUtils.java
+++ b/jaxp/src/jdk/xml/internal/JdkXmlUtils.java
@@ -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;
diff --git a/jaxp/src/jdk/xml/internal/XMLLimitAnalyzer.java b/jaxp/src/jdk/xml/internal/XMLLimitAnalyzer.java
new file mode 100644
index 0000000000..cfc3b69ff7
--- /dev/null
+++ b/jaxp/src/jdk/xml/internal/XMLLimitAnalyzer.java
@@ -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