From 482ed4921cdc5edb51144aa948e67c1462c2e6e9 Mon Sep 17 00:00:00 2001 From: Vincenzo Palazzo Date: Thu, 3 Apr 2025 16:37:08 +0200 Subject: [PATCH] invoice: reproduce parsing mismatch This is a reproduction of the issue that I found in the lightning-invoice crate. The issue is described in details in [1]. [1] https://github.com/lightningdevkit/rust-lightning/issues/3693 Suggested-by: @erickcestari Signed-off-by: Vincenzo Palazzo --- lightning-invoice/.DS_Store | Bin 0 -> 6148 bytes lightning-invoice/src/de.rs | 28 ++++++++++++++++++++++++++++ lightning-invoice/src/lib.rs | 4 ++-- 3 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 lightning-invoice/.DS_Store diff --git a/lightning-invoice/.DS_Store b/lightning-invoice/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..7120522d1247b54c4b7d572be8a7b43600f0f969 GIT binary patch literal 6148 zcmeHKy-or_5S|fCF0rAc+|F3?1}iyUKwf|VMhY%R1Pi+>>3kVlTPs^%#oBLn2DyzF zOJj5<+5KkcXJ_vt><o><@4mM v4QMko5s7O=fk4kL0T{?WGE7eO2hkB14I4$7MeHdZ=of)Rh0fnT;@in literal 0 HcmV?d00001 diff --git a/lightning-invoice/src/de.rs b/lightning-invoice/src/de.rs index 85a0924ce22..d038296c71c 100644 --- a/lightning-invoice/src/de.rs +++ b/lightning-invoice/src/de.rs @@ -1416,4 +1416,32 @@ mod test { assert!(parse_is_code_length_err(&too_long)); assert!(!parse_is_code_length_err(&too_long[..too_long.len() - 1])); } + + #[test] + fn test_raw_data_base32_roundtrip() { + use crate::ser::Base32Iterable; + use crate::RawDataPart; + use bech32::Fe32; + + // These are the expected Fe32 values that should round-trip correctly + // The critical difference is in the handling of tag 5 (Features) with empty payload + let expected_values: Vec = vec![ + 0, 0, 4, 8, 23, 5, 0, 1, 1, 20, 16, 0, 24, 0, 1, 18, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 24, 0, 1, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, + 0, 16, 0, 0, 0, 0, 0, 5, 0, 1, 0, 13, 0, 0, + ]; + + // Convert to Fe32 for processing + let values_input: Vec = expected_values + .iter() + .map(|&v| >::try_from(v).expect("Value out of range")) + .collect(); + + // Round-trip through the parser + let raw_data = RawDataPart::from_base32(&values_input).unwrap(); + let actual_output = raw_data.fe_iter().collect::>(); + + // The test fails because the parser doesn't correctly handle empty Features field + assert_eq!(values_input, actual_output, "Failed to correctly round-trip BOLT11 data"); + } } diff --git a/lightning-invoice/src/lib.rs b/lightning-invoice/src/lib.rs index b814210b390..ddda765e8f6 100644 --- a/lightning-invoice/src/lib.rs +++ b/lightning-invoice/src/lib.rs @@ -77,9 +77,9 @@ mod prelude { use crate::prelude::*; /// Re-export serialization traits -#[cfg(fuzzing)] +#[cfg(any(fuzzing, test))] pub use crate::de::FromBase32; -#[cfg(not(fuzzing))] +#[cfg(not(any(fuzzing, test)))] use crate::de::FromBase32; #[cfg(fuzzing)] pub use crate::ser::Base32Iterable;