Skip to content

Commit a055337

Browse files
authored
lib: refactor to avoid unsafe regex primordials
PR-URL: #43475 Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com> Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
1 parent 411fb21 commit a055337

39 files changed

+206
-208
lines changed

lib/_http_client.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ const {
3131
ObjectKeys,
3232
ObjectSetPrototypeOf,
3333
ReflectApply,
34-
RegExpPrototypeTest,
34+
RegExpPrototypeExec,
3535
String,
3636
StringPrototypeCharCodeAt,
3737
StringPrototypeIncludes,
@@ -165,7 +165,7 @@ function ClientRequest(input, options, cb) {
165165

166166
if (options.path) {
167167
const path = String(options.path);
168-
if (RegExpPrototypeTest(INVALID_PATH_REGEX, path))
168+
if (RegExpPrototypeExec(INVALID_PATH_REGEX, path) !== null)
169169
throw new ERR_UNESCAPED_CHARACTERS('Request path');
170170
}
171171

lib/_http_common.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
const {
2525
MathMin,
2626
Symbol,
27-
RegExpPrototypeTest,
27+
RegExpPrototypeExec,
2828
} = primordials;
2929
const { setImmediate } = require('timers');
3030

@@ -207,7 +207,7 @@ const tokenRegExp = /^[\^_`a-zA-Z\-0-9!#$%&'*+.|~]+$/;
207207
* See https://tools.ietf.org/html/rfc7230#section-3.2.6
208208
*/
209209
function checkIsHttpToken(val) {
210-
return RegExpPrototypeTest(tokenRegExp, val);
210+
return RegExpPrototypeExec(tokenRegExp, val) !== null;
211211
}
212212

213213
const headerCharRegex = /[^\t\x20-\x7e\x80-\xff]/;
@@ -218,7 +218,7 @@ const headerCharRegex = /[^\t\x20-\x7e\x80-\xff]/;
218218
* field-vchar = VCHAR / obs-text
219219
*/
220220
function checkInvalidHeaderChar(val) {
221-
return RegExpPrototypeTest(headerCharRegex, val);
221+
return RegExpPrototypeExec(headerCharRegex, val) !== null;
222222
}
223223

224224
function cleanParser(parser) {

lib/_http_outgoing.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ const {
3333
ObjectValues,
3434
ObjectPrototypeHasOwnProperty,
3535
ObjectSetPrototypeOf,
36-
RegExpPrototypeTest,
36+
RegExpPrototypeExec,
3737
SafeSet,
3838
StringPrototypeToLowerCase,
3939
Symbol,
@@ -542,15 +542,15 @@ function matchHeader(self, state, field, value) {
542542
case 'connection':
543543
state.connection = true;
544544
self._removedConnection = false;
545-
if (RegExpPrototypeTest(RE_CONN_CLOSE, value))
545+
if (RegExpPrototypeExec(RE_CONN_CLOSE, value) !== null)
546546
self._last = true;
547547
else
548548
self.shouldKeepAlive = true;
549549
break;
550550
case 'transfer-encoding':
551551
state.te = true;
552552
self._removedTE = false;
553-
if (RegExpPrototypeTest(RE_TE_CHUNKED, value))
553+
if (RegExpPrototypeExec(RE_TE_CHUNKED, value) !== null)
554554
self.chunkedEncoding = true;
555555
break;
556556
case 'content-length':

lib/_http_server.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ const {
2626
Error,
2727
ObjectKeys,
2828
ObjectSetPrototypeOf,
29-
RegExpPrototypeTest,
29+
RegExpPrototypeExec,
3030
ReflectApply,
3131
Symbol,
3232
SymbolFor,
@@ -192,8 +192,8 @@ function ServerResponse(req) {
192192
this._expect_continue = false;
193193

194194
if (req.httpVersionMajor < 1 || req.httpVersionMinor < 1) {
195-
this.useChunkedEncodingByDefault = RegExpPrototypeTest(chunkExpression,
196-
req.headers.te);
195+
this.useChunkedEncodingByDefault = RegExpPrototypeExec(chunkExpression,
196+
req.headers.te) !== null;
197197
this.shouldKeepAlive = false;
198198
}
199199

@@ -987,7 +987,7 @@ function parserOnIncoming(server, socket, state, req, keepAlive) {
987987
} else if (req.headers.expect !== undefined) {
988988
handled = true;
989989

990-
if (RegExpPrototypeTest(continueExpression, req.headers.expect)) {
990+
if (RegExpPrototypeExec(continueExpression, req.headers.expect) !== null) {
991991
res._expect_continue = true;
992992

993993
if (server.listenerCount('checkContinue') > 0) {

lib/_tls_wrap.js

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,9 @@ const {
3131
ObjectSetPrototypeOf,
3232
ReflectApply,
3333
RegExp,
34-
RegExpPrototypeTest,
35-
StringPrototypeReplace,
34+
RegExpPrototypeExec,
35+
RegExpPrototypeSymbolReplace,
36+
StringPrototypeReplaceAll,
3637
StringPrototypeSlice,
3738
Symbol,
3839
SymbolFor,
@@ -425,8 +426,8 @@ function onerror(err) {
425426
owner.destroy(err);
426427
} else if (owner._tlsOptions?.isServer &&
427428
owner._rejectUnauthorized &&
428-
RegExpPrototypeTest(/peer did not return a certificate/,
429-
err.message)) {
429+
RegExpPrototypeExec(/peer did not return a certificate/,
430+
err.message) !== null) {
430431
// Ignore server's authorization errors
431432
owner.destroy();
432433
} else {
@@ -1447,9 +1448,9 @@ Server.prototype.addContext = function(servername, context) {
14471448
throw new ERR_TLS_REQUIRED_SERVER_NAME();
14481449
}
14491450

1450-
const re = new RegExp('^' + StringPrototypeReplace(
1451-
StringPrototypeReplace(servername, /([.^$+?\-\\[\]{}])/g, '\\$1'),
1452-
/\*/g, '[^.]*'
1451+
const re = new RegExp('^' + StringPrototypeReplaceAll(
1452+
RegExpPrototypeSymbolReplace(/([.^$+?\-\\[\]{}])/g, servername, '\\$1'),
1453+
'*', '[^.]*'
14531454
) + '$');
14541455
ArrayPrototypePush(this._contexts,
14551456
[re, tls.createSecureContext(context).context]);
@@ -1473,7 +1474,7 @@ function SNICallback(servername, callback) {
14731474

14741475
for (let i = contexts.length - 1; i >= 0; --i) {
14751476
const elem = contexts[i];
1476-
if (RegExpPrototypeTest(elem[0], servername)) {
1477+
if (RegExpPrototypeExec(elem[0], servername) !== null) {
14771478
callback(null, elem[1]);
14781479
return;
14791480
}

lib/assert.js

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ const {
3535
ObjectKeys,
3636
ObjectPrototypeIsPrototypeOf,
3737
ReflectApply,
38-
RegExpPrototypeTest,
38+
RegExpPrototypeExec,
39+
RegExpPrototypeSymbolReplace,
3940
SafeMap,
4041
String,
4142
StringPrototypeCharCodeAt,
@@ -345,7 +346,7 @@ function getErrMessage(message, fn) {
345346
// Always normalize indentation, otherwise the message could look weird.
346347
if (StringPrototypeIncludes(message, '\n')) {
347348
if (EOL === '\r\n') {
348-
message = StringPrototypeReplace(message, /\r\n/g, '\n');
349+
message = RegExpPrototypeSymbolReplace(/\r\n/g, message, '\n');
349350
}
350351
const frames = StringPrototypeSplit(message, '\n');
351352
message = ArrayPrototypeShift(frames);
@@ -606,7 +607,7 @@ class Comparison {
606607
if (actual !== undefined &&
607608
typeof actual[key] === 'string' &&
608609
isRegExp(obj[key]) &&
609-
RegExpPrototypeTest(obj[key], actual[key])) {
610+
RegExpPrototypeExec(obj[key], actual[key]) !== null) {
610611
this[key] = actual[key];
611612
} else {
612613
this[key] = obj[key];
@@ -652,7 +653,7 @@ function expectedException(actual, expected, message, fn) {
652653
// Handle regular expressions.
653654
if (isRegExp(expected)) {
654655
const str = String(actual);
655-
if (RegExpPrototypeTest(expected, str))
656+
if (RegExpPrototypeExec(expected, str) !== null)
656657
return;
657658

658659
if (!message) {
@@ -687,7 +688,7 @@ function expectedException(actual, expected, message, fn) {
687688
for (const key of keys) {
688689
if (typeof actual[key] === 'string' &&
689690
isRegExp(expected[key]) &&
690-
RegExpPrototypeTest(expected[key], actual[key])) {
691+
RegExpPrototypeExec(expected[key], actual[key]) !== null) {
691692
continue;
692693
}
693694
compareExceptionKey(actual, expected, key, message, keys, fn);
@@ -851,7 +852,7 @@ function hasMatchingError(actual, expected) {
851852
if (typeof expected !== 'function') {
852853
if (isRegExp(expected)) {
853854
const str = String(actual);
854-
return RegExpPrototypeTest(expected, str);
855+
return RegExpPrototypeExec(expected, str) !== null;
855856
}
856857
throw new ERR_INVALID_ARG_TYPE(
857858
'expected', ['Function', 'RegExp'], expected
@@ -1000,7 +1001,7 @@ function internalMatch(string, regexp, message, fn) {
10001001
}
10011002
const match = fn === assert.match;
10021003
if (typeof string !== 'string' ||
1003-
RegExpPrototypeTest(regexp, string) !== match) {
1004+
RegExpPrototypeExec(regexp, string) !== null !== match) {
10041005
if (message instanceof Error) {
10051006
throw message;
10061007
}

lib/buffer.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ const {
3737
ObjectDefineProperties,
3838
ObjectDefineProperty,
3939
ObjectSetPrototypeOf,
40+
RegExpPrototypeSymbolReplace,
4041
StringPrototypeCharCodeAt,
41-
StringPrototypeReplace,
4242
StringPrototypeSlice,
4343
StringPrototypeToLowerCase,
4444
StringPrototypeTrim,
@@ -837,8 +837,8 @@ Buffer.prototype[customInspectSymbol] = function inspect(recurseTimes, ctx) {
837837
const max = INSPECT_MAX_BYTES;
838838
const actualMax = MathMin(max, this.length);
839839
const remaining = this.length - max;
840-
let str = StringPrototypeTrim(StringPrototypeReplace(
841-
this.hexSlice(0, actualMax), /(.{2})/g, '$1 '));
840+
let str = StringPrototypeTrim(RegExpPrototypeSymbolReplace(
841+
/(.{2})/g, this.hexSlice(0, actualMax), '$1 '));
842842
if (remaining > 0)
843843
str += ` ... ${remaining} more byte${remaining > 1 ? 's' : ''}`;
844844
// Inspect special properties as well, if possible.

lib/child_process.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ const {
3636
ObjectAssign,
3737
ObjectDefineProperty,
3838
ObjectPrototypeHasOwnProperty,
39-
RegExpPrototypeTest,
39+
RegExpPrototypeExec,
4040
SafeSet,
4141
StringPrototypeSlice,
4242
StringPrototypeToUpperCase,
@@ -571,7 +571,7 @@ function normalizeSpawnArguments(file, args, options) {
571571
else
572572
file = process.env.comspec || 'cmd.exe';
573573
// '/d /s /c' is used only for cmd.exe.
574-
if (RegExpPrototypeTest(/^(?:.*\\)?cmd(?:\.exe)?$/i, file)) {
574+
if (RegExpPrototypeExec(/^(?:.*\\)?cmd(?:\.exe)?$/i, file) !== null) {
575575
args = ['/d', '/s', '/c', `"${command}"`];
576576
windowsVerbatimArguments = true;
577577
} else {

lib/internal/blob.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ const {
99
PromiseReject,
1010
SafePromisePrototypeFinally,
1111
ReflectConstruct,
12+
RegExpPrototypeExec,
1213
RegExpPrototypeSymbolReplace,
13-
RegExpPrototypeTest,
1414
StringPrototypeToLowerCase,
1515
StringPrototypeSplit,
1616
Symbol,
@@ -165,7 +165,7 @@ class Blob {
165165
this[kLength] = length;
166166

167167
type = `${type}`;
168-
this[kType] = RegExpPrototypeTest(disallowedTypeCharacters, type) ?
168+
this[kType] = RegExpPrototypeExec(disallowedTypeCharacters, type) !== null ?
169169
'' : StringPrototypeToLowerCase(type);
170170

171171
// eslint-disable-next-line no-constructor-return
@@ -247,7 +247,7 @@ class Blob {
247247
end |= 0;
248248

249249
contentType = `${contentType}`;
250-
if (RegExpPrototypeTest(disallowedTypeCharacters, contentType)) {
250+
if (RegExpPrototypeExec(disallowedTypeCharacters, contentType) !== null) {
251251
contentType = '';
252252
} else {
253253
contentType = StringPrototypeToLowerCase(contentType);

lib/internal/cluster/primary.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ const {
66
ArrayPrototypeSome,
77
ObjectKeys,
88
ObjectValues,
9-
RegExpPrototypeTest,
9+
RegExpPrototypeExec,
1010
SafeMap,
1111
StringPrototypeStartsWith,
1212
} = primordials;
@@ -121,8 +121,8 @@ function createWorkerProcess(id, env) {
121121
const nodeOptions = process.env.NODE_OPTIONS || '';
122122

123123
if (ArrayPrototypeSome(execArgv,
124-
(arg) => RegExpPrototypeTest(debugArgRegex, arg)) ||
125-
RegExpPrototypeTest(debugArgRegex, nodeOptions)) {
124+
(arg) => RegExpPrototypeExec(debugArgRegex, arg) !== null) ||
125+
RegExpPrototypeExec(debugArgRegex, nodeOptions) !== null) {
126126
let inspectPort;
127127
if ('inspectPort' in cluster.settings) {
128128
if (typeof cluster.settings.inspectPort === 'function')

0 commit comments

Comments
 (0)