Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Do not execute the default_value expr until we need it in TLV deser #1588

Merged
merged 4 commits into from Jul 5, 2022

Conversation

TheBlueMatt
Copy link
Collaborator

This fixes an insta-panic in ChannelMonitor deserialization where
we always unwrap a previous value to determine the default value
of a later field. However, because we always ran the unwrap
before the previous field is read, we'd always panic.

The fix is rather simple - use a OptionDeserWrapper for
default_value fields and only fill in the default value if no
value was read while walking the TLV stream.

The only complexity comes from our desire to support
read_tlv_field calls that use an explicit field rather than an
Option of some sort, which requires some statement which can
assign both an OptionDeserWrapper<T> variable and a T variable.
We settle on x = t.into() and implement From<T> for OptionDeserWrapper<T> which works, though it requires users to
specify types explicitly due to Rust determining expression types
prior to macro execution, completely guessing with no knowlege for
integer expressions (see
rust-lang/rust#91369).

In lieu of an explicit and overly-restrictive test, we opt instead for a new fuzzer, which should exercise this code much better.

@TheBlueMatt TheBlueMatt added this to the 0.0.110 milestone Jul 1, 2022
jkczyz
jkczyz previously approved these changes Jul 1, 2022
lightning/src/util/ser.rs Outdated Show resolved Hide resolved
@codecov-commenter
Copy link

codecov-commenter commented Jul 1, 2022

Codecov Report

Merging #1588 (0ee7b7f) into main (f3d5b94) will decrease coverage by 0.04%.
The diff coverage is 0.00%.

❗ Current head 0ee7b7f differs from pull request most recent head f1b9bd3. Consider uploading reports for the commit f1b9bd3 to get more accurate results

@@            Coverage Diff             @@
##             main    #1588      +/-   ##
==========================================
- Coverage   91.07%   91.02%   -0.05%     
==========================================
  Files          80       80              
  Lines       44128    44125       -3     
  Branches    44128    44125       -3     
==========================================
- Hits        40190    40166      -24     
- Misses       3938     3959      +21     
Impacted Files Coverage Δ
lightning/src/ln/channelmanager.rs 84.73% <ø> (ø)
lightning/src/util/config.rs 67.44% <ø> (ø)
lightning/src/util/ser.rs 91.12% <0.00%> (-0.22%) ⬇️
lightning/src/util/ser_macros.rs 89.13% <ø> (ø)
lightning/src/chain/onchaintx.rs 93.98% <0.00%> (-0.93%) ⬇️
lightning/src/util/events.rs 41.66% <0.00%> (-0.33%) ⬇️
lightning/src/ln/functional_tests.rs 96.89% <0.00%> (-0.23%) ⬇️
lightning/src/routing/gossip.rs 91.94% <0.00%> (-0.01%) ⬇️
lightning/src/routing/router.rs 92.62% <0.00%> (-0.01%) ⬇️
lightning/src/chain/channelmonitor.rs 90.90% <0.00%> (-0.01%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update f3d5b94...f1b9bd3. Read the comment docs.

jkczyz
jkczyz previously approved these changes Jul 5, 2022
wpaulino
wpaulino previously approved these changes Jul 5, 2022
Copy link
Contributor

@wpaulino wpaulino left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be squashed now.

This fixes an insta-panic in `ChannelMonitor` deserialization where
we always `unwrap` a previous value to determine the default value
of a later field. However, because we always ran the `unwrap`
before the previous field is read, we'd always panic.

The fix is rather simple - use a `OptionDeserWrapper` for
`default_value` fields and only fill in the default value if no
value was read while walking the TLV stream.

The only complexity comes from our desire to support
`read_tlv_field` calls that use an explicit field rather than an
`Option` of some sort, which requires some statement which can
assign both an `OptionDeserWrapper<T>` variable and a `T` variable.
We settle on `x = t.into()` and implement `From<T> for
OptionDeserWrapper<T>` which works, though it requires users to
specify types explicitly due to Rust determining expression types
prior to macro execution, completely guessing with no knowlege for
integer expressions (see
rust-lang/rust#91369).
@TheBlueMatt
Copy link
Collaborator Author

Squashed.

@TheBlueMatt TheBlueMatt merged commit e403999 into lightningdevkit:main Jul 5, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants