buffer: treat detached ArrayBuffers as empty · nodejs/node@bc6b630 · GitHub
Skip to content

Commit bc6b630

Browse files
Archkonaduh95
authored andcommitted
buffer: treat detached ArrayBuffers as empty
Treat detached ArrayBuffers and Buffer or TypedArray views backed by them as zero-length inputs in buffer.isUtf8() and buffer.isAscii(). Both functions now return true for these inputs, consistent with other empty inputs. Signed-off-by: Archkon <180910180+Archkon@users.noreply.github.com> PR-URL: #64504 Fixes: #64503 Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent 6deeef1 commit bc6b630

4 files changed

Lines changed: 51 additions & 65 deletions

File tree

doc/api/buffer.md

Lines changed: 12 additions & 2 deletions

src/node_buffer.cc

Lines changed: 9 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1360,31 +1360,17 @@ void FastSwap64(Local<Value> receiver,
13601360

13611361
static CFunction fast_swap64(CFunction::Make(FastSwap64));
13621362

1363-
struct ValidationResult {
1364-
bool is_valid;
1365-
bool was_detached;
1366-
};
1367-
1368-
static ValidationResult ValidateUtf8(Local<Value> value) {
1363+
static bool ValidateUtf8(Local<Value> value) {
13691364
ArrayBufferViewContents<char> abv(value);
1370-
bool was_detached = abv.WasDetached();
1371-
return {!was_detached && simdutf::validate_utf8(abv.data(), abv.length()),
1372-
was_detached};
1365+
return abv.length() == 0 || simdutf::validate_utf8(abv.data(), abv.length());
13731366
}
13741367

13751368
static void IsUtf8(const FunctionCallbackInfo<Value>& args) {
1376-
Environment* env = Environment::GetCurrent(args);
13771369
CHECK_EQ(args.Length(), 1);
13781370
CHECK(args[0]->IsTypedArray() || args[0]->IsArrayBuffer() ||
13791371
args[0]->IsSharedArrayBuffer());
13801372

1381-
const ValidationResult result = ValidateUtf8(args[0]);
1382-
if (result.was_detached) {
1383-
return node::THROW_ERR_INVALID_STATE(
1384-
env, "Cannot validate on a detached buffer");
1385-
}
1386-
1387-
args.GetReturnValue().Set(result.is_valid);
1373+
args.GetReturnValue().Set(ValidateUtf8(args[0]));
13881374
}
13891375

13901376
static bool FastIsUtf8(Local<Value> receiver,
@@ -1393,40 +1379,23 @@ static bool FastIsUtf8(Local<Value> receiver,
13931379
FastApiCallbackOptions& options) {
13941380
TRACK_V8_FAST_API_CALL("buffer.isUtf8");
13951381
HandleScope scope(options.isolate);
1396-
1397-
const ValidationResult result = ValidateUtf8(value);
1398-
if (result.was_detached) {
1399-
node::THROW_ERR_INVALID_STATE(options.isolate,
1400-
"Cannot validate on a detached buffer");
1401-
return false;
1402-
}
1403-
return result.is_valid;
1382+
return ValidateUtf8(value);
14041383
}
14051384

14061385
static CFunction fast_is_utf8(CFunction::Make(FastIsUtf8));
14071386

1408-
static ValidationResult ValidateAscii(Local<Value> value) {
1387+
static bool ValidateAscii(Local<Value> value) {
14091388
ArrayBufferViewContents<char> abv(value);
1410-
bool was_detached = abv.WasDetached();
1411-
return {
1412-
!was_detached &&
1413-
!simdutf::validate_ascii_with_errors(abv.data(), abv.length()).error,
1414-
was_detached};
1389+
return abv.length() == 0 ||
1390+
!simdutf::validate_ascii_with_errors(abv.data(), abv.length()).error;
14151391
}
14161392

14171393
static void IsAscii(const FunctionCallbackInfo<Value>& args) {
1418-
Environment* env = Environment::GetCurrent(args);
14191394
CHECK_EQ(args.Length(), 1);
14201395
CHECK(args[0]->IsTypedArray() || args[0]->IsArrayBuffer() ||
14211396
args[0]->IsSharedArrayBuffer());
14221397

1423-
const ValidationResult result = ValidateAscii(args[0]);
1424-
if (result.was_detached) {
1425-
return node::THROW_ERR_INVALID_STATE(
1426-
env, "Cannot validate on a detached buffer");
1427-
}
1428-
1429-
args.GetReturnValue().Set(result.is_valid);
1398+
args.GetReturnValue().Set(ValidateAscii(args[0]));
14301399
}
14311400

14321401
static bool FastIsAscii(Local<Value> receiver,
@@ -1435,14 +1404,7 @@ static bool FastIsAscii(Local<Value> receiver,
14351404
FastApiCallbackOptions& options) {
14361405
TRACK_V8_FAST_API_CALL("buffer.isAscii");
14371406
HandleScope scope(options.isolate);
1438-
1439-
const ValidationResult result = ValidateAscii(value);
1440-
if (result.was_detached) {
1441-
node::THROW_ERR_INVALID_STATE(options.isolate,
1442-
"Cannot validate on a detached buffer");
1443-
return false;
1444-
}
1445-
return result.is_valid;
1407+
return ValidateAscii(value);
14461408
}
14471409

14481410
static CFunction fast_is_ascii(CFunction::Make(FastIsAscii));

test/parallel/test-buffer-isascii.js

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,20 @@ assert.strictEqual(isAscii(Buffer.from([])), true);
3030
});
3131

3232
{
33-
// Test with detached array buffers
34-
const arrayBuffer = new ArrayBuffer(1024);
33+
// Detached array buffers and views are treated as empty.
34+
const arrayBuffer = new ArrayBuffer(1);
35+
const typedArray = new Uint8Array(arrayBuffer);
36+
typedArray[0] = 0xff;
37+
const inputs = [
38+
arrayBuffer,
39+
typedArray,
40+
Buffer.from(arrayBuffer),
41+
];
42+
for (const input of inputs) {
43+
assert.strictEqual(isAscii(input), false);
44+
}
3545
structuredClone(arrayBuffer, { transfer: [arrayBuffer] });
36-
assert.throws(
37-
() => { isAscii(arrayBuffer); },
38-
{
39-
code: 'ERR_INVALID_STATE'
40-
}
41-
);
46+
for (const input of inputs) {
47+
assert.strictEqual(isAscii(input), true);
48+
}
4249
}

test/parallel/test-buffer-isutf8.js

Lines changed: 15 additions & 8 deletions

0 commit comments

Comments
 (0)