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 various overflows and UB in src/ #7494

Closed
wants to merge 3 commits into from

Conversation

indutny
Copy link
Member

@indutny indutny commented Jun 30, 2016

Checklist
  • make -j4 test (UNIX), or vcbuild test nosign (Windows) passes
  • tests and/or benchmarks are included
  • documentation is changed or added
  • commit message follows commit guidelines
Affected 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:

../src/string_search.h:231:68: runtime error: unsigned integer overflow: 0 - 1 cannot be represented in type 'size_t' (aka 'unsigned long')
SUMMARY: AddressSanitizer: undefined-behavior ../src/string_search.h:231:68 in
../src/string_search.h:186:34: runtime error: index 18446744073709451866 out of bounds for type 'int [251]'
SUMMARY: AddressSanitizer: undefined-behavior ../src/string_search.h:186:34 in
../src/string_search.h:194:25: runtime error: index 18446744073709451866 out of bounds for type 'int [251]'
SUMMARY: AddressSanitizer: undefined-behavior ../src/string_search.h:194:25 in

I'm open to suggestions how it could be approached, though.

indutny added 3 commits June 30, 2016 03:41
`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.
@nodejs-github-bot nodejs-github-bot added the c++ Issues and PRs that require attention from people who are familiar with C++. label Jun 30, 2016
@indutny
Copy link
Member Author

indutny commented Jun 30, 2016

Discovered with:

-fsanitize=undefined,address,signed-integer-overflow,unsigned-integer-overflow,integer

@indutny
Copy link
Member Author

indutny commented Jun 30, 2016

@addaleax
Copy link
Member

addaleax commented Jun 30, 2016

For the ../src/string_search.h:231:68: one, I think using i < haystack_len is okay?

@bnoordhuis
Copy link
Member

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.

@mscdex mscdex added the lib / src Issues and PRs related to general changes in the lib or src directory. label Jun 30, 2016
@indutny
Copy link
Member Author

indutny commented Jun 30, 2016

@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.

@indutny
Copy link
Member Author

indutny commented Jun 30, 2016

@addaleax will it be? I think there is some algorithmic trickery there.

@jasnell
Copy link
Member

jasnell commented Jun 30, 2016

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?

@indutny
Copy link
Member Author

indutny commented Jun 30, 2016

Will surely do after I'll land the first two. Thanks!

@addaleax
Copy link
Member

addaleax commented Jun 30, 2016

@indutny I’d actually say it’s a common pattern for descending for loops with unsigned types, even though I know it’s not pretty.

@indutny
Copy link
Member Author

indutny commented Jun 30, 2016

@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");

Copy link
Contributor

@trevnorris trevnorris Jun 30, 2016

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?

Copy link
Member Author

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?

Copy link
Contributor

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.

Copy link
Member

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.

Copy link
Member Author

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

Copy link
Member

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.

Copy link
Member

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)

Copy link
Member

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?

Copy link
Member

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.

@mscdex mscdex added the semver-minor PRs that contain new features and should be released in the next minor version. label Jul 1, 2016
@indutny
Copy link
Member Author

indutny commented Jul 11, 2016

Landing first two commits, since there were no objection on them.

@indutny
Copy link
Member Author

indutny commented Jul 11, 2016

Landed in 46f40cf and c9f6776.

@indutny
Copy link
Member Author

indutny commented Jul 11, 2016

Thank you everyone!

@indutny indutny closed this Jul 11, 2016
indutny added a commit that referenced this pull request Jul 11, 2016
`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>
indutny added a commit that referenced this pull request Jul 11, 2016
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>
@cjihrig cjihrig mentioned this pull request Aug 8, 2016
cjihrig pushed a commit that referenced this pull request Aug 10, 2016
`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>
cjihrig pushed a commit that referenced this pull request Aug 10, 2016
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>
@cjihrig cjihrig mentioned this pull request Aug 11, 2016
@addaleax
Copy link
Member

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?

@indutny
Copy link
Member Author

indutny commented Sep 30, 2016

@addaleax the throw was moved and happens earlier with this PR, not sure if it is acceptable as a patch version change.

@addaleax
Copy link
Member

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.

@MylesBorins
Copy link
Contributor

@addaleax it can still land as a minor

@addaleax
Copy link
Member

Idk, maybe some people use things like utf8Write directly. I doubt it’s common, and it’s undocumented, but @indutny has a point here. There’s probably no compiler which doesn’t handle the code here well, so let’s just leave it off v4.x unless I happened to over-convince somebody else that it should land there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++ Issues and PRs that require attention from people who are familiar with C++. lib / src Issues and PRs related to general changes in the lib or src directory. semver-minor PRs that contain new features and should be released in the next minor version.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants