From 8d4aca42b40f713230a08e4e9618fb76187ff9dd Mon Sep 17 00:00:00 2001 From: Wleeaf <179125857+wleeaf@users.noreply.github.com> Date: Sun, 25 Oct 2026 14:23:23 +0000 Subject: [PATCH] fix: don't treat backslashes in comments as escapes The parser handled escape sequences in every token, including comments. In java.util.Properties a backslash has no special meaning in a comment line, and a comment line can't be continued. Here a comment with a Windows path made loading fail ("# C:\users" is read as a malformed \uXXXX escape), and a comment ending with a backslash swallowed the next line, so the property on it was lost: # temp dir: C:\temp\ alpha=1 Comments are now read as they are, up to the end of the line. --- .../org/codejive/properties/PropertiesParser.java | 3 ++- .../org/codejive/properties/TestProperties.java | 8 ++++++++ .../codejive/properties/TestPropertiesParser.java | 15 +++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/codejive/properties/PropertiesParser.java b/src/main/java/org/codejive/properties/PropertiesParser.java index 8a37551..5bfa3e0 100644 --- a/src/main/java/org/codejive/properties/PropertiesParser.java +++ b/src/main/java/org/codejive/properties/PropertiesParser.java @@ -269,7 +269,8 @@ private int readChar() throws IOException { private void addChar(int ch) throws IOException { str.append((char) ch); - if (ch == '\\') { + // Comments have no escapes or line continuations + if (ch == '\\' && state != Type.COMMENT) { hasEscapes = true; int ch2 = readChar(); str.append((char) ch2); diff --git a/src/test/java/org/codejive/properties/TestProperties.java b/src/test/java/org/codejive/properties/TestProperties.java index 989d325..b53273a 100644 --- a/src/test/java/org/codejive/properties/TestProperties.java +++ b/src/test/java/org/codejive/properties/TestProperties.java @@ -822,6 +822,14 @@ void testPutAtInvalidPosition() throws IOException { assertThat(p).containsEntry("middle", "3"); } + @Test + void testCommentEndingWithBackslash() throws IOException { + Properties p = + Properties.loadProperties(new StringReader("# temp dir: C:\\temp\\\nalpha=1\n")); + + assertThat(p).containsEntry("alpha", "1"); + } + @Test void testPutNewTest2() throws IOException, URISyntaxException { Path f = getResource("/test2.properties"); diff --git a/src/test/java/org/codejive/properties/TestPropertiesParser.java b/src/test/java/org/codejive/properties/TestPropertiesParser.java index f967642..3214ff3 100644 --- a/src/test/java/org/codejive/properties/TestPropertiesParser.java +++ b/src/test/java/org/codejive/properties/TestPropertiesParser.java @@ -108,6 +108,21 @@ void testStringify() throws IOException { assertThat(props2).isEqualTo(props); } + @Test + void testBackslashesInComment() throws IOException { + List tokens = + PropertiesParser.tokens(new StringReader("# C:\\users\\\nfoo=bar")) + .collect(Collectors.toList()); + + assertThat(tokens) + .containsExactly( + new Token(Type.COMMENT, "# C:\\users\\"), + new Token(Type.WHITESPACE, "\n"), + new Token(Type.KEY, "foo"), + new Token(Type.SEPARATOR, "="), + new Token(Type.VALUE, "bar")); + } + @Test void testEmptySeparatorAndValueAtEof() throws IOException { List tokens =