Skip to content

Commit

Permalink
lib: disallow file-backed blob cloning
Browse files Browse the repository at this point in the history
Disallow cloning of file-backed Blobs. If necessary, we can enable
this later but for now we disable it. The reason is because the
underlying FdEntry ends up bound to the Environment/Realm under
which is was created and transfering across worker threads ends up
failing.

Fixes: #47334
PR-URL: #47574
Reviewed-By: Debadree Chatterjee <debadree333@gmail.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
  • Loading branch information
jasnell committed Apr 22, 2023
1 parent 86a8335 commit 595b2b3
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 1 deletion.
11 changes: 10 additions & 1 deletion lib/internal/blob.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ const {
ERR_INVALID_ARG_TYPE,
ERR_INVALID_ARG_VALUE,
ERR_INVALID_THIS,
ERR_INVALID_STATE,
ERR_BUFFER_TOO_LARGE,
},
} = require('internal/errors');
Expand All @@ -74,6 +75,7 @@ const { queueMicrotask } = require('internal/process/task_queues');
const kHandle = Symbol('kHandle');
const kType = Symbol('kType');
const kLength = Symbol('kLength');
const kNotCloneable = Symbol('kNotCloneable');

const disallowedTypeCharacters = /[^\u{0020}-\u{007E}]/u;

Expand Down Expand Up @@ -186,6 +188,11 @@ class Blob {
}

[kClone]() {
if (this[kNotCloneable]) {
// We do not currently allow file-backed Blobs to be cloned or passed across
// worker threads.
throw new ERR_INVALID_STATE.TypeError('File-backed Blobs are not cloneable');
}
const handle = this[kHandle];
const type = this[kType];
const length = this[kLength];
Expand Down Expand Up @@ -438,7 +445,9 @@ function createBlobFromFilePath(path, options) {
return lazyDOMException('The blob could not be read', 'NotReadableError');
}
const { 0: blob, 1: length } = maybeBlob;
return createBlob(blob, length, options?.type);
const res = createBlob(blob, length, options?.type);
res[kNotCloneable] = true;
return res;
}

module.exports = {
Expand Down
12 changes: 12 additions & 0 deletions test/parallel/test-blob-file-backed.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const common = require('../common');
const {
strictEqual,
rejects,
throws,
} = require('assert');
const { TextDecoder } = require('util');
const {
Expand Down Expand Up @@ -99,3 +100,14 @@ writeFileSync(testfile3, '');
const reader = stream.getReader();
await rejects(() => reader.read(), { name: 'NotReadableError' });
})().then(common.mustCall());

(async () => {
// We currently do not allow File-backed blobs to be cloned or transfered
// across worker threads. This is largely because the underlying FdEntry
// is bound to the Environment/Realm under which is was created.
const blob = await openAsBlob(__filename);
throws(() => structuredClone(blob), {
code: 'ERR_INVALID_STATE',
message: 'Invalid state: File-backed Blobs are not cloneable'
});
})().then(common.mustCall());

0 comments on commit 595b2b3

Please sign in to comment.