Skip to content

Commit e836128

Browse files
targosBridgeAR
authored andcommitted
lib: introduce internal/validators
Create a file to centralize argument validators that are used in multiple internal modules. Move validateInt32 and validateUint32 to this file. 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 d5e363b commit e836128

File tree

8 files changed

+112
-99
lines changed

8 files changed

+112
-99
lines changed

lib/fs.js

+9-7
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ const internalUtil = require('internal/util');
5151
const {
5252
copyObject,
5353
getOptions,
54-
isUint32,
5554
modeNum,
5655
nullCheck,
5756
preprocessSymlinkDestination,
@@ -61,16 +60,19 @@ const {
6160
stringToSymlinkType,
6261
toUnixTimestamp,
6362
validateBuffer,
64-
validateLen,
6563
validateOffsetLengthRead,
6664
validateOffsetLengthWrite,
67-
validatePath,
68-
validateUint32
65+
validatePath
6966
} = internalFS;
7067
const {
7168
CHAR_FORWARD_SLASH,
7269
CHAR_BACKWARD_SLASH,
7370
} = require('internal/constants');
71+
const {
72+
isUint32,
73+
validateInt32,
74+
validateUint32
75+
} = require('internal/validators');
7476

7577
Object.defineProperty(exports, 'constants', {
7678
configurable: false,
@@ -755,8 +757,8 @@ fs.ftruncate = function(fd, len = 0, callback) {
755757
// TODO(BridgeAR): This does not seem right.
756758
// There does not seem to be any validation before and if there is any, it
757759
// should work similar to validateUint32 or not have a upper cap at all.
758-
// This applies to all usage of `validateLen`.
759-
validateLen(len);
760+
// This applies to all usage of `validateInt32(len, 'len')`.
761+
validateInt32(len, 'len');
760762
len = Math.max(0, len);
761763
const req = new FSReqWrap();
762764
req.oncomplete = makeCallback(callback);
@@ -765,7 +767,7 @@ fs.ftruncate = function(fd, len = 0, callback) {
765767

766768
fs.ftruncateSync = function(fd, len = 0) {
767769
validateUint32(fd, 'fd');
768-
validateLen(len);
770+
validateInt32(len, 'len');
769771
len = Math.max(0, len);
770772
const ctx = {};
771773
binding.ftruncate(fd, len, undefined, ctx);

lib/fs/promises.js

+7-5
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,22 @@ const {
2424
copyObject,
2525
getOptions,
2626
getStatsFromBinding,
27-
isUint32,
2827
modeNum,
2928
nullCheck,
3029
preprocessSymlinkDestination,
3130
stringToFlags,
3231
stringToSymlinkType,
3332
toUnixTimestamp,
3433
validateBuffer,
35-
validateLen,
3634
validateOffsetLengthRead,
3735
validateOffsetLengthWrite,
38-
validatePath,
39-
validateUint32
36+
validatePath
4037
} = require('internal/fs');
38+
const {
39+
isUint32,
40+
validateInt32,
41+
validateUint32
42+
} = require('internal/validators');
4143
const pathModule = require('path');
4244

4345
const kHandle = Symbol('handle');
@@ -275,7 +277,7 @@ async function truncate(path, len = 0) {
275277

276278
async function ftruncate(handle, len = 0) {
277279
validateFileHandle(handle);
278-
validateLen(len);
280+
validateInt32(len, 'len');
279281
len = Math.max(0, len);
280282
return binding.ftruncate(handle.fd, len, kUsePromises);
281283
}

lib/internal/fs.js

+1-44
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,6 @@ function getOptions(options, defaultOptions) {
7070
return options;
7171
}
7272

73-
function isInt32(n) { return n === (n | 0); }
74-
function isUint32(n) { return n === (n >>> 0); }
75-
7673
function modeNum(m, def) {
7774
if (typeof m === 'number')
7875
return m;
@@ -341,26 +338,6 @@ function validateBuffer(buffer) {
341338
}
342339
}
343340

344-
function validateLen(len) {
345-
let err;
346-
347-
if (!isInt32(len)) {
348-
if (typeof len !== 'number') {
349-
err = new ERR_INVALID_ARG_TYPE('len', 'number', len);
350-
} else if (!Number.isInteger(len)) {
351-
err = new ERR_OUT_OF_RANGE('len', 'an integer', len);
352-
} else {
353-
// 2 ** 31 === 2147483648
354-
err = new ERR_OUT_OF_RANGE('len', '> -2147483649 && < 2147483648', len);
355-
}
356-
}
357-
358-
if (err !== undefined) {
359-
Error.captureStackTrace(err, validateLen);
360-
throw err;
361-
}
362-
}
363-
364341
function validateOffsetLengthRead(offset, length, bufferLength) {
365342
let err;
366343

@@ -410,28 +387,10 @@ function validatePath(path, propName = 'path') {
410387
}
411388
}
412389

413-
function validateUint32(value, propName) {
414-
if (!isUint32(value)) {
415-
let err;
416-
if (typeof value !== 'number') {
417-
err = new ERR_INVALID_ARG_TYPE(propName, 'number', value);
418-
} else if (!Number.isInteger(value)) {
419-
err = new ERR_OUT_OF_RANGE(propName, 'an integer', value);
420-
} else {
421-
// 2 ** 32 === 4294967296
422-
err = new ERR_OUT_OF_RANGE(propName, '>= 0 && < 4294967296', value);
423-
}
424-
Error.captureStackTrace(err, validateUint32);
425-
throw err;
426-
}
427-
}
428-
429390
module.exports = {
430391
assertEncoding,
431392
copyObject,
432393
getOptions,
433-
isInt32,
434-
isUint32,
435394
modeNum,
436395
nullCheck,
437396
preprocessSymlinkDestination,
@@ -443,9 +402,7 @@ module.exports = {
443402
SyncWriteStream,
444403
toUnixTimestamp,
445404
validateBuffer,
446-
validateLen,
447405
validateOffsetLengthRead,
448406
validateOffsetLengthWrite,
449-
validatePath,
450-
validateUint32
407+
validatePath
451408
};

lib/internal/validators.js

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
'use strict';
2+
3+
const {
4+
ERR_INVALID_ARG_TYPE,
5+
ERR_OUT_OF_RANGE
6+
} = require('internal/errors').codes;
7+
8+
function isInt32(value) {
9+
return value === (value | 0);
10+
}
11+
12+
function isUint32(value) {
13+
return value === (value >>> 0);
14+
}
15+
16+
function validateInt32(value, name) {
17+
if (!isInt32(value)) {
18+
let err;
19+
if (typeof value !== 'number') {
20+
err = new ERR_INVALID_ARG_TYPE(name, 'number', value);
21+
} else if (!Number.isInteger(value)) {
22+
err = new ERR_OUT_OF_RANGE(name, 'an integer', value);
23+
} else {
24+
// 2 ** 31 === 2147483648
25+
err = new ERR_OUT_OF_RANGE(name, '> -2147483649 && < 2147483648', value);
26+
}
27+
Error.captureStackTrace(err, validateInt32);
28+
throw err;
29+
}
30+
}
31+
32+
function validateUint32(value, name, positive) {
33+
if (!isUint32(value)) {
34+
let err;
35+
if (typeof value !== 'number') {
36+
err = new ERR_INVALID_ARG_TYPE(name, 'number', value);
37+
} else if (!Number.isInteger(value)) {
38+
err = new ERR_OUT_OF_RANGE(name, 'an integer', value);
39+
} else {
40+
const min = positive ? 1 : 0;
41+
// 2 ** 32 === 4294967296
42+
err = new ERR_OUT_OF_RANGE(name, `>= ${min} && < 4294967296`, value);
43+
}
44+
Error.captureStackTrace(err, validateUint32);
45+
throw err;
46+
} else if (positive && value === 0) {
47+
const err = new ERR_OUT_OF_RANGE(name, '>= 1 && < 4294967296', value);
48+
Error.captureStackTrace(err, validateUint32);
49+
throw err;
50+
}
51+
}
52+
53+
module.exports = {
54+
isInt32,
55+
isUint32,
56+
validateInt32,
57+
validateUint32
58+
};

lib/internal/vm/module.js

+5-15
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ const { URL } = require('internal/url');
66
const { isContext } = process.binding('contextify');
77
const {
88
ERR_INVALID_ARG_TYPE,
9-
ERR_OUT_OF_RANGE,
109
ERR_VM_MODULE_ALREADY_LINKED,
1110
ERR_VM_MODULE_DIFFERENT_CONTEXT,
1211
ERR_VM_MODULE_LINKING_ERRORED,
@@ -19,6 +18,7 @@ const {
1918
customInspectSymbol,
2019
} = require('internal/util');
2120
const { SafePromise } = require('internal/safe_globals');
21+
const { validateInt32, validateUint32 } = require('internal/validators');
2222

2323
const {
2424
ModuleWrap,
@@ -92,8 +92,8 @@ class Module {
9292
perContextModuleId.set(context, 1);
9393
}
9494

95-
validateInteger(lineOffset, 'options.lineOffset');
96-
validateInteger(columnOffset, 'options.columnOffset');
95+
validateInt32(lineOffset, 'options.lineOffset');
96+
validateInt32(columnOffset, 'options.columnOffset');
9797

9898
if (initializeImportMeta !== undefined) {
9999
if (typeof initializeImportMeta === 'function') {
@@ -203,9 +203,8 @@ class Module {
203203
let timeout = options.timeout;
204204
if (timeout === undefined) {
205205
timeout = -1;
206-
} else if (!Number.isInteger(timeout) || timeout <= 0) {
207-
throw new ERR_INVALID_ARG_TYPE('options.timeout', 'a positive integer',
208-
timeout);
206+
} else {
207+
validateUint32(timeout, 'options.timeout', true);
209208
}
210209

211210
const { breakOnSigint = false } = options;
@@ -243,15 +242,6 @@ class Module {
243242
}
244243
}
245244

246-
function validateInteger(prop, propName) {
247-
if (!Number.isInteger(prop)) {
248-
throw new ERR_INVALID_ARG_TYPE(propName, 'integer', prop);
249-
}
250-
if ((prop >> 0) !== prop) {
251-
throw new ERR_OUT_OF_RANGE(propName, '32-bit integer', prop);
252-
}
253-
}
254-
255245
module.exports = {
256246
Module,
257247
initImportMetaMap,

lib/vm.js

+6-18
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,9 @@ const {
2828
isContext: _isContext,
2929
} = process.binding('contextify');
3030

31-
const {
32-
ERR_INVALID_ARG_TYPE,
33-
ERR_OUT_OF_RANGE
34-
} = require('internal/errors').codes;
31+
const { ERR_INVALID_ARG_TYPE } = require('internal/errors').codes;
3532
const { isUint8Array } = require('internal/util/types');
33+
const { validateInt32, validateUint32 } = require('internal/validators');
3634

3735
class Script extends ContextifyScript {
3836
constructor(code, options = {}) {
@@ -56,8 +54,8 @@ class Script extends ContextifyScript {
5654
if (typeof filename !== 'string') {
5755
throw new ERR_INVALID_ARG_TYPE('options.filename', 'string', filename);
5856
}
59-
validateInteger(lineOffset, 'options.lineOffset');
60-
validateInteger(columnOffset, 'options.columnOffset');
57+
validateInt32(lineOffset, 'options.lineOffset');
58+
validateInt32(columnOffset, 'options.columnOffset');
6159
if (cachedData !== undefined && !isUint8Array(cachedData)) {
6260
throw new ERR_INVALID_ARG_TYPE('options.cachedData',
6361
['Buffer', 'Uint8Array'], cachedData);
@@ -119,15 +117,6 @@ function validateContext(sandbox) {
119117
}
120118
}
121119

122-
function validateInteger(prop, propName) {
123-
if (!Number.isInteger(prop)) {
124-
throw new ERR_INVALID_ARG_TYPE(propName, 'integer', prop);
125-
}
126-
if ((prop >> 0) !== prop) {
127-
throw new ERR_OUT_OF_RANGE(propName, '32-bit integer', prop);
128-
}
129-
}
130-
131120
function validateString(prop, propName) {
132121
if (prop !== undefined && typeof prop !== 'string')
133122
throw new ERR_INVALID_ARG_TYPE(propName, 'string', prop);
@@ -151,9 +140,8 @@ function getRunInContextArgs(options = {}) {
151140
let timeout = options.timeout;
152141
if (timeout === undefined) {
153142
timeout = -1;
154-
} else if (!Number.isInteger(timeout) || timeout <= 0) {
155-
throw new ERR_INVALID_ARG_TYPE('options.timeout', 'a positive integer',
156-
timeout);
143+
} else {
144+
validateUint32(timeout, 'options.timeout', true);
157145
}
158146

159147
const {

node.gyp

+1
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@
146146
'lib/internal/v8.js',
147147
'lib/internal/v8_prof_polyfill.js',
148148
'lib/internal/v8_prof_processor.js',
149+
'lib/internal/validators.js',
149150
'lib/internal/stream_base_commons.js',
150151
'lib/internal/vm/module.js',
151152
'lib/internal/streams/lazy_transform.js',

0 commit comments

Comments
 (0)