Add test to kill mutant in push_bytes
What changed, and why it matters
This commit only adds new unit tests for a decoder that reads length-prefixed byte vectors. It does not change any production code, so it cannot introduce or fix a runtime security vulnerability by itself. The tests verify that the decoder stops exactly at the declared payload length and does not accidentally consume extra trailing bytes.
No security action needed; treat as a normal test-only commit. If reviewing the related production code, separately verify ByteVecDecoder::push_bytes correctly computes remaining bytes, but that logic is not changed here.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The diff adds two test cases in consensus_encoding/tests/decode.rs for ByteVecDecoder::push_bytes. They assert that, after a length prefix declares N payload bytes, the decoder leaves any subsequent bytes untouched in the input slice. No implementation code is modified.
Changed components
consensus_encoding/tests/decode.rsInspect captured patch +35 / −0
diff --git a/consensus_encoding/tests/decode.rs b/consensus_encoding/tests/decode.rs
index 958411a9..2a4fb0da 100644
--- a/consensus_encoding/tests/decode.rs
+++ b/consensus_encoding/tests/decode.rs
@@ -194,3 +194,38 @@ fn decode_byte_vec_decoder_empty() {
let result = decoder.end().unwrap();
assert!(result.is_empty());
}
+
+#[cfg(feature = "alloc")]
+#[test]
+fn decode_byte_vec_decoder_does_not_overconsume() {
+ use bitcoin_consensus_encoding::ByteVecDecoder;
+
+ let mut decoder = ByteVecDecoder::new();
+ let mut data = &[0x02, 0xAA, 0xBB, 0xCC, 0xDD][..];
+ assert!(!decoder.push_bytes(&mut data).unwrap());
+ assert_eq!(data, &[0xCC, 0xDD][..]);
+ assert_eq!(decoder.end().unwrap(), vec![0xAA, 0xBB]);
+}
+
+#[test]
+#[cfg(feature = "alloc")]
+fn decode_byte_vec_decoder_does_not_overconsume_on_second_chunk() {
+ use bitcoin_consensus_encoding::ByteVecDecoder;
+
+ // First chunk prefix declares 4 payload bytes and provides the first one.
+ let mut first_chunk: &[u8] = &[0x04, 0xAA];
+ // Second chunk provides the remaining 3 payload bytes plus two trailing bytes.
+ let mut second_chunk: &[u8] = &[0xBB, 0xCC, 0xDD, 0x11, 0x22];
+
+ let mut decoder = ByteVecDecoder::new();
+
+ assert!(decoder.push_bytes(&mut first_chunk).unwrap());
+ assert!(first_chunk.is_empty());
+
+ let needs_more = decoder.push_bytes(&mut second_chunk).unwrap();
+ assert!(!needs_more);
+ assert_eq!(second_chunk, &[0x11, 0x22][..]);
+
+ let decoded_vec = decoder.end().unwrap();
+ assert_eq!(decoded_vec, vec![0xAA, 0xBB, 0xCC, 0xDD]);
+}
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.