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

rmaucher 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 5958a0332a Unescape quoted strings
5958a0332a is described below

commit 5958a0332ac9c84ab65bffcf10744faf08221a8a
Author: remm <[email protected]>
AuthorDate: Mon Sep 14 23:24:29 2026 +0200

    Unescape quoted strings
---
 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]

Reply via email to