add check_trailing_bits: false

While testing message parsing code, there's a chance that the sender
isn't fully compliant with base64.  This leads to failure such as below

base64 decode: non-zero trailing bits at 20211 b='i' in HRtbD4NCi==

As long as it's not destructive, its more convenient to be able to
support non-RFC messages so we can extract message artifacts for its
decision making.

closes: https://github.com/KumoCorp/kumomta/pull/558
This commit is contained in:
kay ozaki
2026-07-28 08:13:06 +01:00
committed by Wez Furlong
parent 290f6d6019
commit abce86bd24
2 changed files with 23 additions and 1 deletions
+17 -1
View File
@@ -16,13 +16,17 @@ use std::str::FromStr;
use std::sync::Arc;
/// Define our own because data_encoding::BASE64_MIME, despite its name,
/// is not RFC2045 compliant, and will not ignore spaces
/// is not RFC2045 compliant, and will not ignore spaces.
/// check_trailing_bits is disabled because real-world MIME producers emit
/// final quantums whose discarded padding bits are non-zero; a strict decoder
/// would reject those otherwise-decodable bodies.
const BASE64_RFC2045: data_encoding::Encoding = data_encoding_macro::new_encoding! {
symbols: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
padding: '=',
ignore: " \r\n\t",
wrap_width: 76,
wrap_separator: "\r\n",
check_trailing_bits: false,
};
#[derive(Debug, Clone, PartialEq)]
@@ -2282,4 +2286,16 @@ Body\r
}
);
}
/// Test the use case of check_trailing_bits being false.
/// This accepts a final quantum whose discarded padding bits are non-zero,
/// which a strict base64 decoder would reject.
/// For reference, valid base64 is aHRtbD4NCg==
#[test]
fn check_trailing_bits_test() {
// The low 4 trailing bits before `==` are non-zero in this sample.
// With check_trailing_bits=false we should still accept and decode it.
let decoded = BASE64_RFC2045.decode(b"aHRtbD4NCi==").unwrap();
assert_eq!(decoded, b"html>\r\n");
}
}
+6
View File
@@ -202,6 +202,11 @@
startup, that would otherwise lead to rocksdb corrupting itself on
the restart *after* the permissions were broken.
* Base64-encoded MIME bodies whose final quantum has non-zero discarded
padding bits are now decoded rather than rejected, matching the
leniency other mail software applies to such non-canonical encodings.
Thanks to @kayozaki! #558
## Fixes
* An SMTP command line containing bytes that are not valid UTF-8 is now
@@ -234,3 +239,4 @@
after it was first persisted are now written back to the meta spool,
rather than being silently dropped on the next reload from spool.
Thanks to @alexanderwburch! #570