Skip to content

Commit a0353fd

Browse files
trxcllnttargos
authored andcommitted
fs: align fs.ReadStream buffer pool writes to 8-byte boundary
Prevents alignment issues when creating a typed array from a buffer. Fixes: #24817 PR-URL: #24838 Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Anna Henningsen <[email protected]>
1 parent a278814 commit a0353fd

File tree

2 files changed

+19
-5
lines changed

2 files changed

+19
-5
lines changed

lib/internal/fs/streams.js

+18-5
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ function checkPosition(pos, name) {
5151
}
5252
}
5353

54+
function roundUpToMultipleOf8(n) {
55+
return (n + 7) & ~7; // Align to 8 byte boundary.
56+
}
57+
5458
function ReadStream(path, options) {
5559
if (!(this instanceof ReadStream))
5660
return new ReadStream(path, options);
@@ -172,10 +176,18 @@ ReadStream.prototype._read = function(n) {
172176
// Now that we know how much data we have actually read, re-wind the
173177
// 'used' field if we can, and otherwise allow the remainder of our
174178
// reservation to be used as a new pool later.
175-
if (start + toRead === thisPool.used && thisPool === pool)
176-
thisPool.used += bytesRead - toRead;
177-
else if (toRead - bytesRead > kMinPoolSpace)
178-
poolFragments.push(thisPool.slice(start + bytesRead, start + toRead));
179+
if (start + toRead === thisPool.used && thisPool === pool) {
180+
const newUsed = thisPool.used + bytesRead - toRead;
181+
thisPool.used = roundUpToMultipleOf8(newUsed);
182+
} else {
183+
// Round down to the next lowest multiple of 8 to ensure the new pool
184+
// fragment start and end positions are aligned to an 8 byte boundary.
185+
const alignedEnd = (start + toRead) & ~7;
186+
const alignedStart = roundUpToMultipleOf8(start + bytesRead);
187+
if (alignedEnd - alignedStart >= kMinPoolSpace) {
188+
poolFragments.push(thisPool.slice(alignedStart, alignedEnd));
189+
}
190+
}
179191

180192
if (bytesRead > 0) {
181193
this.bytesRead += bytesRead;
@@ -189,7 +201,8 @@ ReadStream.prototype._read = function(n) {
189201
// Move the pool positions, and internal position for reading.
190202
if (this.pos !== undefined)
191203
this.pos += toRead;
192-
pool.used += toRead;
204+
205+
pool.used = roundUpToMultipleOf8(pool.used + toRead);
193206
};
194207

195208
ReadStream.prototype._destroy = function(err, cb) {

test/parallel/test-fs-read-stream.js

+1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ const rangeFile = fixtures.path('x.txt');
5555

5656
file.on('data', function(data) {
5757
assert.ok(data instanceof Buffer);
58+
assert.ok(data.byteOffset % 8 === 0);
5859
assert.ok(!paused);
5960
file.length += data.length;
6061

0 commit comments

Comments
 (0)