Skip to content

Commit 405ed60

Browse files
committed
Don't enforce owned values be written in legacy TLV writing
When writing legacy TLVs, we use a lambda that returns an `Option` over a specified type. To avoid implicit type confusion issues, we explicitly check that that lambda writes an `Option<Type>`. However, we may wish to occasionally write an `Option<&Type>` to avoid unnecessary allocations. Here we replace the explicit type confusion check with a verification by reading the written contents back explicitly using the specified Type. This should catch most cases of type confusion as we will generally end up writing a different number of bytes.
1 parent df68774 commit 405ed60

File tree

1 file changed

+18
-3
lines changed

1 file changed

+18
-3
lines changed

lightning/src/util/ser_macros.rs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,24 @@ macro_rules! _encode_tlv {
4242
field.write($stream)?;
4343
}
4444
};
45-
($stream: expr, $optional_type: expr, $optional_field: expr, (legacy, $fieldty: ty, $write: expr) $(, $self: ident)?) => {
46-
$crate::_encode_tlv!($stream, $optional_type, { let value: Option<$fieldty> = $write($($self)?); value }, option);
47-
};
45+
($stream: expr, $optional_type: expr, $optional_field: expr, (legacy, $fieldty: ty, $write: expr) $(, $self: ident)?) => { {
46+
let value: Option<_> = $write($($self)?);
47+
#[cfg(debug_assertions)]
48+
{
49+
// The value we write may be either an Option<$fieldty> or an Option<&$fieldty>.
50+
// Either way, it should decode just fine as a $fieldty, so we check that here.
51+
// This is useful in that it checks that we aren't accidentally writing, for example,
52+
// Option<Option<$fieldty>>.
53+
if let Some(v) = &value {
54+
let encoded_value = v.encode();
55+
let mut read_slice = &encoded_value[..];
56+
let _: $fieldty = $crate::util::ser::Readable::read(&mut read_slice)
57+
.expect("Failed to read written TLV, check types");
58+
assert!(read_slice.is_empty(), "Reading written TLV was short, check types");
59+
}
60+
}
61+
$crate::_encode_tlv!($stream, $optional_type, value, option);
62+
} };
4863
($stream: expr, $type: expr, $field: expr, optional_vec $(, $self: ident)?) => {
4964
if !$field.is_empty() {
5065
$crate::_encode_tlv!($stream, $type, $field, required_vec);

0 commit comments

Comments
 (0)