fs: align fs.ReadStream buffer pool writes to 8-byte boundary
Prevents alignment issues when creating a typed array from a buffer. Fixes: https://github.com/nodejs/node/issues/24817 PR-URL: https://github.com/nodejs/node/pull/24838 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
This commit is contained in:
parent
caf9d3c1d0
commit
b884ceb518
@ -51,6 +51,10 @@ function checkPosition(pos, name) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function roundUpToMultipleOf8(n) {
|
||||||
|
return (n + 7) & ~7; // Align to 8 byte boundary.
|
||||||
|
}
|
||||||
|
|
||||||
function ReadStream(path, options) {
|
function ReadStream(path, options) {
|
||||||
if (!(this instanceof ReadStream))
|
if (!(this instanceof ReadStream))
|
||||||
return new ReadStream(path, options);
|
return new ReadStream(path, options);
|
||||||
@ -172,10 +176,18 @@ ReadStream.prototype._read = function(n) {
|
|||||||
// Now that we know how much data we have actually read, re-wind the
|
// Now that we know how much data we have actually read, re-wind the
|
||||||
// 'used' field if we can, and otherwise allow the remainder of our
|
// 'used' field if we can, and otherwise allow the remainder of our
|
||||||
// reservation to be used as a new pool later.
|
// reservation to be used as a new pool later.
|
||||||
if (start + toRead === thisPool.used && thisPool === pool)
|
if (start + toRead === thisPool.used && thisPool === pool) {
|
||||||
thisPool.used += bytesRead - toRead;
|
const newUsed = thisPool.used + bytesRead - toRead;
|
||||||
else if (toRead - bytesRead > kMinPoolSpace)
|
thisPool.used = roundUpToMultipleOf8(newUsed);
|
||||||
poolFragments.push(thisPool.slice(start + bytesRead, start + toRead));
|
} else {
|
||||||
|
// Round down to the next lowest multiple of 8 to ensure the new pool
|
||||||
|
// fragment start and end positions are aligned to an 8 byte boundary.
|
||||||
|
const alignedEnd = (start + toRead) & ~7;
|
||||||
|
const alignedStart = roundUpToMultipleOf8(start + bytesRead);
|
||||||
|
if (alignedEnd - alignedStart >= kMinPoolSpace) {
|
||||||
|
poolFragments.push(thisPool.slice(alignedStart, alignedEnd));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (bytesRead > 0) {
|
if (bytesRead > 0) {
|
||||||
this.bytesRead += bytesRead;
|
this.bytesRead += bytesRead;
|
||||||
@ -189,7 +201,8 @@ ReadStream.prototype._read = function(n) {
|
|||||||
// Move the pool positions, and internal position for reading.
|
// Move the pool positions, and internal position for reading.
|
||||||
if (this.pos !== undefined)
|
if (this.pos !== undefined)
|
||||||
this.pos += toRead;
|
this.pos += toRead;
|
||||||
pool.used += toRead;
|
|
||||||
|
pool.used = roundUpToMultipleOf8(pool.used + toRead);
|
||||||
};
|
};
|
||||||
|
|
||||||
ReadStream.prototype._destroy = function(err, cb) {
|
ReadStream.prototype._destroy = function(err, cb) {
|
||||||
|
@ -55,6 +55,7 @@ const rangeFile = fixtures.path('x.txt');
|
|||||||
|
|
||||||
file.on('data', function(data) {
|
file.on('data', function(data) {
|
||||||
assert.ok(data instanceof Buffer);
|
assert.ok(data instanceof Buffer);
|
||||||
|
assert.ok(data.byteOffset % 8 === 0);
|
||||||
assert.ok(!paused);
|
assert.ok(!paused);
|
||||||
file.length += data.length;
|
file.length += data.length;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user