This is an automated email from the ASF dual-hosted git repository. chibenwa pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/james-mime4j.git
commit c8ff400ceb7d28ee2cedb7c87fc190ff400bb9b3 Author: Benoit TELLIER <[email protected]> AuthorDate: Mon Nov 2 15:24:38 2026 +0000 [FIX] StructuredFieldParser: a quoted pair escapes one character, also in a comment The outermost comment had no quoted pair rule, so "\)" ended it: "http://example.com/(a\) b)c" was read as "http://example.com/b)c". A quoted pair also matched the backslash and the whole rest of the value, as ANY was one character or more: a quoted pair in a quoted string or a nested comment swallowed the closing quote, and the value read as null. --- .../field/structured/StructuredFieldParser.jj | 9 ++++++++- .../mime4j/field/ContentLocationFieldTest.java | 22 ++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/dom/src/main/javacc/org/apache/james/mime4j/field/structured/StructuredFieldParser.jj b/dom/src/main/javacc/org/apache/james/mime4j/field/structured/StructuredFieldParser.jj index 71f2060f..6ba407de 100644 --- a/dom/src/main/javacc/org/apache/james/mime4j/field/structured/StructuredFieldParser.jj +++ b/dom/src/main/javacc/org/apache/james/mime4j/field/structured/StructuredFieldParser.jj @@ -152,6 +152,12 @@ SKIP : "(" : INCOMMENT } +<INCOMMENT> SKIP : +{ + // a quoted pair such as "\)" does not end the comment + < <QUOTEDPAIR> > +} + <INCOMMENT> SKIP : { // ends a comment @@ -222,6 +228,7 @@ TOKEN : <*> TOKEN : { + // a quoted pair escapes a single character < #QUOTEDPAIR: "\\" <ANY> > -| < #ANY: (~[])+ > +| < #ANY: ~[] > } \ No newline at end of file diff --git a/dom/src/test/java/org/apache/james/mime4j/field/ContentLocationFieldTest.java b/dom/src/test/java/org/apache/james/mime4j/field/ContentLocationFieldTest.java index 2d7bed6d..f2b67879 100644 --- a/dom/src/test/java/org/apache/james/mime4j/field/ContentLocationFieldTest.java +++ b/dom/src/test/java/org/apache/james/mime4j/field/ContentLocationFieldTest.java @@ -60,4 +60,26 @@ public class ContentLocationFieldTest extends TestCase { assertEquals("this/that/whatnot", location); } + public void testQuotedPairInComment() throws Exception { + ContentLocationField f = parse("Content-Location: http://example.com/(a\\) b)c"); + assertEquals("http://example.com/c", f.getLocation()); + assertNull(f.getParseException()); + } + + public void testQuotedPairInCommentShouldAgreeWithTheLenientParser() throws Exception { + String[] values = {"http://example.com/(a\\) b)c", "a(\\()b", "a(x\\\\)b", "a(\\))b", "a((\\)))b"}; + for (String value : values) { + ContentLocationField strict = parse("Content-Location: " + value); + ContentLocationField lenient = LenientContentLocationFieldTest.parse("Content-Location: " + value); + assertEquals(value, lenient.getLocation(), strict.getLocation()); + } + } + + public void testQuotedPairShouldNotSwallowTheRestOfTheValue() throws Exception { + // a quoted pair escapes one character: the closing quote and what follows are still read + ContentLocationField f = parse("Content-Location: \"a\\\"b\" (c\\) d) e"); + assertNotNull(f.getLocation()); + assertTrue(f.getLocation(), f.getLocation().endsWith("e")); + assertNull(f.getParseException()); + } } --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
