Skip to content

Commit

Permalink
lib: avoid unsafe String methods that depend on RegExp prototype methods
Browse files Browse the repository at this point in the history
  • Loading branch information
ExE-Boss committed Dec 21, 2020
1 parent ce658bd commit 4ca6ac7
Show file tree
Hide file tree
Showing 23 changed files with 120 additions and 111 deletions.
18 changes: 10 additions & 8 deletions lib/_tls_common.js
Expand Up @@ -27,7 +27,7 @@ const {
ArrayPrototypeJoin,
ArrayPrototypePush,
ObjectCreate,
StringPrototypeReplace,
RegExpPrototypeSymbolReplace,
StringPrototypeSplit,
StringPrototypeStartsWith,
} = primordials;
Expand Down Expand Up @@ -394,13 +394,15 @@ exports.translatePeerCertificate = function translatePeerCertificate(c) {
c.infoAccess = ObjectCreate(null);

// XXX: More key validation?
StringPrototypeReplace(info, /([^\n:]*):([^\n]*)(?:\n|$)/g,
(all, key, val) => {
if (key in c.infoAccess)
ArrayPrototypePush(c.infoAccess[key], val);
else
c.infoAccess[key] = [val];
});
RegExpPrototypeSymbolReplace(
/([^\n:]*):([^\n]*)(?:\n|$)/g,
info,
(all, key, val) => {
if (key in c.infoAccess)
ArrayPrototypePush(c.infoAccess[key], val);
else
c.infoAccess[key] = [val];
});
}
return c;
};
10 changes: 6 additions & 4 deletions lib/_tls_wrap.js
Expand Up @@ -31,8 +31,9 @@ const {
ObjectSetPrototypeOf,
ReflectApply,
RegExp,
RegExpPrototypeSymbolReplace,
RegExpPrototypeTest,
StringPrototypeReplace,
StringPrototypeReplaceAll,
StringPrototypeSlice,
Symbol,
SymbolFor,
Expand Down Expand Up @@ -1433,9 +1434,10 @@ 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 Down
12 changes: 7 additions & 5 deletions lib/assert.js
Expand Up @@ -35,13 +35,14 @@ const {
ObjectKeys,
ObjectPrototypeIsPrototypeOf,
ReflectApply,
RegExpPrototypeSymbolReplace,
RegExpPrototypeTest,
SafeMap,
String,
StringPrototypeCharCodeAt,
StringPrototypeIncludes,
StringPrototypeIndexOf,
StringPrototypeReplace,
StringPrototypeReplaceAll,
StringPrototypeSlice,
StringPrototypeSplit,
StringPrototypeStartsWith,
Expand Down Expand Up @@ -271,9 +272,10 @@ function parseCode(code, offset) {

return [
node.node.start,
StringPrototypeReplace(StringPrototypeSlice(code,
node.node.start, node.node.end),
escapeSequencesRegExp, escapeFn)
RegExpPrototypeSymbolReplace(
escapeSequencesRegExp,
StringPrototypeSlice(code, node.node.start, node.node.end),
escapeFn)
];
}

Expand Down Expand Up @@ -345,7 +347,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 = StringPrototypeReplaceAll(message, '\r\n', '\n');
}
const frames = StringPrototypeSplit(message, '\n');
message = ArrayPrototypeShift(frames);
Expand Down
6 changes: 3 additions & 3 deletions lib/buffer.js
Expand Up @@ -36,8 +36,8 @@ const {
ObjectDefineProperties,
ObjectDefineProperty,
ObjectSetPrototypeOf,
RegExpPrototypeSymbolReplace,
StringPrototypeCharCodeAt,
StringPrototypeReplace,
StringPrototypeSlice,
StringPrototypeToLowerCase,
StringPrototypeTrim,
Expand Down Expand Up @@ -812,8 +812,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/internal/console/constructor.js
Expand Up @@ -25,7 +25,7 @@ const {
StringPrototypeIncludes,
StringPrototypePadStart,
StringPrototypeRepeat,
StringPrototypeReplace,
StringPrototypeReplaceAll,
StringPrototypeSlice,
StringPrototypeSplit,
Symbol,
Expand Down Expand Up @@ -266,7 +266,7 @@ ObjectDefineProperties(Console.prototype, {

if (groupIndent.length !== 0) {
if (StringPrototypeIncludes(string, '\n')) {
string = StringPrototypeReplace(string, /\n/g, `\n${groupIndent}`);
string = StringPrototypeReplaceAll(string, '\n', `\n${groupIndent}`);
}
string = groupIndent + string;
}
Expand Down
11 changes: 6 additions & 5 deletions lib/internal/dns/utils.js
Expand Up @@ -8,8 +8,8 @@ const {
ArrayPrototypePush,
FunctionPrototypeBind,
NumberParseInt,
StringPrototypeMatch,
StringPrototypeReplace,
RegExpPrototypeExec,
RegExpPrototypeSymbolReplace,
} = primordials;

const errors = require('internal/errors');
Expand Down Expand Up @@ -79,21 +79,22 @@ class Resolver {
if (ipVersion !== 0)
return ArrayPrototypePush(newSet, [ipVersion, serv, IANA_DNS_PORT]);

const match = StringPrototypeMatch(serv, IPv6RE);
const match = RegExpPrototypeExec(IPv6RE, serv);

// Check for an IPv6 in brackets.
if (match) {
ipVersion = isIP(match[1]);

if (ipVersion !== 0) {
const port = NumberParseInt(
StringPrototypeReplace(serv, addrSplitRE, '$2')) || IANA_DNS_PORT;
RegExpPrototypeSymbolReplace(addrSplitRE, serv, '$2')
) || IANA_DNS_PORT;
return ArrayPrototypePush(newSet, [ipVersion, match[1], port]);
}
}

// addr::port
const addrSplitMatch = StringPrototypeMatch(serv, addrSplitRE);
const addrSplitMatch = RegExpPrototypeExec(addrSplitRE, serv);

if (addrSplitMatch) {
const hostIP = addrSplitMatch[1];
Expand Down
4 changes: 2 additions & 2 deletions lib/internal/errors.js
Expand Up @@ -34,13 +34,13 @@ const {
ObjectKeys,
RangeError,
ReflectApply,
RegExpPrototypeExec,
RegExpPrototypeTest,
SafeMap,
SafeWeakMap,
String,
StringPrototypeEndsWith,
StringPrototypeIncludes,
StringPrototypeMatch,
StringPrototypeSlice,
StringPrototypeSplit,
StringPrototypeStartsWith,
Expand Down Expand Up @@ -381,7 +381,7 @@ function getMessage(key, args, self) {
}

const expectedLength =
(StringPrototypeMatch(msg, /%[dfijoOs]/g) || []).length;
(RegExpPrototypeExec(/%[dfijoOs]/g, msg) || []).length;
assert(
expectedLength === args.length,
`Code: ${key}; The provided arguments length (${args.length}) does not ` +
Expand Down
4 changes: 2 additions & 2 deletions lib/internal/fs/utils.js
Expand Up @@ -18,7 +18,7 @@ const {
ReflectOwnKeys,
StringPrototypeEndsWith,
StringPrototypeIncludes,
StringPrototypeReplace,
StringPrototypeReplaceAll,
Symbol,
TypedArrayPrototypeIncludes,
} = primordials;
Expand Down Expand Up @@ -369,7 +369,7 @@ function preprocessSymlinkDestination(path, type, linkPath) {
return pathModule.toNamespacedPath(path);
}
// Windows symlinks don't tolerate forward slashes.
return StringPrototypeReplace(path, /\//g, '\\');
return StringPrototypeReplaceAll(path, '/', '\\');
}

// Constructor for file stats.
Expand Down
12 changes: 6 additions & 6 deletions lib/internal/main/print_help.js
Expand Up @@ -8,9 +8,9 @@ const {
MathMax,
ObjectKeys,
RegExp,
RegExpPrototypeSymbolReplace,
StringPrototypeTrimLeft,
StringPrototypeRepeat,
StringPrototypeReplace,
SafeMap,
} = primordials;

Expand Down Expand Up @@ -72,14 +72,14 @@ const envVars = new SafeMap(ArrayPrototypeConcat([


function indent(text, depth) {
return StringPrototypeReplace(text, /^/gm, StringPrototypeRepeat(' ', depth));
return RegExpPrototypeSymbolReplace(/^/gm, text, StringPrototypeRepeat(' ', depth));
}

function fold(text, width) {
return StringPrototypeReplace(text,
new RegExp(`([^\n]{0,${width}})( |$)`, 'g'),
(_, newLine, end) =>
newLine + (end === ' ' ? '\n' : ''));
return RegExpPrototypeSymbolReplace(
new RegExp(`([^\n]{0,${width}})( |$)`, 'g'),
text,
(_, newLine, end) => newLine + (end === ' ' ? '\n' : ''));
}

function getArgDescription(type) {
Expand Down
4 changes: 2 additions & 2 deletions lib/internal/modules/cjs/loader.js
Expand Up @@ -46,6 +46,7 @@ const {
ObjectSetPrototypeOf,
ReflectApply,
ReflectSet,
RegExpPrototypeExec,
RegExpPrototypeTest,
SafeMap,
SafeWeakMap,
Expand All @@ -55,7 +56,6 @@ const {
StringPrototypeEndsWith,
StringPrototypeLastIndexOf,
StringPrototypeIndexOf,
StringPrototypeMatch,
StringPrototypeSlice,
StringPrototypeSplit,
StringPrototypeStartsWith,
Expand Down Expand Up @@ -463,7 +463,7 @@ const EXPORTS_PATTERN = /^((?:@[^/\\%]+\/)?[^./\\%][^/\\%]*)(\/.*)?$/;
function resolveExports(nmPath, request) {
// The implementation's behavior is meant to mirror resolution in ESM.
const [, name, expansion = ''] =
StringPrototypeMatch(request, EXPORTS_PATTERN) || [];
RegExpPrototypeExec(EXPORTS_PATTERN, request) || [];
if (!name)
return;
const pkgPath = path.resolve(nmPath, name);
Expand Down
13 changes: 7 additions & 6 deletions lib/internal/modules/esm/module_job.js
Expand Up @@ -10,10 +10,10 @@ const {
PromiseResolve,
PromisePrototypeCatch,
ReflectApply,
RegExpPrototypeExec,
RegExpPrototypeSymbolReplace,
SafeSet,
StringPrototypeIncludes,
StringPrototypeMatch,
StringPrototypeReplace,
StringPrototypeSplit,
} = primordials;

Expand Down Expand Up @@ -109,8 +109,9 @@ class ModuleJob {
' does not provide an export named')) {
const splitStack = StringPrototypeSplit(e.stack, '\n');
const parentFileUrl = splitStack[0];
const [, childSpecifier, name] = StringPrototypeMatch(e.message,
/module '(.*)' does not provide an export named '(.+)'/);
const [, childSpecifier, name] = RegExpPrototypeExec(
/module '(.*)' does not provide an export named '(.+)'/,
e.message);
const childFileURL =
await this.loader.resolve(childSpecifier, parentFileUrl);
const format = await this.loader.getFormat(childFileURL);
Expand All @@ -120,9 +121,9 @@ class ModuleJob {
// line which causes the error. For multi-line import statements we
// cannot generate an equivalent object descructuring assignment by
// just parsing the error stack.
const oneLineNamedImports = StringPrototypeMatch(importStatement, /{.*}/);
const oneLineNamedImports = RegExpPrototypeExec(/{.*}/, importStatement);
const destructuringAssignment = oneLineNamedImports &&
StringPrototypeReplace(oneLineNamedImports, /\s+as\s+/g, ': ');
RegExpPrototypeSymbolReplace(/\s+as\s+/g, oneLineNamedImports, ': ');
e.message = `Named export '${name}' not found. The requested module` +
` '${childSpecifier}' is a CommonJS module, which may not support` +
' all module.exports as named exports.\nCommonJS modules can ' +
Expand Down
12 changes: 4 additions & 8 deletions lib/internal/modules/esm/resolve.js
Expand Up @@ -9,15 +9,14 @@ const {
ObjectFreeze,
ObjectGetOwnPropertyNames,
ObjectPrototypeHasOwnProperty,
RegExp,
RegExpPrototypeTest,
SafeMap,
SafeSet,
String,
StringPrototypeEndsWith,
StringPrototypeIndexOf,
StringPrototypeLastIndexOf,
StringPrototypeReplace,
StringPrototypeReplaceAll,
StringPrototypeSlice,
StringPrototypeSplit,
StringPrototypeStartsWith,
Expand Down Expand Up @@ -343,8 +342,6 @@ function throwInvalidPackageTarget(
}

const invalidSegmentRegEx = /(^|\\|\/)(\.\.?|node_modules)(\\|\/|$)/;
const patternRegEx = /\*/g;

function resolvePackageTargetString(
target, subpath, match, packageJSONUrl, base, pattern, internal, conditions) {
if (subpath !== '' && !pattern && target[target.length - 1] !== '/')
Expand All @@ -360,7 +357,7 @@ function resolvePackageTargetString(
} catch {}
if (!isURL) {
const exportTarget = pattern ?
StringPrototypeReplace(target, patternRegEx, subpath) :
StringPrototypeReplaceAll(target, '*', subpath) :
target + subpath;
return packageResolve(exportTarget, packageJSONUrl, conditions);
}
Expand All @@ -384,8 +381,7 @@ function resolvePackageTargetString(
throwInvalidSubpath(match + subpath, packageJSONUrl, internal, base);

if (pattern)
return new URL(StringPrototypeReplace(resolved.href, patternRegEx,
subpath));
return new URL(StringPrototypeReplaceAll(resolved.href, '*', subpath));
return new URL(subpath, resolved);
}

Expand Down Expand Up @@ -779,7 +775,7 @@ function resolveAsCommonJS(specifier, parentURL) {
// Normalize the path separator to give a valid suggestion
// on Windows
if (process.platform === 'win32') {
found = StringPrototypeReplace(found, new RegExp(`\\${sep}`, 'g'), '/');
found = StringPrototypeReplaceAll(found, sep, '/');
}
return found;
} catch {
Expand Down
7 changes: 3 additions & 4 deletions lib/internal/modules/esm/translators.js
Expand Up @@ -14,7 +14,7 @@ const {
RegExpPrototypeTest,
SafeMap,
SafeSet,
StringPrototypeReplace,
StringPrototypeReplaceAll,
StringPrototypeSlice,
StringPrototypeSplit,
StringPrototypeStartsWith,
Expand Down Expand Up @@ -174,13 +174,12 @@ function enrichCJSError(err) {

// Strategy for loading a node-style CommonJS module
const isWindows = process.platform === 'win32';
const winSepRegEx = /\//g;
translators.set('commonjs', async function commonjsStrategy(url, isMain) {
debug(`Translating CJSModule ${url}`);

let filename = internalURLModule.fileURLToPath(new URL(url));
if (isWindows)
filename = StringPrototypeReplace(filename, winSepRegEx, '\\');
filename = StringPrototypeReplaceAll(filename, '/', '\\');

if (!cjsParse) await initCJSParse();
const { module, exportNames } = cjsPreparseModuleExports(filename);
Expand Down Expand Up @@ -299,7 +298,7 @@ translators.set('json', async function jsonStrategy(url) {
let module;
if (pathname) {
modulePath = isWindows ?
StringPrototypeReplace(pathname, winSepRegEx, '\\') : pathname;
StringPrototypeReplaceAll(pathname, '/', '\\') : pathname;
module = CJSModule._cache[modulePath];
if (module && module.loaded) {
const exports = module.exports;
Expand Down

0 comments on commit 4ca6ac7

Please sign in to comment.