Skip to content
17 changes: 11 additions & 6 deletions doc/contributing/writing-and-running-benchmarks.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ which need to be included in the global Windows `PATH`.

If you are using Nix, all the required tools are already listed in the
`benchmarkTools` argument of the `shell.nix` file, so you can skip those
prerequesites.
prerequisites.

### HTTP benchmark requirements

Expand All @@ -47,24 +47,29 @@ By default, `wrk` will be used as the benchmarker. If it is not available,
`autocannon` will be used in its place. When creating an HTTP benchmark, the
benchmarker to be used should be specified by providing it as an argument:

`node benchmark/run.js --set benchmarker=autocannon http`

`node benchmark/http/simple.js benchmarker=autocannon`
```bash
node benchmark/run.js --set benchmarker=autocannon http
node benchmark/http/simple.js benchmarker=autocannon
```

#### HTTPS benchmark requirements

To run the `https` benchmarks, one of `autocannon` or `wrk` benchmarkers must
be used.

`node benchmark/https/simple.js benchmarker=autocannon`
```bash
node benchmark/https/simple.js benchmarker=autocannon
```

#### HTTP/2 benchmark requirements

To run the `http2` benchmarks, the `h2load` benchmarker must be used. The
`h2load` tool is a component of the `nghttp2` project and may be installed
from [nghttp2.org][] or built from source.

`node benchmark/http2/simple.js benchmarker=h2load`
```bash
node benchmark/http2/simple.js benchmarker=h2load
```

### Benchmark analysis requirements

Expand Down
58 changes: 35 additions & 23 deletions lib/fs.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ const {
} = constants;

const pathModule = require('path');
const { isAbsolute } = pathModule;
const { isArrayBufferView } = require('internal/util/types');

const binding = internalBinding('fs');
Expand Down Expand Up @@ -1224,6 +1223,11 @@ function rmSync(path, options) {
function fdatasync(fd, callback) {
const req = new FSReqCallback();
req.oncomplete = makeCallback(callback);

if (permission.isEnabled()) {
callback(new ERR_ACCESS_DENIED('fdatasync API is disabled when Permission Model is enabled.'));
return;
}
binding.fdatasync(fd, req);
}

Expand All @@ -1235,6 +1239,9 @@ function fdatasync(fd, callback) {
* @returns {void}
*/
function fdatasyncSync(fd) {
if (permission.isEnabled()) {
throw new ERR_ACCESS_DENIED('fdatasync API is disabled when Permission Model is enabled.');
}
binding.fdatasync(fd);
}

Expand All @@ -1248,6 +1255,10 @@ function fdatasyncSync(fd) {
function fsync(fd, callback) {
const req = new FSReqCallback();
req.oncomplete = makeCallback(callback);
if (permission.isEnabled()) {
callback(new ERR_ACCESS_DENIED('fsync API is disabled when Permission Model is enabled.'));
return;
}
binding.fsync(fd, req);
}

Expand All @@ -1258,6 +1269,9 @@ function fsync(fd, callback) {
* @returns {void}
*/
function fsyncSync(fd) {
if (permission.isEnabled()) {
throw new ERR_ACCESS_DENIED('fsync API is disabled when Permission Model is enabled.');
}
binding.fsync(fd);
}

Expand Down Expand Up @@ -1763,18 +1777,12 @@ function symlink(target, path, type, callback) {
validateOneOf(type, 'type', ['dir', 'file', 'junction', null, undefined]);
}

if (permission.isEnabled()) {
// The permission model's security guarantees fall apart in the presence of
// relative symbolic links. Thus, we have to prevent their creation.
if (BufferIsBuffer(target)) {
if (!isAbsolute(BufferToString(target))) {
callback(new ERR_ACCESS_DENIED('relative symbolic link target'));
return;
}
} else if (typeof target !== 'string' || !isAbsolute(toPathIfFileURL(target))) {
callback(new ERR_ACCESS_DENIED('relative symbolic link target'));
return;
}
// Due to the nature of Node.js runtime, symlinks has different edge cases that can bypass
// the permission model security guarantees. Thus, this API is disabled unless fs.read
// and fs.write permission has been given.
if (permission.isEnabled() && !permission.has('fs')) {
callback(new ERR_ACCESS_DENIED('fs.symlink API requires full fs.read and fs.write permissions.'));
return;
}

target = getValidatedPath(target, 'target');
Expand Down Expand Up @@ -1838,16 +1846,11 @@ function symlinkSync(target, path, type) {
}
}

if (permission.isEnabled()) {
// The permission model's security guarantees fall apart in the presence of
// relative symbolic links. Thus, we have to prevent their creation.
if (BufferIsBuffer(target)) {
if (!isAbsolute(BufferToString(target))) {
throw new ERR_ACCESS_DENIED('relative symbolic link target');
}
} else if (typeof target !== 'string' || !isAbsolute(toPathIfFileURL(target))) {
throw new ERR_ACCESS_DENIED('relative symbolic link target');
}
// Due to the nature of Node.js runtime, symlinks has different edge cases that can bypass
// the permission model security guarantees. Thus, this API is disabled unless fs.read
// and fs.write permission has been given.
if (permission.isEnabled() && !permission.has('fs')) {
throw new ERR_ACCESS_DENIED('fs.symlink API requires full fs.read and fs.write permissions.');
}

target = getValidatedPath(target, 'target');
Expand Down Expand Up @@ -2188,6 +2191,11 @@ function futimes(fd, atime, mtime, callback) {
mtime = toUnixTimestamp(mtime, 'mtime');
callback = makeCallback(callback);

if (permission.isEnabled()) {
callback(new ERR_ACCESS_DENIED('futimes API is disabled when Permission Model is enabled.'));
return;
}

const req = new FSReqCallback();
req.oncomplete = callback;
binding.futimes(fd, atime, mtime, req);
Expand All @@ -2203,6 +2211,10 @@ function futimes(fd, atime, mtime, callback) {
* @returns {void}
*/
function futimesSync(fd, atime, mtime) {
if (permission.isEnabled()) {
throw new ERR_ACCESS_DENIED('futimes API is disabled when Permission Model is enabled.');
}

binding.futimes(
fd,
toUnixTimestamp(atime, 'atime'),
Expand Down
33 changes: 6 additions & 27 deletions lib/internal/buffer.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const {
hexWrite,
ucs2Write,
utf8WriteStatic,
getZeroFillToggle,
createUnsafeArrayBuffer,
} = internalBinding('buffer');

const {
Expand All @@ -39,13 +39,6 @@ const {
},
} = internalBinding('util');

const {
namespace: {
isBuildingSnapshot,
},
addAfterUserSerializeCallback,
} = require('internal/v8/startup_snapshot');

// Temporary buffers to convert numbers.
const float32Array = new Float32Array(1);
const uInt8Float32Array = new Uint8Array(float32Array.buffer);
Expand Down Expand Up @@ -1086,28 +1079,14 @@ function isMarkedAsUntransferable(obj) {
return obj[untransferable_object_private_symbol] !== undefined;
}

// A toggle used to access the zero fill setting of the array buffer allocator
// in C++.
// |zeroFill| can be undefined when running inside an isolate where we
// do not own the ArrayBuffer allocator. Zero fill is always on in that case.
let zeroFill;
function createUnsafeBuffer(size) {
if (!zeroFill) {
zeroFill = getZeroFillToggle();
if (isBuildingSnapshot()) {
// Reset the toggle so that after serialization, we'll re-create a real
// toggle connected to the C++ one via getZeroFillToggle().
addAfterUserSerializeCallback(() => {
zeroFill = undefined;
});
}
}
zeroFill[0] = 0;
try {
if (size <= 64) {
// Allocated in heap, doesn't call backing store anyway
// This is the same that the old impl did implicitly, but explicit now
return new FastBuffer(size);
} finally {
zeroFill[0] = 1;
}

return new FastBuffer(createUnsafeArrayBuffer(size));
}

module.exports = {
Expand Down
20 changes: 5 additions & 15 deletions lib/internal/fs/promises.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ const {
Symbol,
SymbolAsyncDispose,
Uint8Array,
uncurryThis,
} = primordials;

const { fs: constants } = internalBinding('constants');
Expand All @@ -31,8 +30,6 @@ const {

const binding = internalBinding('fs');
const { Buffer } = require('buffer');
const { isBuffer: BufferIsBuffer } = Buffer;
const BufferToString = uncurryThis(Buffer.prototype.toString);

const {
AbortError,
Expand Down Expand Up @@ -88,8 +85,6 @@ const {
kValidateObjectAllowNullable,
} = require('internal/validators');
const pathModule = require('path');
const { isAbsolute } = pathModule;
const { toPathIfFileURL } = require('internal/url');
const {
getLazy,
kEmptyObject,
Expand Down Expand Up @@ -992,16 +987,11 @@ async function symlink(target, path, type) {
}
}

if (permission.isEnabled()) {
// The permission model's security guarantees fall apart in the presence of
// relative symbolic links. Thus, we have to prevent their creation.
if (BufferIsBuffer(target)) {
if (!isAbsolute(BufferToString(target))) {
throw new ERR_ACCESS_DENIED('relative symbolic link target');
}
} else if (typeof target !== 'string' || !isAbsolute(toPathIfFileURL(target))) {
throw new ERR_ACCESS_DENIED('relative symbolic link target');
}
// Due to the nature of Node.js runtime, symlinks has different edge cases that can bypass
// the permission model security guarantees. Thus, this API is disabled unless fs.read
// and fs.write permission has been given.
if (permission.isEnabled() && !permission.has('fs')) {
throw new ERR_ACCESS_DENIED('fs.symlink API requires full fs.read and fs.write permissions.');
}

target = getValidatedPath(target, 'target');
Expand Down
Loading
Loading