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

rombert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/felix-dev.git


The following commit(s) were added to refs/heads/master by this push:
     new 5d14b67a93 FELIX-6669 - proper detection of string property & comment 
boundaries… (#244)
5d14b67a93 is described below

commit 5d14b67a9372f152513267f0ee4438a4f34d7519
Author: Dominik Süß <[email protected]>
AuthorDate: Thu Nov 16 10:19:32 2023 +0100

    FELIX-6669 - proper detection of string property & comment boundaries… 
(#244)
    
    * proper detection of string property & comment boundaries to avoid mixing 
and false positive and false negative stripping
    * fix inline comment to match logic iteration
    * expand if condition, even there is no logic to hit those lines it's 
better readable and more efficient to shield by shared insideString check
    * fix handling of String properties containing escaped quotes to not 
prematurely detect end of string property
---
 .../apache/felix/cm/json/io/impl/JsonSupport.java  |  79 ++++++++++-----
 .../felix/cm/json/io/impl/JsonSupportTest.java     | 112 +++++++++++++++++++++
 2 files changed, 166 insertions(+), 25 deletions(-)

diff --git 
a/cm.json/src/main/java/org/apache/felix/cm/json/io/impl/JsonSupport.java 
b/cm.json/src/main/java/org/apache/felix/cm/json/io/impl/JsonSupport.java
index fe7ec3b73b..278525e890 100644
--- a/cm.json/src/main/java/org/apache/felix/cm/json/io/impl/JsonSupport.java
+++ b/cm.json/src/main/java/org/apache/felix/cm/json/io/impl/JsonSupport.java
@@ -243,6 +243,7 @@ public class JsonSupport {
         private boolean closed = false;
         private boolean insideComment = false;
         private boolean insideLineComment = false;
+        private boolean insideString = false;
             
         public CommentRemovingReader(Reader reader) {
             super(new BufferedReader(reader));
@@ -260,41 +261,69 @@ public class JsonSupport {
                     StringBuilder filteredContent = new StringBuilder();
                     StringBuilder currentLine = new StringBuilder();
                     
-
                     for (int i = off; i < off + charsRead; i++) {
                         char c = cbuf[i];
+                        
 
-                        // Handle comments
-                        if (!insideComment && c == '/') {
-                            if (i < off + charsRead - 1) {
-                                if (cbuf[i + 1] == '*') {
-                                    insideComment = true;
-                                    i++; // Skip '*' character
-                                    continue;
-                                } else if (cbuf[i + 1] == '/') {
-                                    insideLineComment = true;
-                                    i++; // Skip '/' character
+                        // Detect String start/end if not inside a comment
+                        if (!insideComment && !insideLineComment) {
+                            if (c == '"') {
+                                // handle escaped quotes inside strings
+                                if (i > 0 && cbuf[i - 1] == '\\') {
+                                    // escaped quote inside a string, include 
both the backslash and the quote
+                                    currentLine.append(c);
                                     continue;
                                 }
+                                insideString = !insideString;
                             }
                         }
 
-                        //if inside a multiline comment, count newlines
-                        if (insideComment && !insideLineComment && c == '\n') {
-                            currentLine.append(c);
-                            continue;
-                        }
 
-                        // Skip characters inside multiline comments
-                        if (insideComment && c == '*' && i < off + charsRead - 
1 && cbuf[i + 1] == '/') {
-                            insideComment = false;
-                            i++; // Skip '/' character
-                            continue;
-                        }
+                        // Handle comments only if not inside a string
+                        if (!insideString) {
+                            // Detect start of single-line comment
+                            if (!insideComment && c == '/' && i < off + 
charsRead - 1 && cbuf[i + 1] == '/') {
+                                insideLineComment = true;
+                                i++; // Skip '/' character
+                                continue;
+                            }
+
+                            // Detect start of multi-line comment
+                            if (!insideComment && c == '/' && i < off + 
charsRead - 1 && cbuf[i + 1] == '*') {
+                                insideComment = true;
+                                i++; // Skip '*' character
+                                continue;
+                            }
 
-                        // Skip characters inside single-line comments
-                        if (insideLineComment && c == '\n') {
-                            insideLineComment = false;
+                            // Detect end of multi-line comment
+                            if (insideComment && c == '*' && i < off + 
charsRead - 1 && cbuf[i + 1] == '/') {
+                                insideComment = false;
+                                i++; // Skip '/' character
+                                continue;
+                            }
+
+                            // Skip characters inside single-line comments
+                            if (insideLineComment && c == '\n') {
+                                insideLineComment = false;
+                            }
+                            
+                            // Preserve newline characters inside multiline 
comments
+                            if (insideComment && !insideLineComment && c == 
'\n') {
+                                currentLine.append(c);
+                                continue;
+                            }
+
+                            // Skip characters inside multiline comments
+                            if (insideComment && c == '*' && i < off + 
charsRead - 1 && cbuf[i + 1] == '/') {
+                                insideComment = false;
+                                i++; // Skip '/' character
+                                continue;
+                            }
+
+                            // Skip characters inside single-line comments
+                            if (insideLineComment && c == '\n') {
+                                insideLineComment = false;
+                            }
                         }
 
                         // Preserve characters outside comments
diff --git 
a/cm.json/src/test/java/org/apache/felix/cm/json/io/impl/JsonSupportTest.java 
b/cm.json/src/test/java/org/apache/felix/cm/json/io/impl/JsonSupportTest.java
index bf9d631408..3dfc1d35c1 100644
--- 
a/cm.json/src/test/java/org/apache/felix/cm/json/io/impl/JsonSupportTest.java
+++ 
b/cm.json/src/test/java/org/apache/felix/cm/json/io/impl/JsonSupportTest.java
@@ -195,4 +195,116 @@ public class JsonSupportTest {
                 + "  \"b\" : 2\n"
                 + "}\n", parse(input));
     }
+
+    // Test comment in the middle of a string
+    @Test
+    public void testCommentInString() throws IOException {
+        final String input = "{\n"
+                             + "  \"a\" : \"// comment\",\n"
+                             + "  \"b\" : 2\n"
+                             + "}\n";
+
+        assertEquals("{\n"
+                + "  \"a\" : \"// comment\",\n"
+                + "  \"b\" : 2\n"
+                + "}\n", parse(input));
+    }
+
+    @Test
+    public void testMultilineCommentInString() throws IOException {
+        final String input = "{\n"
+                             + "  \"a\" : \"/* comment */\",\n"
+                             + "  \"b\" : 2\n"
+                             + "  \"c\" : \"value /* comment */\"\n"
+                             + "}\n";
+
+        assertEquals("{\n"
+                + "  \"a\" : \"/* comment */\",\n"
+                + "  \"b\" : 2\n"
+                + "  \"c\" : \"value /* comment */\"\n"
+                + "}\n", parse(input));
+    }
+
+    @Test
+    public void testMultilineCommentInStringWithStripping() throws IOException 
{
+        final String input = "{\n"
+                             + "  \"a\" : \"/* comment */\",\n"
+                             + "  \"b\" : 2\n"
+                             + "  \"c\" : \"value /* comment */\"\n"
+                             + "  // comment\n"
+                             + "  /** And more\n"
+                             + "   * comments\n"
+                             + "   */\n"
+                             + "}\n";
+
+        assertEquals("{\n"
+                + "  \"a\" : \"/* comment */\",\n"
+                + "  \"b\" : 2\n"
+                + "  \"c\" : \"value /* comment */\"\n"
+                + "  \n"
+                + "  \n"
+                + "\n"
+                + "\n"
+                + "}\n", parse(input));
+    }
+    
+    @Test
+    public void testMultiLineStartTokenInString() throws IOException {
+        final String input = "{\n"
+                             + "  \"a\" : \"test/*\",\n"
+                             + "  \"b\" : 2\n"
+                             + "}\n";
+
+        assertEquals("{\n"
+                + "  \"a\" : \"test/*\",\n"
+                + "  \"b\" : 2\n"
+                + "}\n", parse(input));
+    }
+
+    @Test
+    public void testStripLineCommentWithQuotes() throws IOException {
+        final String input = "// Some comment \"with quote \n" 
+                                + "{\n"
+                                + "  \"a\" : 1,\n"
+                                + "  \"b\" : 2\n"
+                                + "}\n";
+        assertEquals("\n" +
+                "{\n"
+                + "  \"a\" : 1,\n"
+                + "  \"b\" : 2\n"
+                + "}\n", parse(input));
+    }
+
+    @Test
+    public void testStripMultiLineCommentWithQuotes() throws IOException {
+        final String input = "{\n"
+                                + "  \"a\" : 1,\n"
+                                + "  // another comment\n"
+                                + "  /** And \"more\n"
+                                + "   * comments\"\n"
+                                + "   */\n"
+                                + "  \"b\" : 2\n"
+                                + "}\n";
+        assertEquals("{\n"
+                + "  \"a\" : 1,\n"
+                + "  \n"
+                + "  \n"
+                + "\n"
+                + "\n"
+                + "  \"b\" : 2\n"
+                + "}\n", parse(input));
+    }
+
+    //test case for escaped quotes in string properties
+    @Test
+    public void testEscapedQuotes() throws IOException {
+        final String input = "{\n"
+                             + "  \"a\" : \"\\\"\",\n"
+                             + "}\n";
+
+        assertEquals("{\n"
+                + "  \"a\" : \"\\\"\",\n"
+                + "}\n", parse(input));
+    }
+
 }

Reply via email to