-
Notifications
You must be signed in to change notification settings - Fork 30k
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 various overflows and UB in src/ #7494
Conversation
`offset` is user supplied variable and may be bigger than `ts_obj_length`. There is no need to subtract them and pass along, so just throw when the subtraction result would overflow.
Many extensions are unknown to the `ClientHelloParser::ParseExtension`, do not cast user-supplied `uint16_t` to `enum`.
Before values are subtracted in C/C++ they are cast to a common type which depends on the types of lhs and rhs. Usually this means casting to a bigger type, and if the sizes are the same - casting to unsigned.
Discovered with:
|
For the |
First two commits LGTM but as to the last one, it would be better to rewrite it to use unsigned types with proper bound checks, rather than haphazardly peppering it with static_casts. |
@bnoordhuis it is using lots of negative integers, and I'm not too confident in the code at the moment to make serious refactoring. Adding casts, on other hand, makes things closer to what developer has intended. |
@addaleax will it be? I think there is some algorithmic trickery there. |
I agree with @bnoordhuis ... the first two are fine, the third is questionable. Perhaps pull that one out into a separate PR where it can be iterated on? |
Will surely do after I'll land the first two. Thanks! |
@indutny I’d actually say it’s a common pattern for descending |
@addaleax oh yeah, I included that warning just for completeness. Sorry, forgot to comment! |
CHECK_NOT_OOB(ParseArrayIndex(args[2], ts_obj_length - offset, &max_length)); | ||
|
||
max_length = MIN(ts_obj_length - offset, max_length); | ||
|
||
if (max_length == 0) | ||
return args.GetReturnValue().Set(0); | ||
|
||
if (offset >= ts_obj_length) | ||
return env->ThrowRangeError("Offset is out of bounds"); | ||
|
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.
just curious, are we missing test coverage that would have caught this?
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.
There is one edge case with max_length
equal to 0
, but otherwise nothing bad happens here. Btw, should we consider this as a breaking change?
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.
IMO you're simply making this defined behavior, which falls under a bug fix and a semver-minor.
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.
@trevnorris @indutny Tracked issue I got after upgrade to this point. Apparently this broke some of my code e.g. using protocol-buffers
(and I'm sure some other binary encoders too) which, for certain data, are writing empty strings in the end of the buffer, which is safe operation (no-op) on its own and worked up until this PR without any extra checks.
I was going to prepare PR to fix this but sounds like it falls under
There is one edge case with max_length equal to 0
and I'm wondering whether we consider this an expected behavior?
Minimal sample: Buffer.alloc(0).write('')
- works in pre-6.4.0, throws now.
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.
Yikes, sorry to break your code!
I don't have any strong opinion on how it should work, but to me it will be fine to not throw in this case.
cc @trevnorris
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.
@RReverser @indutny See #8127/#8154, it should already been fixed on master.
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.
@addaleax By master you mean v6.x
? (because that's where issue is present, at least it was when I checked yesterday)
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.
@RReverser I’m a bit confused – the commit from #8154 is only in master, not yet on the v6.x
branch, yes. I’d anticipate that it lands cleanly, so there should be no need for manual backporting?
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.
@addaleax Ah I thought you meant it should already work on v6.x
branch (as in already landed). Sorry for misunderstanding.
Landing first two commits, since there were no objection on them. |
Thank you everyone! |
`offset` is user supplied variable and may be bigger than `ts_obj_length`. There is no need to subtract them and pass along, so just throw when the subtraction result would overflow. PR-URL: #7494 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Many extensions are unknown to the `ClientHelloParser::ParseExtension`, do not cast user-supplied `uint16_t` to `enum`. PR-URL: #7494 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
`offset` is user supplied variable and may be bigger than `ts_obj_length`. There is no need to subtract them and pass along, so just throw when the subtraction result would overflow. PR-URL: #7494 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Many extensions are unknown to the `ClientHelloParser::ParseExtension`, do not cast user-supplied `uint16_t` to `enum`. PR-URL: #7494 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
I can’t quite see how either commit that landed qualifies as semver-minor… these seem like they could (should?) be backported to v4.x together with #8154? |
@addaleax the |
I don’t think that difference can actually be triggered without touching the binding directly… but we don’t need to make a big fuzz about this, I’m perfectly fine with this not landing in v4. |
@addaleax it can still land as a minor |
Idk, maybe some people use things like |
Checklist
make -j4 test
(UNIX), orvcbuild test nosign
(Windows) passesAffected core subsystem(s)
src
Description of change
Fix various overflows and UB in src/
R= @bnoordhuis and/or @nodejs/collaborators
NOTE: This doesn't fix:
I'm open to suggestions how it could be approached, though.