@@ -89,7 +89,8 @@ impl FromBase32 for Bolt11InvoiceFeatures {
8989 // Carry bits, 0, 1, 2, 3, or 4 bits
9090 let mut carry_bits = 0 ;
9191 let mut carry = 0u8 ;
92- let mut output = Vec :: < u8 > :: new ( ) ;
92+ let expected_raw_length = ( field_data. len ( ) * 5 + 7 ) / 8 ;
93+ let mut output = Vec :: < u8 > :: with_capacity ( expected_raw_length) ;
9394
9495 // Iterate over input in reverse
9596 for curr_in in field_data. iter ( ) . rev ( ) {
@@ -107,14 +108,21 @@ impl FromBase32 for Bolt11InvoiceFeatures {
107108 carry_bits += 5 ;
108109 }
109110 }
111+
110112 // No more inputs, output remaining (if any)
111113 if carry_bits > 0 {
112114 output. push ( carry) ;
113115 }
116+
117+ // This is to double check the estimated length and
118+ // satisfying mutation test on the capacity, which is mutatable
119+ debug_assert_eq ! ( output. len( ) , expected_raw_length) ;
120+
114121 // Trim the highest feature bits
115122 while !output. is_empty ( ) && output[ output. len ( ) - 1 ] == 0 {
116123 output. pop ( ) ;
117124 }
125+
118126 Ok ( Bolt11InvoiceFeatures :: from_le_bytes ( output) )
119127 }
120128}
@@ -364,7 +372,7 @@ impl FromStr for SignedRawBolt11Invoice {
364372 fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
365373 let parsed = CheckedHrpstring :: new :: < Bech32 > ( s) ?;
366374 let hrp = parsed. hrp ( ) ;
367- // Access original non-packed 32 byte values (as Fe32s)
375+ // Access original non-packed 32 byte values (as Fe32s) (iterator type is needed for API hack)
368376 let data: Vec < _ > = parsed. fe32_iter :: < alloc:: boxed:: Box < dyn Iterator < Item = u8 > > > ( ) . collect ( ) ;
369377
370378 const SIGNATURE_LEN5 : usize = 104 ; // 32-bit values, 65 bytes
@@ -470,7 +478,7 @@ impl FromBase32 for Bolt11InvoiceSignature {
470478 "Bolt11InvoiceSignature::from_base32()" . into ( ) ,
471479 ) ) ;
472480 }
473- let recoverable_signature_bytes = Vec :: < u8 > :: from_base32 ( signature) ?;
481+ let recoverable_signature_bytes = < [ u8 ; 65 ] >:: from_base32 ( signature) ?;
474482 let signature = & recoverable_signature_bytes[ 0 ..64 ] ;
475483 let recovery_id = RecoveryId :: from_i32 ( recoverable_signature_bytes[ 64 ] as i32 ) ?;
476484
@@ -582,7 +590,7 @@ impl FromBase32 for Sha256 {
582590 // "A reader MUST skip over […] a p, [or] h […] field that does not have data_length 52 […]."
583591 Err ( Bolt11ParseError :: Skip )
584592 } else {
585- Ok ( Sha256 ( sha256:: Hash :: from_slice ( & Vec :: < u8 > :: from_base32 ( field_data) ?)
593+ Ok ( Sha256 ( sha256:: Hash :: from_slice ( & < [ u8 ; 32 ] >:: from_base32 ( field_data) ?)
586594 . expect ( "length was checked before (52 u5 -> 32 u8)" ) ) )
587595 }
588596 }
@@ -608,7 +616,7 @@ impl FromBase32 for PayeePubKey {
608616 // "A reader MUST skip over […] a n […] field that does not have data_length 53 […]."
609617 Err ( Bolt11ParseError :: Skip )
610618 } else {
611- let data_bytes = Vec :: < u8 > :: from_base32 ( field_data) ?;
619+ let data_bytes = < [ u8 ; 33 ] >:: from_base32 ( field_data) ?;
612620 let pub_key = PublicKey :: from_slice ( & data_bytes) ?;
613621 Ok ( pub_key. into ( ) )
614622 }
0 commit comments