summaryrefslogtreecommitdiff
path: root/lib/internal/policy
diff options
context:
space:
mode:
authorBradley Farias <bradley.meck@gmail.com>2019-08-26 10:40:45 -0500
committerBradley Farias <bradley.meck@gmail.com>2019-09-03 11:12:05 -0500
commit6ce87c027dc2a16e1b8d85c753b52270ae0c6054 (patch)
tree420c362071bd29603eb52eb1ce08da56a36853f9 /lib/internal/policy
parentf2c573cf8bedea85ab4505c839b2332517e4b0b9 (diff)
downloadandroid-node-v8-6ce87c027dc2a16e1b8d85c753b52270ae0c6054.tar.gz
android-node-v8-6ce87c027dc2a16e1b8d85c753b52270ae0c6054.tar.bz2
android-node-v8-6ce87c027dc2a16e1b8d85c753b52270ae0c6054.zip
policy: minor perf opts and cleanup
PR-URL: https://github.com/nodejs/node/pull/29322 Reviewed-By: James M Snell <jasnell@gmail.com>
Diffstat (limited to 'lib/internal/policy')
-rw-r--r--lib/internal/policy/manifest.js137
-rw-r--r--lib/internal/policy/sri.js12
2 files changed, 92 insertions, 57 deletions
diff --git a/lib/internal/policy/manifest.js b/lib/internal/policy/manifest.js
index f91eb5b012..118a89efa6 100644
--- a/lib/internal/policy/manifest.js
+++ b/lib/internal/policy/manifest.js
@@ -1,10 +1,11 @@
'use strict';
const {
- SafeMap,
- SafeWeakMap,
+ Map,
+ MapPrototype,
Object,
RegExpPrototype,
+ SafeMap,
uncurryThis
} = primordials;
const {
@@ -21,16 +22,13 @@ const debug = require('internal/util/debuglog').debuglog('policy');
const SRI = require('internal/policy/sri');
const crypto = require('crypto');
const { Buffer } = require('buffer');
-const { URL } = require('url');
+const { URL } = require('internal/url');
const { createHash, timingSafeEqual } = crypto;
const HashUpdate = uncurryThis(crypto.Hash.prototype.update);
const HashDigest = uncurryThis(crypto.Hash.prototype.digest);
const BufferEquals = uncurryThis(Buffer.prototype.equals);
const BufferToString = uncurryThis(Buffer.prototype.toString);
const { entries } = Object;
-const kIntegrities = new SafeWeakMap();
-const kDependencies = new SafeWeakMap();
-const kReactions = new SafeWeakMap();
const kRelativeURLStringPattern = /^\.{0,2}\//;
const { getOptionValue } = require('internal/options');
const shouldAbortOnUncaughtException =
@@ -54,13 +52,12 @@ function REACTION_LOG(error) {
}
class Manifest {
+ #integrities = new SafeMap();
+ #dependencies = new SafeMap();
+ #reaction = null;
constructor(obj, manifestURL) {
- const integrities = {
- __proto__: null,
- };
- const dependencies = {
- __proto__: null,
- };
+ const integrities = this.#integrities;
+ const dependencies = this.#dependencies;
let reaction = REACTION_THROW;
if (obj.onerror) {
@@ -75,23 +72,33 @@ class Manifest {
}
}
- kReactions.set(this, reaction);
+ this.#reaction = reaction;
const manifestEntries = entries(obj.resources);
+ const parsedURLs = new SafeMap();
for (var i = 0; i < manifestEntries.length; i++) {
- let url = manifestEntries[i][0];
- const originalURL = url;
- if (RegExpPrototype.test(kRelativeURLStringPattern, url)) {
- url = new URL(url, manifestURL).href;
+ let resourceHREF = manifestEntries[i][0];
+ const originalHREF = resourceHREF;
+ let resourceURL;
+ if (parsedURLs.has(resourceHREF)) {
+ resourceURL = parsedURLs.get(resourceHREF);
+ resourceHREF = resourceURL.href;
+ } else if (
+ RegExpPrototype.test(kRelativeURLStringPattern, resourceHREF)
+ ) {
+ resourceURL = new URL(resourceHREF, manifestURL);
+ resourceHREF = resourceURL.href;
+ parsedURLs.set(originalHREF, resourceURL);
+ parsedURLs.set(resourceHREF, resourceURL);
}
let integrity = manifestEntries[i][1].integrity;
if (!integrity) integrity = null;
if (integrity != null) {
- debug(`Manifest contains integrity for url ${originalURL}`);
+ debug(`Manifest contains integrity for url ${originalHREF}`);
if (typeof integrity === 'string') {
const sri = Object.freeze(SRI.parse(integrity));
- if (url in integrities) {
- const old = integrities[url];
+ if (integrities.has(resourceHREF)) {
+ const old = integrities.get(resourceHREF);
let mismatch = false;
if (old.length !== sri.length) {
@@ -112,14 +119,16 @@ class Manifest {
}
if (mismatch) {
- throw new ERR_MANIFEST_INTEGRITY_MISMATCH(url);
+ throw new ERR_MANIFEST_INTEGRITY_MISMATCH(resourceURL);
}
}
- integrities[url] = sri;
+ integrities.set(resourceHREF, sri);
} else if (integrity === true) {
- integrities[url] = true;
+ integrities.set(resourceHREF, true);
} else {
- throw new ERR_MANIFEST_INVALID_RESOURCE_FIELD(url, 'integrity');
+ throw new ERR_MANIFEST_INVALID_RESOURCE_FIELD(
+ resourceHREF,
+ 'integrity');
}
}
@@ -128,50 +137,72 @@ class Manifest {
dependencyMap = {};
}
if (typeof dependencyMap === 'object' && !Array.isArray(dependencyMap)) {
- dependencies[url] = new SafeMap(Object.entries(dependencyMap).map(
- ([ from, to ]) => {
+ /**
+ * @returns {true | URL}
+ */
+ const dependencyRedirectList = (toSpecifier) => {
+ if (toSpecifier in dependencyMap !== true) {
+ return null;
+ } else {
+ const to = dependencyMap[toSpecifier];
if (to === true) {
- return [from, to];
+ return true;
}
- if (canBeRequiredByUsers(to)) {
- return [from, `node:${to}`];
+ if (parsedURLs.has(to)) {
+ return parsedURLs.get(to);
+ } else if (canBeRequiredByUsers(to)) {
+ const href = `node:${to}`;
+ const resolvedURL = new URL(href);
+ parsedURLs.set(to, resolvedURL);
+ parsedURLs.set(href, resolvedURL);
+ return resolvedURL;
} else if (RegExpPrototype.test(kRelativeURLStringPattern, to)) {
- return [from, new URL(to, manifestURL).href];
+ const resolvedURL = new URL(to, manifestURL);
+ const href = resourceURL.href;
+ parsedURLs.set(to, resolvedURL);
+ parsedURLs.set(href, resolvedURL);
+ return resolvedURL;
}
- return [from, new URL(to).href];
- })
- );
+ const resolvedURL = new URL(to);
+ const href = resourceURL.href;
+ parsedURLs.set(to, resolvedURL);
+ parsedURLs.set(href, resolvedURL);
+ return resolvedURL;
+ }
+ };
+ dependencies.set(resourceHREF, dependencyRedirectList);
} else if (dependencyMap === true) {
- dependencies[url] = true;
+ const arbitraryDependencies = () => true;
+ dependencies.set(resourceHREF, arbitraryDependencies);
} else {
- throw new ERR_MANIFEST_INVALID_RESOURCE_FIELD(url, 'dependencies');
+ throw new ERR_MANIFEST_INVALID_RESOURCE_FIELD(
+ resourceHREF,
+ 'dependencies');
}
}
- Object.freeze(integrities);
- kIntegrities.set(this, integrities);
- Object.freeze(dependencies);
- kDependencies.set(this, dependencies);
Object.freeze(this);
}
- getRedirects(requester) {
- const dependencies = kDependencies.get(this);
- if (dependencies && requester in dependencies) {
+ getRedirector(requester) {
+ requester = `${requester}`;
+ const dependencies = this.#dependencies;
+ if (dependencies.has(requester)) {
return {
- map: dependencies[requester],
- reaction: kReactions.get(this)
+ resolve: (to) => dependencies.get(requester)(`${to}`),
+ reaction: this.#reaction
};
}
return null;
}
assertIntegrity(url, content) {
- debug(`Checking integrity of ${url}`);
- const integrities = kIntegrities.get(this);
- const realIntegrities = new SafeMap();
+ const href = `${url}`;
+ debug(`Checking integrity of ${href}`);
+ const integrities = this.#integrities;
+ const realIntegrities = new Map();
- if (integrities && url in integrities) {
- const integrityEntries = integrities[url];
+ if (integrities.has(href)) {
+ const integrityEntries = integrities.get(href);
if (integrityEntries === true) return true;
// Avoid clobbered Symbol.iterator
for (var i = 0; i < integrityEntries.length; i++) {
@@ -186,11 +217,15 @@ class Manifest {
timingSafeEqual(digest, expected)) {
return true;
}
- realIntegrities.set(algorithm, BufferToString(digest, 'base64'));
+ MapPrototype.set(
+ realIntegrities,
+ algorithm,
+ BufferToString(digest, 'base64')
+ );
}
}
const error = new ERR_MANIFEST_ASSERT_INTEGRITY(url, realIntegrities);
- kReactions.get(this)(error);
+ this.#reaction(error);
}
}
diff --git a/lib/internal/policy/sri.js b/lib/internal/policy/sri.js
index 55c3c0c507..877c96a6f7 100644
--- a/lib/internal/policy/sri.js
+++ b/lib/internal/policy/sri.js
@@ -13,16 +13,16 @@ const {
} = require('internal/errors').codes;
const kWSP = '[\\x20\\x09]';
const kVCHAR = '[\\x21-\\x7E]';
-const kHASH_ALGO = 'sha256|sha384|sha512';
+const kHASH_ALGO = 'sha(?:256|384|512)';
// Base64
const kHASH_VALUE = '[A-Za-z0-9+/]+[=]{0,2}';
const kHASH_EXPRESSION = `(${kHASH_ALGO})-(${kHASH_VALUE})`;
const kOPTION_EXPRESSION = `(${kVCHAR}*)`;
const kHASH_WITH_OPTIONS = `${kHASH_EXPRESSION}(?:[?](${kOPTION_EXPRESSION}))?`;
-const kSRIPattern = new RegExp(`(${kWSP}*)(?:${kHASH_WITH_OPTIONS})`, 'g');
+const kSRIPattern = RegExp(`(${kWSP}*)(?:${kHASH_WITH_OPTIONS})`, 'g');
const { freeze } = Object;
Object.seal(kSRIPattern);
-const kAllWSP = new RegExp(`^${kWSP}*$`);
+const kAllWSP = RegExp(`^${kWSP}*$`);
Object.seal(kAllWSP);
const BufferFrom = require('buffer').Buffer.from;
@@ -34,10 +34,10 @@ const parse = (str) => {
const entries = [];
while (match = RegExpPrototype.exec(kSRIPattern, str)) {
if (match.index !== prevIndex) {
- throw new ERR_SRI_PARSE(str, prevIndex);
+ throw new ERR_SRI_PARSE(str, str.charAt(prevIndex), prevIndex);
}
if (entries.length > 0 && match[1] === '') {
- throw new ERR_SRI_PARSE(str, prevIndex);
+ throw new ERR_SRI_PARSE(str, str.charAt(prevIndex), prevIndex);
}
// Avoid setters being fired
@@ -56,7 +56,7 @@ const parse = (str) => {
if (prevIndex !== str.length) {
if (!RegExpPrototype.test(kAllWSP, StringPrototype.slice(str, prevIndex))) {
- throw new ERR_SRI_PARSE(str, prevIndex);
+ throw new ERR_SRI_PARSE(str, str.charAt(prevIndex), prevIndex);
}
}
return entries;