From f1dcfab2934437501ed46274cfd5c366d776643f Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Sun, 17 Mar 2024 22:30:20 +0000 Subject: [PATCH] merkle_block: add resource limit check during deserialization Fixes #2606 --- bitcoin/src/merkle_tree/block.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/bitcoin/src/merkle_tree/block.rs b/bitcoin/src/merkle_tree/block.rs index 563966d7..d3fe4bb4 100644 --- a/bitcoin/src/merkle_tree/block.rs +++ b/bitcoin/src/merkle_tree/block.rs @@ -47,7 +47,7 @@ use self::MerkleBlockError::*; use crate::blockdata::block::{self, Block, TxMerkleNode}; use crate::blockdata::transaction::{Transaction, Txid}; use crate::blockdata::weight::Weight; -use crate::consensus::encode::{self, Decodable, Encodable}; +use crate::consensus::encode::{self, Decodable, Encodable, MAX_VEC_SIZE}; use crate::prelude::*; /// Data structure that represents a block header paired to a partial merkle tree. @@ -459,6 +459,12 @@ impl Decodable for PartialMerkleTree { let hashes: Vec = Decodable::consensus_decode(r)?; let nb_bytes_for_bits = encode::VarInt::consensus_decode(r)?.0 as usize; + if nb_bytes_for_bits > MAX_VEC_SIZE { + return Err(encode::Error::OversizedVectorAllocation { + requested: nb_bytes_for_bits, + max: MAX_VEC_SIZE, + }); + } let mut bits = vec![false; nb_bytes_for_bits * 8]; for chunk in bits.chunks_mut(8) { let byte = u8::consensus_decode(r)?; @@ -816,4 +822,18 @@ mod tests { tree_width_20, 7, 2, 2; tree_width_21, 7, 3, 1; } + + #[test] + fn regression_2606() { + // Attempt + let bytes = hex!( + "000006000000000000000004ee00000004c7f1ccb1000000ffff000000010000\ + 0000ffffffffff1f000000000400000000000002000000000500000000000000\ + 000000000300000000000003000000000200000000ff00000000c7f1ccb10407\ + 00000000000000ccb100c76538b100000004bfa9c251681b1b00040000000025\ + 00000004bfaac251681b1b25\ + "); + let deser = crate::consensus::deserialize::(&bytes); + assert!(deser.is_err()); + } }