mirror of
https://github.com/openjdk/jdk.git
synced 2026-07-28 20:03:39 +00:00
8270504: Better Xpath expression handling
Reviewed-by: naoto, lancea, mschoene, rhalade
This commit is contained in:
parent
3268aba925
commit
616ea1692e
@ -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
|
||||
|
||||
@ -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));
|
||||
|
||||
@ -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());
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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};
|
||||
}
|
||||
|
||||
@ -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}''."},
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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() {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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.
|
||||
*
|
||||
|
||||
@ -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 = "";
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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...
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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()]));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user