This is an automated email from the ASF dual-hosted git repository.

markt-asf pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git


The following commit(s) were added to refs/heads/9.0.x by this push:
     new dde83c536b Avoid double escaping if '\' is Unicode escaped.
dde83c536b is described below

commit dde83c536bde07e90c69ed814f6bcac3396aada4
Author: Mark Thomas <[email protected]>
AuthorDate: Wed Sep 16 12:08:33 2026 +0100

    Avoid double escaping if '\' is Unicode escaped.
    
    Follow-up to "Unescape quoted strings"
---
 java/org/apache/tomcat/util/json/JSONParser.java   |  32 +-
 java/org/apache/tomcat/util/json/JSONParser.jjt    |  25 +-
 .../tomcat/util/json/JSONParserConstants.java      |  22 +-
 .../tomcat/util/json/JSONParserTokenManager.java   | 391 +++++++++++++--------
 .../{JavaCharStream.java => SimpleCharStream.java} | 293 ++++-----------
 .../apache/tomcat/util/json/TestJSONParser.java    |  30 ++
 6 files changed, 407 insertions(+), 386 deletions(-)

diff --git a/java/org/apache/tomcat/util/json/JSONParser.java 
b/java/org/apache/tomcat/util/json/JSONParser.java
index 083f323848..4a2e3d8bd4 100644
--- a/java/org/apache/tomcat/util/json/JSONParser.java
+++ b/java/org/apache/tomcat/util/json/JSONParser.java
@@ -105,6 +105,22 @@ public class JSONParser implements JSONParserConstants {
                 case 't':
                     result.append('\t');
                     break;
+                case 'u':
+                    if (i + 4 >= value.length()) {
+                        throw new IllegalArgumentException("Incomplete Unicode 
escape sequence");
+                    }
+                    int codeUnit = 0;
+                    for (int j = 0; j < 4; j++) {
+                        char hex = value.charAt(++i);
+                        int digit = Character.digit(hex, 16);
+                        if (digit == -1) {
+                            throw new IllegalArgumentException(
+                                    "Invalid hexadecimal character in Unicode 
escape: " + hex);
+                        }
+                        codeUnit = codeUnit << 4 | digit;
+                    }
+                    result.append((char) codeUnit);
+                    break;
                 default:
                     result.append(next);
                     break;
@@ -544,7 +560,7 @@ public class JSONParser implements JSONParserConstants {
 
     /** Generated Token Manager. */
     public JSONParserTokenManager token_source;
-    JavaCharStream jj_input_stream;
+    SimpleCharStream jj_input_stream;
     /** Current token. */
     public Token token;
     /** Next token. */
@@ -557,8 +573,8 @@ public class JSONParser implements JSONParserConstants {
     }
 
     private static void jj_la1_init_0() {
-        jj_la1_0 = new int[] { 0xccf8480, 0x78000, 0x1ccf8000, 0x40, 
0x1ccf8000, 0x40, 0xccf8480, 0xccf8000, 0x60000,
-                0x18000, 0xcc00000, 0x8800000, 0x4400000, };
+        jj_la1_0 = new int[] { 0x330f8480, 0x78000, 0x730f8000, 0x40, 
0x730f8000, 0x40, 0x330f8480, 0x330f8000, 0x60000,
+                0x18000, 0x33000000, 0x22000000, 0x11000000, };
     }
 
     /** Constructor with InputStream. */
@@ -569,7 +585,7 @@ public class JSONParser implements JSONParserConstants {
     /** Constructor with InputStream and supplied encoding */
     public JSONParser(java.io.InputStream stream, String encoding) {
         try {
-            jj_input_stream = new JavaCharStream(stream, encoding, 1, 1);
+            jj_input_stream = new SimpleCharStream(stream, encoding, 1, 1);
         } catch (java.io.UnsupportedEncodingException e) {
             throw new RuntimeException(e);
         }
@@ -605,7 +621,7 @@ public class JSONParser implements JSONParserConstants {
 
     /** Constructor. */
     public JSONParser(java.io.Reader stream) {
-        jj_input_stream = new JavaCharStream(stream, 1, 1);
+        jj_input_stream = new SimpleCharStream(stream, 1, 1);
         token_source = new JSONParserTokenManager(jj_input_stream);
         token = new Token();
         token.next = jj_nt = token_source.getNextToken();
@@ -618,7 +634,7 @@ public class JSONParser implements JSONParserConstants {
     /** Reinitialise. */
     public void ReInit(java.io.Reader stream) {
         if (jj_input_stream == null) {
-            jj_input_stream = new JavaCharStream(stream, 1, 1);
+            jj_input_stream = new SimpleCharStream(stream, 1, 1);
         } else {
             jj_input_stream.ReInit(stream, 1, 1);
         }
@@ -706,7 +722,7 @@ public class JSONParser implements JSONParserConstants {
     /** Generate ParseException. */
     public ParseException generateParseException() {
         jj_expentries.clear();
-        boolean[] la1tokens = new boolean[29];
+        boolean[] la1tokens = new boolean[31];
         if (jj_kind >= 0) {
             la1tokens[jj_kind] = true;
             jj_kind = -1;
@@ -720,7 +736,7 @@ public class JSONParser implements JSONParserConstants {
                 }
             }
         }
-        for (int i = 0; i < 29; i++) {
+        for (int i = 0; i < 31; i++) {
             if (la1tokens[i]) {
                 jj_expentry = new int[1];
                 jj_expentry[0] = i;
diff --git a/java/org/apache/tomcat/util/json/JSONParser.jjt 
b/java/org/apache/tomcat/util/json/JSONParser.jjt
index dd85bebe4f..e794dfab60 100644
--- a/java/org/apache/tomcat/util/json/JSONParser.jjt
+++ b/java/org/apache/tomcat/util/json/JSONParser.jjt
@@ -19,7 +19,7 @@ options {
     CHOICE_AMBIGUITY_CHECK=3;
     OTHER_AMBIGUITY_CHECK=2;
     ERROR_REPORTING=true;
-    JAVA_UNICODE_ESCAPE=true;
+    JAVA_UNICODE_ESCAPE=false;
     UNICODE_INPUT=true;
     IGNORE_CASE=true;
     SUPPORT_CLASS_VISIBILITY_PUBLIC=true;
@@ -138,6 +138,21 @@ public class JSONParser {
                 case 't':
                    result.append('\t');
                    break;
+                case 'u':
+                    if (i + 4 >= value.length()) {
+                        throw new IllegalArgumentException("Incomplete Unicode 
escape sequence");
+                    }
+                    int codeUnit = 0;
+                    for (int j = 0; j < 4; j++) {
+                        char hex = value.charAt(++i);
+                        int digit = Character.digit(hex, 16);
+                        if (digit == -1) {
+                            throw new IllegalArgumentException("Invalid 
hexadecimal character in Unicode escape: " + hex);
+                        }
+                        codeUnit = codeUnit << 4 | digit;
+                    }
+                    result.append((char) codeUnit);
+                    break;
                 default:
                    result.append(next);
                    break;
@@ -223,15 +238,19 @@ TOKEN:{
 TOKEN:{
     <#QUOTE_DOUBLE: "\"">
 | <#QUOTE_SINGLE: "'">
+| <#HEX_DIGIT: ["0"-"9","a"-"f","A"-"F"]>
+| <#UNICODE_ESCAPE: "\\" "u" <HEX_DIGIT> <HEX_DIGIT> <HEX_DIGIT> <HEX_DIGIT>>
 | <STRING_SINGLE_EMPTY: "''">
 | <STRING_DOUBLE_EMPTY: "\"\"">
 | <#STRING_SINGLE_BODY: (
         (~["'","\\","\r","\n","\f","\t"]) |
-        ( "\\" ( "r" | "n" | "f" | "\\" | "/" | "'" | "b" | "t" ) )
+        ( "\\" ( "r" | "n" | "f" | "\\" | "/" | "'" | "b" | "t" ) ) |
+        <UNICODE_ESCAPE>
     )+>
 | <#STRING_DOUBLE_BODY: (
         (~["\"","\\","\r","\n","\f","\t"]) |
-        ( "\\" ( "r" | "n" | "f" | "\\" | "/" | "\"" | "b" | "t" ) )
+        ( "\\" ( "r" | "n" | "f" | "\\" | "/" | "\"" | "b" | "t" ) ) |
+        <UNICODE_ESCAPE>
     )+>
 | <STRING_SINGLE_NONEMPTY: <QUOTE_SINGLE> <STRING_SINGLE_BODY> <QUOTE_SINGLE>>
 | <STRING_DOUBLE_NONEMPTY: <QUOTE_DOUBLE> <STRING_DOUBLE_BODY> <QUOTE_DOUBLE>>
diff --git a/java/org/apache/tomcat/util/json/JSONParserConstants.java 
b/java/org/apache/tomcat/util/json/JSONParserConstants.java
index c89eb50fef..9abea4fbba 100644
--- a/java/org/apache/tomcat/util/json/JSONParserConstants.java
+++ b/java/org/apache/tomcat/util/json/JSONParserConstants.java
@@ -68,19 +68,23 @@ public interface JSONParserConstants {
     /** RegularExpression Id. */
     int QUOTE_SINGLE = 21;
     /** RegularExpression Id. */
-    int STRING_SINGLE_EMPTY = 22;
+    int HEX_DIGIT = 22;
     /** RegularExpression Id. */
-    int STRING_DOUBLE_EMPTY = 23;
+    int UNICODE_ESCAPE = 23;
     /** RegularExpression Id. */
-    int STRING_SINGLE_BODY = 24;
+    int STRING_SINGLE_EMPTY = 24;
     /** RegularExpression Id. */
-    int STRING_DOUBLE_BODY = 25;
+    int STRING_DOUBLE_EMPTY = 25;
     /** RegularExpression Id. */
-    int STRING_SINGLE_NONEMPTY = 26;
+    int STRING_SINGLE_BODY = 26;
     /** RegularExpression Id. */
-    int STRING_DOUBLE_NONEMPTY = 27;
+    int STRING_DOUBLE_BODY = 27;
     /** RegularExpression Id. */
-    int SYMBOL = 28;
+    int STRING_SINGLE_NONEMPTY = 28;
+    /** RegularExpression Id. */
+    int STRING_DOUBLE_NONEMPTY = 29;
+    /** RegularExpression Id. */
+    int SYMBOL = 30;
 
     /** Lexical state. */
     int DEFAULT = 0;
@@ -89,7 +93,7 @@ public interface JSONParserConstants {
     String[] tokenImage = { "<EOF>", "<C_SINGLE_COMMENT>", 
"<C_MULTILINE_COMMENT>", "<SH_SINGLE_COMMENT>",
             "<WHITESPACE>", "<EOL>", "\",\"", "\"{\"", "\"}\"", "\":\"", 
"\"[\"", "\"]\"", "\"0\"", "<DIGIT_NONZERO>",
             "<DIGIT>", "<NUMBER_INTEGER>", "<NUMBER_DECIMAL>", "\"true\"", 
"\"false\"", "\"null\"", "\"\\\"\"",
-            "\"\\\'\"", "\"\\\'\\\'\"", "\"\\\"\\\"\"", 
"<STRING_SINGLE_BODY>", "<STRING_DOUBLE_BODY>",
-            "<STRING_SINGLE_NONEMPTY>", "<STRING_DOUBLE_NONEMPTY>", 
"<SYMBOL>", };
+            "\"\\\'\"", "<HEX_DIGIT>", "<UNICODE_ESCAPE>", "\"\\\'\\\'\"", 
"\"\\\"\\\"\"", "<STRING_SINGLE_BODY>",
+            "<STRING_DOUBLE_BODY>", "<STRING_SINGLE_NONEMPTY>", 
"<STRING_DOUBLE_NONEMPTY>", "<SYMBOL>", };
 
 }
diff --git a/java/org/apache/tomcat/util/json/JSONParserTokenManager.java 
b/java/org/apache/tomcat/util/json/JSONParserTokenManager.java
index 6da2d8a905..c45f585edd 100644
--- a/java/org/apache/tomcat/util/json/JSONParserTokenManager.java
+++ b/java/org/apache/tomcat/util/json/JSONParserTokenManager.java
@@ -33,39 +33,39 @@ public class JSONParserTokenManager implements 
JSONParserConstants {
     private final int jjStopStringLiteralDfa_0(int pos, long active0) {
         switch (pos) {
             case 0:
-                if ((active0 & 0xe0000L) != 0L) {
-                    jjmatchedKind = 28;
-                    return 15;
+                if ((active0 & 0x1000000L) != 0L) {
+                    return 48;
                 }
-                if ((active0 & 0x400000L) != 0L) {
-                    return 38;
+                if ((active0 & 0xe0000L) != 0L) {
+                    jjmatchedKind = 30;
+                    return 25;
                 }
-                if ((active0 & 0x800000L) != 0L) {
-                    return 39;
+                if ((active0 & 0x2000000L) != 0L) {
+                    return 49;
                 }
                 return -1;
             case 1:
                 if ((active0 & 0xe0000L) != 0L) {
-                    jjmatchedKind = 28;
+                    jjmatchedKind = 30;
                     jjmatchedPos = 1;
-                    return 15;
+                    return 25;
                 }
                 return -1;
             case 2:
                 if ((active0 & 0xe0000L) != 0L) {
-                    jjmatchedKind = 28;
+                    jjmatchedKind = 30;
                     jjmatchedPos = 2;
-                    return 15;
+                    return 25;
                 }
                 return -1;
             case 3:
                 if ((active0 & 0xa0000L) != 0L) {
-                    return 15;
+                    return 25;
                 }
                 if ((active0 & 0x40000L) != 0L) {
-                    jjmatchedKind = 28;
+                    jjmatchedKind = 30;
                     jjmatchedPos = 3;
-                    return 15;
+                    return 25;
                 }
                 return -1;
             default:
@@ -86,9 +86,9 @@ public class JSONParserTokenManager implements 
JSONParserConstants {
     private int jjMoveStringLiteralDfa0_0() {
         switch (curChar) {
             case 34:
-                return jjMoveStringLiteralDfa1_0(0x800000L);
+                return jjMoveStringLiteralDfa1_0(0x2000000L);
             case 39:
-                return jjMoveStringLiteralDfa1_0(0x400000L);
+                return jjMoveStringLiteralDfa1_0(0x1000000L);
             case 44:
                 return jjStopAtPos(0, 6);
             case 58:
@@ -124,13 +124,13 @@ public class JSONParserTokenManager implements 
JSONParserConstants {
         }
         switch (curChar) {
             case 34:
-                if ((active0 & 0x800000L) != 0L) {
-                    return jjStopAtPos(1, 23);
+                if ((active0 & 0x2000000L) != 0L) {
+                    return jjStopAtPos(1, 25);
                 }
                 break;
             case 39:
-                if ((active0 & 0x400000L) != 0L) {
-                    return jjStopAtPos(1, 22);
+                if ((active0 & 0x1000000L) != 0L) {
+                    return jjStopAtPos(1, 24);
                 }
                 break;
             case 65:
@@ -185,13 +185,13 @@ public class JSONParserTokenManager implements 
JSONParserConstants {
             case 69:
             case 101:
                 if ((active0 & 0x20000L) != 0L) {
-                    return jjStartNfaWithStates_0(3, 17, 15);
+                    return jjStartNfaWithStates_0(3, 17, 25);
                 }
                 break;
             case 76:
             case 108:
                 if ((active0 & 0x80000L) != 0L) {
-                    return jjStartNfaWithStates_0(3, 19, 15);
+                    return jjStartNfaWithStates_0(3, 19, 25);
                 }
                 break;
             case 83:
@@ -217,7 +217,7 @@ public class JSONParserTokenManager implements 
JSONParserConstants {
             case 69:
             case 101:
                 if ((active0 & 0x40000L) != 0L) {
-                    return jjStartNfaWithStates_0(4, 18, 15);
+                    return jjStartNfaWithStates_0(4, 18, 25);
                 }
                 break;
             default:
@@ -243,7 +243,7 @@ public class JSONParserTokenManager implements 
JSONParserConstants {
 
     private int jjMoveNfa_0(int startState, int curPos) {
         int startsAt = 0;
-        jjnewStateCnt = 38;
+        jjnewStateCnt = 48;
         int i = 1;
         jjstateSet[0] = startState;
         int kind = 0x7fffffff;
@@ -255,13 +255,19 @@ public class JSONParserTokenManager implements 
JSONParserConstants {
                 long l = 1L << curChar;
                 do {
                     switch (jjstateSet[--i]) {
+                        case 49:
+                        case 16:
+                            if ((0xfffffffbffffc9ffL & l) != 0L) {
+                                jjCheckNAddStates(0, 2);
+                            }
+                            break;
                         case 0:
                             if ((0x3ff000000000000L & l) != 0L) {
-                                if (kind > 28) {
-                                    kind = 28;
+                                if (kind > 30) {
+                                    kind = 30;
                                 }
                                 {
-                                    jjCheckNAdd(15);
+                                    jjCheckNAdd(25);
                                 }
                             } else if ((0x3400L & l) != 0L) {
                                 if (kind > 5) {
@@ -272,13 +278,13 @@ public class JSONParserTokenManager implements 
JSONParserConstants {
                                     kind = 4;
                                 }
                             } else if (curChar == 45) {
-                                jjCheckNAddStates(0, 3);
+                                jjCheckNAddStates(3, 6);
                             } else if (curChar == 47) {
-                                jjAddStates(4, 5);
+                                jjAddStates(7, 8);
                             } else if (curChar == 34) {
-                                jjCheckNAddTwoStates(11, 12);
+                                jjCheckNAddTwoStates(16, 18);
                             } else if (curChar == 39) {
-                                jjCheckNAddTwoStates(6, 7);
+                                jjCheckNAddTwoStates(6, 8);
                             } else if (curChar == 35) {
                                 jjCheckNAddTwoStates(1, 2);
                             }
@@ -287,26 +293,20 @@ public class JSONParserTokenManager implements 
JSONParserConstants {
                                     kind = 15;
                                 }
                                 {
-                                    jjCheckNAddStates(6, 8);
+                                    jjCheckNAddStates(9, 11);
                                 }
                             } else if (curChar == 48) {
                                 if (kind > 15) {
                                     kind = 15;
                                 }
                                 {
-                                    jjCheckNAddStates(9, 11);
+                                    jjCheckNAddStates(12, 14);
                                 }
                             }
                             break;
-                        case 38:
+                        case 48:
                         case 6:
                             if ((0xffffff7fffffc9ffL & l) != 0L) {
-                                jjCheckNAddStates(12, 14);
-                            }
-                            break;
-                        case 39:
-                        case 11:
-                            if ((0xfffffffbffffc9ffL & l) != 0L) {
                                 jjCheckNAddStates(15, 17);
                             }
                             break;
@@ -332,181 +332,221 @@ public class JSONParserTokenManager implements 
JSONParserConstants {
                             break;
                         case 5:
                             if (curChar == 39) {
-                                jjCheckNAddTwoStates(6, 7);
+                                jjCheckNAddTwoStates(6, 8);
                             }
                             break;
-                        case 8:
-                            if ((0x808000000000L & l) != 0L) {
-                                jjCheckNAddStates(12, 14);
+                        case 7:
+                            if (curChar == 39 && kind > 28) {
+                                kind = 28;
                             }
                             break;
                         case 9:
-                            if (curChar == 39 && kind > 26) {
-                                kind = 26;
+                            if ((0x808000000000L & l) != 0L) {
+                                jjCheckNAddStates(15, 17);
                             }
                             break;
-                        case 10:
-                            if (curChar == 34) {
-                                jjCheckNAddTwoStates(11, 12);
+                        case 11:
+                            if ((0x3ff000000000000L & l) != 0L) {
+                                jjstateSet[jjnewStateCnt++] = 12;
+                            }
+                            break;
+                        case 12:
+                            if ((0x3ff000000000000L & l) != 0L) {
+                                jjstateSet[jjnewStateCnt++] = 13;
                             }
                             break;
                         case 13:
-                            if ((0x800400000000L & l) != 0L) {
-                                jjCheckNAddStates(15, 17);
+                            if ((0x3ff000000000000L & l) != 0L) {
+                                jjstateSet[jjnewStateCnt++] = 14;
                             }
                             break;
                         case 14:
-                            if (curChar == 34 && kind > 27) {
-                                kind = 27;
+                            if ((0x3ff000000000000L & l) != 0L) {
+                                jjCheckNAddStates(15, 17);
                             }
                             break;
                         case 15:
+                            if (curChar == 34) {
+                                jjCheckNAddTwoStates(16, 18);
+                            }
+                            break;
+                        case 17:
+                            if (curChar == 34 && kind > 29) {
+                                kind = 29;
+                            }
+                            break;
+                        case 19:
+                            if ((0x800400000000L & l) != 0L) {
+                                jjCheckNAddStates(0, 2);
+                            }
+                            break;
+                        case 21:
+                            if ((0x3ff000000000000L & l) != 0L) {
+                                jjstateSet[jjnewStateCnt++] = 22;
+                            }
+                            break;
+                        case 22:
+                            if ((0x3ff000000000000L & l) != 0L) {
+                                jjstateSet[jjnewStateCnt++] = 23;
+                            }
+                            break;
+                        case 23:
+                            if ((0x3ff000000000000L & l) != 0L) {
+                                jjstateSet[jjnewStateCnt++] = 24;
+                            }
+                            break;
+                        case 24:
+                            if ((0x3ff000000000000L & l) != 0L) {
+                                jjCheckNAddStates(0, 2);
+                            }
+                            break;
+                        case 25:
                             if ((0x3ff000000000000L & l) == 0L) {
                                 break;
                             }
-                            if (kind > 28) {
-                                kind = 28;
+                            if (kind > 30) {
+                                kind = 30;
                             } {
-                            jjCheckNAdd(15);
+                            jjCheckNAdd(25);
                         }
                             break;
-                        case 16:
+                        case 26:
                             if (curChar == 47) {
-                                jjAddStates(4, 5);
+                                jjAddStates(7, 8);
                             }
                             break;
-                        case 17:
+                        case 27:
                             if (curChar == 47) {
-                                jjCheckNAddTwoStates(18, 19);
+                                jjCheckNAddTwoStates(28, 29);
                             }
                             break;
-                        case 18:
+                        case 28:
                             if ((0xffffffffffffcbffL & l) != 0L) {
-                                jjCheckNAddTwoStates(18, 19);
+                                jjCheckNAddTwoStates(28, 29);
                             }
                             break;
-                        case 19:
+                        case 29:
                             if ((0x3400L & l) != 0L && kind > 1) {
                                 kind = 1;
                             }
                             break;
-                        case 20:
+                        case 30:
                             if (curChar == 42) {
-                                jjCheckNAddTwoStates(21, 23);
+                                jjCheckNAddTwoStates(31, 33);
                             }
                             break;
-                        case 21: {
-                            jjCheckNAddTwoStates(21, 23);
+                        case 31: {
+                            jjCheckNAddTwoStates(31, 33);
                         }
                             break;
-                        case 22:
+                        case 32:
                             if (curChar == 47 && kind > 2) {
                                 kind = 2;
                             }
                             break;
-                        case 23:
+                        case 33:
                             if (curChar == 42) {
-                                jjstateSet[jjnewStateCnt++] = 22;
+                                jjstateSet[jjnewStateCnt++] = 32;
                             }
                             break;
-                        case 24:
+                        case 34:
                             if (curChar == 45) {
-                                jjCheckNAddStates(0, 3);
+                                jjCheckNAddStates(3, 6);
                             }
                             break;
-                        case 25:
+                        case 35:
                             if (curChar != 48) {
                                 break;
                             }
                             if (kind > 15) {
                                 kind = 15;
                             } {
-                            jjCheckNAdd(25);
+                            jjCheckNAdd(35);
                         }
                             break;
-                        case 26:
+                        case 36:
                             if ((0x3fe000000000000L & l) == 0L) {
                                 break;
                             }
                             if (kind > 15) {
                                 kind = 15;
                             } {
-                            jjCheckNAdd(27);
+                            jjCheckNAdd(37);
                         }
                             break;
-                        case 27:
+                        case 37:
                             if ((0x3ff000000000000L & l) == 0L) {
                                 break;
                             }
                             if (kind > 15) {
                                 kind = 15;
                             } {
-                            jjCheckNAdd(27);
+                            jjCheckNAdd(37);
                         }
                             break;
-                        case 28:
+                        case 38:
                             if (curChar == 48) {
-                                jjCheckNAddTwoStates(28, 29);
+                                jjCheckNAddTwoStates(38, 39);
                             }
                             break;
-                        case 29:
+                        case 39:
                             if (curChar == 46) {
-                                jjCheckNAdd(30);
+                                jjCheckNAdd(40);
                             }
                             break;
-                        case 30:
+                        case 40:
                             if ((0x3ff000000000000L & l) == 0L) {
                                 break;
                             }
                             if (kind > 16) {
                                 kind = 16;
                             } {
-                            jjCheckNAddTwoStates(30, 31);
+                            jjCheckNAddTwoStates(40, 41);
                         }
                             break;
-                        case 32:
+                        case 42:
                             if ((0x280000000000L & l) != 0L) {
-                                jjCheckNAdd(33);
+                                jjCheckNAdd(43);
                             }
                             break;
-                        case 33:
+                        case 43:
                             if ((0x3ff000000000000L & l) == 0L) {
                                 break;
                             }
                             if (kind > 16) {
                                 kind = 16;
                             } {
-                            jjCheckNAdd(33);
+                            jjCheckNAdd(43);
                         }
                             break;
-                        case 34:
+                        case 44:
                             if ((0x3fe000000000000L & l) != 0L) {
-                                jjCheckNAddTwoStates(35, 29);
+                                jjCheckNAddTwoStates(45, 39);
                             }
                             break;
-                        case 35:
+                        case 45:
                             if ((0x3ff000000000000L & l) != 0L) {
-                                jjCheckNAddTwoStates(35, 29);
+                                jjCheckNAddTwoStates(45, 39);
                             }
                             break;
-                        case 36:
+                        case 46:
                             if (curChar != 48) {
                                 break;
                             }
                             if (kind > 15) {
                                 kind = 15;
                             } {
-                            jjCheckNAddStates(9, 11);
+                            jjCheckNAddStates(12, 14);
                         }
                             break;
-                        case 37:
+                        case 47:
                             if ((0x3fe000000000000L & l) == 0L) {
                                 break;
                             }
                             if (kind > 15) {
                                 kind = 15;
                             } {
-                            jjCheckNAddStates(6, 8);
+                            jjCheckNAddStates(9, 11);
                         }
                             break;
                         default:
@@ -517,76 +557,126 @@ public class JSONParserTokenManager implements 
JSONParserConstants {
                 long l = 1L << (curChar & 077);
                 do {
                     switch (jjstateSet[--i]) {
+                        case 49:
+                            if ((0xffffffffefffffffL & l) != 0L) {
+                                jjCheckNAddStates(0, 2);
+                            } else if (curChar == 92) {
+                                jjAddStates(18, 19);
+                            }
+                            break;
                         case 0:
-                        case 15:
+                        case 25:
                             if ((0x7fffffe07fffffeL & l) == 0L) {
                                 break;
                             }
-                            if (kind > 28) {
-                                kind = 28;
+                            if (kind > 30) {
+                                kind = 30;
                             } {
-                            jjCheckNAdd(15);
+                            jjCheckNAdd(25);
                         }
                             break;
-                        case 38:
-                            if ((0xffffffffefffffffL & l) != 0L) {
-                                jjCheckNAddStates(12, 14);
-                            } else if (curChar == 92) {
-                                jjstateSet[jjnewStateCnt++] = 8;
-                            }
-                            break;
-                        case 39:
+                        case 48:
                             if ((0xffffffffefffffffL & l) != 0L) {
                                 jjCheckNAddStates(15, 17);
                             } else if (curChar == 92) {
-                                jjstateSet[jjnewStateCnt++] = 13;
+                                jjAddStates(20, 21);
                             }
                             break;
                         case 1: {
-                            jjAddStates(18, 19);
+                            jjAddStates(22, 23);
                         }
                             break;
                         case 6:
                             if ((0xffffffffefffffffL & l) != 0L) {
-                                jjCheckNAddStates(12, 14);
+                                jjCheckNAddStates(15, 17);
                             }
                             break;
-                        case 7:
+                        case 8:
                             if (curChar == 92) {
-                                jjstateSet[jjnewStateCnt++] = 8;
+                                jjAddStates(20, 21);
                             }
                             break;
-                        case 8:
+                        case 9:
                             if ((0x14404410144044L & l) != 0L) {
-                                jjCheckNAddStates(12, 14);
+                                jjCheckNAddStates(15, 17);
+                            }
+                            break;
+                        case 10:
+                            if ((0x20000000200000L & l) != 0L) {
+                                jjstateSet[jjnewStateCnt++] = 11;
                             }
                             break;
                         case 11:
-                            if ((0xffffffffefffffffL & l) != 0L) {
-                                jjCheckNAddStates(15, 17);
+                            if ((0x7e0000007eL & l) != 0L) {
+                                jjstateSet[jjnewStateCnt++] = 12;
                             }
                             break;
                         case 12:
-                            if (curChar == 92) {
+                            if ((0x7e0000007eL & l) != 0L) {
                                 jjstateSet[jjnewStateCnt++] = 13;
                             }
                             break;
                         case 13:
-                            if ((0x14404410144044L & l) != 0L) {
+                            if ((0x7e0000007eL & l) != 0L) {
+                                jjstateSet[jjnewStateCnt++] = 14;
+                            }
+                            break;
+                        case 14:
+                            if ((0x7e0000007eL & l) != 0L) {
                                 jjCheckNAddStates(15, 17);
                             }
                             break;
-                        case 18: {
-                            jjAddStates(20, 21);
+                        case 16:
+                            if ((0xffffffffefffffffL & l) != 0L) {
+                                jjCheckNAddStates(0, 2);
+                            }
+                            break;
+                        case 18:
+                            if (curChar == 92) {
+                                jjAddStates(18, 19);
+                            }
+                            break;
+                        case 19:
+                            if ((0x14404410144044L & l) != 0L) {
+                                jjCheckNAddStates(0, 2);
+                            }
+                            break;
+                        case 20:
+                            if ((0x20000000200000L & l) != 0L) {
+                                jjstateSet[jjnewStateCnt++] = 21;
+                            }
+                            break;
+                        case 21:
+                            if ((0x7e0000007eL & l) != 0L) {
+                                jjstateSet[jjnewStateCnt++] = 22;
+                            }
+                            break;
+                        case 22:
+                            if ((0x7e0000007eL & l) != 0L) {
+                                jjstateSet[jjnewStateCnt++] = 23;
+                            }
+                            break;
+                        case 23:
+                            if ((0x7e0000007eL & l) != 0L) {
+                                jjstateSet[jjnewStateCnt++] = 24;
+                            }
+                            break;
+                        case 24:
+                            if ((0x7e0000007eL & l) != 0L) {
+                                jjCheckNAddStates(0, 2);
+                            }
+                            break;
+                        case 28: {
+                            jjAddStates(24, 25);
                         }
                             break;
-                        case 21: {
-                            jjAddStates(22, 23);
+                        case 31: {
+                            jjAddStates(26, 27);
                         }
                             break;
-                        case 31:
+                        case 41:
                             if ((0x2000000020L & l) != 0L) {
-                                jjAddStates(24, 25);
+                                jjAddStates(28, 29);
                             }
                             break;
                         default:
@@ -601,31 +691,31 @@ public class JSONParserTokenManager implements 
JSONParserConstants {
                 long l2 = 1L << (curChar & 077);
                 do {
                     switch (jjstateSet[--i]) {
-                        case 38:
-                        case 6:
+                        case 49:
+                        case 16:
                             if (jjCanMove_0(hiByte, i1, i2, l1, l2)) {
-                                jjCheckNAddStates(12, 14);
+                                jjCheckNAddStates(0, 2);
                             }
                             break;
-                        case 39:
-                        case 11:
+                        case 48:
+                        case 6:
                             if (jjCanMove_0(hiByte, i1, i2, l1, l2)) {
                                 jjCheckNAddStates(15, 17);
                             }
                             break;
                         case 1:
                             if (jjCanMove_0(hiByte, i1, i2, l1, l2)) {
-                                jjAddStates(18, 19);
+                                jjAddStates(22, 23);
                             }
                             break;
-                        case 18:
+                        case 28:
                             if (jjCanMove_0(hiByte, i1, i2, l1, l2)) {
-                                jjAddStates(20, 21);
+                                jjAddStates(24, 25);
                             }
                             break;
-                        case 21:
+                        case 31:
                             if (jjCanMove_0(hiByte, i1, i2, l1, l2)) {
-                                jjAddStates(22, 23);
+                                jjAddStates(26, 27);
                             }
                             break;
                         default:
@@ -643,7 +733,7 @@ public class JSONParserTokenManager implements 
JSONParserConstants {
                 kind = 0x7fffffff;
             }
             ++curPos;
-            if ((i = jjnewStateCnt) == (startsAt = 38 - (jjnewStateCnt = 
startsAt))) {
+            if ((i = jjnewStateCnt) == (startsAt = 48 - (jjnewStateCnt = 
startsAt))) {
                 return curPos;
             }
             try {
@@ -657,7 +747,7 @@ public class JSONParserTokenManager implements 
JSONParserConstants {
     /** Token literal values. */
     public static final String[] jjstrLiteralImages =
             { "", null, null, null, null, null, "\54", "\173", "\175", "\72", 
"\133", "\135", null, null, null, null,
-                    null, null, null, null, null, null, "\47\47", "\42\42", 
null, null, null, null, null, };
+                    null, null, null, null, null, null, null, null, "\47\47", 
"\42\42", null, null, null, null, null, };
 
     protected Token jjFillToken() {
         final Token t;
@@ -682,8 +772,8 @@ public class JSONParserTokenManager implements 
JSONParserConstants {
         return t;
     }
 
-    static final int[] jjnextStates =
-            { 25, 26, 28, 34, 17, 20, 27, 35, 29, 25, 28, 29, 6, 7, 9, 11, 12, 
14, 1, 2, 18, 19, 21, 23, 32, 33, };
+    static final int[] jjnextStates = { 16, 17, 18, 35, 36, 38, 44, 27, 30, 
37, 45, 39, 35, 38, 39, 6, 7, 8, 19, 20, 9,
+            10, 1, 2, 28, 29, 31, 33, 42, 43, };
 
     private static final boolean jjCanMove_0(int hiByte, int i1, int i2, long 
l1, long l2) {
         switch (hiByte) {
@@ -807,9 +897,9 @@ public class JSONParserTokenManager implements 
JSONParserConstants {
     }
 
     /** Constructor. */
-    public JSONParserTokenManager(JavaCharStream stream) {
+    public JSONParserTokenManager(SimpleCharStream stream) {
 
-        if (JavaCharStream.staticFlag) {
+        if (SimpleCharStream.staticFlag) {
             throw new Error("ERROR: Cannot use a static CharStream class with 
a non-static lexical analyzer.");
         }
 
@@ -817,13 +907,14 @@ public class JSONParserTokenManager implements 
JSONParserConstants {
     }
 
     /** Constructor. */
-    public JSONParserTokenManager(JavaCharStream stream, int lexState) {
+    public JSONParserTokenManager(SimpleCharStream stream, int lexState) {
         ReInit(stream);
         SwitchTo(lexState);
     }
 
     /** Reinitialise parser. */
-    public void ReInit(JavaCharStream stream) {
+
+    public void ReInit(SimpleCharStream stream) {
         jjmatchedPos = jjnewStateCnt = 0;
         curLexState = defaultLexState;
         input_stream = stream;
@@ -833,13 +924,13 @@ public class JSONParserTokenManager implements 
JSONParserConstants {
     private void ReInitRounds() {
         int i;
         jjround = 0x80000001;
-        for (i = 38; i-- > 0;) {
+        for (i = 48; i-- > 0;) {
             jjrounds[i] = 0x80000000;
         }
     }
 
     /** Reinitialise parser. */
-    public void ReInit(JavaCharStream stream, int lexState) {
+    public void ReInit(SimpleCharStream stream, int lexState) {
         ReInit(stream);
         SwitchTo(lexState);
     }
@@ -860,15 +951,15 @@ public class JSONParserTokenManager implements 
JSONParserConstants {
 
     /** Lex State array. */
     public static final int[] jjnewLexState = { -1, -1, -1, -1, -1, -1, -1, 
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, };
-    static final long[] jjtoToken = { 0x1ccf8fc1L, };
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, };
+    static final long[] jjtoToken = { 0x730f8fc1L, };
     static final long[] jjtoSkip = { 0x3eL, };
     static final long[] jjtoSpecial = { 0x0L, };
     static final long[] jjtoMore = { 0x0L, };
-    protected JavaCharStream input_stream;
+    protected SimpleCharStream input_stream;
 
-    private final int[] jjrounds = new int[38];
-    private final int[] jjstateSet = new int[2 * 38];
+    private final int[] jjrounds = new int[48];
+    private final int[] jjstateSet = new int[2 * 48];
     private final StringBuilder jjimage = new StringBuilder();
     private StringBuilder image = jjimage;
     private int jjimageLen;
diff --git a/java/org/apache/tomcat/util/json/JavaCharStream.java 
b/java/org/apache/tomcat/util/json/SimpleCharStream.java
similarity index 63%
rename from java/org/apache/tomcat/util/json/JavaCharStream.java
rename to java/org/apache/tomcat/util/json/SimpleCharStream.java
index 379afda6a9..4a019e8bb5 100644
--- a/java/org/apache/tomcat/util/json/JavaCharStream.java
+++ b/java/org/apache/tomcat/util/json/SimpleCharStream.java
@@ -1,4 +1,4 @@
-/* Generated By:JavaCC: Do not edit this line. JavaCharStream.java Version 7.0 
*/
+/* Generated By:JavaCC: Do not edit this line. SimpleCharStream.java Version 
7.0 */
 /* JavaCCOptions:STATIC=false,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -19,65 +19,18 @@
 package org.apache.tomcat.util.json;
 
 /**
- * An implementation of interface CharStream, where the stream is assumed to 
contain only ASCII characters (with
- * java-like unicode escape processing).
+ * An implementation of interface CharStream, where the stream is assumed to 
contain only ASCII characters (without
+ * unicode processing).
  */
 @SuppressWarnings("all") // Ignore warnings in generated code
-public class JavaCharStream {
+public class SimpleCharStream {
     /** Whether parser is static. */
     public static final boolean staticFlag = false;
-
-    static final int hexval(char c) throws java.io.IOException {
-        switch (c) {
-            case '0':
-                return 0;
-            case '1':
-                return 1;
-            case '2':
-                return 2;
-            case '3':
-                return 3;
-            case '4':
-                return 4;
-            case '5':
-                return 5;
-            case '6':
-                return 6;
-            case '7':
-                return 7;
-            case '8':
-                return 8;
-            case '9':
-                return 9;
-
-            case 'a':
-            case 'A':
-                return 10;
-            case 'b':
-            case 'B':
-                return 11;
-            case 'c':
-            case 'C':
-                return 12;
-            case 'd':
-            case 'D':
-                return 13;
-            case 'e':
-            case 'E':
-                return 14;
-            case 'f':
-            case 'F':
-                return 15;
-        }
-
-        throw new java.io.IOException(); // Should never come here
-    }
-
-    /** Position in buffer. */
-    public int bufpos = -1;
     int bufsize;
     int available;
     int tokenBegin;
+    /** Position in buffer. */
+    public int bufpos = -1;
     protected int bufline[];
     protected int bufcolumn[];
 
@@ -89,10 +42,8 @@ public class JavaCharStream {
 
     protected java.io.Reader inputStream;
 
-    protected char[] nextCharBuf;
     protected char[] buffer;
     protected int maxNextCharInd = 0;
-    protected int nextCharInd = -1;
     protected int inBuf = 0;
     protected int tabSize = 1;
     protected boolean trackLineColumn = true;
@@ -105,6 +56,7 @@ public class JavaCharStream {
         return tabSize;
     }
 
+
     protected void ExpandBuff(boolean wrapAround) {
         char[] newbuffer = new char[bufsize + 2048];
         int newbufline[] = new int[bufsize + 2048];
@@ -124,7 +76,7 @@ public class JavaCharStream {
                 System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - 
tokenBegin, bufpos);
                 bufcolumn = newbufcolumn;
 
-                bufpos += (bufsize - tokenBegin);
+                maxNextCharInd = (bufpos += (bufsize - tokenBegin));
             } else {
                 System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - 
tokenBegin);
                 buffer = newbuffer;
@@ -135,24 +87,41 @@ public class JavaCharStream {
                 System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, 
bufsize - tokenBegin);
                 bufcolumn = newbufcolumn;
 
-                bufpos -= tokenBegin;
+                maxNextCharInd = (bufpos -= tokenBegin);
             }
         } catch (Throwable t) {
             throw new Error(t.getMessage());
         }
 
-        available = (bufsize += 2048);
+
+        bufsize += 2048;
+        available = bufsize;
         tokenBegin = 0;
     }
 
     protected void FillBuff() throws java.io.IOException {
-        int i;
-        if (maxNextCharInd == 4096) {
-            maxNextCharInd = nextCharInd = 0;
+        if (maxNextCharInd == available) {
+            if (available == bufsize) {
+                if (tokenBegin > 2048) {
+                    bufpos = maxNextCharInd = 0;
+                    available = tokenBegin;
+                } else if (tokenBegin < 0) {
+                    bufpos = maxNextCharInd = 0;
+                } else {
+                    ExpandBuff(false);
+                }
+            } else if (available > tokenBegin) {
+                available = bufsize;
+            } else if ((tokenBegin - available) < 2048) {
+                ExpandBuff(true);
+            } else {
+                available = tokenBegin;
+            }
         }
 
+        int i;
         try {
-            if ((i = inputStream.read(nextCharBuf, maxNextCharInd, 4096 - 
maxNextCharInd)) == -1) {
+            if ((i = inputStream.read(buffer, maxNextCharInd, available - 
maxNextCharInd)) == -1) {
                 inputStream.close();
                 throw new java.io.IOException();
             } else {
@@ -160,59 +129,22 @@ public class JavaCharStream {
             }
             return;
         } catch (java.io.IOException e) {
-            if (bufpos != 0) {
-                --bufpos;
-                backup(0);
-            } else {
-                bufline[bufpos] = line;
-                bufcolumn[bufpos] = column;
+            --bufpos;
+            backup(0);
+            if (tokenBegin == -1) {
+                tokenBegin = bufpos;
             }
             throw e;
         }
     }
 
-    protected char ReadByte() throws java.io.IOException {
-        if (++nextCharInd >= maxNextCharInd) {
-            FillBuff();
-        }
-
-        return nextCharBuf[nextCharInd];
-    }
-
-    /** @return starting character for token. */
+    /** Start. */
     public char BeginToken() throws java.io.IOException {
-        if (inBuf > 0) {
-            --inBuf;
-
-            if (++bufpos == bufsize) {
-                bufpos = 0;
-            }
-
-            tokenBegin = bufpos;
-            return buffer[bufpos];
-        }
+        tokenBegin = -1;
+        char c = readChar();
+        tokenBegin = bufpos;
 
-        tokenBegin = 0;
-        bufpos = -1;
-
-        return readChar();
-    }
-
-    protected void AdjustBuffSize() {
-        if (available == bufsize) {
-            if (tokenBegin > 2048) {
-                bufpos = 0;
-                available = tokenBegin;
-            } else {
-                ExpandBuff(false);
-            }
-        } else if (available > tokenBegin) {
-            available = bufsize;
-        } else if ((tokenBegin - available) < 2048) {
-            ExpandBuff(true);
-        } else {
-            available = tokenBegin;
-        }
+        return c;
     }
 
     protected void UpdateLineColumn(char c) {
@@ -261,124 +193,57 @@ public class JavaCharStream {
             return buffer[bufpos];
         }
 
-        char c;
-
-        if (++bufpos == available) {
-            AdjustBuffSize();
+        if (++bufpos >= maxNextCharInd) {
+            FillBuff();
         }
 
-        if ((buffer[bufpos] = c = ReadByte()) == '\\') {
-            if (trackLineColumn) {
-                UpdateLineColumn(c);
-            }
-
-            int backSlashCnt = 1;
-
-            for (;;) // Read all the backslashes
-            {
-                if (++bufpos == available) {
-                    AdjustBuffSize();
-                }
-
-                try {
-                    if ((buffer[bufpos] = c = ReadByte()) != '\\') {
-                        if (trackLineColumn) {
-                            UpdateLineColumn(c);
-                        }
-                        // found a non-backslash char.
-                        if ((c == 'u') && ((backSlashCnt & 1) == 1)) {
-                            if (--bufpos < 0) {
-                                bufpos = bufsize - 1;
-                            }
-
-                            break;
-                        }
-
-                        backup(backSlashCnt);
-                        return '\\';
-                    }
-                } catch (java.io.IOException e) {
-                    // We are returning one backslash so we should only backup 
(count-1)
-                    if (backSlashCnt > 1) {
-                        backup(backSlashCnt - 1);
-                    }
-
-                    return '\\';
-                }
-
-                if (trackLineColumn) {
-                    UpdateLineColumn(c);
-                }
-                backSlashCnt++;
-            }
+        char c = buffer[bufpos];
 
-            // Here, we have seen an odd number of backslash's followed by a 
'u'
-            try {
-                while ((c = ReadByte()) == 'u') {
-                    ++column;
-                }
-
-                buffer[bufpos] = c = (char) (hexval(c) << 12 | 
hexval(ReadByte()) << 8 | hexval(ReadByte()) << 4 |
-                        hexval(ReadByte()));
-
-                column += 4;
-            } catch (java.io.IOException e) {
-                throw new Error("Invalid escape character at line " + line + " 
column " + column + ".");
-            }
-
-            if (backSlashCnt == 1) {
-                return c;
-            } else {
-                backup(backSlashCnt - 1);
-                return '\\';
-            }
-        } else {
-            UpdateLineColumn(c);
-            return c;
-        }
+        UpdateLineColumn(c);
+        return c;
     }
 
-    @Deprecated
     /**
      * @deprecated
      *
      * @see #getEndColumn
      */
+    @Deprecated
     public int getColumn() {
         return bufcolumn[bufpos];
     }
 
-    @Deprecated
     /**
      * @deprecated
      *
      * @see #getEndLine
      */
+    @Deprecated
     public int getLine() {
         return bufline[bufpos];
     }
 
-    /** Get end column. */
+    /** Get token end column number. */
     public int getEndColumn() {
         return bufcolumn[bufpos];
     }
 
-    /** Get end line. */
+    /** Get token end line number. */
     public int getEndLine() {
         return bufline[bufpos];
     }
 
-    /** @return column of token start */
+    /** Get token beginning column number. */
     public int getBeginColumn() {
         return bufcolumn[tokenBegin];
     }
 
-    /** @return line number of token start */
+    /** Get token beginning line number. */
     public int getBeginLine() {
         return bufline[tokenBegin];
     }
 
-    /** Retreat. */
+    /** Backup a number of characters. */
     public void backup(int amount) {
 
         inBuf += amount;
@@ -388,7 +253,7 @@ public class JavaCharStream {
     }
 
     /** Constructor. */
-    public JavaCharStream(java.io.Reader dstream, int startline, int 
startcolumn, int buffersize) {
+    public SimpleCharStream(java.io.Reader dstream, int startline, int 
startcolumn, int buffersize) {
         inputStream = dstream;
         line = startline;
         column = startcolumn - 1;
@@ -397,16 +262,15 @@ public class JavaCharStream {
         buffer = new char[buffersize];
         bufline = new int[buffersize];
         bufcolumn = new int[buffersize];
-        nextCharBuf = new char[4096];
     }
 
     /** Constructor. */
-    public JavaCharStream(java.io.Reader dstream, int startline, int 
startcolumn) {
+    public SimpleCharStream(java.io.Reader dstream, int startline, int 
startcolumn) {
         this(dstream, startline, startcolumn, 4096);
     }
 
     /** Constructor. */
-    public JavaCharStream(java.io.Reader dstream) {
+    public SimpleCharStream(java.io.Reader dstream) {
         this(dstream, 1, 1, 4096);
     }
 
@@ -421,11 +285,10 @@ public class JavaCharStream {
             buffer = new char[buffersize];
             bufline = new int[buffersize];
             bufcolumn = new int[buffersize];
-            nextCharBuf = new char[4096];
         }
         prevCharIsLF = prevCharIsCR = false;
         tokenBegin = inBuf = maxNextCharInd = 0;
-        nextCharInd = bufpos = -1;
+        bufpos = -1;
     }
 
     /** Reinitialise. */
@@ -439,35 +302,35 @@ public class JavaCharStream {
     }
 
     /** Constructor. */
-    public JavaCharStream(java.io.InputStream dstream, String encoding, int 
startline, int startcolumn, int buffersize)
-            throws java.io.UnsupportedEncodingException {
+    public SimpleCharStream(java.io.InputStream dstream, String encoding, int 
startline, int startcolumn,
+            int buffersize) throws java.io.UnsupportedEncodingException {
         this(encoding == null ? new java.io.InputStreamReader(dstream) :
                 new java.io.InputStreamReader(dstream, encoding), startline, 
startcolumn, buffersize);
     }
 
     /** Constructor. */
-    public JavaCharStream(java.io.InputStream dstream, int startline, int 
startcolumn, int buffersize) {
-        this(new java.io.InputStreamReader(dstream), startline, startcolumn, 
4096);
+    public SimpleCharStream(java.io.InputStream dstream, int startline, int 
startcolumn, int buffersize) {
+        this(new java.io.InputStreamReader(dstream), startline, startcolumn, 
buffersize);
     }
 
     /** Constructor. */
-    public JavaCharStream(java.io.InputStream dstream, String encoding, int 
startline, int startcolumn)
+    public SimpleCharStream(java.io.InputStream dstream, String encoding, int 
startline, int startcolumn)
             throws java.io.UnsupportedEncodingException {
         this(dstream, encoding, startline, startcolumn, 4096);
     }
 
     /** Constructor. */
-    public JavaCharStream(java.io.InputStream dstream, int startline, int 
startcolumn) {
+    public SimpleCharStream(java.io.InputStream dstream, int startline, int 
startcolumn) {
         this(dstream, startline, startcolumn, 4096);
     }
 
     /** Constructor. */
-    public JavaCharStream(java.io.InputStream dstream, String encoding) throws 
java.io.UnsupportedEncodingException {
+    public SimpleCharStream(java.io.InputStream dstream, String encoding) 
throws java.io.UnsupportedEncodingException {
         this(dstream, encoding, 1, 1, 4096);
     }
 
     /** Constructor. */
-    public JavaCharStream(java.io.InputStream dstream) {
+    public SimpleCharStream(java.io.InputStream dstream) {
         this(dstream, 1, 1, 4096);
     }
 
@@ -484,27 +347,27 @@ public class JavaCharStream {
     }
 
     /** Reinitialise. */
-    public void ReInit(java.io.InputStream dstream, String encoding, int 
startline, int startcolumn)
-            throws java.io.UnsupportedEncodingException {
-        ReInit(dstream, encoding, startline, startcolumn, 4096);
+    public void ReInit(java.io.InputStream dstream, String encoding) throws 
java.io.UnsupportedEncodingException {
+        ReInit(dstream, encoding, 1, 1, 4096);
     }
 
     /** Reinitialise. */
-    public void ReInit(java.io.InputStream dstream, int startline, int 
startcolumn) {
-        ReInit(dstream, startline, startcolumn, 4096);
+    public void ReInit(java.io.InputStream dstream) {
+        ReInit(dstream, 1, 1, 4096);
     }
 
     /** Reinitialise. */
-    public void ReInit(java.io.InputStream dstream, String encoding) throws 
java.io.UnsupportedEncodingException {
-        ReInit(dstream, encoding, 1, 1, 4096);
+    public void ReInit(java.io.InputStream dstream, String encoding, int 
startline, int startcolumn)
+            throws java.io.UnsupportedEncodingException {
+        ReInit(dstream, encoding, startline, startcolumn, 4096);
     }
 
     /** Reinitialise. */
-    public void ReInit(java.io.InputStream dstream) {
-        ReInit(dstream, 1, 1, 4096);
+    public void ReInit(java.io.InputStream dstream, int startline, int 
startcolumn) {
+        ReInit(dstream, startline, startcolumn, 4096);
     }
 
-    /** @return token image as String */
+    /** Get token literal value. */
     public String GetImage() {
         if (bufpos >= tokenBegin) {
             return new String(buffer, tokenBegin, bufpos - tokenBegin + 1);
@@ -513,7 +376,7 @@ public class JavaCharStream {
         }
     }
 
-    /** @return suffix */
+    /** Get the suffix. */
     public char[] GetSuffix(int len) {
         char[] ret = new char[len];
 
@@ -527,9 +390,8 @@ public class JavaCharStream {
         return ret;
     }
 
-    /** Set buffers back to null when finished. */
+    /** Reset buffer when finished. */
     public void Done() {
-        nextCharBuf = null;
         buffer = null;
         bufline = null;
         bufcolumn = null;
@@ -583,6 +445,5 @@ public class JavaCharStream {
     void setTrackLineColumn(boolean tlc) {
         trackLineColumn = tlc;
     }
-
 }
-/* JavaCC - OriginalChecksum=58f718af3466d6064ba0132bca4fbce2 (do not edit 
this line) */
+/* JavaCC - OriginalChecksum=913d499a3288e6d720c716dd95c5aa25 (do not edit 
this line) */
diff --git a/test/org/apache/tomcat/util/json/TestJSONParser.java 
b/test/org/apache/tomcat/util/json/TestJSONParser.java
new file mode 100644
index 0000000000..33a6c77aeb
--- /dev/null
+++ b/test/org/apache/tomcat/util/json/TestJSONParser.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.util.json;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestJSONParser {
+
+    @Test
+    public void testUnicodeEscapeIsNotUnescapedTwice() throws ParseException {
+        String json = "\"\\u005cn\"";
+
+        Assert.assertEquals("\\n", new JSONParser(json).parse());
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to