Limit bytes read with Take

This commit is contained in:
Riccardo Casatta 2021-04-20 13:59:37 +02:00
parent dc0e2b0a52
commit f692c4a938
No known key found for this signature in database
GPG Key ID: FD986A969E450397
6 changed files with 22 additions and 7 deletions

View File

@ -34,6 +34,7 @@ use blockdata::constants::WITNESS_SCALE_FACTOR;
#[cfg(feature="bitcoinconsensus")] use blockdata::script; #[cfg(feature="bitcoinconsensus")] use blockdata::script;
use blockdata::script::Script; use blockdata::script::Script;
use consensus::{encode, Decodable, Encodable}; use consensus::{encode, Decodable, Encodable};
use consensus::encode::MAX_VEC_SIZE;
use hash_types::{SigHash, Txid, Wtxid}; use hash_types::{SigHash, Txid, Wtxid};
use VarInt; use VarInt;
@ -566,7 +567,8 @@ impl Encodable for Transaction {
} }
impl Decodable for Transaction { impl Decodable for Transaction {
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, encode::Error> { fn consensus_decode<D: io::Read>(d: D) -> Result<Self, encode::Error> {
let mut d = d.take(MAX_VEC_SIZE as u64);
let version = i32::consensus_decode(&mut d)?; let version = i32::consensus_decode(&mut d)?;
let input = Vec::<TxIn>::consensus_decode(&mut d)?; let input = Vec::<TxIn>::consensus_decode(&mut d)?;
// segwit // segwit

View File

@ -575,6 +575,7 @@ macro_rules! impl_vec {
return Err(self::Error::OversizedVectorAllocation { requested: byte_size, max: MAX_VEC_SIZE }) return Err(self::Error::OversizedVectorAllocation { requested: byte_size, max: MAX_VEC_SIZE })
} }
let mut ret = Vec::with_capacity(len as usize); let mut ret = Vec::with_capacity(len as usize);
let mut d = d.take(MAX_VEC_SIZE as u64);
for _ in 0..len { for _ in 0..len {
ret.push(Decodable::consensus_decode(&mut d)?); ret.push(Decodable::consensus_decode(&mut d)?);
} }
@ -997,6 +998,15 @@ mod tests {
assert_eq!(cd.ok(), Some(CheckedData(vec![1u8, 2, 3, 4, 5]))); assert_eq!(cd.ok(), Some(CheckedData(vec![1u8, 2, 3, 4, 5])));
} }
#[test]
fn limit_read_test() {
let witness = vec![vec![0u8; 3_999_999]; 2];
let ser = serialize(&witness);
let mut reader = io::Cursor::new(ser);
let err = Vec::<Vec<u8>>::consensus_decode(&mut reader);
assert!(err.is_err());
}
#[test] #[test]
fn serialization_round_trips() { fn serialization_round_trips() {
macro_rules! round_trip { macro_rules! round_trip {

View File

@ -33,8 +33,9 @@ macro_rules! impl_consensus_encoding {
impl $crate::consensus::Decodable for $thing { impl $crate::consensus::Decodable for $thing {
#[inline] #[inline]
fn consensus_decode<D: ::std::io::Read>( fn consensus_decode<D: ::std::io::Read>(
mut d: D, d: D,
) -> Result<$thing, $crate::consensus::encode::Error> { ) -> Result<$thing, $crate::consensus::encode::Error> {
let mut d = d.take($crate::consensus::encode::MAX_VEC_SIZE as u64);
Ok($thing { Ok($thing {
$($field: $crate::consensus::Decodable::consensus_decode(&mut d)?),+ $($field: $crate::consensus::Decodable::consensus_decode(&mut d)?),+
}) })

View File

@ -29,9 +29,8 @@ use network::address::{Address, AddrV2Message};
use network::message_network; use network::message_network;
use network::message_blockdata; use network::message_blockdata;
use network::message_filter; use network::message_filter;
use consensus::encode::{CheckedData, Decodable, Encodable, VarInt}; use consensus::encode::{CheckedData, Decodable, Encodable, VarInt, MAX_VEC_SIZE};
use consensus::{encode, serialize}; use consensus::{encode, serialize};
use consensus::encode::MAX_VEC_SIZE;
/// The maximum number of [Inventory] items in an `inv` message. /// The maximum number of [Inventory] items in an `inv` message.
/// ///

View File

@ -19,6 +19,7 @@ use std::cmp;
use blockdata::transaction::Transaction; use blockdata::transaction::Transaction;
use consensus::{encode, Encodable, Decodable}; use consensus::{encode, Encodable, Decodable};
use consensus::encode::MAX_VEC_SIZE;
use util::psbt::map::Map; use util::psbt::map::Map;
use util::psbt::raw; use util::psbt::raw;
use util::psbt; use util::psbt;
@ -228,8 +229,8 @@ impl Map for Global {
impl_psbtmap_consensus_encoding!(Global); impl_psbtmap_consensus_encoding!(Global);
impl Decodable for Global { impl Decodable for Global {
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, encode::Error> { fn consensus_decode<D: io::Read>(d: D) -> Result<Self, encode::Error> {
let mut d = d.take(MAX_VEC_SIZE as u64);
let mut tx: Option<Transaction> = None; let mut tx: Option<Transaction> = None;
let mut version: Option<u32> = None; let mut version: Option<u32> = None;
let mut unknowns: BTreeMap<raw::Key, Vec<u8>> = Default::default(); let mut unknowns: BTreeMap<raw::Key, Vec<u8>> = Default::default();

View File

@ -21,6 +21,7 @@
use blockdata::script::Script; use blockdata::script::Script;
use blockdata::transaction::Transaction; use blockdata::transaction::Transaction;
use consensus::{encode, Encodable, Decodable}; use consensus::{encode, Encodable, Decodable};
use consensus::encode::MAX_VEC_SIZE;
use std::io; use std::io;
@ -162,7 +163,8 @@ impl Encodable for PartiallySignedTransaction {
} }
impl Decodable for PartiallySignedTransaction { impl Decodable for PartiallySignedTransaction {
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, encode::Error> { fn consensus_decode<D: io::Read>(d: D) -> Result<Self, encode::Error> {
let mut d = d.take(MAX_VEC_SIZE as u64);
let magic: [u8; 4] = Decodable::consensus_decode(&mut d)?; let magic: [u8; 4] = Decodable::consensus_decode(&mut d)?;
if *b"psbt" != magic { if *b"psbt" != magic {