2014-04-24 12:35 GMT+04:00 <ma...@apache.org>: > Author: markt > Date: Thu Apr 24 08:35:06 2014 > New Revision: 1589635 > > URL: http://svn.apache.org/r1589635 > Log: > Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=56334 > Correct double unescaping > > Modified: > tomcat/tc6.0.x/trunk/STATUS.txt > tomcat/tc6.0.x/trunk/java/org/apache/jasper/compiler/ELParser.java > tomcat/tc6.0.x/trunk/java/org/apache/jasper/compiler/Validator.java > tomcat/tc6.0.x/trunk/test/org/apache/jasper/compiler/TestELParser.java > tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml > > Modified: tomcat/tc6.0.x/trunk/STATUS.txt > URL: > http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/STATUS.txt?rev=1589635&r1=1589634&r2=1589635&view=diff > ============================================================================== > --- tomcat/tc6.0.x/trunk/STATUS.txt (original) > +++ tomcat/tc6.0.x/trunk/STATUS.txt Thu Apr 24 08:35:06 2014 > @@ -28,12 +28,6 @@ None > PATCHES PROPOSED TO BACKPORT: > [ New proposals should be added at the end of the list ] > > -* Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=56334 > - Correct double unescaping > - > http://people.apache.org/~markt/patches/2014-04-17-attribute-escaping-tc6-v2.patch > - +1: markt, remm, fhanik > - -1: > - > * Enabling building with Java 8 > > http://people.apache.org/~markt/patches/2014-04-12-build-with-java8-tc6-v1.patch > (Note: It is easier to verify the AbstractReplicatedMap changes by diffing > > Modified: tomcat/tc6.0.x/trunk/java/org/apache/jasper/compiler/ELParser.java > URL: > http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/jasper/compiler/ELParser.java?rev=1589635&r1=1589634&r2=1589635&view=diff > ============================================================================== > --- tomcat/tc6.0.x/trunk/java/org/apache/jasper/compiler/ELParser.java > (original) > +++ tomcat/tc6.0.x/trunk/java/org/apache/jasper/compiler/ELParser.java Thu > Apr 24 08:35:06 2014 > @@ -203,15 +203,22 @@ public class ELParser { > while (hasNextChar()) { > char ch = nextChar(); > if (prev == '\\') { > + if (ch == '$' || (!isDeferredSyntaxAllowedAsLiteral && ch == > '#')) { > prev = 0; > - if (ch == '\\') { > + 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; > + } else { > + // Not an escape > + prev = 0; > buf.append('\\'); > - prev = '\\'; > - } else if (ch == '$' > - || (!isDeferredSyntaxAllowedAsLiteral && ch == '#')) > { > buf.append(ch); > + continue; > } > - // else error! > } else if (prev == '$' > || (!isDeferredSyntaxAllowedAsLiteral && prev == '#')) { > if (ch == '{') { > @@ -235,6 +242,98 @@ public class ELParser { > return buf.toString(); > } > > + > + /** > + * Escape '\\', '$' and '#', inverting the unescaping performed in > + * {@link #skipUntilEL()}. > + * > + * @param input Non-EL input to be escaped > + * @param isDeferredSyntaxAllowedAsLiteral > + * > + * @return The escaped version of the input > + */ > + private static String escapeLiteralExpression(String input, > + boolean isDeferredSyntaxAllowedAsLiteral) { > + int len = input.length(); > + int lastAppend = 0; > + StringBuilder output = null; > + for (int i = 0; i < len; i++) { > + char ch = input.charAt(i); > + if (ch =='$' || (!isDeferredSyntaxAllowedAsLiteral && ch == > '#')) { > + if (output == null) { > + output = new StringBuilder(len + 20); > + }
String.subSequence() = String.substring(), but StringBuilder.append uses array copy with string but iteration with a sequence > + output.append(input.subSequence(lastAppend, i)); > + lastAppend = i + 1; > + output.append('\\'); > + output.append(ch); > + } > + } > + if (output == null) { > + return input; > + } else { substring() is already used here. > + output.append(input.substring(lastAppend, len)); > + return output.toString(); > + } > + } > + > + > + /** > + * Escape '\\', '\'' and '\"', inverting the unescaping performed in > + * {@link #skipUntilEL()}. > + * > + * @param input Non-EL input to be escaped > + * @param isDeferredSyntaxAllowedAsLiteral > + * > + * @return The escaped version of the input > + */ > + private static String escapeELText(String input) { > + int len = input.length(); > + char quote = 0; > + int lastAppend = 0; > + > + if (len > 1) { > + // Might be quoted > + quote = input.charAt(0); > + if (quote == '\'' || quote == '\"') { > + if (input.charAt(len - 1) != quote) { > + throw new IllegalArgumentException(Localizer.getMessage( > + > "org.apache.jasper.compiler.ELParser.invalidQuotesForStringLiteral", The LocalString.properties change is missing from backport. See r1587887 BTW, maybe s /must be contained with/must be contained within/ in message text. > + input)); > + } > + lastAppend = 1; > + len--; > + } else { > + quote = 0; > + } > + } > + > + StringBuilder output = null; > + for (int i = lastAppend; i < len; i++) { > + char ch = input.charAt(i); > + if (ch == '\\' || ch == quote) { > + if (output == null) { > + output = new StringBuilder(len + 20); > + output.append(quote); > + } > + output.append(input.subSequence(lastAppend, i)); Ditto, s/subSequence/substring/. > + lastAppend = i + 1; > + output.append('\\'); > + output.append(ch); > + } > + } > + if (output == null) { > + return input; > + } else { > + output.append(input.substring(lastAppend, len)); > + if (quote != 0) { > + output.append(quote); > + } > + return output.toString(); > + } > + } > + > + > /* > * @return true if there is something left in EL expression buffer other > * than white spaces. > @@ -281,7 +380,7 @@ public class ELParser { > > /* > * Parse a string in single or double quotes, allowing for escape > sequences > - * '\\', and ('\"', or "\'") > + * '\\', '\"' and "\'" > */ > private Token parseQuotedChars(char quote) { > StringBuilder buf = new StringBuilder(); > @@ -290,10 +389,13 @@ public class ELParser { > char ch = nextChar(); > if (ch == '\\') { > ch = nextChar(); > - if (ch == '\\' || ch == quote) { > + if (ch == '\\' || ch == '\'' || ch == '\"') { > buf.append(ch); > + } else { > + throw new IllegalArgumentException(Localizer.getMessage( > + > "org.apache.jasper.compiler.ELParser.invalidQuoting", > + expression)); > } > - // else error! > } else if (ch == quote) { > buf.append(ch); > break; > @@ -448,8 +550,13 @@ public class ELParser { > > protected static class TextBuilder extends ELNode.Visitor { > > + private final boolean isDeferredSyntaxAllowedAsLiteral; > protected StringBuilder output = new StringBuilder(); > > + protected TextBuilder(boolean isDeferredSyntaxAllowedAsLiteral) { > + this.isDeferredSyntaxAllowedAsLiteral = > isDeferredSyntaxAllowedAsLiteral; > + } > + > public String getText() { > return output.toString(); > } > @@ -464,18 +571,18 @@ public class ELParser { > > @Override > public void visit(Function n) throws JasperException { > - output.append(n.getOriginalText()); > + output.append(escapeLiteralExpression(n.getOriginalText(), > isDeferredSyntaxAllowedAsLiteral)); > output.append('('); > } > > @Override > public void visit(Text n) throws JasperException { > - output.append(n.getText()); > + > output.append(escapeLiteralExpression(n.getText(),isDeferredSyntaxAllowedAsLiteral)); > } > > @Override > public void visit(ELText n) throws JasperException { > - output.append(n.getText()); > + output.append(escapeELText(n.getText())); > } > } > } > (...) Best regards, Konstantin Kolinko --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org