8289486: Improve XSLT XPath operators count efficiency

Reviewed-by: naoto, lancea
This commit is contained in:
Joe Wang 2022-07-07 19:07:04 +00:00
parent a8eb728680
commit 3212dc9c6f
2 changed files with 55 additions and 28 deletions
src/java.xml/share/classes/com/sun
java_cup/internal/runtime
org/apache/xalan/internal/xsltc/compiler

@ -137,7 +137,7 @@ import java.util.Stack;
* @see com.sun.java_cup.internal.runtime.virtual_parse_stack
* @author Frank Flannery
*
* @LastModified: June 2022
* @LastModified: July 2022
*/
public abstract class lr_parser {
@ -150,6 +150,10 @@ public abstract class lr_parser {
private int opCount = 0;
private int totalOpCount = 0;
private int lastSym;
private boolean overLimit = false;
public int grpLimit = 0;
public int opLimit = 0;
public int totalOpLimit = 0;
/*-----------------------------------------------------------*/
/*--- Constructor(s) ----------------------------------------*/
@ -376,11 +380,13 @@ public abstract class lr_parser {
grpCount++;
}
opCount++; // function
totalOpCount++;
isLiteral = false;
} else if (contains(sym.OPERATORS, s.sym)) {
// axis nodetest is counted as one step, so not counted if last=DCOLON
if (lastSym != sym.DCOLON) {
opCount++;
totalOpCount++;
}
isLiteral = false;
}
@ -390,6 +396,16 @@ public abstract class lr_parser {
}
lastSym = s.sym;
/*
* Sets the overLimit status as soon as the count of operators is over the
* limit, which in turn triggers the XPathParser to report an error.
*/
if (grpLimit > 0 && grpCount > grpLimit
|| opLimit > 0 && opCount > opLimit
|| totalOpLimit > 0 && totalOpCount > totalOpLimit) {
overLimit = true;
}
return s;
}
@ -591,12 +607,14 @@ public abstract class lr_parser {
/* do user initialization */
user_init();
isLiteral = false;
overLimit = false;
grpCount = 0;
opCount = 0;
lastSym = -1;
/* get the first token */
cur_token = scan();
if (overLimit) return null;
/* push dummy Symbol with start state to get us underway */
stack.removeAllElements();
@ -671,12 +689,16 @@ public abstract class lr_parser {
lhs_sym = stack.peek();
}
}
if (overLimit) return null;
}
totalOpCount += opCount;
return lhs_sym;
}
public boolean isOverLimit() {
return overLimit;
}
/**
* Returns the count of operators in XPath expressions.
*

@ -43,12 +43,9 @@ import jdk.xml.internal.XMLSecurityManager.Limit;
* CUP v0.11b generated parser.
* This class was generated by CUP v0.11b on Nov 12, 2019.
*
* @LastModified: Jan 2022
* @LastModified: July 2022
*/
public class XPathParser extends lr_parser {
private int grpLimit = 0;
private int opLimit = 0;
private int totalOpLimit = 0;
/**
* Default constructor.
@ -1118,29 +1115,37 @@ public class XPathParser extends lr_parser {
_expression = expression;
_lineNumber = lineNumber;
Symbol s = super.parse();
int grpCount = getCount(ID_GROUP);
int opCount = getCount(ID_OPERATOR);
int totalOpCount = getCount(ID_TOTAL_OPERATOR);
/*
* While the Java CUP parser is used for parsing symbols, the error
* report mechanism has so far been kept within the Xalan implementation.
* An error, i.e. the count of operators is over the limit, is
* therefore handled here.
*/
if (isOverLimit()) {
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);
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) {