From 29a2866326df47b3eb9c472c2c5eb815205a7af4 Mon Sep 17 00:00:00 2001 From: codingpeanut157 Date: Mon, 28 Jul 2025 12:16:47 +0200 Subject: [PATCH] TransactionId::from_hex check bytes len before copy_from_slice avoid panicking when the input does not convert to an [u8;32] byte array --- crates/cdk-common/src/wallet.rs | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/crates/cdk-common/src/wallet.rs b/crates/cdk-common/src/wallet.rs index d9aca538..7359d730 100644 --- a/crates/cdk-common/src/wallet.rs +++ b/crates/cdk-common/src/wallet.rs @@ -310,6 +310,9 @@ impl TransactionId { /// From hex string pub fn from_hex(value: &str) -> Result { let bytes = hex::decode(value)?; + if bytes.len() != 32 { + return Err(Error::InvalidTransactionId); + } let mut array = [0u8; 32]; array.copy_from_slice(&bytes); Ok(Self(array)) @@ -357,3 +360,29 @@ impl TryFrom for TransactionId { Self::from_proofs(proofs) } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_transaction_id_from_hex() { + let hex_str = "a1b2c3d4e5f60718293a0b1c2d3e4f506172839a0b1c2d3e4f506172839a0b1c"; + let transaction_id = TransactionId::from_hex(hex_str).unwrap(); + assert_eq!(transaction_id.to_string(), hex_str); + } + + #[test] + fn test_transaction_id_from_hex_empty_string() { + let hex_str = ""; + let res = TransactionId::from_hex(hex_str); + assert!(matches!(res, Err(Error::InvalidTransactionId))); + } + + #[test] + fn test_transaction_id_from_hex_longer_string() { + let hex_str = "a1b2c3d4e5f60718293a0b1c2d3e4f506172839a0b1c2d3e4f506172839a0b1ca1b2"; + let res = TransactionId::from_hex(hex_str); + assert!(matches!(res, Err(Error::InvalidTransactionId))); + } +}