You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by kk...@apache.org on 2014/04/29 01:35:36 UTC
svn commit: r1590842 - in /tomcat/trunk: java/org/apache/jasper/compiler/
test/org/apache/jasper/compiler/ test/webapp/bug5nnnn/ webapps/docs/
Author: kkolinko
Date: Mon Apr 28 23:35:36 2014
New Revision: 1590842
URL: http://svn.apache.org/r1590842
Log:
Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=56334
Additional tests and fixes
Includes the following:
1. Allow '\' in xmlns attributes of UninterpretedTag. A test added.
(Java escaping was missing. Xml-escaping is still missing. I think it is unlikely that anybody would use such values for xmlns attributes)
2. Fix interaction between Validator.ValidateVisitor.checkXmlAttributes(CustomTag ..) and getJspAttribute().
- EL expression was parsed twice in both methods. Now I am passing the already parsed EL.
- getJspAttribute() has EL validation code, so reduce duplication
- When calling getJspAttribute() you have to pass original attrs.getValue(i), not the textual value.
3. Fix Validator.ValidateVisitor.XmlEscapeNonELVisitor
- It was not EL-escaping its text. Tests added.
Modified:
tomcat/trunk/java/org/apache/jasper/compiler/ELParser.java
tomcat/trunk/java/org/apache/jasper/compiler/Generator.java
tomcat/trunk/java/org/apache/jasper/compiler/Validator.java
tomcat/trunk/test/org/apache/jasper/compiler/TestParser.java
tomcat/trunk/test/webapp/bug5nnnn/bug56334.jspx
tomcat/trunk/webapps/docs/changelog.xml
Modified: tomcat/trunk/java/org/apache/jasper/compiler/ELParser.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/compiler/ELParser.java?rev=1590842&r1=1590841&r2=1590842&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/jasper/compiler/ELParser.java (original)
+++ tomcat/trunk/java/org/apache/jasper/compiler/ELParser.java Mon Apr 28 23:35:36 2014
@@ -255,7 +255,7 @@ public class ELParser {
*
* @return The escaped version of the input
*/
- private static String escapeLiteralExpression(String input,
+ static String escapeLiteralExpression(String input,
boolean isDeferredSyntaxAllowedAsLiteral) {
int len = input.length();
int lastAppend = 0;
@@ -552,10 +552,10 @@ public class ELParser {
}
- protected static class TextBuilder extends ELNode.Visitor {
+ static class TextBuilder extends ELNode.Visitor {
- private final boolean isDeferredSyntaxAllowedAsLiteral;
- protected StringBuilder output = new StringBuilder();
+ protected final boolean isDeferredSyntaxAllowedAsLiteral;
+ protected final StringBuilder output = new StringBuilder();
protected TextBuilder(boolean isDeferredSyntaxAllowedAsLiteral) {
this.isDeferredSyntaxAllowedAsLiteral = isDeferredSyntaxAllowedAsLiteral;
Modified: tomcat/trunk/java/org/apache/jasper/compiler/Generator.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/compiler/Generator.java?rev=1590842&r1=1590841&r2=1590842&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/jasper/compiler/Generator.java (original)
+++ tomcat/trunk/java/org/apache/jasper/compiler/Generator.java Mon Apr 28 23:35:36 2014
@@ -1820,7 +1820,7 @@ class Generator {
out.print(attrs.getQName(i));
out.print("=");
out.print(DOUBLE_QUOTE);
- out.print(attrs.getValue(i).replace("\"", """));
+ out.print(escape(attrs.getValue(i).replace("\"", """)));
out.print(DOUBLE_QUOTE);
}
}
@@ -1839,7 +1839,7 @@ class Generator {
out.print(" + \"\\\"");
} else {
out.print(DOUBLE_QUOTE);
- out.print(jspAttrs[i].getValue().replace("\"", """));
+ out.print(escape(jspAttrs[i].getValue().replace("\"", """)));
out.print(DOUBLE_QUOTE);
}
}
Modified: tomcat/trunk/java/org/apache/jasper/compiler/Validator.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/compiler/Validator.java?rev=1590842&r1=1590841&r2=1590842&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/jasper/compiler/Validator.java (original)
+++ tomcat/trunk/java/org/apache/jasper/compiler/Validator.java Mon Apr 28 23:35:36 2014
@@ -561,7 +561,7 @@ class Validator {
// request-time expression
throwErrorIfExpression(n, "name", "jsp:param");
n.setValue(getJspAttribute(null, "value", null, null, n
- .getAttributeValue("value"), n, false));
+ .getAttributeValue("value"), n, null, false));
visitBody(n);
}
@@ -580,7 +580,7 @@ class Validator {
JspUtil.checkAttributes("Include action", n, includeActionAttrs,
err);
n.setPage(getJspAttribute(null, "page", null, null, n
- .getAttributeValue("page"), n, false));
+ .getAttributeValue("page"), n, null, false));
visitBody(n);
}
@@ -588,7 +588,7 @@ class Validator {
public void visit(Node.ForwardAction n) throws JasperException {
JspUtil.checkAttributes("Forward", n, forwardActionAttrs, err);
n.setPage(getJspAttribute(null, "page", null, null, n
- .getAttributeValue("page"), n, false));
+ .getAttributeValue("page"), n, null, false));
visitBody(n);
}
@@ -605,7 +605,7 @@ class Validator {
String value = n.getAttributeValue("value");
n.setValue(getJspAttribute(null, "value", null, null, value,
- n, false));
+ n, null, false));
boolean valueSpecified = n.getValue() != null;
@@ -641,7 +641,7 @@ class Validator {
err.jspError(n, "jsp.error.usebean.noSession");
Node.JspAttribute jattr = getJspAttribute(null, "beanName", null,
- null, n.getAttributeValue("beanName"), n, false);
+ null, n.getAttributeValue("beanName"), n, null, false);
n.setBeanName(jattr);
if (className != null && jattr != null)
err.jspError(n, "jsp.error.usebean.notBoth");
@@ -680,11 +680,11 @@ class Validator {
err.jspError(n, "jsp.error.plugin.nocode");
Node.JspAttribute width = getJspAttribute(null, "width", null,
- null, n.getAttributeValue("width"), n, false);
+ null, n.getAttributeValue("width"), n, null, false);
n.setWidth(width);
Node.JspAttribute height = getJspAttribute(null, "height", null,
- null, n.getAttributeValue("height"), n, false);
+ null, n.getAttributeValue("height"), n, null, false);
n.setHeight(height);
visitBody(n);
@@ -694,7 +694,7 @@ class Validator {
public void visit(Node.NamedAttribute n) throws JasperException {
JspUtil.checkAttributes("Attribute", n, attributeAttrs, err);
n.setOmit(getJspAttribute(null, "omit", null, null, n
- .getAttributeValue("omit"), n, false));
+ .getAttributeValue("omit"), n, null, false));
visitBody(n);
}
@@ -773,7 +773,7 @@ class Validator {
}
jspAttrs[i] = getJspAttribute(null, attrs.getQName(i),
attrs.getURI(i), attrs.getLocalName(i), value, n,
- false);
+ null, false);
}
n.setJspAttributes(jspAttrs);
}
@@ -922,12 +922,13 @@ class Validator {
if ("name".equals(attrs.getLocalName(i))) {
n.setNameAttribute(getJspAttribute(null, attrs.getQName(i),
attrs.getURI(i), attrs.getLocalName(i), attrs
- .getValue(i), n, false));
+ .getValue(i), n, null, false));
} else {
if (jspAttrIndex < jspAttrSize) {
- jspAttrs[jspAttrIndex++] = getJspAttribute(null, attrs
- .getQName(i), attrs.getURI(i), attrs
- .getLocalName(i), attrs.getValue(i), n, false);
+ jspAttrs[jspAttrIndex++] = getJspAttribute(null,
+ attrs.getQName(i), attrs.getURI(i),
+ attrs.getLocalName(i), attrs.getValue(i), n,
+ null, false);
}
}
}
@@ -1091,10 +1092,11 @@ class Validator {
pageInfo.isDeferredSyntaxAllowedAsLiteral() ||
libraryVersion < 2.1;
- String attributeValue;
+ String xmlAttributeValue = attrs.getValue(i);
+
ELNode.Nodes el = null;
if (!runtimeExpression && !pageInfo.isELIgnored()) {
- el = ELParser.parse(attrs.getValue(i),
+ el = ELParser.parse(xmlAttributeValue,
deferredSyntaxAllowedAsLiteral);
Iterator<ELNode> nodes = el.iterator();
while (nodes.hasNext()) {
@@ -1116,18 +1118,20 @@ class Validator {
}
}
}
- if (elExpression) {
- attributeValue = attrs.getValue(i);
- } else {
- // Should be a single Text node
- attributeValue = ((ELNode.Text) el.iterator().next()).getText();
- }
- } else {
- attributeValue = attrs.getValue(i);
}
boolean expression = runtimeExpression || elExpression;
+ // When attribute is not an expression,
+ // contains its textual value with \$ and \# escaping removed.
+ String textAttributeValue;
+ if (!elExpression && el != null) {
+ // Should be a single Text node
+ textAttributeValue = ((ELNode.Text) el.iterator().next()).getText();
+ } else {
+ textAttributeValue = xmlAttributeValue;
+ }
+
for (int j = 0; tldAttrs != null && j < tldAttrs.length; j++) {
if (attrs.getLocalName(i).equals(tldAttrs[j].getName())
&& (attrs.getURI(i) == null
@@ -1192,11 +1196,11 @@ class Validator {
Boolean.TYPE == expectedClass ||
expectedClass.isEnum()) {
try {
- expressionFactory.coerceToType(attributeValue, expectedClass);
+ expressionFactory.coerceToType(textAttributeValue, expectedClass);
} catch (Exception e) {
err.jspError
(n, "jsp.error.coerce_to_type",
- tldAttr.getName(), expectedType, attributeValue);
+ tldAttr.getName(), expectedType, textAttributeValue);
}
}
}
@@ -1204,7 +1208,7 @@ class Validator {
jspAttrs[i] = new Node.JspAttribute(tldAttr,
attrs.getQName(i), attrs.getURI(i),
attrs.getLocalName(i),
- attributeValue, false, null, false);
+ textAttributeValue, false, null, false);
} else {
if (deferred && !tldAttr.isDeferredMethod() && !tldAttr.isDeferredValue()) {
@@ -1218,30 +1222,11 @@ class Validator {
tldAttr.getName());
}
- if (elExpression) {
- // El expression
- validateFunctions(el, n);
- jspAttrs[i] = new Node.JspAttribute(tldAttr,
- attrs.getQName(i), attrs.getURI(i),
- attrs.getLocalName(i),
- attributeValue, false, el, false);
- ELContextImpl ctx = new ELContextImpl(
- expressionFactory);
- ctx.setFunctionMapper(getFunctionMapper(el));
- try {
- jspAttrs[i].validateEL(this.pageInfo.getExpressionFactory(), ctx);
- } catch (ELException e) {
- this.err.jspError(n.getStart(),
- "jsp.error.invalid.expression",
- attributeValue, e.toString());
- }
- } else {
- // Runtime expression
- jspAttrs[i] = getJspAttribute(tldAttr,
- attrs.getQName(i), attrs.getURI(i),
- attrs.getLocalName(i),
- attributeValue, n, false);
- }
+ // EL or Runtime expression
+ jspAttrs[i] = getJspAttribute(tldAttr,
+ attrs.getQName(i), attrs.getURI(i),
+ attrs.getLocalName(i),
+ xmlAttributeValue, n, el, false);
}
} else {
@@ -1254,13 +1239,14 @@ class Validator {
jspAttrs[i] = new Node.JspAttribute(tldAttr,
attrs.getQName(i), attrs.getURI(i),
attrs.getLocalName(i),
- attributeValue, false, null, false);
+ textAttributeValue, false, null, false);
}
if (expression) {
tagDataAttrs.put(attrs.getQName(i),
TagData.REQUEST_TIME_VALUE);
} else {
- tagDataAttrs.put(attrs.getQName(i), attributeValue);
+ tagDataAttrs.put(attrs.getQName(i),
+ textAttributeValue);
}
found = true;
break;
@@ -1270,7 +1256,7 @@ class Validator {
if (tagInfo.hasDynamicAttributes()) {
jspAttrs[i] = getJspAttribute(null, attrs.getQName(i),
attrs.getURI(i), attrs.getLocalName(i),
- attributeValue, n, true);
+ xmlAttributeValue, n, el, true);
} else {
err.jspError(n, "jsp.error.bad_attribute", attrs
.getQName(i), n.getLocalName());
@@ -1345,10 +1331,13 @@ class Validator {
* If value is null, checks if there are any NamedAttribute subelements
* in the tree node, and if so, constructs a JspAttribute out of a child
* NamedAttribute node.
+ *
+ * @param el EL expression, if already parsed by the caller (so that we
+ * can skip re-parsing it)
*/
private Node.JspAttribute getJspAttribute(TagAttributeInfo tai,
String qName, String uri, String localName, String value,
- Node n, boolean dynamic)
+ Node n, ELNode.Nodes el, boolean dynamic)
throws JasperException {
Node.JspAttribute result = null;
@@ -1368,7 +1357,6 @@ class Validator {
value.substring(3, value.length() - 2), true, null,
dynamic);
} else {
- ELNode.Nodes el = null;
if (!pageInfo.isELIgnored()) {
// The attribute can contain expressions but is not a
// scriptlet expression; thus, we want to run it through
@@ -1376,12 +1364,18 @@ class Validator {
// validate expression syntax if string contains
// expression(s)
- el = ELParser.parse(value,
+ if (el == null) {
+ el = ELParser.parse(value,
pageInfo.isDeferredSyntaxAllowedAsLiteral());
+ }
if (el.containsEL()) {
validateFunctions(el, n);
} else {
+ // Get text with \$ and \# escaping removed.
+ // Should be a single Text node
+ value = ((ELNode.Text) el.iterator().next())
+ .getText();
el = null;
}
}
@@ -1448,7 +1442,9 @@ class Validator {
@Override
public void visit(Text n) throws JasperException {
- output.append(xmlEscape(n.getText()));
+ output.append(ELParser.escapeLiteralExpression(
+ xmlEscape(n.getText()),
+ isDeferredSyntaxAllowedAsLiteral));
}
}
Modified: tomcat/trunk/test/org/apache/jasper/compiler/TestParser.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/jasper/compiler/TestParser.java?rev=1590842&r1=1590841&r2=1590842&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/jasper/compiler/TestParser.java (original)
+++ tomcat/trunk/test/org/apache/jasper/compiler/TestParser.java Mon Apr 28 23:35:36 2014
@@ -412,6 +412,10 @@ public class TestParser extends TomcatBa
Assert.assertTrue(result, result.contains("<set data-value=\"03b\\\\x\\?resize03b\"/>"));
Assert.assertTrue(result, result.contains("<04a\\?resize04a/>"));
Assert.assertTrue(result, result.contains("<04b\\\\x\\?resize04b/>"));
+ Assert.assertTrue(result, result.contains("<set data-value=\"05a$${&\"/>"));
+ Assert.assertTrue(result, result.contains("<set data-value=\"05b$${&2\"/>"));
+ Assert.assertTrue(result, result.contains("<set data-value=\"05c##{>hello<\"/>"));
+ Assert.assertTrue(result, result.contains("<set xmlns:foo=\"urn:06a\\bar\\baz\"/>"));
}
/** Assertion for text printed by tags:echo */
Modified: tomcat/trunk/test/webapp/bug5nnnn/bug56334.jspx
URL: http://svn.apache.org/viewvc/tomcat/trunk/test/webapp/bug5nnnn/bug56334.jspx?rev=1590842&r1=1590841&r2=1590842&view=diff
==============================================================================
--- tomcat/trunk/test/webapp/bug5nnnn/bug56334.jspx (original)
+++ tomcat/trunk/test/webapp/bug5nnnn/bug56334.jspx Mon Apr 28 23:35:36 2014
@@ -29,4 +29,12 @@
<jsp:element name="04b\\x${'\\?resize04b'}"></jsp:element>
+ <!-- Test 5: Use \$, \# in template text -->
+ <set data-value="05a\$\${&" />
+ <set data-value="05b\$\${&${1+1}" />
+ <set data-value="05c\#\#{>${'hello'}<" />
+
+ <!-- Test 6: nonTaglibXmlnsAttributes on a Node.UninterpretedTag -->
+ <set xmlns:foo="urn:06a\bar\baz" />
+
</jsp:root>
\ No newline at end of file
Modified: tomcat/trunk/webapps/docs/changelog.xml
URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1590842&r1=1590841&r2=1590842&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/trunk/webapps/docs/changelog.xml Mon Apr 28 23:35:36 2014
@@ -188,7 +188,7 @@
<changelog>
<fix>
<bug>56334</bug>: Fix a regression in the handling of back-slash
- escaping introduced by the fix for <bug>55735</bug>. (markt)
+ escaping introduced by the fix for <bug>55735</bug>. (markt/kkolinko)
</fix>
<fix>
<bug>56425</bug>: Improve method matching for EL expressions. When
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org