You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by co...@apache.org on 2021/06/24 07:16:39 UTC

[cxf] 01/02: CXF-8555 - JsonMapObjectReaderWriter escapes now any back slash (#819)

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

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

commit 4d3b017b46d475ea3c904a070eec7d329b4ae54f
Author: Colm O hEigeartaigh <co...@users.noreply.github.com>
AuthorDate: Thu Jun 24 06:34:31 2021 +0100

    CXF-8555 - JsonMapObjectReaderWriter escapes now any back slash (#819)
    
    (cherry picked from commit f01fd3146da4b25229ea951b1f00b61b123e950c)
    (cherry picked from commit 7663d41fe2a101532eeeb80511d27e94ef375e97)
    
    # Conflicts:
    #	rt/rs/extensions/json-basic/src/main/java/org/apache/cxf/jaxrs/json/basic/JsonMapObjectReaderWriter.java
    #	rt/rs/extensions/json-basic/src/test/java/org/apache/cxf/jaxrs/json/basic/JsonMapObjectReaderWriterTest.java
---
 .../json/basic/JsonMapObjectReaderWriter.java      | 60 +++++++++++++++++-----
 .../json/basic/JsonMapObjectReaderWriterTest.java  | 56 ++++++++++++++++++--
 2 files changed, 100 insertions(+), 16 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 4ebcd99..702cd20 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
@@ -21,13 +21,8 @@ package org.apache.cxf.jaxrs.json.basic;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
+import java.io.UncheckedIOException;
+import java.util.*;
 
 import org.apache.cxf.common.util.StringUtils;
 import org.apache.cxf.helpers.IOUtils;
@@ -35,6 +30,7 @@ import org.apache.cxf.helpers.IOUtils;
 
 
 public class JsonMapObjectReaderWriter {
+    private static final Set<Character> ESCAPED_CHARS;
     private static final char DQUOTE = '"';
     private static final char COMMA = ',';
     private static final char COLON = ':';
@@ -46,6 +42,19 @@ public class JsonMapObjectReaderWriter {
     private static final String NULL_VALUE = "null";
     private boolean format;
 
+    static {
+        Set<Character> chars = new HashSet<>();
+        chars.add('"');
+        chars.add('\\');
+        chars.add('/');
+        chars.add('b');
+        chars.add('f');
+        chars.add('h');
+        chars.add('r');
+        chars.add('t');
+        ESCAPED_CHARS = Collections.unmodifiableSet(chars);
+    }
+
     public JsonMapObjectReaderWriter() {
 
     }
@@ -253,9 +262,19 @@ public class JsonMapObjectReaderWriter {
             }
         }
 
-        if (value instanceof String && ((String)value).contains("\\/")) {
-            // Escape an encoded forward slash
-            value = ((String) value).replace("\\/", "/");
+        if (value instanceof String) {
+            if (((String) value).contains("\\/")) {
+                // Escape an encoded forward slash
+                value = ((String) value).replace("\\/", "/");
+            }
+            if (((String) value).contains("\\\"")) {
+                // Escape an encoded quotation mark
+                value = ((String) value).replace("\\\"", "\"");
+            }
+            if (((String) value).contains("\\\\")) {
+                // Escape an encoded backslash
+                value = ((String) value).replace("\\\\", "\\");
+            }
         }
         return value;
     }
@@ -369,8 +388,25 @@ public class JsonMapObjectReaderWriter {
     }
 
     private String escapeJson(String value) {
-        return value.replace("\"", "\\\"")
-                .replace("\\", "\\\\");
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < value.length(); i++) {
+            char c = value.charAt(i);
+            // If we have " and the previous char was not \ then escape it
+            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)))) {
+                sb.append('\\').append(c);
+            } else {
+                sb.append(c);
+            }
+        }
+        return sb.toString();
+    }
+
+    private boolean isEscapedChar(char c) {
+        return ESCAPED_CHARS.contains(Character.valueOf(c));
     }
 
 }
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 166b5ac..d2f9ca0 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
@@ -31,6 +31,7 @@ import org.junit.Test;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 
 public class JsonMapObjectReaderWriterTest {
 
@@ -125,7 +126,7 @@ public class JsonMapObjectReaderWriterTest {
         assertEquals(1, map.size());
         Map<String, Object> xMap = CastUtils.cast((Map<?, ?>)map.get("x"));
         assertEquals(1, xMap.size());
-        assertEquals("{\\\"}", xMap.get("y"));
+        assertEquals("{\"}", xMap.get("y"));
     }
 
     @Test
@@ -152,13 +153,60 @@ public class JsonMapObjectReaderWriterTest {
     public void testEscapeDoubleQuotes() throws Exception {
         JsonMapObjectReaderWriter jsonMapObjectReaderWriter = new JsonMapObjectReaderWriter();
         Map<String, Object> content = new HashMap<>();
-        content.put("userInput", "a\",\"exp\":9999999999,\"b\":\"x");
+        content.put("userInput", "a\"");
         String json = jsonMapObjectReaderWriter.toJson(content);
+        assertTrue(json.contains("a\\\""));
 
         Map<String, Object> map = jsonMapObjectReaderWriter.fromJson(json);
         assertEquals(1, map.size());
-        assertEquals("userInput", map.keySet().iterator().next());
+        Map.Entry<String, Object> entry = map.entrySet().iterator().next();
+        assertEquals("userInput", entry.getKey());
+        assertEquals("a\"", entry.getValue());
     }
 
-}
+    @Test
+    public void testAlreadyEscapedDoubleQuotes() throws Exception {
+        JsonMapObjectReaderWriter jsonMapObjectReaderWriter = new JsonMapObjectReaderWriter();
+        Map<String, Object> content = new HashMap<>();
+        content.put("userInput", "a\\\"");
+        String json = jsonMapObjectReaderWriter.toJson(content);
+        assertTrue(json.contains("a\\\""));
+
+        Map<String, Object> map = jsonMapObjectReaderWriter.fromJson(json);
+        assertEquals(1, map.size());
+        Map.Entry<String, Object> entry = map.entrySet().iterator().next();
+        assertEquals("userInput", entry.getKey());
+        assertEquals("a\"", entry.getValue());
+    }
+
+    @Test
+    public void testEscapeBackslash() throws Exception {
+        JsonMapObjectReaderWriter jsonMapObjectReaderWriter = new JsonMapObjectReaderWriter();
+        Map<String, Object> content = new HashMap<>();
+        content.put("userInput", "a\\");
+        String json = jsonMapObjectReaderWriter.toJson(content);
+        assertTrue(json.contains("a\\\\"));
 
+        Map<String, Object> map = jsonMapObjectReaderWriter.fromJson(json);
+        assertEquals(1, map.size());
+        Map.Entry<String, Object> entry = map.entrySet().iterator().next();
+        assertEquals("userInput", entry.getKey());
+        assertEquals("a\\", entry.getValue());
+    }
+
+    @Test
+    public void testAlreadyEscapedBackslash() throws Exception {
+        JsonMapObjectReaderWriter jsonMapObjectReaderWriter = new JsonMapObjectReaderWriter();
+        Map<String, Object> content = new HashMap<>();
+        content.put("userInput", "a\\\\");
+        String json = jsonMapObjectReaderWriter.toJson(content);
+        assertTrue(json.contains("a\\\\"));
+
+        Map<String, Object> map = jsonMapObjectReaderWriter.fromJson(json);
+        assertEquals(1, map.size());
+        Map.Entry<String, Object> entry = map.entrySet().iterator().next();
+        assertEquals("userInput", entry.getKey());
+        assertEquals("a\\", entry.getValue());
+    }
+
+}