Skip to content

Commit dcefcbc

Browse files
committed
fs: coerce FileHandle.read length like fs.read
Non-number length values reached node::fs::Read, which CHECKs IsInt32() and aborts the process. Apply length |= 0 after defaulting, matching fs.read and fs.readSync. Signed-off-by: Xia Chao <236466140+bun-unsafe@users.noreply.github.com>
1 parent f509cf1 commit dcefcbc

2 files changed

Lines changed: 23 additions & 0 deletions

File tree

lib/internal/fs/promises.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1420,6 +1420,7 @@ async function read(handle, bufferOrParams, offset, length, position) {
14201420
}
14211421

14221422
length ??= buffer.byteLength - offset;
1423+
length |= 0;
14231424

14241425
if (position == null) {
14251426
position = -1;

test/parallel/test-fs-promises-file-handle-read.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,27 @@ async function validateReadLength(len) {
112112
}
113113
}
114114

115+
async function validateReadLengthCoercedFromString() {
116+
// Align with fs.read / fs.readSync (`length |= 0`). A non-number length
117+
// must not reach node::fs::Read (CHECK args[3]->IsInt32()).
118+
const buf = Buffer.alloc(4);
119+
const filePath = fixtures.path('x.txt');
120+
const fileHandle = await open(filePath, 'r');
121+
try {
122+
const { bytesRead } = await fileHandle.read(buf, 0, '1', 0);
123+
assert.strictEqual(bytesRead, 1);
124+
const { bytesRead: bytesReadOptions } = await fileHandle.read({
125+
buffer: buf,
126+
offset: 0,
127+
length: '1',
128+
position: 0,
129+
});
130+
assert.strictEqual(bytesReadOptions, 1);
131+
} finally {
132+
await fileHandle.close();
133+
}
134+
}
135+
115136
async function validateReadWithNoOptions(byte) {
116137
const buf = Buffer.alloc(byte);
117138
const filePath = fixtures.path('x.txt');
@@ -144,6 +165,7 @@ async function validateReadWithNoOptions(byte) {
144165
await validateReadWithPositionZero();
145166
await validateReadLength(0);
146167
await validateReadLength(1);
168+
await validateReadLengthCoercedFromString();
147169
await validateReadWithNoOptions(0);
148170
await validateReadWithNoOptions(1);
149171
})().then(common.mustCall());

0 commit comments

Comments
 (0)