diff options
author | Bradley Farias <bradley.meck@gmail.com> | 2019-08-26 10:40:45 -0500 |
---|---|---|
committer | Bradley Farias <bradley.meck@gmail.com> | 2019-09-03 11:12:05 -0500 |
commit | 6ce87c027dc2a16e1b8d85c753b52270ae0c6054 (patch) | |
tree | 420c362071bd29603eb52eb1ce08da56a36853f9 /lib/internal/policy | |
parent | f2c573cf8bedea85ab4505c839b2332517e4b0b9 (diff) | |
download | android-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.js | 137 | ||||
-rw-r--r-- | lib/internal/policy/sri.js | 12 |
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; |