Skip to content

Commit

Permalink
process: add code validation in process.exit()
Browse files Browse the repository at this point in the history
This commit validates the `code` in `process.exit([code])`.

According to the API doc, the `code` argument must be an integer value.
However, the current implementation accepts various types of values and
internally converts them into integer values. Also, the actual
meaningful code range is 0 - 255, but it doesn't validate the range.

Signed-off-by: Daeyeon Jeong [email protected]
  • Loading branch information
daeyeon committed Jul 7, 2022
1 parent 7d13f5e commit dcc27ac
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 4 deletions.
2 changes: 1 addition & 1 deletion doc/api/process.md
Original file line number Diff line number Diff line change
Expand Up @@ -1716,7 +1716,7 @@ that started the Node.js process. Symbolic links, if any, are resolved.
added: v0.1.13
-->
* `code` {integer} The exit code. **Default:** `0`.
* `code` {integer} The exit code in the range `0``255`. **Default:** `0`.
The `process.exit()` method instructs Node.js to terminate the process
synchronously with an exit status of `code`. If `code` is omitted, exit uses
Expand Down
5 changes: 4 additions & 1 deletion lib/internal/process/per_thread.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ const {
const format = require('internal/util/inspect').format;
const {
validateArray,
validateInteger,
validateNumber,
validateObject,
} = require('internal/validators');
Expand Down Expand Up @@ -181,8 +182,10 @@ function wrapProcessMethods(binding) {
function exit(code) {
process.off('exit', handleProcessExit);

if (code || code === 0)
if (code !== null && code !== undefined) {
validateInteger(code, 'code', 0, 255);
process.exitCode = code;
}

if (!process._exiting) {
process._exiting = true;
Expand Down
7 changes: 6 additions & 1 deletion test/fixtures/exit.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,9 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.

process.exit(process.argv[2] || 1);
let code;
if (process.argv[2] !== undefined) {
code = parseInt(process.argv[2]);
}

process.exit(code ?? 1);
50 changes: 50 additions & 0 deletions test/parallel/test-process-exit-code-validation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
'use strict';

require('../common');
const { strictEqual } = require('node:assert');

const isParent = () => process.argv[2] === undefined;
const invalid_type_samples = ['', '0', {}, [], true, false];
const out_of_range_samples = [-1, 256];
const args = [...invalid_type_samples, ...out_of_range_samples];

if (isParent()) {
const { spawn } = require('node:child_process');

// Test the samples.
strictEqual(
invalid_type_samples.every(
(v) => typeof v !== 'number' && v !== null && v !== undefined,
),
true,
);

strictEqual(
out_of_range_samples.every(
(v) => typeof v == 'number' && (v < 0 || v > 255),
),
true,
);

// Test process.exit() with the samepls.
const node = process.execPath;
const test = (arg, expectedCode) => {
spawn(node, [__filename, arg]).on('exit', (code) => {
strictEqual(
code,
expectedCode,
`args[${arg}] - actual: ${code}, expected: ${expectedCode}`,
);
});
};

for (const index of args.keys()) {
test(index, 1);
}
} else {
const i = parseInt(process.argv[2]);
if (Number.isNaN(i)) {
return process.exit(100);
}
process.exit(args[i]);
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ if (isMainThread) {
assert.strictEqual(headers[':status'], 200);
}));

req.on('data', common.mustCall(process.exit));
req.on('data', common.mustCall(() => process.exit()));
req.on('end', common.mustNotCall());
req.end();
}

0 comments on commit dcc27ac

Please sign in to comment.