Skip to content

Commit 93db1e0

Browse files
committed
primitives: fix TransactionDecoder::end to not panic on early calls to end
If the data stream ends early we shouldn't panic. This is not a programmer error. It indicates that we ran out of data. This one has observable changes. Unit test in next commit.
1 parent e86a56c commit 93db1e0

File tree

1 file changed

+15
-7
lines changed

1 file changed

+15
-7
lines changed

primitives/src/transaction.rs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -514,15 +514,18 @@ impl Decoder for TransactionDecoder {
514514

515515
#[inline]
516516
fn end(self) -> Result<Self::Output, Self::Error> {
517-
use TransactionDecoderState as State;
517+
use {
518+
TransactionDecoderError as E, TransactionDecoderErrorInner as Inner,
519+
TransactionDecoderState as State,
520+
};
518521

519522
match self.state {
520-
State::Version(_) => panic!("tried to end decoder in state: Version"),
521-
State::Inputs(..) => panic!("tried to end decoder in state: Inputs"),
522-
State::SegwitFlag(..) => panic!("tried to end decoder in state: SegwitFlag"),
523-
State::Outputs(..) => panic!("tried to end decoder in state: Outputs"),
524-
State::Witnesses(..) => panic!("tried to end decoder in state: Witnesses"),
525-
State::LockTime(..) => panic!("tried to end decoder in state: LockTime"),
523+
State::Version(_) => Err(E(Inner::EarlyEnd("version"))),
524+
State::Inputs(..) => Err(E(Inner::EarlyEnd("inputs"))),
525+
State::SegwitFlag(..) => Err(E(Inner::EarlyEnd("segwit flag"))),
526+
State::Outputs(..) => Err(E(Inner::EarlyEnd("outputs"))),
527+
State::Witnesses(..) => Err(E(Inner::EarlyEnd("witnesses"))),
528+
State::LockTime(..) => Err(E(Inner::EarlyEnd("locktime"))),
526529
State::Done(tx) => Ok(tx),
527530
State::Errored => panic!("call to end() after decoder errored"),
528531
}
@@ -622,6 +625,9 @@ enum TransactionDecoderErrorInner {
622625
NoWitnesses,
623626
/// Error while decoding the `lock_time`.
624627
LockTime(LockTimeDecoderError),
628+
/// Attempt to call `end()` before the transaction was complete. Holds
629+
/// a description of the current state.
630+
EarlyEnd(&'static str),
625631
}
626632

627633
#[cfg(feature = "alloc")]
@@ -672,6 +678,7 @@ impl fmt::Display for TransactionDecoderError {
672678
E::Witness(ref e) => write_err!(f, "transaction decoder error"; e),
673679
E::NoWitnesses => write!(f, "non-empty Segwit transaction with no witnesses"),
674680
E::LockTime(ref e) => write_err!(f, "transaction decoder error"; e),
681+
E::EarlyEnd(s) => write!(f, "early end of transaction (still decoding {})", s),
675682
}
676683
}
677684
}
@@ -690,6 +697,7 @@ impl std::error::Error for TransactionDecoderError {
690697
E::Witness(ref e) => Some(e),
691698
E::NoWitnesses => None,
692699
E::LockTime(ref e) => Some(e),
700+
E::EarlyEnd(_) => None,
693701
}
694702
}
695703
}

0 commit comments

Comments
 (0)