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: ethtypes: handle length overflow case #11082

Merged
merged 1 commit into from
Jul 21, 2023
Merged

Conversation

arajasek
Copy link
Contributor

Related Issues

Similar to #11053

Proposed Changes

The string length field can overflow and turn negative here, leading to a panic

Additional Info

Checklist

Before you mark the PR ready for review, please make sure that:

  • Commits have a clear commit message.
  • PR title is in the form of of <PR type>: <area>: <change being made>
    • example: fix: mempool: Introduce a cache for valid signatures
    • PR type: fix, feat, build, chore, ci, docs, perf, refactor, revert, style, test
    • area, e.g. api, chain, state, market, mempool, multisig, networking, paych, proving, sealing, wallet, deps
  • New features have usage guidelines and / or documentation updates in
  • Tests exist for new functionality or change in behavior
  • CI is green

@arajasek arajasek requested a review from a team as a code owner July 17, 2023 18:34
Comment on lines 140 to 142
fmt.Println(strLenInBytes)
fmt.Println(strLen)
fmt.Println(totalLen)
Copy link
Member

Choose a reason for hiding this comment

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

removeme

@@ -134,9 +134,12 @@ func decodeRLP(data []byte) (res interface{}, consumed int, err error) {
return nil, 0, err
}
totalLen := 1 + strLenInBytes + strLen
if totalLen > len(data) {
if totalLen > len(data) || totalLen < 0 {
Copy link
Contributor

@fridrik01 fridrik01 Jul 18, 2023

Choose a reason for hiding this comment

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

You may want to do this check inside decodeLength (when checking lenInBytes+int(decodedLength) > len(data)) as that is overflowing the int64 to a negative number which is the root cause. That will also cover the case above when we are parsing lists which should have the same problem.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@fridrik01 Isn't that the check you already added in #11079? Sorry, I'm a little confused.

In this PR I'm trying to catch an edge-case where decodedLength doesn't overflow, but decodedLength + strLenInBytes + 1 does.

Copy link
Contributor

Choose a reason for hiding this comment

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

@arajasek Yes I added a check for negative decodedLength (see L160 below) but we can add a check for overflow in L163:

if err := binary.Read(r, binary.BigEndian, &decodedLength); err != nil {
return 0, xerrors.Errorf("invalid rlp data: cannot parse string length: %w", err)
}
if decodedLength < 0 {
return 0, xerrors.Errorf("invalid rlp data: negative string length")
}
if lenInBytes+int(decodedLength) > len(data) {
return 0, xerrors.Errorf("invalid rlp data: out of bound while parsing list")
}

So something like

totalLen := lenInBytes+decodedLength
if totalLen < 0 || totalLen > len(data) {
    return 0, xerrors.Errorf("invalid rlp data: out of bound while parsing list")
}

Whats happening is that decodedLength is close to Int64 max so when we add lenInBytes it overflows and becomes negative.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, got it! I think I'm gonna do both -- your suggestion SGTM, but we do have to check again in the caller because we wind up indexing data[totalLen + 1]

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.

3 participants