@@ -354,58 +354,78 @@ macro_rules! _check_missing_tlv {
354354#[ doc( hidden) ]
355355#[ macro_export]
356356macro_rules! _decode_tlv {
357- ( $reader: expr, $field: ident, ( default_value, $default: expr) ) => { {
358- $crate:: _decode_tlv!( $reader, $field, required)
357+ ( $outer_reader : expr , $ reader: expr, $field: ident, ( default_value, $default: expr) ) => { {
358+ $crate:: _decode_tlv!( $outer_reader , $ reader, $field, required)
359359 } } ;
360- ( $reader: expr, $field: ident, ( static_value, $value: expr) ) => { {
360+ ( $outer_reader : expr , $ reader: expr, $field: ident, ( static_value, $value: expr) ) => { {
361361 } } ;
362- ( $reader: expr, $field: ident, required) => { {
362+ ( $outer_reader : expr , $ reader: expr, $field: ident, required) => { {
363363 $field = $crate:: util:: ser:: Readable :: read( & mut $reader) ?;
364364 } } ;
365- ( $reader: expr, $field: ident, ( required: $trait: ident $( , $read_arg: expr) ?) ) => { {
365+ ( $outer_reader : expr , $ reader: expr, $field: ident, ( required: $trait: ident $( , $read_arg: expr) ?) ) => { {
366366 $field = $trait:: read( & mut $reader $( , $read_arg) * ) ?;
367367 } } ;
368- ( $reader: expr, $field: ident, required_vec) => { {
368+ ( $outer_reader : expr , $ reader: expr, $field: ident, required_vec) => { {
369369 let f: $crate:: util:: ser:: WithoutLength <Vec <_>> = $crate:: util:: ser:: Readable :: read( & mut $reader) ?;
370370 $field = f. 0 ;
371371 } } ;
372- ( $reader: expr, $field: ident, option) => { {
372+ ( $outer_reader : expr , $ reader: expr, $field: ident, option) => { {
373373 $field = Some ( $crate:: util:: ser:: Readable :: read( & mut $reader) ?) ;
374374 } } ;
375- ( $reader: expr, $field: ident, optional_vec) => { {
375+ ( $outer_reader : expr , $ reader: expr, $field: ident, optional_vec) => { {
376376 let f: $crate:: util:: ser:: WithoutLength <Vec <_>> = $crate:: util:: ser:: Readable :: read( & mut $reader) ?;
377377 $field = Some ( f. 0 ) ;
378378 } } ;
379379 // `upgradable_required` indicates we're reading a required TLV that may have been upgraded
380380 // without backwards compat. We'll error if the field is missing, and return `Ok(None)` if the
381381 // field is present but we can no longer understand it.
382382 // Note that this variant can only be used within a `MaybeReadable` read.
383- ( $reader: expr, $field: ident, upgradable_required) => { {
383+ ( $outer_reader : expr , $ reader: expr, $field: ident, upgradable_required) => { {
384384 $field = match $crate:: util:: ser:: MaybeReadable :: read( & mut $reader) ? {
385385 Some ( res) => res,
386- _ => return Ok ( None )
386+ None => {
387+ // If we successfully read a value but we don't know how to parse it, we give up
388+ // and immediately return `None`. However, we need to make sure we read the correct
389+ // number of bytes for this TLV stream, which is implicitly the end of the stream.
390+ // Thus, we consume everything left in the `$outer_reader` here, ensuring that if
391+ // we're being read as a part of another TLV stream we don't spuriously fail to
392+ // deserialize the outer object due to a TLV length mismatch.
393+ $crate:: io_extras:: copy( $outer_reader, & mut $crate:: io_extras:: sink( ) ) . unwrap( ) ;
394+ return Ok ( None )
395+ } ,
387396 } ;
388397 } } ;
389398 // `upgradable_option` indicates we're reading an Option-al TLV that may have been upgraded
390399 // without backwards compat. $field will be None if the TLV is missing or if the field is present
391400 // but we can no longer understand it.
392- ( $reader: expr, $field: ident, upgradable_option) => { {
401+ ( $outer_reader : expr , $ reader: expr, $field: ident, upgradable_option) => { {
393402 $field = $crate:: util:: ser:: MaybeReadable :: read( & mut $reader) ?;
403+ if $field. is_none( ) {
404+ #[ cfg( not( debug_assertions) ) ] {
405+ // In general, MaybeReadable implementations are required to consume all the bytes
406+ // of the object even if they don't understand it, but due to a bug in the
407+ // serialization format for `impl_writeable_tlv_based_enum_upgradable` we sometimes
408+ // don't know how many bytes that is. In such cases, we'd like to spuriously allow
409+ // TLV length mismatches, which we do here by calling `eat_remaining` so that the
410+ // `s.bytes_remain()` check in `_decode_tlv_stream_range` doesn't fail.
411+ $reader. eat_remaining( ) ?;
412+ }
413+ }
394414 } } ;
395- ( $reader: expr, $field: ident, ( option: $trait: ident $( , $read_arg: expr) ?) ) => { {
415+ ( $outer_reader : expr , $ reader: expr, $field: ident, ( option: $trait: ident $( , $read_arg: expr) ?) ) => { {
396416 $field = Some ( $trait:: read( & mut $reader $( , $read_arg) * ) ?) ;
397417 } } ;
398- ( $reader: expr, $field: ident, ( option, encoding: ( $fieldty: ty, $encoding: ident, $encoder: ty) ) ) => { {
399- $crate:: _decode_tlv!( $reader, $field, ( option, encoding: ( $fieldty, $encoding) ) ) ;
418+ ( $outer_reader : expr , $ reader: expr, $field: ident, ( option, encoding: ( $fieldty: ty, $encoding: ident, $encoder: ty) ) ) => { {
419+ $crate:: _decode_tlv!( $outer_reader , $ reader, $field, ( option, encoding: ( $fieldty, $encoding) ) ) ;
400420 } } ;
401- ( $reader: expr, $field: ident, ( option, encoding: ( $fieldty: ty, $encoding: ident) ) ) => { {
421+ ( $outer_reader : expr , $ reader: expr, $field: ident, ( option, encoding: ( $fieldty: ty, $encoding: ident) ) ) => { {
402422 $field = {
403423 let field: $encoding<$fieldty> = ser:: Readable :: read( & mut $reader) ?;
404424 Some ( field. 0 )
405425 } ;
406426 } } ;
407- ( $reader: expr, $field: ident, ( option, encoding: $fieldty: ty) ) => { {
408- $crate:: _decode_tlv!( $reader, $field, option) ;
427+ ( $outer_reader : expr , $ reader: expr, $field: ident, ( option, encoding: $fieldty: ty) ) => { {
428+ $crate:: _decode_tlv!( $outer_reader , $ reader, $field, option) ;
409429 } } ;
410430}
411431
@@ -539,7 +559,7 @@ macro_rules! _decode_tlv_stream_range {
539559 let mut s = ser:: FixedLengthReader :: new( & mut stream_ref, length. 0 ) ;
540560 match typ. 0 {
541561 $( _t if $crate:: _decode_tlv_stream_match_check!( _t, $type, $fieldty) => {
542- $crate:: _decode_tlv!( s, $field, $fieldty) ;
562+ $crate:: _decode_tlv!( $stream , s, $field, $fieldty) ;
543563 if s. bytes_remain( ) {
544564 s. eat_remaining( ) ?; // Return ShortRead if there's actually not enough bytes
545565 return Err ( DecodeError :: InvalidValue ) ;
@@ -1065,6 +1085,10 @@ macro_rules! impl_writeable_tlv_based_enum {
10651085/// when [`MaybeReadable`] is practical instead of just [`Readable`] as it provides an upgrade path for
10661086/// new variants to be added which are simply ignored by existing clients.
10671087///
1088+ /// Note that only struct and unit variants (not tuple variants) will support downgrading, thus any
1089+ /// new odd variants MUST be non-tuple (i.e. described using `$variant_id` and `$variant_name` not
1090+ /// `$tuple_variant_id` and `$tuple_variant_name`).
1091+ ///
10681092/// [`MaybeReadable`]: crate::util::ser::MaybeReadable
10691093/// [`Writeable`]: crate::util::ser::Writeable
10701094/// [`DecodeError::UnknownRequiredFeature`]: crate::ln::msgs::DecodeError::UnknownRequiredFeature
@@ -1102,7 +1126,14 @@ macro_rules! impl_writeable_tlv_based_enum_upgradable {
11021126 $( $( $tuple_variant_id => {
11031127 Ok ( Some ( $st:: $tuple_variant_name( Readable :: read( reader) ?) ) )
11041128 } ) ,* ) *
1105- _ if id % 2 == 1 => Ok ( None ) ,
1129+ _ if id % 2 == 1 => {
1130+ // Assume that a $variant_id was written, not a $tuple_variant_id, and read
1131+ // the length prefix and discard the correct number of bytes.
1132+ let tlv_len: $crate:: util:: ser:: BigSize = $crate:: util:: ser:: Readable :: read( reader) ?;
1133+ let mut rd = $crate:: util:: ser:: FixedLengthReader :: new( reader, tlv_len. 0 ) ;
1134+ rd. eat_remaining( ) . map_err( |_| $crate:: ln:: msgs:: DecodeError :: ShortRead ) ?;
1135+ Ok ( None )
1136+ } ,
11061137 _ => Err ( $crate:: ln:: msgs:: DecodeError :: UnknownRequiredFeature ) ,
11071138 }
11081139 }
0 commit comments