diff options
author | Jan Engelhardt <[email protected]> | 2019-10-05 09:24:48 +0000 |
---|---|---|
committer | Jan Engelhardt <[email protected]> | 2019-10-05 09:37:09 +0000 |
commit | b06e9e6f86389864854ece1207cd30cfe6a874a2 (patch) | |
tree | 8bf4749284a3d6cece5aa00bb84ce5744afb1e0e | |
parent | Disregard whitespace between leading boundary hyphens and marker (diff) | |
download | vmime-b06e9e6f86389864854ece1207cd30cfe6a874a2.tar.gz vmime-b06e9e6f86389864854ece1207cd30cfe6a874a2.zip |
Skip delimiter lines that are not exactly equal to the boundary
There is crap software out there that generates mails violating the
prefix ban clause from RFC 2046 §5.1 ¶2.
Switch vmime from a prefix match to an equality match, similar to
what Alpine and Thunderbird do too.
-rw-r--r-- | src/vmime/body.cpp | 18 | ||||
-rw-r--r-- | tests/parser/bodyPartTest.cpp | 38 |
2 files changed, 56 insertions, 0 deletions
diff --git a/src/vmime/body.cpp b/src/vmime/body.cpp index 4103f328..a3875b9d 100644 --- a/src/vmime/body.cpp +++ b/src/vmime/body.cpp @@ -53,6 +53,11 @@ body::~body() { } +/* + * boundaryStart: will become the index for "\r\n--marker" + * boundaryEnd: will become the index after "marker", i.e. index for potential trailing "--", "\r\n", etc. + * return value: index for "marker" + */ // static size_t body::findNextBoundaryPosition( const shared_ptr <utility::parserInputStreamAdapter>& parser, @@ -271,6 +276,19 @@ void body::parseImpl( boundaryEnd += 2; } else if (boundaryEnd < end && parser->peekByte() == '\n') { ++boundaryEnd; + } else if (boundaryEnd == end) { + } else { + /* + * RFC 2046 §5.1.1 page 19: """[...] optional + * linear whitespace, and a terminating + * CRLF.""" — junk handling is left + * unspecified, so we might as well skip it to + * facilitate broken mails. + */ + boundaryEnd += parser->skipIf([](char_t c) { return c != '\n'; }, end); + pos = findNextBoundaryPosition(parser, boundary, boundaryEnd, end, &boundaryStart, &boundaryEnd); + --index; + continue; } if (index == 0) { diff --git a/tests/parser/bodyPartTest.cpp b/tests/parser/bodyPartTest.cpp index 062007d9..3aaadd03 100644 --- a/tests/parser/bodyPartTest.cpp +++ b/tests/parser/bodyPartTest.cpp @@ -39,6 +39,7 @@ VMIME_TEST_SUITE_BEGIN(bodyPartTest) VMIME_TEST(testGenerate7bit) VMIME_TEST(testTextUsageForQPEncoding) VMIME_TEST(testParseVeryBigMessage) + VMIME_TEST(testParseBoundaryPrefix) VMIME_TEST_LIST_END @@ -373,4 +374,41 @@ VMIME_TEST_SUITE_BEGIN(bodyPartTest) VASSERT("2.2", vmime::dynamicCast <const vmime::streamContentHandler>(body2Cts) != NULL); } + void testParseBoundaryPrefix() { + /* + * Clients are not supposed to create boundary identifiers that + * contain a prefix of another (RFC 2046 section 5.1), but alas + * CANCOM FortiMail produces this garbage. + */ + vmime::string str = + "Content-Type: multipart/related; boundary=\"--b12\"\r\n" + "\r\n" + "----b12\r\n" + "Content-Type: multipart/alternative; boundary=\"--b12-1\"\r\n" + "\r\n" + "----b12-1\r\n" + "Content-Type: text/plain; charset=utf-8\r\n" + "\r\n" + "P11\r\n" + "----b12-1\r\n" + "Content-Type: text/html; charset=utf-8\r\n" + "\r\n" + "P12\r\n" + "----b12-1--\r\n" + "----b12\r\n" + "\r\n" + "P2\r\n" + "----b12--\r\n"; + + vmime::bodyPart relco; + relco.parse(str); + auto relbd = relco.getBody(); + VASSERT_EQ("global-partcount", 2, relbd->getPartCount()); + auto altbd = relbd->getPartAt(0)->getBody(); + VASSERT_EQ("part1-partcount", 2, altbd->getPartCount()); + VASSERT_EQ("part1.1-body", "P11", extractContents(altbd->getPartAt(0)->getBody()->getContents())); + VASSERT_EQ("part1.2-body", "P12", extractContents(altbd->getPartAt(1)->getBody()->getContents())); + VASSERT_EQ("part2-body", "P2", extractContents(relbd->getPartAt(1)->getBody()->getContents())); + } + VMIME_TEST_SUITE_END |