Author: markt Date: Fri Oct 24 16:28:48 2014 New Revision: 1634089 URL: http://svn.apache.org/r1634089 Log: Ensure only \${ and \#{ are treated as escapes for ${ and #{ rather than \$ and \# being treated as escapes for $ and # when processing literal expressions in expression language.
Modified: tomcat/trunk/java/org/apache/el/parser/AstLiteralExpression.java tomcat/trunk/java/org/apache/jasper/compiler/ELParser.java tomcat/trunk/java/org/apache/jasper/compiler/JspDocumentParser.java tomcat/trunk/java/org/apache/jasper/compiler/Parser.java tomcat/trunk/test/org/apache/el/TestELEvaluation.java tomcat/trunk/test/org/apache/el/TestELInJsp.java tomcat/trunk/test/webapp/bug45nnn/bug45451.jspf tomcat/trunk/test/webapp/bug45nnn/bug45451d.jspx tomcat/trunk/webapps/docs/changelog.xml Modified: tomcat/trunk/java/org/apache/el/parser/AstLiteralExpression.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/el/parser/AstLiteralExpression.java?rev=1634089&r1=1634088&r2=1634089&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/el/parser/AstLiteralExpression.java (original) +++ tomcat/trunk/java/org/apache/el/parser/AstLiteralExpression.java Fri Oct 24 16:28:48 2014 @@ -51,9 +51,10 @@ public final class AstLiteralExpression StringBuilder buf = new StringBuilder(size); for (int i = 0; i < size; i++) { char c = image.charAt(i); - if (c == '\\' && i + 1 < size) { + if (c == '\\' && i + 2 < size) { char c1 = image.charAt(i + 1); - if (c1 == '#' || c1 == '$') { + char c2 = image.charAt(i + 2); + if ((c1 == '#' || c1 == '$') && c2 == '{') { c = c1; i++; } 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=1634089&r1=1634088&r2=1634089&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/jasper/compiler/ELParser.java (original) +++ tomcat/trunk/java/org/apache/jasper/compiler/ELParser.java Fri Oct 24 16:28:48 2014 @@ -196,58 +196,39 @@ public class ELParser { /** * Skip until an EL expression ('${' || '#{') is reached, allowing escape - * sequences '\\' and '\$' and '\#'. + * sequences '\$' and '\#'. * * @return The text string up to the EL expression */ private String skipUntilEL() { - char prev = 0; StringBuilder buf = new StringBuilder(); while (hasNextChar()) { char ch = nextChar(); - if (prev == '\\') { - if (ch == '$' || (!isDeferredSyntaxAllowedAsLiteral && ch == '#')) { - prev = 0; - buf.append(ch); - continue; - } else if (ch == '\\') { - // Not an escape (this time). - // Optimisation - no need to set prev as it is unchanged - buf.append('\\'); - continue; + if (ch == '\\') { + // Is this the start of a "\${" or "\#{" escape sequence? + char p0 = peek(0); + char p1 = peek(1); + if ((p0 == '$' || (p0 == '#' && !isDeferredSyntaxAllowedAsLiteral)) && p1 == '{') { + buf.append(nextChar()); + buf.append(nextChar()); } else { - // Not an escape - prev = 0; - buf.append('\\'); buf.append(ch); - continue; - } - } else if (prev == '$' - || (!isDeferredSyntaxAllowedAsLiteral && prev == '#')) { - if (ch == '{') { - this.type = prev; - prev = 0; - break; } - buf.append(prev); - prev = 0; - } - if (ch == '\\' || ch == '$' - || (!isDeferredSyntaxAllowedAsLiteral && ch == '#')) { - prev = ch; + } else if ((ch == '$' || (ch == '#' && !isDeferredSyntaxAllowedAsLiteral)) && + peek(0) == '{') { + this.type = ch; + nextChar(); + break; } else { buf.append(ch); } } - if (prev != 0) { - buf.append(prev); - } return buf.toString(); } /** - * Escape '\\', '$' and '#', inverting the unescaping performed in + * Escape '$' and '#', inverting the unescaping performed in * {@link #skipUntilEL()}. * * @param input Non-EL input to be escaped @@ -438,6 +419,14 @@ public class ELParser { return expression.charAt(index++); } + private char peek(int advance) { + int target = index + advance; + if (target >= expression.length()) { + return (char) -1; + } + return expression.charAt(target); + } + private int getIndex() { return index; } Modified: tomcat/trunk/java/org/apache/jasper/compiler/JspDocumentParser.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/compiler/JspDocumentParser.java?rev=1634089&r1=1634088&r2=1634089&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/jasper/compiler/JspDocumentParser.java (original) +++ tomcat/trunk/java/org/apache/jasper/compiler/JspDocumentParser.java Fri Oct 24 16:28:48 2014 @@ -605,7 +605,11 @@ class JspDocumentParser lastCh = ch; } } else if (lastCh == '\\' && (ch == '$' || ch == '#')) { - if (pageInfo.isELIgnored()) { + if (i + 1 < charBuffer.length() && charBuffer.charAt(i + 1) == '{') { + if (pageInfo.isELIgnored()) { + ttext.write('\\'); + } + } else { ttext.write('\\'); } ttext.write(ch); Modified: tomcat/trunk/java/org/apache/jasper/compiler/Parser.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/compiler/Parser.java?rev=1634089&r1=1634088&r2=1634089&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/jasper/compiler/Parser.java (original) +++ tomcat/trunk/java/org/apache/jasper/compiler/Parser.java Fri Oct 24 16:28:48 2014 @@ -1275,7 +1275,7 @@ class Parser implements TagConstants { /* * Parse for a template text string until '<' or "${" or "#{" is encountered, - * recognizing escape sequences "<\%", "\$", and "\#". + * recognizing escape sequences "<\%", "\${", and "\#{". */ private void parseTemplateText(Node parent) throws JasperException { @@ -1292,39 +1292,53 @@ class Parser implements TagConstants { } while (reader.hasMoreInput()) { - int prev = ch; ch = reader.nextChar(); if (ch == '<') { - reader.pushChar(); - break; - } else if ((ch == '$' || ch == '#') && !pageInfo.isELIgnored()) { - if (!reader.hasMoreInput()) { - ttext.write(ch); + // Check for "<\%" + if (reader.nextChar() == '\\') { + if (reader.nextChar() == '%') { + ttext.append('<'); + ttext.append('%'); + } else { + reader.pushChar(); + reader.pushChar(); + reader.pushChar(); + break; + } + } else { + reader.pushChar(); + reader.pushChar(); break; } + } else if (ch == '\\' && !pageInfo.isELIgnored()) { + int next = reader.nextChar(); + if (next == '$' || next == '#') { + if (reader.nextChar() == '{') { + ttext.write(next); + ttext.append('{'); + } else { + ttext.append('\\'); + ttext.write(next); + reader.pushChar(); + } + } else { + ttext.append('\\'); + reader.pushChar(); + } + } else if ((ch == '$' || ch == '#') && !pageInfo.isELIgnored()) { if (reader.nextChar() == '{') { reader.pushChar(); reader.pushChar(); break; + } else { + reader.pushChar(); + ttext.write(ch); } + } else { ttext.write(ch); - reader.pushChar(); - continue; - } else if (ch == '\\') { - if (!reader.hasMoreInput()) { - ttext.write('\\'); - break; - } - char next = (char) reader.peekChar(); - // Looking for \% or \$ or \# - if ((prev == '<' && next == '%') || - ((next == '$' || next == '#') && - !pageInfo.isELIgnored())) { - ch = reader.nextChar(); - } } - ttext.write(ch); } + @SuppressWarnings("unused") Node unused = new Node.TemplateText(ttext.toString(), start, parent); } Modified: tomcat/trunk/test/org/apache/el/TestELEvaluation.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/el/TestELEvaluation.java?rev=1634089&r1=1634088&r2=1634089&view=diff ============================================================================== --- tomcat/trunk/test/org/apache/el/TestELEvaluation.java (original) +++ tomcat/trunk/test/org/apache/el/TestELEvaluation.java Fri Oct 24 16:28:48 2014 @@ -110,19 +110,19 @@ public class TestELEvaluation { assertEquals("\\", evaluateExpression("\\")); assertEquals("$", evaluateExpression("$")); assertEquals("#", evaluateExpression("#")); - assertEquals("$", evaluateExpression("\\$")); - assertEquals("#", evaluateExpression("\\#")); - assertEquals("\\$", evaluateExpression("\\\\$")); - assertEquals("\\#", evaluateExpression("\\\\#")); + assertEquals("\\$", evaluateExpression("\\$")); + assertEquals("\\#", evaluateExpression("\\#")); + assertEquals("\\\\$", evaluateExpression("\\\\$")); + assertEquals("\\\\#", evaluateExpression("\\\\#")); assertEquals("${", evaluateExpression("\\${")); assertEquals("#{", evaluateExpression("\\#{")); assertEquals("\\${", evaluateExpression("\\\\${")); assertEquals("\\#{", evaluateExpression("\\\\#{")); - // '\' is only an escape for '$' and '#'. - assertEquals("$", evaluateExpression("\\$")); + // '\' is only an escape for '${' and '#{'. + assertEquals("\\$", evaluateExpression("\\$")); assertEquals("${", evaluateExpression("\\${")); - assertEquals("$a", evaluateExpression("\\$a")); + assertEquals("\\$a", evaluateExpression("\\$a")); assertEquals("\\a", evaluateExpression("\\a")); assertEquals("\\\\", evaluateExpression("\\\\")); } Modified: tomcat/trunk/test/org/apache/el/TestELInJsp.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/el/TestELInJsp.java?rev=1634089&r1=1634088&r2=1634089&view=diff ============================================================================== --- tomcat/trunk/test/org/apache/el/TestELInJsp.java (original) +++ tomcat/trunk/test/org/apache/el/TestELInJsp.java Fri Oct 24 16:28:48 2014 @@ -173,16 +173,18 @@ public class TestELInJsp extends TomcatB assertEcho(result, "01-${1+1}"); assertEcho(result, "02-\\${1+1}"); assertEcho(result, "03-\\\\${1+1}"); - assertEcho(result, "04-2"); - assertEcho(result, "05-${1+1}"); - assertEcho(result, "06-\\2"); - assertEcho(result, "07-\\${1+1}"); - assertEcho(result, "08-\\\\2"); - assertEcho(result, "09-2"); - assertEcho(result, "10-#{1+1}"); - assertEcho(result, "11-\\2"); - assertEcho(result, "12-\\#{1+1}"); - assertEcho(result, "13-\\\\2"); + assertEcho(result, "04-\\$500"); + assertEcho(result, "10-2"); + assertEcho(result, "11-${1+1}"); + assertEcho(result, "12-\\2"); + assertEcho(result, "13-\\${1+1}"); + assertEcho(result, "14-\\\\2"); + assertEcho(result, "15-\\$500"); + assertEcho(result, "20-2"); + assertEcho(result, "21-#{1+1}"); + assertEcho(result, "22-\\2"); + assertEcho(result, "23-\\#{1+1}"); + assertEcho(result, "24-\\\\2"); res = getUrl("http://localhost:" + getPort() + "/test/bug45nnn/bug45451c.jsp"); result = res.toString(); @@ -193,16 +195,18 @@ public class TestELInJsp extends TomcatB assertEcho(result, "01-\\${1+1}"); assertEcho(result, "02-\\\\${1+1}"); assertEcho(result, "03-\\\\\\${1+1}"); - assertEcho(result, "04-${1+1}"); - assertEcho(result, "05-\\${1+1}"); - assertEcho(result, "06-\\${1+1}"); - assertEcho(result, "07-\\\\${1+1}"); - assertEcho(result, "08-\\\\${1+1}"); - assertEcho(result, "09-#{1+1}"); - assertEcho(result, "10-\\#{1+1}"); - assertEcho(result, "11-\\#{1+1}"); - assertEcho(result, "12-\\\\#{1+1}"); - assertEcho(result, "13-\\\\#{1+1}"); + assertEcho(result, "04-\\$500"); + assertEcho(result, "10-${1+1}"); + assertEcho(result, "11-\\${1+1}"); + assertEcho(result, "12-\\${1+1}"); + assertEcho(result, "13-\\\\${1+1}"); + assertEcho(result, "14-\\\\${1+1}"); + assertEcho(result, "15-\\$500"); + assertEcho(result, "20-#{1+1}"); + assertEcho(result, "21-\\#{1+1}"); + assertEcho(result, "22-\\#{1+1}"); + assertEcho(result, "23-\\\\#{1+1}"); + assertEcho(result, "24-\\\\#{1+1}"); res = getUrl("http://localhost:" + getPort() + "/test/bug45nnn/bug45451d.jspx"); result = res.toString(); @@ -212,16 +216,18 @@ public class TestELInJsp extends TomcatB assertEcho(result, "01-${1+1}"); assertEcho(result, "02-\\${1+1}"); assertEcho(result, "03-\\\\${1+1}"); - assertEcho(result, "04-2"); - assertEcho(result, "05-${1+1}"); - assertEcho(result, "06-\\${1+1}"); - assertEcho(result, "07-\\\\${1+1}"); - assertEcho(result, "08-\\\\\\${1+1}"); - assertEcho(result, "09-2"); - assertEcho(result, "10-#{1+1}"); - assertEcho(result, "11-\\#{1+1}"); - assertEcho(result, "12-\\\\#{1+1}"); - assertEcho(result, "13-\\\\\\#{1+1}"); + assertEcho(result, "04-\\$500"); + assertEcho(result, "10-2"); + assertEcho(result, "11-${1+1}"); + assertEcho(result, "12-\\${1+1}"); + assertEcho(result, "13-\\\\${1+1}"); + assertEcho(result, "14-\\\\\\${1+1}"); + assertEcho(result, "15-\\$500"); + assertEcho(result, "20-2"); + assertEcho(result, "21-#{1+1}"); + assertEcho(result, "22-\\#{1+1}"); + assertEcho(result, "23-\\\\#{1+1}"); + assertEcho(result, "24-\\\\\\#{1+1}"); res = getUrl("http://localhost:" + getPort() + "/test/bug45nnn/bug45451e.jsp"); result = res.toString(); @@ -232,16 +238,18 @@ public class TestELInJsp extends TomcatB assertEcho(result, "01-${1+1}"); assertEcho(result, "02-\\${1+1}"); assertEcho(result, "03-\\\\${1+1}"); - assertEcho(result, "04-2"); - assertEcho(result, "05-${1+1}"); - assertEcho(result, "06-\\2"); - assertEcho(result, "07-\\${1+1}"); - assertEcho(result, "08-\\\\2"); - assertEcho(result, "09-#{1+1}"); - assertEcho(result, "10-\\#{1+1}"); - assertEcho(result, "11-\\#{1+1}"); - assertEcho(result, "12-\\\\#{1+1}"); - assertEcho(result, "13-\\\\#{1+1}"); + assertEcho(result, "04-\\$500"); + assertEcho(result, "10-2"); + assertEcho(result, "11-${1+1}"); + assertEcho(result, "12-\\2"); + assertEcho(result, "13-\\${1+1}"); + assertEcho(result, "14-\\\\2"); + assertEcho(result, "15-\\$500"); + assertEcho(result, "20-#{1+1}"); + assertEcho(result, "21-\\#{1+1}"); + assertEcho(result, "22-\\#{1+1}"); + assertEcho(result, "23-\\\\#{1+1}"); + assertEcho(result, "24-\\\\#{1+1}"); } @Test Modified: tomcat/trunk/test/webapp/bug45nnn/bug45451.jspf URL: http://svn.apache.org/viewvc/tomcat/trunk/test/webapp/bug45nnn/bug45451.jspf?rev=1634089&r1=1634088&r2=1634089&view=diff ============================================================================== --- tomcat/trunk/test/webapp/bug45nnn/bug45451.jspf (original) +++ tomcat/trunk/test/webapp/bug45nnn/bug45451.jspf Fri Oct 24 16:28:48 2014 @@ -18,13 +18,15 @@ <p>01-\${1+1}</p> <p>02-\\${1+1}</p> <p>03-\\\${1+1}</p> -<tags:echo echo="04-${1+1}" /> -<tags:echo echo="05-\${1+1}" /> -<tags:echo echo="06-\\${1+1}" /> -<tags:echo echo="07-\\\${1+1}" /> -<tags:echo echo="08-\\\\${1+1}" /> -<tags:echo-deferred echo="09-#{1+1}" /> -<tags:echo-deferred echo="10-\#{1+1}" /> -<tags:echo-deferred echo="11-\\#{1+1}" /> -<tags:echo-deferred echo="12-\\\#{1+1}" /> -<tags:echo-deferred echo="13-\\\\#{1+1}" /> \ No newline at end of file +<p>04-\$500</p> +<tags:echo echo="10-${1+1}" /> +<tags:echo echo="11-\${1+1}" /> +<tags:echo echo="12-\\${1+1}" /> +<tags:echo echo="13-\\\${1+1}" /> +<tags:echo echo="14-\\\\${1+1}" /> +<tags:echo echo="15-\$500" /> +<tags:echo-deferred echo="20-#{1+1}" /> +<tags:echo-deferred echo="21-\#{1+1}" /> +<tags:echo-deferred echo="22-\\#{1+1}" /> +<tags:echo-deferred echo="23-\\\#{1+1}" /> +<tags:echo-deferred echo="24-\\\\#{1+1}" /> \ No newline at end of file Modified: tomcat/trunk/test/webapp/bug45nnn/bug45451d.jspx URL: http://svn.apache.org/viewvc/tomcat/trunk/test/webapp/bug45nnn/bug45451d.jspx?rev=1634089&r1=1634088&r2=1634089&view=diff ============================================================================== --- tomcat/trunk/test/webapp/bug45nnn/bug45451d.jspx (original) +++ tomcat/trunk/test/webapp/bug45nnn/bug45451d.jspx Fri Oct 24 16:28:48 2014 @@ -25,16 +25,18 @@ <p>01-\${1+1}</p> <p>02-\\${1+1}</p> <p>03-\\\${1+1}</p> - <tags:echo echo="04-${1+1}" /> - <tags:echo echo="05-\${1+1}" /> - <tags:echo echo="06-\\${1+1}" /> - <tags:echo echo="07-\\\${1+1}" /> - <tags:echo echo="08-\\\\${1+1}" /> - <tags:echo-deferred echo="09-#{1+1}" /> - <tags:echo-deferred echo="10-\#{1+1}" /> - <tags:echo-deferred echo="11-\\#{1+1}" /> - <tags:echo-deferred echo="12-\\\#{1+1}" /> - <tags:echo-deferred echo="13-\\\\#{1+1}" /> + <p>04-\$500</p> + <tags:echo echo="10-${1+1}" /> + <tags:echo echo="11-\${1+1}" /> + <tags:echo echo="12-\\${1+1}" /> + <tags:echo echo="13-\\\${1+1}" /> + <tags:echo echo="14-\\\\${1+1}" /> + <tags:echo echo="15-\$500" /> + <tags:echo-deferred echo="20-#{1+1}" /> + <tags:echo-deferred echo="21-\#{1+1}" /> + <tags:echo-deferred echo="22-\\#{1+1}" /> + <tags:echo-deferred echo="23-\\\#{1+1}" /> + <tags:echo-deferred echo="24-\\\\#{1+1}" /> </body> </html> </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=1634089&r1=1634088&r2=1634089&view=diff ============================================================================== --- tomcat/trunk/webapps/docs/changelog.xml (original) +++ tomcat/trunk/webapps/docs/changelog.xml Fri Oct 24 16:28:48 2014 @@ -228,6 +228,13 @@ an error. The second and subsequent calls for the same class will be ignored. (markt) </fix> + <fix> + <bug>57136</bug>: Ensure only <code>\${</code> and <code>\#{</code> are + treated as escapes for <code>${</code> and <code>#{</code> rather than + <code>\$</code> and <code>\#</code> being treated as escapes for + <code>$</code> and <code>#</code> when processing literal expressions in + expression language. (markt) + </fix> </changelog> </subsection> <subsection name="Cluster"> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org