-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Conversation
chain/types/ethtypes/rlp.go
Outdated
fmt.Println(strLenInBytes) | ||
fmt.Println(strLen) | ||
fmt.Println(totalLen) |
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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:
lotus/chain/types/ethtypes/rlp.go
Lines 157 to 165 in 871d1ba
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.
There was a problem hiding this comment.
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]
86692f5
to
9b8af13
Compare
9b8af13
to
990b5a0
Compare
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:
<PR type>: <area>: <change being made>
fix: mempool: Introduce a cache for valid signatures
PR type
: fix, feat, build, chore, ci, docs, perf, refactor, revert, style, testarea
, e.g. api, chain, state, market, mempool, multisig, networking, paych, proving, sealing, wallet, deps