This is an automated email from the ASF dual-hosted git repository.
markt-asf pushed a commit to branch 11.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/11.0.x by this push:
new e11cbe70bc Avoid double escaping if '\' is Unicode escaped.
e11cbe70bc is described below
commit e11cbe70bcb83693d48392e0ea4265ebadeed3e9
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]