8270504: Better Xpath expression handling

Reviewed-by: naoto, lancea, mschoene, rhalade
This commit is contained in:
Joe Wang 2022-01-14 01:56:50 +00:00 committed by Henry Jen
parent 3268aba925
commit 616ea1692e
27 changed files with 1249 additions and 393 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2017, 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,29 @@ 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) {
return Arrays.stream(arr).anyMatch(i -> i == key);
}
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
@ -552,6 +585,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 +666,29 @@ public abstract class lr_parser {
}
}
}
totalOpCount += opCount;
return lhs_sym;
}
/**
* Returns the count of operators in XPath expressions.
*
* @param id the ID of the count
* @return the count associated with the ID
*/
public int getCount(int id) {
switch (id) {
case ID_GROUP:
return grpCount;
case ID_OPERATOR:
return opCount;
case ID_TOTAL_OPERATOR:
return totalOpCount;
}
return 0;
}
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** Write a debugging message to System.err for the debugging version

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2021, 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
@ -22,7 +22,6 @@ package com.sun.org.apache.xalan.internal.xsltc.compiler;
import com.sun.java_cup.internal.runtime.Symbol;
import com.sun.org.apache.xalan.internal.utils.ObjectFactory;
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.MethodType;
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type;
@ -46,6 +45,7 @@ import jdk.xml.internal.JdkConstants;
import jdk.xml.internal.JdkXmlFeatures;
import jdk.xml.internal.JdkXmlUtils;
import jdk.xml.internal.SecuritySupport;
import jdk.xml.internal.XMLSecurityManager;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
@ -62,7 +62,7 @@ import org.xml.sax.helpers.AttributesImpl;
* @author G. Todd Miller
* @author Morten Jorgensen
* @author Erwin Bolwidt <ejb@klomp.org>
* @LastModified: May 2021
* @LastModified: Jan 2022
*/
public class Parser implements Constants, ContentHandler {
@ -504,8 +504,10 @@ public class Parser implements Constants, ContentHandler {
XMLSecurityManager securityManager =
(XMLSecurityManager)_xsltc.getProperty(JdkConstants.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 = JdkConstants.JDK_DEBUG_LIMIT;
@ -1169,6 +1171,9 @@ public class Parser implements Constants, ContentHandler {
expression, parent));
}
catch (Exception e) {
if (ErrorMsg.XPATH_LIMIT.equals(e.getMessage())) {
throw new RuntimeException(ErrorMsg.XPATH_LIMIT);
}
if (_xsltc.debug()) e.printStackTrace();
reportError(ERROR, new ErrorMsg(ErrorMsg.XPATH_PARSER_ERR,
expression, parent));

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 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
@ -34,14 +34,21 @@ import com.sun.org.apache.xml.internal.dtm.DTM;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import jdk.xml.internal.JdkConstants;
import jdk.xml.internal.XMLLimitAnalyzer;
import jdk.xml.internal.XMLSecurityManager;
import jdk.xml.internal.XMLSecurityManager.Limit;
/**
* CUP v0.11b generated parser.
* This class was generated by CUP v0.11b on Nov 12, 2019.
*
* @LastModified: Nov 2019
* @LastModified: Jan 2022
*/
public class XPathParser extends lr_parser {
private int grpLimit = 0;
private int opLimit = 0;
private int totalOpLimit = 0;
/**
* Default constructor.
@ -953,10 +960,19 @@ public class XPathParser extends 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(JdkConstants.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() {
@ -1101,7 +1117,32 @@ public class XPathParser extends 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,
lineNumber, e.getMessage());

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2021, 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
@ -21,7 +21,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.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;
@ -47,8 +46,8 @@ import javax.xml.XMLConstants;
import javax.xml.catalog.CatalogFeatures;
import jdk.xml.internal.JdkConstants;
import jdk.xml.internal.JdkXmlFeatures;
import jdk.xml.internal.JdkXmlUtils;
import jdk.xml.internal.SecuritySupport;
import jdk.xml.internal.XMLSecurityManager;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
@ -58,7 +57,7 @@ import org.xml.sax.XMLReader;
* @author G. Todd Miller
* @author Morten Jorgensen
* @author John Howard (johnh@schemasoft.com)
* @LastModified: Nov 2021
* @LastModified: Jan 2022
*/
public final class XSLTC {
@ -508,7 +507,10 @@ public final class XSLTC {
}
}
catch (Exception e) {
/*if (_debug)*/ e.printStackTrace();
if (_debug) e.printStackTrace();
if (ErrorMsg.XPATH_LIMIT.equals(e.getMessage())) {
return !_parser.errorsFound();
}
_parser.reportError(Constants.FATAL, new ErrorMsg(ErrorMsg.JAXP_COMPILE_ERR, e));
}
catch (Error e) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2004, 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,9 +25,13 @@
package com.sun.org.apache.xalan.internal.xsltc.compiler;
import java.util.Arrays;
/**
* CUP generated class containing symbol constants.
* This class was generated by CUP v0.10j on Fri Feb 27 13:01:50 PST 2004.
*
* @LastModified: Jan 2022
*/
public class sym {
/* terminals */
@ -85,4 +89,12 @@ public class sym {
public static final int ATTRIBUTE = 41;
public static final int GT = 19;
public static final int NODE = 31;
/*
AXES: count once at DCOLON,
these axes names are therefore not counted:
NAMESPACE, FOLLOWINGSIBLING, CHILD, DESCENDANTORSELF, DESCENDANT
, PRECEDINGSIBLING, SELF, ANCESTORORSELF, PRECEDING, ANCESTOROR, PARENT, FOLLOWING, ATTRIBUTE
*/
public static final int[] OPERATORS = {GE, SLASH, ATSIGN, LPAREN, DCOLON,
MINUS, STAR, LT, OR, DIV, PLUS, LE, VBAR, MOD, EQ, LBRACK, DOLLAR, NE, GT};
}

View File

@ -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.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@ -24,6 +24,7 @@ import java.util.ListResourceBundle;
/**
* @author Morten Jorgensen
* @LastModified: Jan 2022
*/
public class ErrorMessages extends ListResourceBundle {
@ -1027,12 +1028,22 @@ public class ErrorMessages extends ListResourceBundle {
"smaller templates."
},
{ErrorMsg.DESERIALIZE_TRANSLET_ERR, "When Java security is enabled, " +
"support for deserializing TemplatesImpl is disabled." +
"This can be overridden by setting the jdk.xml.enableTemplatesImplDeserialization" +
" system property to true."}
{ErrorMsg.DESERIALIZE_TRANSLET_ERR, "When Java security is enabled, "
+ "support for deserializing TemplatesImpl is disabled. This can be "
+ "overridden by setting the jdk.xml.enableTemplatesImplDeserialization"
+ " system property to true."},
};
{ErrorMsg.XPATH_GROUP_LIMIT,
"JAXP0801001: the compiler encountered an XPath expression containing "
+ "''{0}'' groups that exceeds the ''{1}'' limit set by ''{2}''."},
{ErrorMsg.XPATH_OPERATOR_LIMIT,
"JAXP0801002: the compiler encountered an XPath expression containing "
+ "''{0}'' operators that exceeds the ''{1}'' limit set by ''{2}''."},
{ErrorMsg.XPATH_TOTAL_OPERATOR_LIMIT,
"JAXP0801003: the compiler encountered XPath expressions with an accumulated "
+ "''{0}'' operators that exceeds the ''{1}'' limit set by ''{2}''."},
};
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@ -33,7 +33,7 @@ import jdk.xml.internal.SecuritySupport;
* @author G. Todd Miller
* @author Erwin Bolwidt <ejb@klomp.org>
* @author Morten Jorgensen
* @LastModified: Sep 2017
* @LastModified: Jan 2022
*/
public final class ErrorMsg {
@ -171,6 +171,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;
@ -207,7 +212,11 @@ public final class ErrorMsg {
public ErrorMsg(String code, int line, Object param) {
_code = code;
_line = line;
_params = new Object[] { param };
if (param instanceof Object[]) {
_params = (Object[])param;
} else {
_params = new Object[] { param };
}
}
public ErrorMsg(String code, Object param) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2021, 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
@ -21,9 +21,9 @@
package com.sun.org.apache.xalan.internal.xsltc.trax;
import jdk.xml.internal.JdkConstants;
import jdk.xml.internal.XMLSecurityManager;
import com.sun.org.apache.xalan.internal.utils.FeaturePropertyBase;
import com.sun.org.apache.xalan.internal.utils.ObjectFactory;
import com.sun.org.apache.xalan.internal.utils.XMLSecurityManager;
import com.sun.org.apache.xalan.internal.utils.XMLSecurityPropertyManager.Property;
import com.sun.org.apache.xalan.internal.utils.XMLSecurityPropertyManager;
import com.sun.org.apache.xalan.internal.xsltc.compiler.Constants;
@ -88,7 +88,7 @@ import org.xml.sax.XMLReader;
* @author G. Todd Miller
* @author Morten Jorgensen
* @author Santiago Pericas-Geertsen
* @LastModified: May 2021
* @LastModified: Jan 2022
*/
public class TransformerFactoryImpl
extends SAXTransformerFactory implements SourceLoader
@ -286,7 +286,8 @@ public class TransformerFactoryImpl
_xmlSecurityManager = new XMLSecurityManager(true);
//Unmodifiable hash map with loaded external extension functions
_xsltcExtensionFunctions = null;
_extensionClassLoader = new JdkProperty<>(ImplPropMap.EXTCLSLOADER, null, State.DEFAULT);
_extensionClassLoader = new JdkProperty<>(ImplPropMap.EXTCLSLOADER,
ClassLoader.class, null, State.DEFAULT);
}
public Map<String, Class<?>> getExternalExtensionsMap() {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2021, 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
@ -20,7 +20,6 @@
package com.sun.org.apache.xalan.internal.xsltc.trax;
import com.sun.org.apache.xalan.internal.utils.XMLSecurityManager;
import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.DOMCache;
import com.sun.org.apache.xalan.internal.xsltc.StripFilter;
@ -89,6 +88,7 @@ import jdk.xml.internal.JdkXmlFeatures;
import jdk.xml.internal.JdkXmlUtils;
import jdk.xml.internal.JdkProperty.ImplPropMap;
import jdk.xml.internal.JdkProperty.State;
import jdk.xml.internal.XMLSecurityManager;
import jdk.xml.internal.SecuritySupport;
import jdk.xml.internal.TransformErrorListener;
import org.xml.sax.ContentHandler;
@ -101,7 +101,7 @@ import org.xml.sax.ext.LexicalHandler;
* @author Morten Jorgensen
* @author G. Todd Miller
* @author Santiago Pericas-Geertsen
* @LastModified: Sept 2021
* @LastModified: Jan 2022
*/
public final class TransformerImpl extends Transformer
implements DOMCache
@ -288,10 +288,8 @@ public final class TransformerImpl extends Transformer
_translet.setMessageHandler(new MessageHandler(_errorListener));
}
_properties = createOutputProperties(outputProperties);
String isStandalone = SecuritySupport.getJAXPSystemProperty(
String.class, SP_XSLTC_IS_STANDALONE, "no");
_xsltcIsStandalone = new JdkProperty<>(ImplPropMap.XSLTCISSTANDALONE,
isStandalone, State.DEFAULT);
String.class, "no", State.DEFAULT);
_propertiesClone = (Properties) _properties.clone();
_indentNumber = indentNumber;
_tfactory = tfactory;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@ -20,7 +20,6 @@
package com.sun.org.apache.xalan.internal.xsltc.trax;
import com.sun.org.apache.xalan.internal.utils.XMLSecurityManager;
import com.sun.org.apache.xalan.internal.xsltc.compiler.XSLTC;
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
import java.io.InputStream;
@ -39,6 +38,7 @@ import javax.xml.transform.stream.StreamSource;
import jdk.xml.internal.JdkConstants;
import jdk.xml.internal.JdkXmlFeatures;
import jdk.xml.internal.JdkXmlUtils;
import jdk.xml.internal.XMLSecurityManager;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
@ -51,7 +51,7 @@ import org.xml.sax.XMLReader;
*
* Added Catalog Support for URI resolution
*
* @LastModified: May 2021
* @LastModified: Jan 2022
*/
@SuppressWarnings("deprecation") //org.xml.sax.helpers.XMLReaderFactory
public final class Util {
@ -113,9 +113,11 @@ public final class Util {
(XMLSecurityManager)xsltc.getProperty(JdkConstants.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 = JdkConstants.JDK_DEBUG_LIMIT;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one
@ -70,7 +70,7 @@ import org.w3c.dom.ls.LSSerializerFilter;
* @version $Id:
*
* @xsl.usage internal
* @LastModified: May 2021
* @LastModified: Jan 2022
*/
final public class LSSerializerImpl implements DOMConfiguration, LSSerializer {
@ -364,13 +364,10 @@ final public class LSSerializerImpl implements DOMConfiguration, LSSerializer {
// xml-declaration
fDOMConfigProperties.setProperty(DOMConstants.S_XSL_OUTPUT_OMIT_XML_DECL, "no");
// JDK specific property isStandalone
boolean isStandalone = SecuritySupport.getJAXPSystemProperty(
Boolean.class, JdkConstants.SP_IS_STANDALONE, "false");
fIsStandalone = new JdkProperty<>(ImplPropMap.ISSTANDALONE, isStandalone, State.DEFAULT);
// JDK specific property isStandalone, the default value is false
fIsStandalone = new JdkProperty<>(ImplPropMap.ISSTANDALONE, Boolean.class, false, State.DEFAULT);
// the system property is true only if it is "true" and false otherwise
if (isStandalone) {
if (fIsStandalone.getValue()) {
fFeatures |= IS_STANDALONE;
fDOMConfigProperties.setProperty(DOMConstants.NS_IS_STANDALONE,
DOMConstants.DOM3_EXPLICIT_TRUE);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2021, 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
@ -20,7 +20,6 @@
package com.sun.org.apache.xml.internal.utils;
import com.sun.org.apache.xalan.internal.utils.XMLSecurityManager;
import java.util.HashMap;
import javax.xml.XMLConstants;
import javax.xml.catalog.CatalogFeatures;
@ -28,6 +27,7 @@ import jdk.xml.internal.JdkConstants;
import jdk.xml.internal.JdkXmlFeatures;
import jdk.xml.internal.JdkXmlUtils;
import jdk.xml.internal.SecuritySupport;
import jdk.xml.internal.XMLSecurityManager;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
@ -37,7 +37,7 @@ import org.xml.sax.XMLReader;
* Creates XMLReader objects and caches them for re-use.
* This class follows the singleton pattern.
*
* @LastModified: May 2021
* @LastModified: Jan 2022
*/
public class XMLReaderManager {
@ -143,9 +143,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 = JdkConstants.JDK_DEBUG_LIMIT;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@ -22,6 +22,7 @@ package com.sun.org.apache.xpath.internal;
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.QName;
import com.sun.org.apache.xml.internal.utils.SAXSourceLocator;
@ -35,12 +36,13 @@ import java.util.List;
import javax.xml.transform.ErrorListener;
import javax.xml.transform.SourceLocator;
import javax.xml.transform.TransformerException;
import jdk.xml.internal.XMLSecurityManager;
/**
* The XPath class wraps an expression object and provides general services
* for execution of that expression.
* @xsl.usage advanced
* @LastModified: May 2019
* @LastModified: Jan 2022
*/
public class XPath implements Serializable, ExpressionOwner
{
@ -160,40 +162,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);
}
/**
@ -207,22 +180,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)
@ -261,13 +239,32 @@ public class XPath implements Serializable, ExpressionOwner
*
* @throws javax.xml.transform.TransformerException if syntax or other error.
*/
public XPath(
String exprString, SourceLocator locator, PrefixResolver prefixResolver, int type)
throws javax.xml.transform.TransformerException
public XPath(String exprString, SourceLocator locator, PrefixResolver prefixResolver,
int type)
throws TransformerException
{
this(exprString, locator, prefixResolver, type, null);
}
/**
* Constructs an XPath object.
*
* @param exprString The XPath expression.
* @param locator The location of the expression, may be null.
* @param prefixResolver A prefix resolver to use to resolve prefixes to
* namespace URIs.
* @param type one of {@link #SELECT} or {@link #MATCH}.
* @param errorListener The error listener, or null if default should be used.
* @param funcTable the function table
* @throws TransformerException
*/
public XPath(String exprString, SourceLocator locator, PrefixResolver prefixResolver,
int type, ErrorListener errorListener, FunctionTable funcTable)
throws TransformerException
{
this(exprString, locator, prefixResolver, type, errorListener, funcTable, null);
}
/**
* Construct an XPath object.
*

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@ -20,15 +20,20 @@
package com.sun.org.apache.xpath.internal.compiler;
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.List;
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
* expression into tokens.
*
* @LastModified: Nov 2017
* @LastModified: Jan 2022
*/
class Lexer
{
@ -70,6 +75,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.
*
@ -77,14 +100,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;
}
/**
@ -92,7 +123,7 @@ class Lexer
* elements.
* @param pat XSLT Expression.
*
* @throws javax.xml.transform.TransformerException
* @throws TransformerException
*/
void tokenize(String pat) throws javax.xml.transform.TransformerException
{
@ -105,13 +136,14 @@ class Lexer
* @param pat XSLT Expression.
* @param targetStrings a list to hold Strings, may be null.
*
* @throws javax.xml.transform.TransformerException
* @throws TransformerException
*/
@SuppressWarnings("fallthrough") // on purpose at case '-', '(' and default
void tokenize(String pat, List<String> targetStrings)
throws javax.xml.transform.TransformerException
throws TransformerException
{
boolean isGroup = false;
m_compiler.m_currentPattern = pat;
m_patternMapSize = 0;
@ -136,7 +168,7 @@ class Lexer
switch (c)
{
case '\"' :
case Token.DQ :
{
if (startSubstring != -1)
{
@ -171,7 +203,7 @@ class Lexer
}
}
break;
case '\'' :
case Token.SQ :
if (startSubstring != -1)
{
isNum = false;
@ -190,9 +222,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 +252,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 +280,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 +313,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 +325,7 @@ class Lexer
if (0 == nesting)
{
if ('|' == c)
if (Token.VBAR == c)
{
if (null != targetStrings)
{
@ -298,18 +336,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 +376,7 @@ class Lexer
isAttrName = false;
startSubstring = -1;
posOfNSSep = -1;
m_opCount++;
addToTokenQueue(pat.substring(i - 1, i + 1));
break;
@ -337,6 +389,7 @@ class Lexer
// fall through on purpose
default :
isLiteral = true;
if (-1 == startSubstring)
{
startSubstring = i;
@ -347,6 +400,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 +444,20 @@ 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) {
Objects.checkIndex(index, s.length());
if (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 +580,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 +610,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 +646,13 @@ class Lexer
* @param posOfNSSep The position of the namespace seperator (':').
* @param posOfScan The end of the name index.
*
* @throws javax.xml.transform.TransformerException
* @throws TransformerException
*
* @return -1 always.
*/
private int mapNSTokens(String pat, int startSubstring, int posOfNSSep,
int posOfScan)
throws javax.xml.transform.TransformerException
throws TransformerException
{
String prefix = "";

View File

@ -0,0 +1,76 @@
/*
* 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) {
return Arrays.stream(OPERATORS).anyMatch(str::equals);
}
private Token() {
//to prevent instantiation
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@ -20,21 +20,22 @@
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;
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;
/**
* 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
{
@ -75,13 +76,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;
}
/**
@ -99,18 +105,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);
@ -178,18 +184,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);
@ -382,9 +388,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
{
@ -496,10 +502,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))
@ -524,10 +530,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))
@ -749,9 +755,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();
}
@ -763,16 +769,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);
@ -790,16 +796,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);
@ -823,9 +829,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);
@ -837,7 +843,7 @@ public class XPathParser
if (null != m_token)
{
if (tokenIs('!') && lookahead('=', 1))
if (tokenIs(Token.EM) && lookahead(Token.EQ, 1))
{
nextToken();
nextToken();
@ -850,7 +856,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);
@ -883,9 +889,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);
@ -897,11 +903,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);
@ -918,11 +924,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);
@ -958,9 +964,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);
@ -972,7 +978,7 @@ public class XPathParser
if (null != m_token)
{
if (tokenIs('+'))
if (tokenIs(Token.PLUS))
{
nextToken();
insertOp(addPos, 2, OpCodes.OP_PLUS);
@ -984,7 +990,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);
@ -1016,9 +1022,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);
@ -1030,7 +1036,7 @@ public class XPathParser
if (null != m_token)
{
if (tokenIs('*'))
if (tokenIs(Token.STAR))
{
nextToken();
insertOp(addPos, 2, OpCodes.OP_MULT);
@ -1042,7 +1048,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);
@ -1054,7 +1060,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);
@ -1066,7 +1072,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);
@ -1089,15 +1095,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);
@ -1117,9 +1123,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);
@ -1137,9 +1143,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);
@ -1163,9 +1169,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);
@ -1188,9 +1194,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);
@ -1201,7 +1207,7 @@ public class XPathParser
{
PathExpr();
if (tokenIs('|'))
if (tokenIs(Token.VBAR))
{
if (false == foundUnion)
{
@ -1234,9 +1240,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);
@ -1249,7 +1255,7 @@ public class XPathParser
// have been inserted.
boolean locationPathStarted = (filterExprMatch==FILTER_MATCH_PREDICATES);
if (tokenIs('/'))
if (tokenIs(Token.SLASH))
{
nextToken();
@ -1299,9 +1305,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);
@ -1310,13 +1316,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();
}
@ -1354,16 +1360,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();
@ -1373,7 +1379,7 @@ public class XPathParser
matchFound = true;
}
else if (m_tokenChar == '$')
else if (m_tokenChar == Token.DOLLAR)
{
nextToken(); // consume '$'
appendOp(2, OpCodes.OP_VARIABLE);
@ -1384,12 +1390,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);
@ -1407,7 +1413,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();
}
@ -1424,9 +1430,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);
@ -1444,14 +1450,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);
@ -1491,22 +1497,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!");
@ -1514,7 +1521,7 @@ public class XPathParser
}
}
consumeExpected(')');
consumeExpected(Token.RPAREN);
// Terminate for safety.
m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), OpCodes.ENDOP);
@ -1533,9 +1540,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);
@ -1543,7 +1550,7 @@ public class XPathParser
// int locationPathOpPos = opPos;
appendOp(2, OpCodes.OP_LOCATIONPATH);
boolean seenSlash = tokenIs('/');
boolean seenSlash = tokenIs(Token.SLASH);
if (seenSlash)
{
@ -1584,17 +1591,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();
@ -1616,13 +1623,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
@ -1654,11 +1661,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.");
}
@ -1669,7 +1676,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);
@ -1682,12 +1689,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();
}
@ -1716,23 +1723,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;
@ -1763,9 +1770,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);
@ -1791,12 +1798,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);
@ -1814,17 +1821,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
@ -1834,9 +1841,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);
}
@ -1846,7 +1853,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);
@ -1863,7 +1870,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);
}
@ -1873,7 +1880,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);
@ -1891,11 +1898,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();
@ -1910,9 +1917,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);
@ -1932,12 +1939,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);
@ -1979,16 +1986,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
@ -2019,9 +2026,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)
@ -2062,16 +2069,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();
}
@ -2090,9 +2097,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);
@ -2105,17 +2112,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);
@ -2133,9 +2140,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);
@ -2168,7 +2175,7 @@ public class XPathParser
if (relativePathStatus != RELATIVE_PATH_NOT_PERMITTED)
{
if (!tokenIs('|') && (null != m_token))
if (!tokenIs(Token.VBAR) && (null != m_token))
{
RelativePathPattern();
}
@ -2193,9 +2200,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();
}
@ -2206,17 +2213,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();
@ -2236,10 +2243,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);
}
@ -2253,10 +2260,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);
@ -2265,22 +2272,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;
@ -2298,7 +2305,7 @@ public class XPathParser
nextToken();
nextToken();
}
else if (tokenIs('/'))
else if (tokenIs(Token.SLASH))
{
if (!isLeadingSlashPermitted)
{
@ -2327,7 +2334,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();
}
@ -2346,7 +2353,7 @@ public class XPathParser
// If current step is on the attribute axis (e.g., "@x//b"), we won't
// change the current step, and let following step be marked as
// MATCH_ANY_ANCESTOR on next call instead.
if ((matchTypePos > -1) && tokenIs('/') && lookahead('/', 1))
if ((matchTypePos > -1) && tokenIs(Token.SLASH) && lookahead(Token.SLASH, 1))
{
m_ops.setOp(matchTypePos, OpCodes.MATCH_ANY_ANCESTOR);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@ -30,13 +30,14 @@ import javax.xml.xpath.XPathVariableResolver;
import jdk.xml.internal.JdkConstants;
import jdk.xml.internal.JdkProperty;
import jdk.xml.internal.JdkXmlFeatures;
import jdk.xml.internal.XMLSecurityManager;
/**
* The XPathFactory builds XPaths.
*
* @author Ramesh Mandava
*
* @LastModified: Nov 2021
* @LastModified: Jan 2022
*/
public class XPathFactoryImpl extends XPathFactory {
@ -69,6 +70,11 @@ public class XPathFactoryImpl extends XPathFactory {
*/
private final JdkXmlFeatures _featureManager;
/**
* The XML security manager
*/
private XMLSecurityManager _xmlSecMgr;
/**
* javax.xml.xpath.XPathFactory implementation.
*/
@ -79,7 +85,9 @@ public class XPathFactoryImpl extends XPathFactory {
_isNotSecureProcessing = false;
}
_featureManager = new JdkXmlFeatures(!_isNotSecureProcessing);
_xmlSecMgr = new XMLSecurityManager(true);
}
/**
* <p>Is specified object model supported by this
* <code>XPathFactory</code>?</p>
@ -126,9 +134,8 @@ public class XPathFactoryImpl extends XPathFactory {
* @return New <code>XPath</code>
*/
public javax.xml.xpath.XPath newXPath() {
return new com.sun.org.apache.xpath.internal.jaxp.XPathImpl(
xPathVariableResolver, xPathFunctionResolver,
!_isNotSecureProcessing, _featureManager );
return new XPathImpl(xPathVariableResolver, xPathFunctionResolver,
!_isNotSecureProcessing, _featureManager, _xmlSecMgr);
}
/**
@ -311,7 +318,23 @@ public class XPathFactoryImpl extends XPathFactory {
xPathVariableResolver = resolver;
}
@Override
/**
* Sets a property for the {@code XPathFactory}. The property applies to
* {@code XPath} objects that the {@code XPathFactory} creates. It has no
* impact on {@code XPath} objects that are already created.
* <p>
* A property can either be defined in the {@code XPathFactory}, or by the
* underlying implementation.
*
* @param name the property name
* @param value the value for the property
*
* @throws IllegalArgumentException if the property name is not recognized,
* or the value can not be assigned
* @throws UnsupportedOperationException if the implementation does not
* support the method
* @throws NullPointerException if the {@code name} is {@code null}
*/
public void setProperty(String name, String value) {
// property name cannot be null
if (name == null) {
@ -321,6 +344,11 @@ public class XPathFactoryImpl extends XPathFactory {
throw new NullPointerException(fmsg);
}
if (_xmlSecMgr != null &&
_xmlSecMgr.setLimit(name, JdkProperty.State.APIPROPERTY, value)) {
return;
}
// property name not recognized
String fmsg = XSLMessages.createXPATHMessage(
XPATHErrorResources.ER_PROPERTY_UNKNOWN,
@ -328,7 +356,19 @@ public class XPathFactoryImpl extends XPathFactory {
throw new IllegalArgumentException(fmsg);
}
@Override
/**
* Returns the value of the specified property.
*
* @param name the property name
* @return the value of the property.
*
* @throws IllegalArgumentException if the property name is not recognized
* @throws UnsupportedOperationException if the implementation does not
* support the method
* @throws NullPointerException if the {@code name} is {@code null}
*
* @since 18
*/
public String getProperty(String name) {
// property name cannot be null
if (name == null) {
@ -338,6 +378,13 @@ public class XPathFactoryImpl extends XPathFactory {
throw new NullPointerException(fmsg);
}
/** Check to see if the property is managed by the security manager **/
String propertyValue = (_xmlSecMgr != null) ?
_xmlSecMgr.getLimitAsString(name) : null;
if (propertyValue != null) {
return propertyValue;
}
// unknown property
String fmsg = XSLMessages.createXPATHMessage(
XPATHErrorResources.ER_GETTING_UNKNOWN_PROPERTY,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@ -32,6 +32,7 @@ import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFunctionResolver;
import javax.xml.xpath.XPathVariableResolver;
import jdk.xml.internal.JdkXmlFeatures;
import jdk.xml.internal.XMLSecurityManager;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
@ -45,6 +46,8 @@ import org.xml.sax.InputSource;
* Updated 12/04/2014:
* New methods: evaluateExpression
* Refactored to share code with XPathExpressionImpl.
*
* @LastModified: Jan 2022
*/
public class XPathImpl extends XPathImplUtil implements javax.xml.xpath.XPath {
@ -54,18 +57,19 @@ public class XPathImpl extends XPathImplUtil implements javax.xml.xpath.XPath {
private NamespaceContext namespaceContext=null;
XPathImpl(XPathVariableResolver vr, XPathFunctionResolver fr) {
this(vr, fr, false, new JdkXmlFeatures(false));
this(vr, fr, false, new JdkXmlFeatures(false), new XMLSecurityManager(true));
}
XPathImpl(XPathVariableResolver vr, XPathFunctionResolver fr,
boolean featureSecureProcessing, JdkXmlFeatures featureManager) {
boolean featureSecureProcessing, JdkXmlFeatures featureManager,
XMLSecurityManager xmlSecMgr) {
this.origVariableResolver = this.variableResolver = vr;
this.origFunctionResolver = this.functionResolver = fr;
this.featureSecureProcessing = featureSecureProcessing;
this.featureManager = featureManager;
overrideDefaultParser = featureManager.getFeature(
JdkXmlFeatures.XmlFeature.JDK_OVERRIDE_PARSER);
this.xmlSecMgr = xmlSecMgr;
}
@ -113,8 +117,8 @@ public class XPathImpl extends XPathImplUtil implements javax.xml.xpath.XPath {
private XObject eval(String expression, Object contextItem)
throws TransformerException {
requireNonNull(expression, "XPath expression");
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);
XPath xpath = new XPath(expression, null, prefixResolver, XPath.SELECT,
null, null, xmlSecMgr);
return eval(contextItem, xpath);
}
@ -159,8 +163,8 @@ public class XPathImpl extends XPathImplUtil implements javax.xml.xpath.XPath {
throws XPathExpressionException {
requireNonNull(expression, "XPath expression");
try {
com.sun.org.apache.xpath.internal.XPath xpath = new XPath (expression, null,
prefixResolver, com.sun.org.apache.xpath.internal.XPath.SELECT);
XPath xpath = new XPath(expression, null, prefixResolver, XPath.SELECT,
null, null, xmlSecMgr);
// Can have errorListener
XPathExpressionImpl ximpl = new XPathExpressionImpl (xpath,
prefixResolver, functionResolver, variableResolver,

View File

@ -43,6 +43,7 @@ import javax.xml.xpath.XPathNodes;
import javax.xml.xpath.XPathVariableResolver;
import jdk.xml.internal.JdkXmlFeatures;
import jdk.xml.internal.JdkXmlUtils;
import jdk.xml.internal.XMLSecurityManager;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.traversal.NodeIterator;
@ -52,6 +53,8 @@ import org.xml.sax.SAXException;
/**
* This class contains several utility methods used by XPathImpl and
* XPathExpressionImpl
*
* @LastModified: Jan 2022
*/
class XPathImplUtil {
XPathFunctionResolver functionResolver;
@ -63,6 +66,7 @@ class XPathImplUtil {
// extensions function need to throw XPathFunctionException
boolean featureSecureProcessing = false;
JdkXmlFeatures featureManager;
XMLSecurityManager xmlSecMgr;
/**
* Evaluate an XPath context using the internal XPath engine

View File

@ -171,7 +171,11 @@ class XPathResultImpl<T> implements XPathEvaluationResult<T> {
case XObject.CLASS_RTREEFRAG: //NODE
NodeIterator ni = resultObject.nodeset();
//Return the first node, or null
return type.cast(ni.nextNode());
try {
return type.cast(ni.nextNode());
} catch (RuntimeException e) {
throw new TransformerException(e.getMessage(), e.getCause());
}
}
return null;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@ -31,7 +31,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: Nov 2021
* @LastModified: Jan 2022
*/
public class XPATHErrorResources extends ListResourceBundle
{
@ -326,6 +326,9 @@ public static final String ER_IGNORABLE_WHITESPACE_NOT_HANDLED =
public static final String ER_PROPERTY_UNKNOWN = "ER_PROPERTY_UNKNOWN";
public static final String ER_GETTING_NULL_PROPERTY = "ER_GETTING_NULL_PROPERTY";
public static final String ER_GETTING_UNKNOWN_PROPERTY = "ER_GETTING_UNKNOWN_PROPERTY";
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 =
@ -860,6 +863,14 @@ public static final String ER_IGNORABLE_WHITESPACE_NOT_HANDLED =
{ ER_GETTING_UNKNOWN_PROPERTY,
"Trying to get the unknown property \"{0}\":{1}#getProperty({0})"},
{ ER_XPATH_GROUP_LIMIT,
"JAXP0801001: the compiler encountered an XPath expression containing "
+ "''{0}'' groups that exceeds the ''{1}'' limit set by ''{2}''."},
{ ER_XPATH_OPERATOR_LIMIT,
"JAXP0801002: the compiler encountered an XPath expression containing "
+ "''{0}'' operators that exceeds the ''{1}'' limit set by ''{2}''."},
//END: Definitions of error keys used in exception messages of JAXP 1.3 XPath API implementation
// Warnings...

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 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
@ -205,6 +205,21 @@ public final class JdkConstants {
*/
public static final String SP_MAX_ELEMENT_DEPTH = "jdk.xml.maxElementDepth";
/**
* 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";
/**
* JDK TransformerFactory and Transformer attribute that specifies a class
* loader that will be used for extension functions class loading

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, 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
@ -51,20 +51,43 @@ import static jdk.xml.internal.JdkConstants.RESET_SYMBOL_TABLE;
*/
public final class JdkProperty<T> {
private ImplPropMap pName;
private final ImplPropMap pName;
private final Class<T> pType;
private T pValue;
private State pState = State.DEFAULT;
/**
* Constructs a JDkProperty.
* @param name the name of the property
* @param type the type of the value
* @param value the initial value
* @param state the state of the property
*/
public JdkProperty(ImplPropMap name, T value, State state) {
public JdkProperty(ImplPropMap name, Class<T> type, T value, State state) {
this.pName = name;
this.pType = type;
this.pValue = value;
this.pState = state;
readSystemProperty();
}
/**
* Read from system properties, or those in jaxp.properties
*/
private void readSystemProperty() {
if (pState == State.DEFAULT) {
T value = null;
if (pName.systemProperty() != null) {
value = SecuritySupport.getJAXPSystemProperty(pType, pName.systemProperty(), null);
}
if (value == null && pName.systemPropertyOld() != null) {
value = SecuritySupport.getJAXPSystemProperty(pType, pName.systemPropertyOld(), null);
}
if (value != null) {
pValue = value;
pState = State.SYSTEMPROPERTY;
}
}
}
/**

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 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
@ -24,7 +24,6 @@
*/
package jdk.xml.internal;
import com.sun.org.apache.xalan.internal.utils.XMLSecurityManager;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import com.sun.org.apache.xerces.internal.impl.Constants;
import com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl;

View File

@ -0,0 +1,248 @@
/*
* 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;
/**
* 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(JdkConstants.SP_ENTITY_EXPANSION_LIMIT, JdkConstants.ENTITY_EXPANSION_LIMIT),
MAX_OCCUR_NODE_LIMIT(JdkConstants.SP_MAX_OCCUR_LIMIT, JdkConstants.MAX_OCCUR_LIMIT),
ELEMENT_ATTRIBUTE_LIMIT(JdkConstants.SP_ELEMENT_ATTRIBUTE_LIMIT, JdkConstants.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.GENERAL_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.GENERAL_ENTITY_SIZE_LIMIT.ordinal()) {
names[limit.ordinal()] = null;
values[limit.ordinal()] = 0;
caches[limit.ordinal()] = null;
totalValue[limit.ordinal()] = 0;
}
}
public void debugPrint(XMLSecurityManager securityManager) {
Formatter formatter = new Formatter();
System.out.println(formatter.format("%30s %15s %15s %15s %30s",
"Property","Limit","Total size","Size","Entity Name"));
for (Limit limit : Limit.values()) {
formatter = new Formatter();
System.out.println(formatter.format("%30s %15d %15d %15d %30s",
limit.name(),
securityManager.getLimit(limit),
totalValue[limit.ordinal()],
values[limit.ordinal()],
names[limit.ordinal()]));
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2021, 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
@ -22,23 +22,17 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.xml.internal;
package com.sun.org.apache.xalan.internal.utils;
import com.sun.org.apache.xerces.internal.util.SecurityManager;
import java.util.concurrent.CopyOnWriteArrayList;
import jdk.xml.internal.JdkConstants;
import jdk.xml.internal.JdkProperty.ImplPropMap;
import jdk.xml.internal.JdkProperty.State;
import jdk.xml.internal.SecuritySupport;
import jdk.xml.internal.JdkProperty.ImplPropMap;
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 {
@ -48,38 +42,47 @@ public final class XMLSecurityManager {
*/
@SuppressWarnings("deprecation")
public static enum Limit {
ENTITY_EXPANSION_LIMIT("EntityExpansionLimit", JdkConstants.JDK_ENTITY_EXPANSION_LIMIT,
JdkConstants.SP_ENTITY_EXPANSION_LIMIT, 0, 64000),
JdkConstants.SP_ENTITY_EXPANSION_LIMIT, 0, 64000, Processor.PARSER),
MAX_OCCUR_NODE_LIMIT("MaxOccurLimit", JdkConstants.JDK_MAX_OCCUR_LIMIT,
JdkConstants.SP_MAX_OCCUR_LIMIT, 0, 5000),
JdkConstants.SP_MAX_OCCUR_LIMIT, 0, 5000, Processor.PARSER),
ELEMENT_ATTRIBUTE_LIMIT("ElementAttributeLimit", JdkConstants.JDK_ELEMENT_ATTRIBUTE_LIMIT,
JdkConstants.SP_ELEMENT_ATTRIBUTE_LIMIT, 0, 10000),
JdkConstants.SP_ELEMENT_ATTRIBUTE_LIMIT, 0, 10000, Processor.PARSER),
TOTAL_ENTITY_SIZE_LIMIT("TotalEntitySizeLimit", JdkConstants.JDK_TOTAL_ENTITY_SIZE_LIMIT,
JdkConstants.SP_TOTAL_ENTITY_SIZE_LIMIT, 0, 50000000),
JdkConstants.SP_TOTAL_ENTITY_SIZE_LIMIT, 0, 50000000, Processor.PARSER),
GENERAL_ENTITY_SIZE_LIMIT("MaxEntitySizeLimit", JdkConstants.JDK_GENERAL_ENTITY_SIZE_LIMIT,
JdkConstants.SP_GENERAL_ENTITY_SIZE_LIMIT, 0, 0),
JdkConstants.SP_GENERAL_ENTITY_SIZE_LIMIT, 0, 0, Processor.PARSER),
PARAMETER_ENTITY_SIZE_LIMIT("MaxEntitySizeLimit", JdkConstants.JDK_PARAMETER_ENTITY_SIZE_LIMIT,
JdkConstants.SP_PARAMETER_ENTITY_SIZE_LIMIT, 0, 1000000),
JdkConstants.SP_PARAMETER_ENTITY_SIZE_LIMIT, 0, 1000000, Processor.PARSER),
MAX_ELEMENT_DEPTH_LIMIT("MaxElementDepthLimit", JdkConstants.JDK_MAX_ELEMENT_DEPTH,
JdkConstants.SP_MAX_ELEMENT_DEPTH, 0, 0),
JdkConstants.SP_MAX_ELEMENT_DEPTH, 0, 0, Processor.PARSER),
MAX_NAME_LIMIT("MaxXMLNameLimit", JdkConstants.JDK_XML_NAME_LIMIT,
JdkConstants.SP_XML_NAME_LIMIT, 1000, 1000),
JdkConstants.SP_XML_NAME_LIMIT, 1000, 1000, Processor.PARSER),
ENTITY_REPLACEMENT_LIMIT("EntityReplacementLimit", JdkConstants.JDK_ENTITY_REPLACEMENT_LIMIT,
JdkConstants.SP_ENTITY_REPLACEMENT_LIMIT, 0, 3000000);
JdkConstants.SP_ENTITY_REPLACEMENT_LIMIT, 0, 3000000, Processor.PARSER),
XPATH_GROUP_LIMIT("XPathGroupLimit", JdkConstants.XPATH_GROUP_LIMIT,
JdkConstants.XPATH_GROUP_LIMIT, 10, 10, Processor.XPATH),
XPATH_OP_LIMIT("XPathExprOpLimit", JdkConstants.XPATH_OP_LIMIT,
JdkConstants.XPATH_OP_LIMIT, 100, 100, Processor.XPATH),
XPATH_TOTALOP_LIMIT("XPathTotalOpLimit", JdkConstants.XPATH_TOTALOP_LIMIT,
JdkConstants.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;
}
/**
@ -130,6 +133,10 @@ public final class XMLSecurityManager {
return defaultValue;
}
public boolean isSupported(Processor p) {
return processor == p;
}
int secureValue() {
return secureValue;
}
@ -140,12 +147,9 @@ public final class XMLSecurityManager {
*/
public static enum NameMap {
ENTITY_EXPANSION_LIMIT(JdkConstants.SP_ENTITY_EXPANSION_LIMIT,
JdkConstants.ENTITY_EXPANSION_LIMIT),
MAX_OCCUR_NODE_LIMIT(JdkConstants.SP_MAX_OCCUR_LIMIT,
JdkConstants.MAX_OCCUR_LIMIT),
ELEMENT_ATTRIBUTE_LIMIT(JdkConstants.SP_ELEMENT_ATTRIBUTE_LIMIT,
JdkConstants.ELEMENT_ATTRIBUTE_LIMIT);
ENTITY_EXPANSION_LIMIT(JdkConstants.SP_ENTITY_EXPANSION_LIMIT, JdkConstants.ENTITY_EXPANSION_LIMIT),
MAX_OCCUR_NODE_LIMIT(JdkConstants.SP_MAX_OCCUR_LIMIT, JdkConstants.MAX_OCCUR_LIMIT),
ELEMENT_ATTRIBUTE_LIMIT(JdkConstants.SP_ELEMENT_ATTRIBUTE_LIMIT, JdkConstants.ELEMENT_ATTRIBUTE_LIMIT);
final String newName;
final String oldName;
@ -161,14 +165,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
*/
@ -198,9 +220,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();
@ -215,6 +238,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());
@ -224,6 +248,33 @@ public final class XMLSecurityManager {
}
}
/**
* Return the state of secure processing
* @return the state of secure processing
*/
public boolean isSecureProcessing() {
return secureProcessing;
}
/**
* Finds a limit's new name with the given property name.
* @param propertyName the property name specified
* @return the limit's new name if found, null otherwise
*/
public String find(String propertyName) {
for (Limit limit : Limit.values()) {
if (limit.is(propertyName)) {
// current spec: new property name == systemProperty
return limit.systemProperty();
}
}
//ENTITYCOUNT's new name is qName
if (ImplPropMap.ENTITYCOUNT.is(propertyName)) {
return ImplPropMap.ENTITYCOUNT.qName();
}
return null;
}
/**
* Set limit by property name and state
* @param propertyName property name
@ -265,7 +316,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;
@ -302,9 +352,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
@ -318,17 +367,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
*
@ -342,14 +380,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
@ -361,6 +400,7 @@ public final class XMLSecurityManager {
return Integer.toString(values[index]);
}
/**
* Return the state of the limit property
*
@ -402,6 +442,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(JdkConstants.JDK_YES)) {
limitAnalyzer.debugPrint(this);
}
}
/**
* Indicate if a property is set explicitly
* @param index
@ -414,6 +533,7 @@ public final class XMLSecurityManager {
public boolean printEntityCountInfo() {
return printEntityCountInfo.equals(JdkConstants.JDK_YES);
}
/**
* Read from system properties, or those in jaxp.properties
*/
@ -477,4 +597,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;
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 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
@ -407,7 +407,7 @@
* <tr>
* <th scope="row" style="font-weight:normal" id="XPATH">XPath</th>
* <td style="text-align:center">XPath</td>
* <td>
* <td>N/A
* </td>
* <td>
* {@code XPathFactory factory = XPathFactory.newInstance();} <br>
@ -432,12 +432,13 @@
* <th scope="col" rowspan="2">Full Name (<a href="#NamingConvention">prefix + name</a>)
* <a href="#Note1">[1]</a></th>
* <th scope="col" rowspan="2">Description</th>
* <th scope="col" rowspan="2">System Property <a href="#Note2">[2]</a></th>
* <th scope="col" rowspan="2">jaxp.properties <a href="#Note2">[2]</a></th>
* <th scope="col" colspan="4" style="text-align:center">Value <a href="#Note3">[3]</a></th>
* <th scope="col" rowspan="2">Security <a href="#Note4">[4]</a></th>
* <th scope="col" rowspan="2">Supported Processor <a href="#Note5">[5]</a></th>
* <th scope="col" rowspan="2">Since <a href="#Note6">[6]</a></th>
* <th scope="col" rowspan="2">API Property <a href="#Note2">[2]</a></th>
* <th scope="col" rowspan="2">System Property <a href="#Note3">[3]</a></th>
* <th scope="col" rowspan="2">jaxp.properties <a href="#Note3">[3]</a></th>
* <th scope="col" colspan="4" style="text-align:center">Value <a href="#Note4">[4]</a></th>
* <th scope="col" rowspan="2">Security <a href="#Note5">[5]</a></th>
* <th scope="col" rowspan="2">Supported Processor <a href="#Note6">[6]</a></th>
* <th scope="col" rowspan="2">Since <a href="#Note7">[7]</a></th>
* </tr>
* <tr>
* <th scope="col">Type</th>
@ -455,6 +456,7 @@
* </td>
* <td style="text-align:center" rowspan="9">yes</td>
* <td style="text-align:center" rowspan="9">yes</td>
* <td style="text-align:center" rowspan="9">yes</td>
* <td style="text-align:center" rowspan="9">Integer</td>
* <td rowspan="9">
* A positive integer. A value less than or equal to 0 indicates no limit.
@ -544,6 +546,7 @@
* </td>
* <td style="text-align:center">yes</td>
* <td style="text-align:center">yes</td>
* <td style="text-align:center">yes</td>
* <td style="text-align:center">boolean</td>
* <td style="text-align:center">true/false</td>
* <td style="text-align:center">false</td>
@ -567,6 +570,7 @@
* </td>
* <td style="text-align:center">yes</td>
* <td style="text-align:center">yes</td>
* <td style="text-align:center">yes</td>
* <td style="text-align:center">String</td>
* <td style="text-align:center">yes/no</td>
* <td style="text-align:center">no</td>
@ -584,6 +588,7 @@
* </td>
* <td style="text-align:center">yes</td>
* <td style="text-align:center">yes</td>
* <td style="text-align:center">yes</td>
* <td style="text-align:center">Integer</td>
* <td>A positive integer. A value less than
* or equal to 0 indicates that the property is not specified. If the value is not
@ -599,6 +604,7 @@
* <td>Sets a non-null ClassLoader instance to be used for loading XSLTC java
* extension functions.
* </td>
* <td style="text-align:center">yes</td>
* <td style="text-align:center">no</td>
* <td style="text-align:center">no</td>
* <td style="text-align:center">Object</td>
@ -609,6 +615,46 @@
* <td style="text-align:center"><a href="#Transform">Transform</a></td>
* <td style="text-align:center">9</td>
* </tr>
* <tr>
* <td id="extensionClassLoader">jdk.xml.xpathExprGrpLimit</td>
* <td>Limits the number of groups an XPath expression can contain.
* </td>
* <td style="text-align:center" rowspan="2">
* <a href="#Transform">Transform</a>:yes<br>
* <a href="#XPATH">XPath</a>:no
* </td>
* <td style="text-align:center" rowspan="3">yes</td>
* <td style="text-align:center" rowspan="3">yes</td>
* <td style="text-align:center" rowspan="3">Integer</td>
* <td rowspan="3">A positive integer. A value less than or equal to 0 indicates no limit.
* If the value is not an integer, a NumberFormatException is thrown. </td>
* <td style="text-align:center">10</td>
* <td style="text-align:center">10</td>
* <td style="text-align:center" rowspan="3">Yes</td>
* <td style="text-align:center" rowspan="2">
* <a href="#Transform">Transform</a><br>
* <a href="#XPath">XPath</a>
* </td>
* <td style="text-align:center" rowspan="3">19</td>
* </tr>
* <tr>
* <td id="extensionClassLoader">jdk.xml.xpathExprOpLimit</td>
* <td>Limits the number of operators an XPath expression can contain.
* </td>
* <td style="text-align:center">100</td>
* <td style="text-align:center">100</td>
* </tr>
* <tr>
* <td id="extensionClassLoader">jdk.xml.xpathTotalOpLimit</td>
* <td>Limits the total number of XPath operators in an XSL Stylesheet.
* </td>
* <td style="text-align:center">yes</td>
* <td style="text-align:center">10000</td>
* <td style="text-align:center">10000</td>
* <td style="text-align:center">
* <a href="#Transform">Transform</a><br>
* </td>
* </tr>
* </tbody>
* </table>
* <p>
@ -622,12 +668,13 @@
* <th scope="col" rowspan="2">Full Name (<a href="#NamingConvention">prefix + name</a>)
* <a href="#Note1">[1]</a></th>
* <th scope="col" rowspan="2">Description</th>
* <th scope="col" rowspan="2">System Property <a href="#Note2">[2]</a></th>
* <th scope="col" rowspan="2">jaxp.properties <a href="#Note2">[2]</a></th>
* <th scope="col" colspan="4" style="text-align:center">Value <a href="#Note3">[3]</a></th>
* <th scope="col" rowspan="2">Security <a href="#Note4">[4]</a></th>
* <th scope="col" rowspan="2">Supported Processor <a href="#Note5">[5]</a></th>
* <th scope="col" rowspan="2">Since <a href="#Note6">[6]</a></th>
* <th scope="col" rowspan="2">API Property <a href="#Note2">[2]</a></th>
* <th scope="col" rowspan="2">System Property <a href="#Note3">[3]</a></th>
* <th scope="col" rowspan="2">jaxp.properties <a href="#Note3">[3]</a></th>
* <th scope="col" colspan="4" style="text-align:center">Value <a href="#Note4">[4]</a></th>
* <th scope="col" rowspan="2">Security <a href="#Note5">[5]</a></th>
* <th scope="col" rowspan="2">Supported Processor <a href="#Note6">[6]</a></th>
* <th scope="col" rowspan="2">Since <a href="#Note7">[7]</a></th>
* </tr>
* <tr>
* <th scope="col">Type</th>
@ -643,6 +690,7 @@
* </td>
* <td style="text-align:center" rowspan="3">yes</td>
* <td style="text-align:center" rowspan="3">yes</td>
* <td style="text-align:center" rowspan="3">yes</td>
* <td style="text-align:center" rowspan="3">Boolean</td>
* <td>
* true or false. True indicates that extension functions are allowed; False otherwise.
@ -700,11 +748,14 @@
* <p id="Note1">
* <b>[1]</b> The full name of a property should be used to set the property.
* <p id="Note2">
* <b>[2]</b> A value "yes" indicates there is a corresponding System Property
* <b>[2]</b> A value "yes" indicates that the property can be set through the
* processor or its factory, "no" otherwise.
* <p id="Note3">
* <b>[3]</b> A value "yes" indicates there is a corresponding System Property
* for the property, "no" otherwise.
*
* <p id="Note3">
* <b>[3]</b> The value must be exactly as listed in this table, case-sensitive.
* <p id="Note4">
* <b>[4]</b> The value must be exactly as listed in this table, case-sensitive.
* The value of the corresponding System Property is the String representation of
* the property value. If the type is boolean, the system property is true only
* if it is "true"; If the type is String, the system property is true only if
@ -713,15 +764,15 @@
* is Integer, the value of the System Property is the String representation of
* the value (e.g. "64000" for {@code entityExpansionLimit}).
*
* <p id="Note4">
* <b>[4]</b> A value "yes" indicates the property is a Security Property. Refer
* <p id="Note5">
* <b>[5]</b> A value "yes" indicates the property is a Security Property. Refer
* to the <a href="#ScopeAndOrder">Scope and Order</a> on how secure processing
* may affect the value of a Security Property.
* <p id="Note5">
* <b>[5]</b> One or more processors that support the property. The values of the
* field are IDs described in table <a href="#Processor">Processors</a>.
* <p id="Note6">
* <b>[6]</b> Indicates the initial release the property is introduced.
* <b>[6]</b> One or more processors that support the property. The values of the
* field are IDs described in table <a href="#Processor">Processors</a>.
* <p id="Note7">
* <b>[7]</b> Indicates the initial release the property is introduced.
*
* <h3>Legacy Property Names (deprecated)</h3>
* JDK releases prior to JDK 17 support the use of URI style prefix for properties.