From 7a9818679f70cea9d081e9909e71ca081270d27e Mon Sep 17 00:00:00 2001 From: NetterSilver <133535268+Silvertree2010@users.noreply.github.com> Date: Sun, 25 Oct 2026 12:00:58 +0000 Subject: [PATCH] Reject misplaced or excess '=' padding in base64_decode Found while testing crates/format/src/lib.rs:690-717 (base64_decode) Co-Authored-By: Claude Haiku 5.5 Co-Authored-By: Claude Sonnet 5.5 --- crates/format/src/lib.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/crates/format/src/lib.rs b/crates/format/src/lib.rs index d76453bee..f0ac3b452 100644 --- a/crates/format/src/lib.rs +++ b/crates/format/src/lib.rs @@ -694,17 +694,23 @@ pub fn base64_decode(s: &str) -> Option> { return None; } let mut out = Vec::with_capacity(clean.len() / 4 * 3); - for c in clean.chunks(4) { + let groups = clean.len() / 4; + for (i, c) in clean.chunks(4).enumerate() { let mut n = 0u32; let mut pad = 0; for &b in c { n <<= 6; if b == b'=' { pad += 1; + } else if pad > 0 { + return None; } else { n |= val(b)?; } } + if pad > 2 || (pad > 0 && i + 1 != groups) { + return None; + } out.push((n >> 16) as u8); if pad < 2 { out.push((n >> 8) as u8); @@ -782,4 +788,14 @@ mod tests { } assert_eq!(base64_encode(b"foobar"), "Zm9vYmFy"); } + + #[test] + fn base64_rejects_misplaced_padding() { + for s in ["====", "A===", "AA=A", "=AAA", "QQ==QUJD", "QUI=QUJD"] { + assert_eq!(base64_decode(s), None, "{s}"); + } + assert_eq!(base64_decode("QQ=="), Some(vec![0x41])); + assert_eq!(base64_decode("QUI="), Some(vec![0x41, 0x42])); + assert_eq!(base64_decode("QUJD"), Some(vec![0x41, 0x42, 0x43])); + } }