From 51e2cce2a8256d0510a0c0decd7e5183bbf65da9 Mon Sep 17 00:00:00 2001 From: Elliotte Rusty Harold Date: Tue, 30 Jun 2026 16:30:07 -0400 Subject: [PATCH 1/2] Add missing EOF checks in MultiDelimiterInterpolatorFilterReaderLineEnding.read() The escape-detection loop (line 223) and delimiter-detection loop (line 246) were missing ch == -1 checks. When EOF is reached mid-token, (char) -1 produces 0xFFFF which gets appended to the key StringBuilder as garbage. The equivalent single-delimiter class InterpolatorFilterReaderLineEnding already has these checks. --- .../MultiDelimiterInterpolatorFilterReaderLineEnding.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/apache/maven/shared/filtering/MultiDelimiterInterpolatorFilterReaderLineEnding.java b/src/main/java/org/apache/maven/shared/filtering/MultiDelimiterInterpolatorFilterReaderLineEnding.java index 40213307..20847ea6 100644 --- a/src/main/java/org/apache/maven/shared/filtering/MultiDelimiterInterpolatorFilterReaderLineEnding.java +++ b/src/main/java/org/apache/maven/shared/filtering/MultiDelimiterInterpolatorFilterReaderLineEnding.java @@ -220,7 +220,7 @@ public int read() throws IOException { for (int i = 0; i < getEscapeString().length(); i++) { key.append((char) ch); - if (ch != getEscapeString().charAt(i) || ch == '\n' && !supportMultiLineFiltering) { + if (ch != getEscapeString().charAt(i) || ch == -1 || ch == '\n' && !supportMultiLineFiltering) { // mismatch, EOF or EOL, no escape string here in.reset(); inEscape = false; @@ -243,7 +243,7 @@ public int read() throws IOException { } for (int i = 0; i < begin.length(); i++) { - if (ch != begin.charAt(i) || ch == '\n' && !supportMultiLineFiltering) { + if (ch != begin.charAt(i) || ch == -1 || ch == '\n' && !supportMultiLineFiltering) { // mismatch, EOF or EOL, no match break; } From 6af127109c08e35b1d893a26ab00433cc8f035a7 Mon Sep 17 00:00:00 2001 From: Elliotte Rusty Harold Date: Tue, 30 Jun 2026 16:37:33 -0400 Subject: [PATCH 2/2] Guard against (char) -1 in escape handling; add regression test --- ...tiDelimiterInterpolatorFilterReaderLineEnding.java | 4 +++- ...limiterInterpolatorFilterReaderLineEndingTest.java | 11 +++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/apache/maven/shared/filtering/MultiDelimiterInterpolatorFilterReaderLineEnding.java b/src/main/java/org/apache/maven/shared/filtering/MultiDelimiterInterpolatorFilterReaderLineEnding.java index 20847ea6..37b84e27 100644 --- a/src/main/java/org/apache/maven/shared/filtering/MultiDelimiterInterpolatorFilterReaderLineEnding.java +++ b/src/main/java/org/apache/maven/shared/filtering/MultiDelimiterInterpolatorFilterReaderLineEnding.java @@ -274,7 +274,9 @@ public int read() throws IOException { beginToken = null; endToken = null; - key.append((char) ch); + if (ch >= 0) { + key.append((char) ch); + } replaceData = key.toString(); replaceIndex = key.length(); diff --git a/src/test/java/org/apache/maven/shared/filtering/MultiDelimiterInterpolatorFilterReaderLineEndingTest.java b/src/test/java/org/apache/maven/shared/filtering/MultiDelimiterInterpolatorFilterReaderLineEndingTest.java index d8891602..2f9af31f 100644 --- a/src/test/java/org/apache/maven/shared/filtering/MultiDelimiterInterpolatorFilterReaderLineEndingTest.java +++ b/src/test/java/org/apache/maven/shared/filtering/MultiDelimiterInterpolatorFilterReaderLineEndingTest.java @@ -108,4 +108,15 @@ void atDollarExpression() throws Exception { assertEquals(" url=\"jdbc:oracle:thin:@DB_SERVER:DB_PORT:DB_NAME\"", IOUtils.toString(reader)); } + + @Test + void eofAfterEscapeCharDoesNotProduceGarbage() throws Exception { + Reader in = new StringReader("\\"); + MultiDelimiterInterpolatorFilterReaderLineEnding reader = + new MultiDelimiterInterpolatorFilterReaderLineEnding(in, interpolator, true); + reader.setDelimiterSpecs(Collections.singleton("@")); + reader.setEscapeString("\\"); + + assertEquals("\\", IOUtils.toString(reader)); + } }