@@ -43,7 +43,20 @@ mod sealed {
4343 // Offer encoding may be split by '+' followed by optional whitespace.
4444 let encoded = match s. split ( '+' ) . skip ( 1 ) . next ( ) {
4545 Some ( _) => {
46- for chunk in s. split ( '+' ) {
46+ let mut chunks = s. split ( '+' ) ;
47+
48+ // Check first chunk without trimming
49+ if let Some ( first_chunk) = chunks. next ( ) {
50+ if first_chunk. contains ( char:: is_whitespace) {
51+ return Err ( Bolt12ParseError :: InvalidLeadingWhitespace ) ;
52+ }
53+ if first_chunk. is_empty ( ) {
54+ return Err ( Bolt12ParseError :: InvalidContinuation ) ;
55+ }
56+ }
57+
58+ // Check remaining chunks
59+ for chunk in chunks {
4760 let chunk = chunk. trim_start ( ) ;
4861 if chunk. is_empty ( ) || chunk. contains ( char:: is_whitespace) {
4962 return Err ( Bolt12ParseError :: InvalidContinuation ) ;
@@ -123,6 +136,8 @@ pub enum Bolt12ParseError {
123136 /// The bech32 encoding does not conform to the BOLT 12 requirements for continuing messages
124137 /// across multiple parts (i.e., '+' followed by whitespace).
125138 InvalidContinuation ,
139+ /// The bech32 string starts with whitespace, which violates BOLT 12 encoding requirements.
140+ InvalidLeadingWhitespace ,
126141 /// The bech32 encoding's human-readable part does not match what was expected for the message
127142 /// being parsed.
128143 InvalidBech32Hrp ,
@@ -322,6 +337,15 @@ mod tests {
322337 }
323338 }
324339
340+ #[ test]
341+ fn fails_parsing_bech32_encoded_offer_with_leading_whitespace ( ) {
342+ let encoded_offer = "\u{b} lno1pqpzwyq2p32x2um5ypmx2cm5dae8x93pqthvwfzadd7jejes8q9lhc4rvjxd022zv5l44g6qah+\u{b} \u{b} \u{b} \u{b} 82ru5rdpnpj" ;
343+ match encoded_offer. parse :: < Offer > ( ) {
344+ Ok ( _) => panic ! ( "Valid offer: {}" , encoded_offer) ,
345+ Err ( e) => assert_eq ! ( e, Bolt12ParseError :: InvalidLeadingWhitespace ) ,
346+ }
347+ }
348+
325349 #[ test]
326350 fn fails_parsing_bech32_encoded_offer_with_invalid_bech32_data ( ) {
327351 let encoded_offer = "lno1pqps7sjqpgtyzm3qv4uxzmtsd3jjqer9wd3hy6tsw35k7msjzfpy7nz5yqcnygrfdej82um5wf5k2uckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd5xvxo" ;
0 commit comments