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

fix(TypedTransaction::decode): do not panic on bad rlp input #2694

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

emostov
Copy link

@emostov emostov commented Dec 5, 2023

Motivation

I encountered an edge case where TypedTransaction::decode panicked from a malformed transaction.

Solution

Explicitly check the leading byte of the tx for the transaction type.

PR Checklist

  • Added Tests
  • Added Documentation
  • Breaking changes

@emostov emostov force-pushed the avoid-panic-on-transaction-deserialization branch from 0095e6f to 1975cfd Compare December 5, 2023 19:45
@emostov emostov force-pushed the avoid-panic-on-transaction-deserialization branch from 1975cfd to 7b60416 Compare December 5, 2023 19:47
@emostov emostov changed the title Avoid panic on transaction deserialization fix(TypedTransaction::decode): do not panic on bad rlp input Dec 5, 2023
@@ -417,7 +417,7 @@ impl TypedTransaction {
impl Decodable for TypedTransaction {
fn decode(rlp: &rlp::Rlp) -> Result<Self, rlp::DecoderError> {
let tx_type: Option<U64> = match rlp.is_data() {
true => Some(rlp.data()?.into()),
true => Some(U64::decode(rlp)?),
Copy link
Collaborator

Choose a reason for hiding this comment

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

hmm, unclear what this even did before.

this entire function looks a bit weird.

this should not rlp decode here I believe, because this is the type id of the envelope?

unclear what rlp.data()?.into() even did, but I think this here should just use the single byte.

idk what is_data is

Copy link
Collaborator

@DaniPopes DaniPopes Dec 5, 2023

Choose a reason for hiding this comment

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

rlp.data() returns Result<&[u8]>, and apparently Parity Uint types implement From<&[u8]> with a function that can panic on bad input ^^

Copy link
Author

Choose a reason for hiding this comment

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

I refactored a bit to explicitly check the first byte as a the tx type - see e7f8369.

It is a bit strange that the initial code was trying to coerce into a U64, when EIP-2718 specifies a single u8 as the tx type

Copy link
Author

@emostov emostov Dec 5, 2023

Choose a reason for hiding this comment

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

I also noticed decode_signed has similar logic and saw that you made a similar refactor to it in pr 1733. I am not familiar with the code base, but wondering if there are other places that may make the same mistake


#[test]
fn malformed_transaction_does_not_panic() {
let tx = hex::decode("b9011e02f9011a0180850ba43b7400850df8475864830493e0947a250d5630b4cf539739df2c5dacb4c659f2488d88016345785d8a0000b8e4b6f9de95000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000005bd929b84c3dac16515c6b6c95f70fdae9c05c0c00000000000000000000000000000000000000000000000000000000650267140000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7c0808080").unwrap();
Copy link
Collaborator

Choose a reason for hiding this comment

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

where's this coming from?

Copy link
Author

@emostov emostov Dec 5, 2023

Choose a reason for hiding this comment

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

This was given to me - apparently it was spit out from go-ethereum. But I also have encountered the same issue while fuzzing inputs to this function. Regardless of the exact payload, I don't think think we want it to panic. If you run the test on the commit prior (9ad0740) to the fix being introduced, it will panic and the test will fail

@emostov
Copy link
Author

emostov commented Dec 6, 2023

Pushed a fix that should get CI to pass (or at least get farther along)

@emostov
Copy link
Author

emostov commented Dec 7, 2023

Looks like CI is good other then just a flaky example

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

3 participants