On Wed, Sep 16, 2026 at 10:15 AM Mark Thomas <[email protected]> wrote:
>
> On 14/09/2026 22:24, [email protected] wrote:
> > This is an automated email from the ASF dual-hosted git repository.
> >
> > rmaucher pushed a commit to branch main
> > in repository https://gitbox.apache.org/repos/asf/tomcat.git
> >
> >
> > The following commit(s) were added to refs/heads/main by this push:
> > new 5578eb98c1 Unescape quoted strings
> > 5578eb98c1 is described below
> >
> > commit 5578eb98c185d38f76b03af1994cc515892e2813
> > Author: remm <[email protected]>
> > AuthorDate: Mon Sep 14 23:24:29 2026 +0200
> >
> > Unescape quoted strings
>
> Which version of JavaCC are you using to generate the parser? I am
> trying to fix an issue around double-decoding with unicode escaped '\'
> and can't seem to recreate the same output given the current jjt file.
Oops. So this is direct editing (which is bad, but it seemed
straightforward). Rationale for the change: the JSON was written
escaped, so expecting to read it back unescaped did not seem
unreasonable.
Rémy
> Mark
>
>
> > ---
> > java/org/apache/tomcat/util/json/JSONParser.java | 32
> > ++++++++++++++++++++++--
> > java/org/apache/tomcat/util/json/JSONParser.jjt | 32
> > ++++++++++++++++++++++--
> > 2 files changed, 60 insertions(+), 4 deletions(-)
> >
> > diff --git a/java/org/apache/tomcat/util/json/JSONParser.java
> > b/java/org/apache/tomcat/util/json/JSONParser.java
> > index c21b0f67f9..88c880e6ee 100644
> > --- a/java/org/apache/tomcat/util/json/JSONParser.java
> > +++ b/java/org/apache/tomcat/util/json/JSONParser.java
> > @@ -75,6 +75,34 @@ public class JSONParser implements JSONParserConstants {
> > return str.substring(0, pos);
> > }
> >
> > + /**
> > + * Resolve the JSON escape sequences of a string token body (the
> > + * surrounding quotes are already removed). The token grammar only
> > + * admits the short escapes: {@code \b}, {@code \f}, {@code \n},
> > + * {@code \r}, {@code \t}, {@code \/}, {@code \\} and the
> > + * self-escaped quote character.
> > + */
> > + private static String unescape(String value) {
> > + StringBuilder result = new StringBuilder(value.length());
> > + for (int i = 0; i < value.length(); i++) {
> > + char c = value.charAt(i);
> > + if (c != '\\' || i + 1 >= value.length()) {
> > + result.append(c);
> > + continue;
> > + }
> > + char next = value.charAt(++i);
> > + switch (next) {
> > + case 'b' -> result.append('\b');
> > + case 'f' -> result.append('\f');
> > + case 'n' -> result.append('\n');
> > + case 'r' -> result.append('\r');
> > + case 't' -> result.append('\t');
> > + default -> result.append(next);
> > + }
> > + }
> > + return result.toString();
> > + }
> > +
> > public void setNativeNumbers(boolean value) {
> > this.nativeNumbers = value;
> > }
> > @@ -452,7 +480,7 @@ public class JSONParser implements JSONParserConstants {
> > String image = token.image;
> > {
> > if ("" != null) {
> > - return image.substring(1, image.length() - 1);
> > + return unescape(image.substring(1, image.length()
> > - 1));
> > }
> > }
> > break;
> > @@ -481,7 +509,7 @@ public class JSONParser implements JSONParserConstants {
> > String image = token.image;
> > {
> > if ("" != null) {
> > - return image.substring(1, image.length() - 1);
> > + return unescape(image.substring(1, image.length()
> > - 1));
> > }
> > }
> > break;
> > diff --git a/java/org/apache/tomcat/util/json/JSONParser.jjt
> > b/java/org/apache/tomcat/util/json/JSONParser.jjt
> > index 08996d10ab..1726c4cab4 100644
> > --- a/java/org/apache/tomcat/util/json/JSONParser.jjt
> > +++ b/java/org/apache/tomcat/util/json/JSONParser.jjt
> > @@ -106,6 +106,34 @@ public class JSONParser {
> > return str.substring(0, pos);
> > }
> >
> > + /**
> > + * Resolve the JSON escape sequences of a string token body (the
> > + * surrounding quotes are already removed). The token grammar only
> > + * admits the short escapes: {@code \b}, {@code \f}, {@code \n},
> > + * {@code \r}, {@code \t}, {@code \/}, {@code \\} and the
> > + * self-escaped quote character.
> > + */
> > + private static String unescape(String value) {
> > + StringBuilder result = new StringBuilder(value.length());
> > + for (int i = 0; i < value.length(); i++) {
> > + char c = value.charAt(i);
> > + if (c != '\\' || i + 1 >= value.length()) {
> > + result.append(c);
> > + continue;
> > + }
> > + char next = value.charAt(++i);
> > + switch (next) {
> > + case 'b' -> result.append('\b');
> > + case 'f' -> result.append('\f');
> > + case 'n' -> result.append('\n');
> > + case 'r' -> result.append('\r');
> > + case 't' -> result.append('\t');
> > + default -> result.append(next);
> > + }
> > + }
> > + return result.toString();
> > + }
> > +
> > public void setNativeNumbers(boolean value) {
> > this.nativeNumbers = value;
> > }
> > @@ -358,7 +386,7 @@ String doubleQuoteString() : {
> > <STRING_DOUBLE_NONEMPTY>
> > {
> > String image = token.image;
> > - return image.substring(1, image.length() - 1);
> > + return unescape(image.substring(1, image.length() - 1));
> > }
> > )
> > }
> > @@ -372,7 +400,7 @@ String singleQuoteString() : {
> > <STRING_SINGLE_NONEMPTY>
> > {
> > String image = token.image;
> > - return image.substring(1, image.length() - 1);
> > + return unescape(image.substring(1, image.length() - 1));
> > }
> > )
> > }
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: [email protected]
> > For additional commands, e-mail: [email protected]
> >
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [email protected]
> For additional commands, e-mail: [email protected]
>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]