-
Notifications
You must be signed in to change notification settings - Fork 29.6k
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
process: fix two overflow cases in SourceMap VLQ decoding #31490
Conversation
These both have to do with extremely large numbers, so it's unlikely to cause a problem in practice. Still, correctness. First, encoding `-2147483648` in VLQ returns the value `"B"`. When decoding, we get the value `1` after reading the base64. We then check if the first bit is set (it is) to see if we should negate it, then we shift all bits right once. Now, `value` will be `0` and `negate` will be `true`. So, we'd return `-0`. Which is a bug! `-0` isn't `-2147483648`, and we've broken a round trip. Second, encoding any number with the 31st bit set, we'd return the opposite sign. Let's use `1073741824`. Encoding, we get `"ggggggC"`. When decoding, we get the value `-2147483648` after reading the base64. Notice, it's already negative (the 32nd bit is set, because the 31st was set and we shifted everything left once). We'd then check the first bit (it's not) and shift right. But we used `>>`, which does not shift the sign bit. We actually wanted `>>>`, which will. Because of that bug, we get back `-1073741824` instead of the positive `1073741824`. It's even worse if the 32nd and 31st bits are set, `-1610612736` becomes `536870912` after a round trip. I recently fixed the same two bugs in Closure Compiler: google/closure-compiler@584418eb
Can you include some tests? |
Sure. Is it ok to expose the |
It's probably better to test via |
Tests added. |
This comment has been minimized.
This comment has been minimized.
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.
Thanks for adding the tests, It's great to have an extra set of eyes on the implementation.
Landed in 0214b90 |
These both have to do with extremely large numbers, so it's unlikely to cause a problem in practice. Still, correctness. First, encoding `-2147483648` in VLQ returns the value `"B"`. When decoding, we get the value `1` after reading the base64. We then check if the first bit is set (it is) to see if we should negate it, then we shift all bits right once. Now, `value` will be `0` and `negate` will be `true`. So, we'd return `-0`. Which is a bug! `-0` isn't `-2147483648`, and we've broken a round trip. Second, encoding any number with the 31st bit set, we'd return the opposite sign. Let's use `1073741824`. Encoding, we get `"ggggggC"`. When decoding, we get the value `-2147483648` after reading the base64. Notice, it's already negative (the 32nd bit is set, because the 31st was set and we shifted everything left once). We'd then check the first bit (it's not) and shift right. But we used `>>`, which does not shift the sign bit. We actually wanted `>>>`, which will. Because of that bug, we get back `-1073741824` instead of the positive `1073741824`. It's even worse if the 32nd and 31st bits are set, `-1610612736` becomes `536870912` after a round trip. I recently fixed the same two bugs in Closure Compiler: google/closure-compiler@584418eb PR-URL: #31490 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Ben Coe <bencoe@gmail.com> Reviewed-By: David Carlier <devnexen@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Gus Caplan <me@gus.host>
These both have to do with extremely large numbers, so it's unlikely to cause a problem in practice. Still, correctness. First, encoding `-2147483648` in VLQ returns the value `"B"`. When decoding, we get the value `1` after reading the base64. We then check if the first bit is set (it is) to see if we should negate it, then we shift all bits right once. Now, `value` will be `0` and `negate` will be `true`. So, we'd return `-0`. Which is a bug! `-0` isn't `-2147483648`, and we've broken a round trip. Second, encoding any number with the 31st bit set, we'd return the opposite sign. Let's use `1073741824`. Encoding, we get `"ggggggC"`. When decoding, we get the value `-2147483648` after reading the base64. Notice, it's already negative (the 32nd bit is set, because the 31st was set and we shifted everything left once). We'd then check the first bit (it's not) and shift right. But we used `>>`, which does not shift the sign bit. We actually wanted `>>>`, which will. Because of that bug, we get back `-1073741824` instead of the positive `1073741824`. It's even worse if the 32nd and 31st bits are set, `-1610612736` becomes `536870912` after a round trip. I recently fixed the same two bugs in Closure Compiler: google/closure-compiler@584418eb PR-URL: #31490 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Ben Coe <bencoe@gmail.com> Reviewed-By: David Carlier <devnexen@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Gus Caplan <me@gus.host>
Depends on #31132 to land on v12.x |
These both have to do with extremely large numbers, so it's unlikely to cause a problem in practice. Still, correctness. First, encoding `-2147483648` in VLQ returns the value `"B"`. When decoding, we get the value `1` after reading the base64. We then check if the first bit is set (it is) to see if we should negate it, then we shift all bits right once. Now, `value` will be `0` and `negate` will be `true`. So, we'd return `-0`. Which is a bug! `-0` isn't `-2147483648`, and we've broken a round trip. Second, encoding any number with the 31st bit set, we'd return the opposite sign. Let's use `1073741824`. Encoding, we get `"ggggggC"`. When decoding, we get the value `-2147483648` after reading the base64. Notice, it's already negative (the 32nd bit is set, because the 31st was set and we shifted everything left once). We'd then check the first bit (it's not) and shift right. But we used `>>`, which does not shift the sign bit. We actually wanted `>>>`, which will. Because of that bug, we get back `-1073741824` instead of the positive `1073741824`. It's even worse if the 32nd and 31st bits are set, `-1610612736` becomes `536870912` after a round trip. I recently fixed the same two bugs in Closure Compiler: google/closure-compiler@584418eb PR-URL: nodejs#31490 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Ben Coe <bencoe@gmail.com> Reviewed-By: David Carlier <devnexen@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Gus Caplan <me@gus.host>
These both have to do with extremely large numbers, so it's unlikely to cause a problem in practice. Still, correctness. First, encoding `-2147483648` in VLQ returns the value `"B"`. When decoding, we get the value `1` after reading the base64. We then check if the first bit is set (it is) to see if we should negate it, then we shift all bits right once. Now, `value` will be `0` and `negate` will be `true`. So, we'd return `-0`. Which is a bug! `-0` isn't `-2147483648`, and we've broken a round trip. Second, encoding any number with the 31st bit set, we'd return the opposite sign. Let's use `1073741824`. Encoding, we get `"ggggggC"`. When decoding, we get the value `-2147483648` after reading the base64. Notice, it's already negative (the 32nd bit is set, because the 31st was set and we shifted everything left once). We'd then check the first bit (it's not) and shift right. But we used `>>`, which does not shift the sign bit. We actually wanted `>>>`, which will. Because of that bug, we get back `-1073741824` instead of the positive `1073741824`. It's even worse if the 32nd and 31st bits are set, `-1610612736` becomes `536870912` after a round trip. I recently fixed the same two bugs in Closure Compiler: google/closure-compiler@584418eb PR-URL: #31490 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Ben Coe <bencoe@gmail.com> Reviewed-By: David Carlier <devnexen@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Gus Caplan <me@gus.host>
These both have to do with extremely large numbers, so it's unlikely to cause a problem in practice. Still, correctness.
First, encoding
-2147483648
in VLQ returns the value"B"
. When decoding, we get the value1
after reading the base64. We then check if the first bit is set (it is) to see if we should negate it, then we shift all bits right once. Now,value
will be0
andnegate
will betrue
. So, we'd return-0
. Which is a bug!-0
isn't-2147483648
, and we've broken a round trip.Second, encoding any number with the 31st bit set, we'd return the opposite sign. Let's use
1073741824
. Encoding, we get"ggggggC"
. When decoding, we get the value-2147483648
after reading the base64. Notice, it's already negative (the 32nd bit is set, because the 31st was set and we shifted everything left once). We'd then check the first bit (it's not) and shift right. But we used>>
, which does not shift the sign bit. We actually wanted>>>
, which will. Because of that bug, we get back-1073741824
instead of the positive1073741824
. It's even worse if the 32nd and 31st bits are set,-1610612736
becomes536870912
after a round trip.I recently fixed the same two bugs in Closure Compiler: google/closure-compiler@584418eb
/cc @bcoe
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passes