Skip to content

Commit

Permalink
lib: refactor to avoid unsafe regex primordials
Browse files Browse the repository at this point in the history
PR-URL: nodejs#43475
Reviewed-By: Geoffrey Booth <[email protected]>
Reviewed-By: Stephen Belanger <[email protected]>
  • Loading branch information
aduh95 committed Aug 1, 2022
1 parent 4327ff8 commit 9994a1b
Show file tree
Hide file tree
Showing 39 changed files with 209 additions and 207 deletions.
4 changes: 2 additions & 2 deletions lib/_http_client.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const {
ObjectKeys,
ObjectSetPrototypeOf,
ReflectApply,
RegExpPrototypeTest,
RegExpPrototypeExec,
String,
StringPrototypeCharCodeAt,
StringPrototypeIncludes,
Expand Down Expand Up @@ -169,7 +169,7 @@ function ClientRequest(input, options, cb) {

if (options.path) {
const path = String(options.path);
if (RegExpPrototypeTest(INVALID_PATH_REGEX, path))
if (RegExpPrototypeExec(INVALID_PATH_REGEX, path) !== null)
throw new ERR_UNESCAPED_CHARACTERS('Request path');
}

Expand Down
6 changes: 3 additions & 3 deletions lib/_http_common.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
const {
MathMin,
Symbol,
RegExpPrototypeTest,
RegExpPrototypeExec,
} = primordials;
const { setImmediate } = require('timers');

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

const headerCharRegex = /[^\t\x20-\x7e\x80-\xff]/;
Expand All @@ -229,7 +229,7 @@ const headerCharRegex = /[^\t\x20-\x7e\x80-\xff]/;
* field-vchar = VCHAR / obs-text
*/
function checkInvalidHeaderChar(val) {
return RegExpPrototypeTest(headerCharRegex, val);
return RegExpPrototypeExec(headerCharRegex, val) !== null;
}

function cleanParser(parser) {
Expand Down
6 changes: 3 additions & 3 deletions lib/_http_outgoing.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ const {
ObjectValues,
ObjectPrototypeHasOwnProperty,
ObjectSetPrototypeOf,
RegExpPrototypeTest,
RegExpPrototypeExec,
SafeSet,
StringPrototypeToLowerCase,
Symbol,
Expand Down Expand Up @@ -542,15 +542,15 @@ function matchHeader(self, state, field, value) {
case 'connection':
state.connection = true;
self._removedConnection = false;
if (RegExpPrototypeTest(RE_CONN_CLOSE, value))
if (RegExpPrototypeExec(RE_CONN_CLOSE, value) !== null)
self._last = true;
else
self.shouldKeepAlive = true;
break;
case 'transfer-encoding':
state.te = true;
self._removedTE = false;
if (RegExpPrototypeTest(RE_TE_CHUNKED, value))
if (RegExpPrototypeExec(RE_TE_CHUNKED, value) !== null)
self.chunkedEncoding = true;
break;
case 'content-length':
Expand Down
8 changes: 4 additions & 4 deletions lib/_http_server.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const {
Error,
ObjectKeys,
ObjectSetPrototypeOf,
RegExpPrototypeTest,
RegExpPrototypeExec,
Symbol,
SymbolFor,
} = primordials;
Expand Down Expand Up @@ -191,8 +191,8 @@ function ServerResponse(req) {
this._expect_continue = false;

if (req.httpVersionMajor < 1 || req.httpVersionMinor < 1) {
this.useChunkedEncodingByDefault = RegExpPrototypeTest(chunkExpression,
req.headers.te);
this.useChunkedEncodingByDefault = RegExpPrototypeExec(chunkExpression,
req.headers.te) !== null;
this.shouldKeepAlive = false;
}

Expand Down Expand Up @@ -957,7 +957,7 @@ function parserOnIncoming(server, socket, state, req, keepAlive) {
} else if (req.headers.expect !== undefined) {
handled = true;

if (RegExpPrototypeTest(continueExpression, req.headers.expect)) {
if (RegExpPrototypeExec(continueExpression, req.headers.expect) !== null) {
res._expect_continue = true;

if (server.listenerCount('checkContinue') > 0) {
Expand Down
17 changes: 9 additions & 8 deletions lib/_tls_wrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@ const {
ObjectSetPrototypeOf,
ReflectApply,
RegExp,
RegExpPrototypeTest,
StringPrototypeReplace,
RegExpPrototypeExec,
RegExpPrototypeSymbolReplace,
StringPrototypeReplaceAll,
StringPrototypeSlice,
Symbol,
SymbolFor,
Expand Down Expand Up @@ -426,8 +427,8 @@ function onerror(err) {
owner.destroy(err);
} else if (owner._tlsOptions?.isServer &&
owner._rejectUnauthorized &&
RegExpPrototypeTest(/peer did not return a certificate/,
err.message)) {
RegExpPrototypeExec(/peer did not return a certificate/,
err.message) !== null) {
// Ignore server's authorization errors
owner.destroy();
} else {
Expand Down Expand Up @@ -1448,9 +1449,9 @@ Server.prototype.addContext = function(servername, context) {
throw new ERR_TLS_REQUIRED_SERVER_NAME();
}

const re = new RegExp('^' + StringPrototypeReplace(
StringPrototypeReplace(servername, /([.^$+?\-\\[\]{}])/g, '\\$1'),
/\*/g, '[^.]*'
const re = new RegExp('^' + StringPrototypeReplaceAll(
RegExpPrototypeSymbolReplace(/([.^$+?\-\\[\]{}])/g, servername, '\\$1'),
'*', '[^.]*'
) + '$');
ArrayPrototypePush(this._contexts,
[re, tls.createSecureContext(context).context]);
Expand All @@ -1474,7 +1475,7 @@ function SNICallback(servername, callback) {

for (let i = contexts.length - 1; i >= 0; --i) {
const elem = contexts[i];
if (RegExpPrototypeTest(elem[0], servername)) {
if (RegExpPrototypeExec(elem[0], servername) !== null) {
callback(null, elem[1]);
return;
}
Expand Down
15 changes: 8 additions & 7 deletions lib/assert.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ const {
ObjectKeys,
ObjectPrototypeIsPrototypeOf,
ReflectApply,
RegExpPrototypeTest,
RegExpPrototypeExec,
RegExpPrototypeSymbolReplace,
SafeMap,
String,
StringPrototypeCharCodeAt,
Expand Down Expand Up @@ -345,7 +346,7 @@ function getErrMessage(message, fn) {
// Always normalize indentation, otherwise the message could look weird.
if (StringPrototypeIncludes(message, '\n')) {
if (EOL === '\r\n') {
message = StringPrototypeReplace(message, /\r\n/g, '\n');
message = RegExpPrototypeSymbolReplace(/\r\n/g, message, '\n');
}
const frames = StringPrototypeSplit(message, '\n');
message = ArrayPrototypeShift(frames);
Expand Down Expand Up @@ -606,7 +607,7 @@ class Comparison {
if (actual !== undefined &&
typeof actual[key] === 'string' &&
isRegExp(obj[key]) &&
RegExpPrototypeTest(obj[key], actual[key])) {
RegExpPrototypeExec(obj[key], actual[key]) !== null) {
this[key] = actual[key];
} else {
this[key] = obj[key];
Expand Down Expand Up @@ -652,7 +653,7 @@ function expectedException(actual, expected, message, fn) {
// Handle regular expressions.
if (isRegExp(expected)) {
const str = String(actual);
if (RegExpPrototypeTest(expected, str))
if (RegExpPrototypeExec(expected, str) !== null)
return;

if (!message) {
Expand Down Expand Up @@ -687,7 +688,7 @@ function expectedException(actual, expected, message, fn) {
for (const key of keys) {
if (typeof actual[key] === 'string' &&
isRegExp(expected[key]) &&
RegExpPrototypeTest(expected[key], actual[key])) {
RegExpPrototypeExec(expected[key], actual[key]) !== null) {
continue;
}
compareExceptionKey(actual, expected, key, message, keys, fn);
Expand Down Expand Up @@ -851,7 +852,7 @@ function hasMatchingError(actual, expected) {
if (typeof expected !== 'function') {
if (isRegExp(expected)) {
const str = String(actual);
return RegExpPrototypeTest(expected, str);
return RegExpPrototypeExec(expected, str) !== null;
}
throw new ERR_INVALID_ARG_TYPE(
'expected', ['Function', 'RegExp'], expected
Expand Down Expand Up @@ -1000,7 +1001,7 @@ function internalMatch(string, regexp, message, fn) {
}
const match = fn === assert.match;
if (typeof string !== 'string' ||
RegExpPrototypeTest(regexp, string) !== match) {
RegExpPrototypeExec(regexp, string) !== null !== match) {
if (message instanceof Error) {
throw message;
}
Expand Down
6 changes: 3 additions & 3 deletions lib/buffer.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ const {
ObjectDefineProperties,
ObjectDefineProperty,
ObjectSetPrototypeOf,
RegExpPrototypeSymbolReplace,
StringPrototypeCharCodeAt,
StringPrototypeReplace,
StringPrototypeSlice,
StringPrototypeToLowerCase,
StringPrototypeTrim,
Expand Down Expand Up @@ -840,8 +840,8 @@ Buffer.prototype[customInspectSymbol] = function inspect(recurseTimes, ctx) {
const max = INSPECT_MAX_BYTES;
const actualMax = MathMin(max, this.length);
const remaining = this.length - max;
let str = StringPrototypeTrim(StringPrototypeReplace(
this.hexSlice(0, actualMax), /(.{2})/g, '$1 '));
let str = StringPrototypeTrim(RegExpPrototypeSymbolReplace(
/(.{2})/g, this.hexSlice(0, actualMax), '$1 '));
if (remaining > 0)
str += ` ... ${remaining} more byte${remaining > 1 ? 's' : ''}`;
// Inspect special properties as well, if possible.
Expand Down
4 changes: 2 additions & 2 deletions lib/child_process.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const {
ObjectAssign,
ObjectDefineProperty,
ObjectPrototypeHasOwnProperty,
RegExpPrototypeTest,
RegExpPrototypeExec,
SafeSet,
StringPrototypeSlice,
StringPrototypeToUpperCase,
Expand Down Expand Up @@ -592,7 +592,7 @@ function normalizeSpawnArguments(file, args, options) {
else
file = process.env.comspec || 'cmd.exe';
// '/d /s /c' is used only for cmd.exe.
if (RegExpPrototypeTest(/^(?:.*\\)?cmd(?:\.exe)?$/i, file)) {
if (RegExpPrototypeExec(/^(?:.*\\)?cmd(?:\.exe)?$/i, file) !== null) {
args = ['/d', '/s', '/c', `"${command}"`];
windowsVerbatimArguments = true;
} else {
Expand Down
6 changes: 3 additions & 3 deletions lib/internal/blob.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ const {
PromiseReject,
SafePromisePrototypeFinally,
ReflectConstruct,
RegExpPrototypeExec,
RegExpPrototypeSymbolReplace,
RegExpPrototypeTest,
StringPrototypeToLowerCase,
StringPrototypeSplit,
Symbol,
Expand Down Expand Up @@ -164,7 +164,7 @@ class Blob {
this[kLength] = length;

type = `${type}`;
this[kType] = RegExpPrototypeTest(disallowedTypeCharacters, type) ?
this[kType] = RegExpPrototypeExec(disallowedTypeCharacters, type) !== null ?
'' : StringPrototypeToLowerCase(type);

// eslint-disable-next-line no-constructor-return
Expand Down Expand Up @@ -246,7 +246,7 @@ class Blob {
end |= 0;

contentType = `${contentType}`;
if (RegExpPrototypeTest(disallowedTypeCharacters, contentType)) {
if (RegExpPrototypeExec(disallowedTypeCharacters, contentType) !== null) {
contentType = '';
} else {
contentType = StringPrototypeToLowerCase(contentType);
Expand Down
6 changes: 3 additions & 3 deletions lib/internal/cluster/primary.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const {
ArrayPrototypeSome,
ObjectKeys,
ObjectValues,
RegExpPrototypeTest,
RegExpPrototypeExec,
SafeMap,
StringPrototypeStartsWith,
} = primordials;
Expand Down Expand Up @@ -121,8 +121,8 @@ function createWorkerProcess(id, env) {
const nodeOptions = process.env.NODE_OPTIONS || '';

if (ArrayPrototypeSome(execArgv,
(arg) => RegExpPrototypeTest(debugArgRegex, arg)) ||
RegExpPrototypeTest(debugArgRegex, nodeOptions)) {
(arg) => RegExpPrototypeExec(debugArgRegex, arg) !== null) ||
RegExpPrototypeExec(debugArgRegex, nodeOptions) !== null) {
let inspectPort;
if ('inspectPort' in cluster.settings) {
if (typeof cluster.settings.inspectPort === 'function')
Expand Down
4 changes: 2 additions & 2 deletions lib/internal/console/constructor.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@ const {
ReflectApply,
ReflectConstruct,
ReflectOwnKeys,
RegExpPrototypeSymbolReplace,
SafeArrayIterator,
SafeMap,
SafeWeakMap,
StringPrototypeIncludes,
StringPrototypePadStart,
StringPrototypeRepeat,
StringPrototypeReplace,
StringPrototypeSlice,
StringPrototypeSplit,
Symbol,
Expand Down Expand Up @@ -279,7 +279,7 @@ ObjectDefineProperties(Console.prototype, {

if (groupIndent.length !== 0) {
if (StringPrototypeIncludes(string, '\n')) {
string = StringPrototypeReplace(string, /\n/g, `\n${groupIndent}`);
string = RegExpPrototypeSymbolReplace(/\n/g, string, `\n${groupIndent}`);
}
string = groupIndent + string;
}
Expand Down
11 changes: 5 additions & 6 deletions lib/internal/debugger/inspect.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,8 @@ const {
PromisePrototypeThen,
PromiseResolve,
Proxy,
RegExpPrototypeSymbolMatch,
RegExpPrototypeExec,
RegExpPrototypeSymbolSplit,
RegExpPrototypeTest,
StringPrototypeEndsWith,
StringPrototypeSplit,
} = primordials;
Expand Down Expand Up @@ -91,7 +90,7 @@ async function runScript(script, scriptArgs, inspectHost, inspectPort,
return new Promise((resolve) => {
function waitForListenHint(text) {
output += text;
const debug = RegExpPrototypeSymbolMatch(debugRegex, output);
const debug = RegExpPrototypeExec(debugRegex, output);
if (debug) {
const host = debug[1];
const port = Number(debug[2]);
Expand Down Expand Up @@ -282,8 +281,8 @@ function parseArgv(args) {
let script = target;
let scriptArgs = args;

const hostMatch = RegExpPrototypeSymbolMatch(/^([^:]+):(\d+)$/, target);
const portMatch = RegExpPrototypeSymbolMatch(/^--port=(\d+)$/, target);
const hostMatch = RegExpPrototypeExec(/^([^:]+):(\d+)$/, target);
const portMatch = RegExpPrototypeExec(/^--port=(\d+)$/, target);

if (hostMatch) {
// Connecting to remote debugger
Expand All @@ -296,7 +295,7 @@ function parseArgv(args) {
port = Number(portMatch[1]);
script = args[0];
scriptArgs = ArrayPrototypeSlice(args, 1);
} else if (args.length === 1 && RegExpPrototypeTest(/^\d+$/, args[0]) &&
} else if (args.length === 1 && RegExpPrototypeExec(/^\d+$/, args[0]) !== null &&
target === '-p') {
// Start debugger against a given pid
const pid = Number(args[0]);
Expand Down
8 changes: 4 additions & 4 deletions lib/internal/debugger/inspect_repl.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const {
PromiseResolve,
ReflectGetOwnPropertyDescriptor,
ReflectOwnKeys,
RegExpPrototypeSymbolMatch,
RegExpPrototypeExec,
RegExpPrototypeSymbolReplace,
SafeMap,
SafePromiseAll,
Expand Down Expand Up @@ -113,7 +113,7 @@ takeHeapSnapshot(filepath = 'node.heapsnapshot')
const FUNCTION_NAME_PATTERN = /^(?:function\*? )?([^(\s]+)\(/;
function extractFunctionName(description) {
const fnNameMatch =
RegExpPrototypeSymbolMatch(FUNCTION_NAME_PATTERN, description);
RegExpPrototypeExec(FUNCTION_NAME_PATTERN, description);
return fnNameMatch ? `: ${fnNameMatch[1]}` : '';
}

Expand Down Expand Up @@ -170,7 +170,7 @@ function markSourceColumn(sourceText, position, useColors) {

function extractErrorMessage(stack) {
if (!stack) return '<unknown>';
const m = RegExpPrototypeSymbolMatch(/^\w+: ([^\n]+)/, stack);
const m = RegExpPrototypeExec(/^\w+: ([^\n]+)/, stack);
return m?.[1] ?? stack;
}

Expand Down Expand Up @@ -574,7 +574,7 @@ function createRepl(inspector) {
function prepareControlCode(input) {
if (input === '\n') return lastCommand;
// Add parentheses: exec process.title => exec("process.title");
const match = RegExpPrototypeSymbolMatch(/^\s*(?:exec|p)\s+([^\n]*)/, input);
const match = RegExpPrototypeExec(/^\s*(?:exec|p)\s+([^\n]*)/, input);
if (match) {
lastCommand = `exec(${JSONStringify(match[1])})`;
} else {
Expand Down
Loading

0 comments on commit 9994a1b

Please sign in to comment.