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

Reply via email to