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

coheigea pushed a commit to branch 4.1.x-fixes
in repository https://gitbox.apache.org/repos/asf/cxf.git


The following commit(s) were added to refs/heads/4.1.x-fixes by this push:
     new e35cd88c0eb escape raw quotes after an escaped backslash in escapeJson 
(#3167)
e35cd88c0eb is described below

commit e35cd88c0ebfd6102e084f93f24ee2fc86788937
Author: Javid Khan <[email protected]>
AuthorDate: Wed Jun 3 11:47:55 2026 +0530

    escape raw quotes after an escaped backslash in escapeJson (#3167)
    
    (cherry picked from commit fd8674cfc7cee4eb6af9fddebbf6723d44af1f12)
---
 .../jaxrs/json/basic/JsonMapObjectReaderWriter.java  | 20 +++++++++++++-------
 .../json/basic/JsonMapObjectReaderWriterTest.java    | 20 ++++++++++++++++++++
 2 files changed, 33 insertions(+), 7 deletions(-)

diff --git 
a/rt/rs/extensions/json-basic/src/main/java/org/apache/cxf/jaxrs/json/basic/JsonMapObjectReaderWriter.java
 
b/rt/rs/extensions/json-basic/src/main/java/org/apache/cxf/jaxrs/json/basic/JsonMapObjectReaderWriter.java
index 117c6692c4c..22cf717f8d7 100644
--- 
a/rt/rs/extensions/json-basic/src/main/java/org/apache/cxf/jaxrs/json/basic/JsonMapObjectReaderWriter.java
+++ 
b/rt/rs/extensions/json-basic/src/main/java/org/apache/cxf/jaxrs/json/basic/JsonMapObjectReaderWriter.java
@@ -551,7 +551,8 @@ public class JsonMapObjectReaderWriter {
 
     private String escapeJson(String value) {
         StringBuilder sb = new StringBuilder();
-        for (int i = 0; i < value.length(); i++) {
+        int i = 0;
+        while (i < value.length()) {
             char c = value.charAt(i);
             if (c < 0x20) {
                 // RFC 8259 section 7: all control characters (U+0000–U+001F) 
MUST be escaped.
@@ -563,15 +564,20 @@ public class JsonMapObjectReaderWriter {
                 case '\r': sb.append("\\r");  break;
                 default:   sb.append(String.format("\\u%04x", (int) c)); break;
                 }
-            // If we have " and the previous char was not \ then escape it
-            } else if (c == '"' && (i == 0 || value.charAt(i - 1) != '\\')) {
-                sb.append('\\').append(c);
-            // If we have \ and the previous char was not \ and the next char 
is not an escaped char, then escape it
-            } else if (c == '\\' && (i == 0 || value.charAt(i - 1) != '\\')
-                    && (i == value.length() - 1 || 
!isEscapedChar(value.charAt(i + 1)))) {
+                i++;
+            // A \ that introduces an existing escape sequence (\" \\ \/ \b \f 
\n \r \t) is
+            // consumed together with the following char so it is not 
re-escaped. Looking only
+            // at the previous char misclassifies a " or \ that follows a 
complete \\ pair as
+            // already escaped, leaving it raw and breaking out of the JSON 
string.
+            } else if (c == '\\' && i + 1 < value.length() && 
isEscapedChar(value.charAt(i + 1))) {
+                sb.append(c).append(value.charAt(i + 1));
+                i += 2;
+            } else if (c == '"' || c == '\\') {
                 sb.append('\\').append(c);
+                i++;
             } else {
                 sb.append(c);
+                i++;
             }
         }
         return sb.toString();
diff --git 
a/rt/rs/extensions/json-basic/src/test/java/org/apache/cxf/jaxrs/json/basic/JsonMapObjectReaderWriterTest.java
 
b/rt/rs/extensions/json-basic/src/test/java/org/apache/cxf/jaxrs/json/basic/JsonMapObjectReaderWriterTest.java
index 124a9b1669a..034cc98b7c0 100644
--- 
a/rt/rs/extensions/json-basic/src/test/java/org/apache/cxf/jaxrs/json/basic/JsonMapObjectReaderWriterTest.java
+++ 
b/rt/rs/extensions/json-basic/src/test/java/org/apache/cxf/jaxrs/json/basic/JsonMapObjectReaderWriterTest.java
@@ -282,6 +282,26 @@ public class JsonMapObjectReaderWriterTest {
         assertEquals("a\\", entry.getValue());
     }
 
+    /**
+     * Writer-side counterpart of {@link 
#testReadStringValueEndingWithEscapedBackslashDropsSubsequentKey}.
+     * {@code escapeJson} only looked at the single character before a {@code 
"}/{@code \} to decide
+     * whether it was already escaped, so a value ending in an escaped 
backslash pair ({@code \\})
+     * followed by content left the next quote raw, breaking out of the JSON 
string.
+     */
+    @Test
+    public void testEscapeQuoteAfterEscapedBackslash() throws Exception {
+        JsonMapObjectReaderWriter jsonMapObjectReaderWriter = new 
JsonMapObjectReaderWriter();
+        Map<String, Object> content = new LinkedHashMap<>();
+        // value is: \ (escaped backslash) followed by a raw quote and an 
injected key
+        content.put("role", "user\\\\\",\"admin\":true");
+        String json = jsonMapObjectReaderWriter.toJson(content);
+
+        Map<String, Object> map = jsonMapObjectReaderWriter.fromJson(json);
+        assertEquals(1, map.size());
+        assertEquals("user\\\",\"admin\":true", map.get("role"));
+        assertNull(map.get("admin"));
+    }
+
     /**
      * Regression test for "[MEDIUM] Unicode Escapes Not Decoded — Potential 
Bypass".
      *

Reply via email to