Skip to content
This repository has been archived by the owner on Jan 11, 2022. It is now read-only.

Ensure we do not decode invalid RLPs #101

Merged
merged 21 commits into from
Dec 28, 2021
Merged

Ensure we do not decode invalid RLPs #101

merged 21 commits into from
Dec 28, 2021

Conversation

jochem-brouwer
Copy link
Member

@jochem-brouwer jochem-brouwer commented Aug 30, 2021

There are some cases where we successfully decode invalid RLPs - we should throw in these cases. In this PR, (rather old) tests from ethereum/tests are added, as well some tests from Geth.

This also updates the tests, as they are using deprecated methods like equal which should be strictEqual.

@coveralls
Copy link

coveralls commented Dec 20, 2021

Coverage Status

Coverage increased (+5.2%) to 95.763% when pulling ec6737d on invalid-tests into efe7073 on master.

@jochem-brouwer
Copy link
Member Author

Note: f114898 in this commit I remove one invalid test. If we use Geth's rlpdump -hex 0x then it does not throw. Thus an empty buffer is apparently OK as input..?

The majority of the invalid RLP errors come from rather interesting Buffer.slice(start, end) behavior. If either start or end is larger than the length of the Buffer, then this method should not throw. There are some cases where you can produce an RLP which does not throw in our library but are invalid nevertheless.

We also don't have this specific check from Geth which I have added as well.

I also had to edit some tests which now throw with a different error message. I'm not super happy with the error messages and we should probably make them more explicit. Am also not entirely convinced that we have now covered all cases, especially because comparing the RLP implementation in Go and in JS is prone to off-by-one errors; in JS we use Buffer.slice(start, end) where you thus provide a region where you want to slice, but in Go you have the semantics of Buffer.slice(start, length), i.e. in JS that would be Buffer.slice(start, start+length), and since most times we use the first byte of the RLP to switch on behavior, we thus have to subtract 1 on the reported "length" to actually get the end parameter which we should slice into.

@jochem-brouwer
Copy link
Member Author

Maybe it is an idea to convert this file to JS tests?

@ryanio
Copy link
Contributor

ryanio commented Dec 20, 2021

i think part of the issue with the linting was your master branch was pointed to an older commit.

rebased on master and tidied up official.spec.ts

looking good!

@ryanio
Copy link
Contributor

ryanio commented Dec 20, 2021

Maybe it is an idea to convert this file to JS tests?

that's a good idea, one step further would be to see if any of the cases there are not covered in ethereum/tests and have them added upstream for the greater benefit

return statement in else block can be placed outside if statement (https://eslint.org/docs/rules/no-else-return)
@jochem-brouwer
Copy link
Member Author

Maybe it is an idea to convert this file to JS tests?

that's a good idea, one step further would be to see if any of the cases there are not covered in ethereum/tests and have them added upstream for the greater benefit

I'll check with ethereum/tests team to see if these RLP tests are managed since the last change was 2+ years ago :) But nevertheless it would be great to see if we have now covered all cases, since fuzzing this thing seems to be rather complicated.

@jochem-brouwer
Copy link
Member Author

Thanks for the rebase @ryanio 😄

I added the test cases from Geth (not all, since some were duplicate or some threw in Go because of type errors, which I have converted).

@jochem-brouwer jochem-brouwer marked this pull request as ready for review December 21, 2021 21:32
@jochem-brouwer
Copy link
Member Author

I'd like at least 2 approvals before merging here, since this is a rather big change.

@jochem-brouwer
Copy link
Member Author

jochem-brouwer commented Dec 21, 2021

Two things to do;

  • Check if these new error cases are covered by tests, coverage seems to say no to some cases
  • Cleanup tests, move all invalid tests to invalid.spec.ts

@@ -201,9 +198,6 @@ function _decode(input: Buffer): Decoded {
}

innerRemainder = safeSlice(input, llength, totalLength)
if (innerRemainder.length === 0) {
throw new Error('invalid rlp, List has a invalid length')
Copy link
Member Author

Choose a reason for hiding this comment

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

This one can also be removed but is a bit more complex. We only have innerRemainder.length === 0 in case that llength and totalLength are equal (any other combination would throw safeSlice. However, we have totalLength = llength + length and therefore we have that length should be 0, but a few lines above there is a check whether length < 56; if that is the case then it throws. So, this condition can also not be reached.

@jochem-brouwer jochem-brouwer marked this pull request as ready for review December 23, 2021 16:51
@jochem-brouwer
Copy link
Member Author

Coverage increased to more than 95% :) Now it is really ready for review, will not push any changes anymore.

src/index.ts Outdated Show resolved Hide resolved
test/official.spec.ts Outdated Show resolved Hide resolved
ryanio
ryanio previously approved these changes Dec 23, 2021
Copy link
Contributor

@ryanio ryanio left a comment

Choose a reason for hiding this comment

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

lgtm, nice! great PR. we can wait for one more approval before merging

@jochem-brouwer
Copy link
Member Author

Thanks for the review and changes, let's indeed wait for one more approval 😄

@jochem-brouwer jochem-brouwer changed the title Add invalid tests from ethereum/tests Ensure we do not decode invalid RLPs Dec 23, 2021
Copy link
Contributor

@acolytec3 acolytec3 left a comment

Choose a reason for hiding this comment

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

Left a couple of comments but looks good otherwise!

src/index.ts Show resolved Hide resolved
test/dataTypes.spec.ts Outdated Show resolved Hide resolved
test/official.spec.ts Outdated Show resolved Hide resolved
test/official.spec.ts Outdated Show resolved Hide resolved
acolytec3
acolytec3 previously approved these changes Dec 28, 2021
Copy link
Contributor

@acolytec3 acolytec3 left a comment

Choose a reason for hiding this comment

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

LGTM!

@jochem-brouwer jochem-brouwer merged commit ced5ef2 into master Dec 28, 2021
@holgerd77 holgerd77 deleted the invalid-tests branch December 31, 2021 16:49
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants