Skip to content

Commit 2fd248f

Browse files
targosBridgeAR
authored andcommitted
process: migrate methods to throw errors with code
Migrate some methods from node.cc to JS in order to properly throw errors with codes. PR-URL: #19973 Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent e836128 commit 2fd248f

File tree

10 files changed

+246
-93
lines changed

10 files changed

+246
-93
lines changed

doc/api/errors.md

+5
Original file line numberDiff line numberDiff line change
@@ -1607,6 +1607,11 @@ A string that contained unescaped characters was received.
16071607
An unhandled error occurred (for instance, when an `'error'` event is emitted
16081608
by an [`EventEmitter`][] but an `'error'` handler is not registered).
16091609

1610+
<a id="ERR_UNKNOWN_CREDENTIAL"></a>
1611+
### ERR_UNKNOWN_CREDENTIAL
1612+
1613+
A Unix group or user identifier that does not exist was passed.
1614+
16101615
<a id="ERR_UNKNOWN_ENCODING"></a>
16111616
### ERR_UNKNOWN_ENCODING
16121617

lib/internal/bootstrap/node.js

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
NativeModule.require('internal/process/warning').setup();
4242
NativeModule.require('internal/process/next_tick').setup();
4343
NativeModule.require('internal/process/stdio').setup();
44+
NativeModule.require('internal/process/methods').setup();
4445

4546
const perf = process.binding('performance');
4647
const {

lib/internal/errors.js

+1
Original file line numberDiff line numberDiff line change
@@ -1017,6 +1017,7 @@ E('ERR_UNHANDLED_ERROR',
10171017
if (err === undefined) return msg;
10181018
return `${msg} (${err})`;
10191019
}, Error);
1020+
E('ERR_UNKNOWN_CREDENTIAL', '%s identifier does not exist: %s', Error);
10201021
E('ERR_UNKNOWN_ENCODING', 'Unknown encoding: %s', TypeError);
10211022

10221023
// This should probably be a `TypeError`.

lib/internal/process/methods.js

+137
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
'use strict';
2+
3+
const {
4+
ERR_INVALID_ARG_TYPE,
5+
ERR_INVALID_ARG_VALUE,
6+
ERR_UNKNOWN_CREDENTIAL
7+
} = require('internal/errors').codes;
8+
const {
9+
validateUint32
10+
} = require('internal/validators');
11+
12+
function setupProcessMethods() {
13+
// Non-POSIX platforms like Windows don't have certain methods.
14+
if (process.setgid !== undefined) {
15+
setupPosixMethods();
16+
}
17+
18+
const {
19+
chdir: _chdir,
20+
umask: _umask,
21+
} = process;
22+
23+
process.chdir = chdir;
24+
process.umask = umask;
25+
26+
function chdir(directory) {
27+
if (typeof directory !== 'string') {
28+
throw new ERR_INVALID_ARG_TYPE('directory', 'string', directory);
29+
}
30+
return _chdir(directory);
31+
}
32+
33+
const octalReg = /^[0-7]+$/;
34+
function umask(mask) {
35+
if (typeof mask === 'undefined') {
36+
return _umask(mask);
37+
}
38+
39+
if (typeof mask === 'number') {
40+
validateUint32(mask, 'mask');
41+
return _umask(mask);
42+
}
43+
44+
if (typeof mask === 'string') {
45+
if (!octalReg.test(mask)) {
46+
throw new ERR_INVALID_ARG_VALUE('mask', mask,
47+
'must be an octal string');
48+
}
49+
const octal = Number.parseInt(mask, 8);
50+
validateUint32(octal, 'mask');
51+
return _umask(octal);
52+
}
53+
54+
throw new ERR_INVALID_ARG_TYPE('mask', ['number', 'string', 'undefined'],
55+
mask);
56+
}
57+
}
58+
59+
function setupPosixMethods() {
60+
const {
61+
initgroups: _initgroups,
62+
setegid: _setegid,
63+
seteuid: _seteuid,
64+
setgid: _setgid,
65+
setuid: _setuid,
66+
setgroups: _setgroups
67+
} = process;
68+
69+
process.initgroups = initgroups;
70+
process.setegid = setegid;
71+
process.seteuid = seteuid;
72+
process.setgid = setgid;
73+
process.setuid = setuid;
74+
process.setgroups = setgroups;
75+
76+
function initgroups(user, extraGroup) {
77+
validateId(user, 'user');
78+
validateId(extraGroup, 'extraGroup');
79+
// Result is 0 on success, 1 if user is unknown, 2 if group is unknown.
80+
const result = _initgroups(user, extraGroup);
81+
if (result === 1) {
82+
throw new ERR_UNKNOWN_CREDENTIAL('User', user);
83+
} else if (result === 2) {
84+
throw new ERR_UNKNOWN_CREDENTIAL('Group', extraGroup);
85+
}
86+
}
87+
88+
function setegid(id) {
89+
return execId(id, 'Group', _setegid);
90+
}
91+
92+
function seteuid(id) {
93+
return execId(id, 'User', _seteuid);
94+
}
95+
96+
function setgid(id) {
97+
return execId(id, 'Group', _setgid);
98+
}
99+
100+
function setuid(id) {
101+
return execId(id, 'User', _setuid);
102+
}
103+
104+
function setgroups(groups) {
105+
if (!Array.isArray(groups)) {
106+
throw new ERR_INVALID_ARG_TYPE('groups', 'Array', groups);
107+
}
108+
for (var i = 0; i < groups.length; i++) {
109+
validateId(groups[i], `groups[${i}]`);
110+
}
111+
// Result is 0 on success. A positive integer indicates that the
112+
// corresponding group was not found.
113+
const result = _setgroups(groups);
114+
if (result > 0) {
115+
throw new ERR_UNKNOWN_CREDENTIAL('Group', groups[result - 1]);
116+
}
117+
}
118+
119+
function execId(id, type, method) {
120+
validateId(id, 'id');
121+
// Result is 0 on success, 1 if credential is unknown.
122+
const result = method(id);
123+
if (result === 1) {
124+
throw new ERR_UNKNOWN_CREDENTIAL(type, id);
125+
}
126+
}
127+
128+
function validateId(id, name) {
129+
if (typeof id === 'number') {
130+
validateUint32(id, name);
131+
} else if (typeof id !== 'string') {
132+
throw new ERR_INVALID_ARG_TYPE(name, ['number', 'string'], id);
133+
}
134+
}
135+
}
136+
137+
exports.setup = setupProcessMethods;

node.gyp

+1
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@
118118
'lib/internal/net.js',
119119
'lib/internal/os.js',
120120
'lib/internal/process/esm_loader.js',
121+
'lib/internal/process/methods.js',
121122
'lib/internal/process/next_tick.js',
122123
'lib/internal/process/promises.js',
123124
'lib/internal/process/stdio.js',

0 commit comments

Comments
 (0)