From e96be5ee6e141b5d8a9163dc4066301d81957fa9 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Thu, 17 Aug 2023 09:34:46 +1000 Subject: [PATCH 1/2] Fix Witness debug display bug Currently if the witness has zero elements or any of the individual witnesses is empty we panic. Panic is caused by subtracting 1 from a zero length. Check the length is non-zero before subtracting 1, print `[]` if empty. --- bitcoin/src/blockdata/witness.rs | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/bitcoin/src/blockdata/witness.rs b/bitcoin/src/blockdata/witness.rs index 390ff0b0..3d10a0a0 100644 --- a/bitcoin/src/blockdata/witness.rs +++ b/bitcoin/src/blockdata/witness.rs @@ -68,20 +68,26 @@ fn fmt_debug(w: &Witness, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> f.write_str("witnesses: [")?; let instructions = w.iter(); - let last_instruction = instructions.len() - 1; - - for (i, instruction) in instructions.enumerate() { - let bytes = instruction.iter(); - let last_byte = bytes.len() - 1; - - f.write_str("[")?; - - for (j, byte) in bytes.enumerate() { - write!(f, "{:#04x}", byte)?; - f.write_str(comma_or_close(j, last_byte))?; + if instructions.len() > 0 { + let last_instruction = instructions.len() - 1; + for (i, instruction) in instructions.enumerate() { + let bytes = instruction.iter(); + if bytes.len() > 0 { + let last_byte = bytes.len() - 1; + f.write_str("[")?; + for (j, byte) in bytes.enumerate() { + write!(f, "{:#04x}", byte)?; + f.write_str(comma_or_close(j, last_byte))?; + } + } else { + // This is possible because the varint is not part of the instruction (see Iter). + write!(f, "[]")?; + } + f.write_str(comma_or_close(i, last_instruction))?; } - - f.write_str(comma_or_close(i, last_instruction))?; + } else { + // Witnesses can be empty because the 0x00 var int is not stored in content. + write!(f, "]")?; } f.write_str(" }") From 84614d9997a69bac249f3e8ac3b90240b38ca747 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Wed, 16 Aug 2023 16:03:33 +1000 Subject: [PATCH 2/2] Unit test debug print of witness with empty instruction We recently fixed a bug that causes a panic if a `Witness` contains an empty instruction. Add a unit test to verify it. --- bitcoin/src/blockdata/witness.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/bitcoin/src/blockdata/witness.rs b/bitcoin/src/blockdata/witness.rs index 3d10a0a0..43e69d69 100644 --- a/bitcoin/src/blockdata/witness.rs +++ b/bitcoin/src/blockdata/witness.rs @@ -535,6 +535,16 @@ mod test { v } + #[test] + fn witness_debug_can_display_empty_instruction() { + let witness = Witness { + witness_elements: 1, + content: append_u32_vec(vec![], &[0]), + indices_start: 2, + }; + println!("{:?}", witness); + } + #[test] fn test_push() { let mut witness = Witness::default();