-
Notifications
You must be signed in to change notification settings - Fork 29.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
doc, test: document and test vm timeout escapes
Using `process.nextTick()`, `Promise`, or `queueMicrotask()`, it is possible to escape the `timeout` set when running code with `vm.runInContext()`, `vm.runInThisContext()`, and `vm.runInNewContext()`. This documents the issue and adds three known_issues tests. Refs: #3020 PR-URL: #23743 Refs: #3020 Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com>
- Loading branch information
Showing
4 changed files
with
152 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
'use strict'; | ||
|
||
// https://github.com/nodejs/node/issues/3020 | ||
// Promises, nextTick, and queueMicrotask allow code to escape the timeout | ||
// set for runInContext, runInNewContext, and runInThisContext | ||
|
||
require('../common'); | ||
const assert = require('assert'); | ||
const vm = require('vm'); | ||
|
||
const NS_PER_MS = 1000000n; | ||
|
||
const hrtime = process.hrtime.bigint; | ||
const nextTick = process.nextTick; | ||
|
||
function loop() { | ||
const start = hrtime(); | ||
while (1) { | ||
const current = hrtime(); | ||
const span = (current - start) / NS_PER_MS; | ||
if (span >= 100n) { | ||
throw new Error( | ||
`escaped timeout at ${span} milliseconds!`); | ||
} | ||
} | ||
} | ||
|
||
assert.throws(() => { | ||
vm.runInNewContext( | ||
'nextTick(loop); loop();', | ||
{ | ||
hrtime, | ||
nextTick, | ||
loop | ||
}, | ||
{ timeout: 5 } | ||
); | ||
}, { | ||
code: 'ERR_SCRIPT_EXECUTION_TIMEOUT', | ||
message: 'Script execution timed out after 5ms' | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
'use strict'; | ||
|
||
// https://github.com/nodejs/node/issues/3020 | ||
// Promises, nextTick, and queueMicrotask allow code to escape the timeout | ||
// set for runInContext, runInNewContext, and runInThisContext | ||
|
||
require('../common'); | ||
const assert = require('assert'); | ||
const vm = require('vm'); | ||
|
||
const NS_PER_MS = 1000000n; | ||
|
||
const hrtime = process.hrtime.bigint; | ||
|
||
function loop() { | ||
const start = hrtime(); | ||
while (1) { | ||
const current = hrtime(); | ||
const span = (current - start) / NS_PER_MS; | ||
if (span >= 100n) { | ||
throw new Error( | ||
`escaped timeout at ${span} milliseconds!`); | ||
} | ||
} | ||
} | ||
|
||
assert.throws(() => { | ||
vm.runInNewContext( | ||
'Promise.resolve().then(loop); loop();', | ||
{ | ||
hrtime, | ||
loop | ||
}, | ||
{ timeout: 5 } | ||
); | ||
}, { | ||
code: 'ERR_SCRIPT_EXECUTION_TIMEOUT', | ||
message: 'Script execution timed out after 5ms' | ||
}); |
40 changes: 40 additions & 0 deletions
40
test/known_issues/test-vm-timeout-escape-queuemicrotask.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
'use strict'; | ||
|
||
// https://github.com/nodejs/node/issues/3020 | ||
// Promises, nextTick, and queueMicrotask allow code to escape the timeout | ||
// set for runInContext, runInNewContext, and runInThisContext | ||
|
||
require('../common'); | ||
const assert = require('assert'); | ||
const vm = require('vm'); | ||
|
||
const NS_PER_MS = 1000000n; | ||
|
||
const hrtime = process.hrtime.bigint; | ||
|
||
function loop() { | ||
const start = hrtime(); | ||
while (1) { | ||
const current = hrtime(); | ||
const span = (current - start) / NS_PER_MS; | ||
if (span >= 100n) { | ||
throw new Error( | ||
`escaped timeout at ${span} milliseconds!`); | ||
} | ||
} | ||
} | ||
|
||
assert.throws(() => { | ||
vm.runInNewContext( | ||
'queueMicrotask(loop); loop();', | ||
{ | ||
hrtime, | ||
queueMicrotask, | ||
loop | ||
}, | ||
{ timeout: 5 } | ||
); | ||
}, { | ||
code: 'ERR_SCRIPT_EXECUTION_TIMEOUT', | ||
message: 'Script execution timed out after 5ms' | ||
}); |