From 639c964f91894bf5f22d7a3fe9ac504ab31a3c7d Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Tue, 18 Jun 2024 18:57:27 +0000 Subject: [PATCH] transaction: range-check pegin data when parsing It is possible to cause a panic by calling `TxIn::pegin_data` on a malformed pegin, which has 6 entries and the last one (which should be a Merkle proof of block inclusion) is too small to even have a blockhash in it. On the actual chain this should not be possible because invalid pegin data would be rejected. --- src/transaction.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/transaction.rs b/src/transaction.rs index aac60ea7..3d401d3e 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -436,6 +436,9 @@ impl<'tx> PeginData<'tx> { if pegin_witness.len() != 6 { return Err("size not 6"); } + if pegin_witness[5].len() < 80 { + return Err("merkle proof too short"); + } Ok(PeginData { outpoint: prevout, @@ -2379,4 +2382,21 @@ mod tests { Err(encode::Error::ParseFailed("superfluous asset issuance")), )); } + + #[test] + fn malformed_pegin() { + let mut input: TxIn = hex_deserialize!("\ + 0004000000000000ffffffff0000040000c0c0c0c0c0c0c0c0c0000000000000\ + 00805555555555555505c0c0c0c0c03fc0c0c0c0c0c0c0c0c0c0c0c00200ff01\ + 0000000000fd0000000000000000010000000000ffffffffffffffff00000000\ + 000000ff000000000000010000000000000000000001002d342d35313700\ + "); + input.witness = hex_deserialize!("\ + 0000000608202020202020202020202020202020202020202020202020202020\ + 2020202020202020202020202020202020202020202020202020202020202020\ + 2020202020202020202020202020202020202020202020202020202020200000\ + 00000000000000000000000000000002000400000000\ + "); + assert!(input.pegin_data().is_none()); + } }