Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lib: refactor to avoid unsafe regex primordials #43475

Merged
merged 3 commits into from Jun 27, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions lib/_http_client.js
Expand Up @@ -31,7 +31,7 @@ const {
ObjectKeys,
ObjectSetPrototypeOf,
ReflectApply,
RegExpPrototypeTest,
RegExpPrototypeExec,
String,
StringPrototypeCharCodeAt,
StringPrototypeIncludes,
Expand Down Expand Up @@ -165,7 +165,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
Expand Up @@ -24,7 +24,7 @@
const {
MathMin,
Symbol,
RegExpPrototypeTest,
RegExpPrototypeExec,
} = primordials;
const { setImmediate } = require('timers');

Expand Down Expand Up @@ -208,7 +208,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 @@ -219,7 +219,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
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
Expand Up @@ -26,7 +26,7 @@ const {
Error,
ObjectKeys,
ObjectSetPrototypeOf,
RegExpPrototypeTest,
RegExpPrototypeExec,
ReflectApply,
Symbol,
SymbolFor,
Expand Down Expand Up @@ -193,8 +193,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 @@ -971,7 +971,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
Expand Up @@ -31,8 +31,9 @@ const {
ObjectSetPrototypeOf,
ReflectApply,
RegExp,
RegExpPrototypeTest,
StringPrototypeReplace,
RegExpPrototypeExec,
RegExpPrototypeSymbolReplace,
StringPrototypeReplaceAll,
StringPrototypeSlice,
Symbol,
SymbolFor,
Expand Down Expand Up @@ -425,8 +426,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 @@ -1447,9 +1448,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 @@ -1473,7 +1474,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
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
Expand Up @@ -37,8 +37,8 @@ const {
ObjectDefineProperties,
ObjectDefineProperty,
ObjectSetPrototypeOf,
RegExpPrototypeSymbolReplace,
StringPrototypeCharCodeAt,
StringPrototypeReplace,
StringPrototypeSlice,
StringPrototypeToLowerCase,
StringPrototypeTrim,
Expand Down Expand Up @@ -837,8 +837,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
Expand Up @@ -36,7 +36,7 @@ const {
ObjectAssign,
ObjectDefineProperty,
ObjectPrototypeHasOwnProperty,
RegExpPrototypeTest,
RegExpPrototypeExec,
SafeSet,
StringPrototypeSlice,
StringPrototypeToUpperCase,
Expand Down Expand Up @@ -571,7 +571,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
Expand Up @@ -9,8 +9,8 @@ const {
PromiseReject,
SafePromisePrototypeFinally,
ReflectConstruct,
RegExpPrototypeExec,
RegExpPrototypeSymbolReplace,
RegExpPrototypeTest,
StringPrototypeToLowerCase,
StringPrototypeSplit,
Symbol,
Expand Down Expand Up @@ -165,7 +165,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 @@ -247,7 +247,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
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
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
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
Expand Up @@ -29,7 +29,7 @@ const {
PromiseResolve,
ReflectGetOwnPropertyDescriptor,
ReflectOwnKeys,
RegExpPrototypeSymbolMatch,
RegExpPrototypeExec,
RegExpPrototypeSymbolReplace,
SafeArrayIterator,
SafeMap,
Expand Down Expand Up @@ -114,7 +114,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 @@ -171,7 +171,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 @@ -578,7 +578,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