diff options
author | Jan Engelhardt <[email protected]> | 2024-05-21 13:47:05 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2024-05-21 13:47:05 +0000 |
commit | b447adbe373d3940d2023d8e7a6ec21c7bfb8a48 (patch) | |
tree | 5c8092e7215d83400ec5ad3a377f3da9db7678c0 | |
parent | vmime: avoid changing SEVEN_BIT when encoding::decideImpl sees U+007F (#303) (diff) | |
download | vmime-b447adbe373d3940d2023d8e7a6ec21c7bfb8a48.tar.gz vmime-b447adbe373d3940d2023d8e7a6ec21c7bfb8a48.zip |
Fixes/comments for guessBestEncoding (#304)
* tests: add case for getRecommendedEncoding
* vmime: avoid integer multiply wraparound in wordEncoder::guessBestEncoding
If the input string is 42949673 characters long or larger, there will
be integer overflow on 32-bit platforms when multiplying by 100.
Switch that one computation to floating point.
* vmime: update comment in wordEncoder::guessBestEncoding
-rw-r--r-- | src/vmime/wordEncoder.cpp | 10 | ||||
-rw-r--r-- | tests/parser/textTest.cpp | 12 | ||||
-rw-r--r-- | tests/parser/wordEncoderTest.cpp | 9 |
3 files changed, 27 insertions, 4 deletions
diff --git a/src/vmime/wordEncoder.cpp b/src/vmime/wordEncoder.cpp index 4f47d047..d1632022 100644 --- a/src/vmime/wordEncoder.cpp +++ b/src/vmime/wordEncoder.cpp @@ -302,14 +302,16 @@ wordEncoder::Encoding wordEncoder::guessBestEncoding( } } - // Use Base64 if more than 40% non-ASCII, or Quoted-Printable else (default) + // Base64 would be more space-efficient when the ASCII content is + // below 83.33%, but QP has a legibility arugment going for it, so we + // picked 60%. const size_t asciiCount = utility::stringUtils::countASCIIchars(buffer.begin(), buffer.end()); - const size_t asciiPercent = - buffer.length() == 0 ? 100 : (100 * asciiCount) / buffer.length(); + const double asciiPercent = + buffer.length() == 0 ? 100 : static_cast<double>(asciiCount) / buffer.length(); - if (asciiPercent < 60) { + if (asciiPercent < 0.60) { return ENCODING_B64; } else { return ENCODING_QP; diff --git a/tests/parser/textTest.cpp b/tests/parser/textTest.cpp index e9ddc262..f5111e79 100644 --- a/tests/parser/textTest.cpp +++ b/tests/parser/textTest.cpp @@ -32,6 +32,7 @@ VMIME_TEST_SUITE_BEGIN(textTest) VMIME_TEST_LIST_BEGIN VMIME_TEST(testConstructors) VMIME_TEST(testCopy) + VMIME_TEST(testRecommendedEncoding) VMIME_TEST(testNewFromString) VMIME_TEST(testDisplayForm) VMIME_TEST(testParse) @@ -155,6 +156,17 @@ VMIME_TEST_SUITE_BEGIN(textTest) VASSERT("copyFrom", t1 == t2); } + void testRecommendedEncoding() { + + vmime::encoding enc; + VASSERT_TRUE("1.1", vmime::charset("iso8859-1").getRecommendedEncoding(enc)); + VASSERT_TRUE("1.2", enc.getName() == vmime::encodingTypes::QUOTED_PRINTABLE); + VASSERT_TRUE("1.2", vmime::charset("iso8859-2").getRecommendedEncoding(enc)); + VASSERT_TRUE("1.3", enc.getName() == vmime::encodingTypes::QUOTED_PRINTABLE); + VASSERT_FALSE("1.3", vmime::charset(vmime::charsets::UTF_8).getRecommendedEncoding(enc)); + + } + void testNewFromString() { vmime::string s1 = "only ASCII characters"; diff --git a/tests/parser/wordEncoderTest.cpp b/tests/parser/wordEncoderTest.cpp index 08d34aa4..0c827bff 100644 --- a/tests/parser/wordEncoderTest.cpp +++ b/tests/parser/wordEncoderTest.cpp @@ -36,6 +36,7 @@ VMIME_TEST_SUITE_BEGIN(wordEncoderTest) VMIME_TEST(testIsEncodingNeeded_specialChars) VMIME_TEST(testGuessBestEncoding_QP) VMIME_TEST(testGuessBestEncoding_B64) + VMIME_TEST(testGuessBestEncoding_size) VMIME_TEST(testEncodeQP_RFC2047) VMIME_TEST_LIST_END @@ -159,6 +160,14 @@ VMIME_TEST_SUITE_BEGIN(wordEncoderTest) ); } + void testGuessBestEncoding_size() { + + std::string i(42949673, 'a'); + auto enc = vmime::wordEncoder::guessBestEncoding(i, vmime::charset("utf-8")); + VASSERT_EQ("1", enc, vmime::wordEncoder::ENCODING_QP); + + } + void testEncodeQP_RFC2047() { // When Quoted-Printable is used, it should be RFC-2047 QP encoding |