Add regression test for from_base64 bug
What changed, and why it matters
This commit only adds a new regression test. It does not change any production code. The test checks that a function called from_base64 correctly rejects base64 inputs that decode to fewer or more than 65 bytes. Because no actual fix is included in this commit, the commit itself does not introduce or remove a security vulnerability; it merely adds a test to help catch the bug in the future.
No immediate action is required for this commit because it only adds a test. Reviewers should locate the separate commit that fixed the from_base64 bug and evaluate whether that fix is complete and present in all relevant branches.
Security signals we found
Regression test references a prior bug in message-signature base64 decoding
Test verifies length validation of decoded base64 input
No production code change in this commit
Evidence from the diff
The diff adds a unit test from_base64_rejects_non_65_byte_decode in bitcoin/src/sign_message.rs. The test constructs 88-character base64 strings (which can decode to 64, 65, or 66 bytes depending on padding) and asserts that MessageSignature::from_base64 returns an error for the 64-byte and 66-byte cases. The commit message references a pre-existing ‘from_base64 bug’ involving ‘non-65 byte invalid behaviour,’ but the patch does not contain the fix for that bug.
Changed components
bitcoin/src/sign_message.rsMessageSignature::from_base64Inspect captured patch +23 / −0
diff --git a/bitcoin/src/sign_message.rs b/bitcoin/src/sign_message.rs
index 35a1b05a..9183cdba 100644
--- a/bitcoin/src/sign_message.rs
+++ b/bitcoin/src/sign_message.rs
@@ -239,6 +239,9 @@ pub mod error {
#[cfg(test)]
mod tests {
+ #[cfg(feature = "base64")]
+ #[cfg(feature = "secp-recovery")]
+ use alloc::string::String;
use alloc::string::ToString;
use super::*;
@@ -324,4 +327,24 @@ mod tests {
let p2pkh = Address::p2pkh(pubkey, NetworkKind::Main);
assert_eq!(signature.is_signed_by_address(&p2pkh, msg_hash), Ok(false));
}
+
+ #[test]
+ #[cfg(feature = "base64")]
+ #[cfg(feature = "secp-recovery")]
+ fn from_base64_rejects_non_65_byte_decode() {
+ // 88-char base64 can decode to 64, 65, or 66 bytes.
+ let input: String = "A".repeat(88);
+ let result = super::MessageSignature::from_base64(&input);
+ assert!(result.is_err());
+
+ let mut input: String = "A".repeat(86);
+ input.extend(['=', '=']);
+ let result = super::MessageSignature::from_base64(&input);
+ assert!(result.is_err());
+
+ let mut input: String = "A".repeat(87);
+ input.extend(['=']);
+ let result = super::MessageSignature::from_base64(&input);
+ assert!(result.is_err());
+ }
}
Why this scored 12/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.