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

buffer: coerce offset using Math.trunc() #9341

Merged
merged 1 commit into from
Nov 5, 2016
Merged

Conversation

cjihrig
Copy link
Contributor

@cjihrig cjihrig commented Oct 28, 2016

Checklist
  • make -j8 test (UNIX), or vcbuild test nosign (Windows) passes
  • tests and/or benchmarks are included
  • commit message follows commit guidelines
Affected core subsystem(s)

buffer

Description of change

This is a partial revert of 14d1a8a, which coerced the offset of Buffer#slice() using the | operator. This causes some edge cases to be handled incorrectly. This commit restores the old behavior, but converts offsets to integers using Math.trunc(). This commit does not revert any tests, and adds an additional
regression test.

Refs: #9101
Refs: #9096

cc: @nodejs/buffer

@nodejs-github-bot nodejs-github-bot added the buffer Issues and PRs related to the buffer subsystem. label Oct 28, 2016
@Fishrock123
Copy link
Contributor

Does offset >> 0 fix these bugs rather than Math.floor()?

@cjihrig
Copy link
Contributor Author

cjihrig commented Oct 28, 2016

Did you mean offset >>> 0? If so, that would create an uint32, and slice() supports negative numbers.

@Fishrock123
Copy link
Contributor

@cjihrig no, I mean a signed shift. It does similar to what | 0 does but perhaps with less caveats.

offset |= 0;
if (offset === 0) {
offset = Math.floor(+offset);
if (offset === 0 || Number.isNaN(offset)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Wouldn't it be better if we had Number.isInteger here and drop the Math.floor in the previous line?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So, for example, an offset of 3.3 would become 0? That seems like it would be a surprising 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.

Since slice() supports negative numbers Math.round() must be used. A simple test for that would be

const buf = Buffer.from('abc');
assert.strictEqual(buf.slice(-0.5).toString(), buf.toString();

@cjihrig
Copy link
Contributor Author

cjihrig commented Oct 28, 2016

no, I mean a signed shift.

It looks like it has the same problems. Using the example from #9101:

> (-(-1 >>> 0) + 1) | 0
2
> (-(-1 >>> 0) + 1) >> 0
2

@mscdex
Copy link
Contributor

mscdex commented Oct 28, 2016

I just noticed that this PR actually fixes another bug (that has existed since v6.3.0 or ac8e1bf) not covered by the regression test in this PR. Here is a test case to add:

const buf = Buffer.from([
  1, 29,  0,   0, 1, 143, 216, 162, 92, 254, 248, 63, 0,
  0,  0, 18, 184, 6,   0, 175,  29,  0,   8,  11,  1, 0, 0
]);
const chunk1 = Buffer.from([
  1, 29, 0, 0, 1, 143, 216, 162, 92, 254, 248, 63, 0
]);
const chunk2 = Buffer.from([
  0, 0, 18, 184, 6, 0, 175, 29, 0, 8, 11, 1, 0, 0
]);
const middle = buf.length / 2;
assert.deepStrictEqual(buf.slice(0, middle), chunk1);
assert.deepStrictEqual(buf.slice(middle), chunk2);

@cjihrig
Copy link
Contributor Author

cjihrig commented Oct 29, 2016

@mscdex that code is passing for me on master already, probably because of 14d1a8a.

@mscdex
Copy link
Contributor

mscdex commented Oct 29, 2016

@cjihrig It doesn't pass on v6.x though. Will both commits get backported to v6.x?

@cjihrig
Copy link
Contributor Author

cjihrig commented Oct 29, 2016

I think it would be simplest to backport both together.

@rvagg
Copy link
Member

rvagg commented Oct 29, 2016

Might be good to add that new test case to this PR even if it passes on master. Moar regression tests!

This will be good to expedite into the next v6 patch release but it'd be preferable to get it into a v7 asap.

@trevnorris
Copy link
Contributor

@cjihrig My bad. I meant to say to use round() in my PR review.

@cjihrig
Copy link
Contributor Author

cjihrig commented Oct 30, 2016

Using round() seems like it could lead to some confusion. What about Math.trunc() to just drop everything after the decimal point?

@trevnorris
Copy link
Contributor

@cjihrig thanks for the correction. Math.trunc() is the correct solution.

@cjihrig cjihrig changed the title buffer: coerce offset using Math.floor() buffer: coerce offset using Math.trunc() Nov 2, 2016
@cjihrig
Copy link
Contributor Author

cjihrig commented Nov 2, 2016

OK, moved from Math.floor() to Math.trunc(), and added the code from #9341 (comment) and #9341 (comment) as regression tests.

@@ -807,8 +807,8 @@ Buffer.prototype.toJSON = function() {


function adjustOffset(offset, length) {
offset |= 0;
if (offset === 0) {
offset = Math.trunc(+offset);
Copy link
Contributor

Choose a reason for hiding this comment

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

Is the + here still necessary? It seems Math.trunc() handles conversions already?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think you're right. Removed the +

@mscdex
Copy link
Contributor

mscdex commented Nov 2, 2016

@cjihrig
Copy link
Contributor Author

cjihrig commented Nov 2, 2016

@jasnell
Copy link
Member

jasnell commented Nov 2, 2016

given that use of | is pretty common already, would you mind adding a code comment indicating why Math.trunc() is used so that someone later on doesn't come along and change it? Otherwise LGTM

@cjihrig
Copy link
Contributor Author

cjihrig commented Nov 3, 2016

@jasnell I added a comment. Does it work for you?

@cjihrig
Copy link
Contributor Author

cjihrig commented Nov 3, 2016

Looks like there were two simultaneous CI runs today. One was green. The other had a single Jenkins issue.

@jasnell
Copy link
Member

jasnell commented Nov 3, 2016

Yep! Thank you!

@cjihrig
Copy link
Contributor Author

cjihrig commented Nov 3, 2016

@trevnorris @mscdex @rvagg are any of you interested in signing off on this?

@mscdex
Copy link
Contributor

mscdex commented Nov 3, 2016

LGTM

@trevnorris
Copy link
Contributor

LGTM

@jasnell we use binary conversions in several places we shouldn't. Should probably be fixed at some point.

@jasnell
Copy link
Member

jasnell commented Nov 4, 2016

Agreed

On Friday, November 4, 2016, Trevor Norris notifications@github.com wrote:

LGTM

@jasnell https://github.com/jasnell we use binary conversions in
several places we shouldn't. Should probably be fixed at some point.


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
#9341 (comment), or mute
the thread
https://github.com/notifications/unsubscribe-auth/AAa2eazC9UGhivwqia5zjnVbztBtippKks5q63DugaJpZM4Kjgw5
.

This is a partial revert of
14d1a8a, which coerced the offset
of Buffer#slice() using the | operator. This causes some edge
cases to be handled incorrectly. This commit restores the old
behavior, but converts offsets to integers using Math.trunc().
This commit does not revert any tests, and adds an additional
regression test.

Refs: nodejs#9096
Refs: nodejs#9101
PR-URL: nodejs#9341
Reviewed-By: Sakthipriyan Vairamani <thechargingvolcano@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Brian White <mscdex@mscdex.net>
Reviewed-By: Trevor Norris <trev.norris@gmail.com>
@cjihrig cjihrig merged commit a02b13f into nodejs:master Nov 5, 2016
@cjihrig cjihrig deleted the buf branch November 5, 2016 00:45
evanlucas pushed a commit that referenced this pull request Nov 7, 2016
This is a partial revert of
14d1a8a, which coerced the offset
of Buffer#slice() using the | operator. This causes some edge
cases to be handled incorrectly. This commit restores the old
behavior, but converts offsets to integers using Math.trunc().
This commit does not revert any tests, and adds an additional
regression test.

Refs: #9096
Refs: #9101
PR-URL: #9341
Reviewed-By: Sakthipriyan Vairamani <thechargingvolcano@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Brian White <mscdex@mscdex.net>
Reviewed-By: Trevor Norris <trev.norris@gmail.com>
MylesBorins pushed a commit that referenced this pull request Nov 18, 2016
This is a partial revert of
14d1a8a, which coerced the offset
of Buffer#slice() using the | operator. This causes some edge
cases to be handled incorrectly. This commit restores the old
behavior, but converts offsets to integers using Math.trunc().
This commit does not revert any tests, and adds an additional
regression test.

Refs: #9096
Refs: #9101
PR-URL: #9341
Reviewed-By: Sakthipriyan Vairamani <thechargingvolcano@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Brian White <mscdex@mscdex.net>
Reviewed-By: Trevor Norris <trev.norris@gmail.com>
MylesBorins pushed a commit that referenced this pull request Nov 19, 2016
This is a partial revert of
14d1a8a, which coerced the offset
of Buffer#slice() using the | operator. This causes some edge
cases to be handled incorrectly. This commit restores the old
behavior, but converts offsets to integers using Math.trunc().
This commit does not revert any tests, and adds an additional
regression test.

Refs: #9096
Refs: #9101
PR-URL: #9341
Reviewed-By: Sakthipriyan Vairamani <thechargingvolcano@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Brian White <mscdex@mscdex.net>
Reviewed-By: Trevor Norris <trev.norris@gmail.com>
@MylesBorins MylesBorins mentioned this pull request Nov 22, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
buffer Issues and PRs related to the buffer subsystem.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants