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));
+ }
+
}