From d1ae5c5f57a65c9316d08a34d4c27bb9e21188fc Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Fri, 4 Dec 2020 14:48:52 +0100 Subject: [PATCH 1/2] lib: add primordials.SafeStringIterator --- lib/internal/per_context/primordials.js | 8 ++++++++ lib/internal/repl/utils.js | 3 ++- lib/internal/source_map/prepare_stack_trace.js | 4 +++- lib/internal/tls.js | 3 ++- lib/internal/util/inspect.js | 3 ++- lib/readline.js | 5 +++-- lib/tls.js | 4 +++- 7 files changed, 23 insertions(+), 7 deletions(-) diff --git a/lib/internal/per_context/primordials.js b/lib/internal/per_context/primordials.js index ad5707954738ae..b51be5dfef16c6 100644 --- a/lib/internal/per_context/primordials.js +++ b/lib/internal/per_context/primordials.js @@ -232,6 +232,9 @@ primordials.SafeWeakSet = makeSafe( // Refs: https://tc39.es/ecma262/#sec-%typedarray%-intrinsic-object [ { name: 'TypedArray', original: Reflect.getPrototypeOf(Uint8Array) }, + { name: 'StringIterator', original: { + prototype: Reflect.getPrototypeOf(String.prototype[Symbol.iterator]()), + } }, ].forEach(({ name, original }) => { primordials[name] = original; // The static %TypedArray% methods require a valid `this`, but can't be bound, @@ -240,5 +243,10 @@ primordials.SafeWeakSet = makeSafe( copyPrototype(original.prototype, primordials, `${name}Prototype`); }); +primordials.SafeStringIterator = createSafeIterator( + primordials.StringPrototypeSymbolIterator, + primordials.StringIteratorPrototypeNext +); + Object.setPrototypeOf(primordials, null); Object.freeze(primordials); diff --git a/lib/internal/repl/utils.js b/lib/internal/repl/utils.js index e2bda7665a9138..594b6a0c4485c7 100644 --- a/lib/internal/repl/utils.js +++ b/lib/internal/repl/utils.js @@ -9,6 +9,7 @@ const { MathMin, RegExpPrototypeTest, SafeSet, + SafeStringIterator, StringPrototypeEndsWith, StringPrototypeIndexOf, StringPrototypeLastIndexOf, @@ -425,7 +426,7 @@ function setupPreview(repl, contextSymbol, bufferSymbol, active) { getStringWidth(inspected) > maxColumns) { maxColumns -= 4 + (repl.useColors ? 0 : 3); let res = ''; - for (const char of inspected) { + for (const char of new SafeStringIterator(inspected)) { maxColumns -= getStringWidth(char); if (maxColumns < 0) break; diff --git a/lib/internal/source_map/prepare_stack_trace.js b/lib/internal/source_map/prepare_stack_trace.js index 60bcb2fcadd1a1..c32f9780c2fb3f 100644 --- a/lib/internal/source_map/prepare_stack_trace.js +++ b/lib/internal/source_map/prepare_stack_trace.js @@ -9,6 +9,7 @@ const { StringPrototypeSlice, StringPrototypeSplit, StringPrototypeStartsWith, + SafeStringIterator, } = primordials; let debug = require('internal/util/debuglog').debuglog('source_map', (fn) => { @@ -144,7 +145,8 @@ function getErrorSource( // Display ^ in appropriate position, regardless of whether tabs or // spaces are used: let prefix = ''; - for (const character of StringPrototypeSlice(line, 0, originalColumn + 1)) { + for (const character of new SafeStringIterator( + StringPrototypeSlice(line, 0, originalColumn + 1))) { prefix += (character === '\t') ? '\t' : StringPrototypeRepeat(' ', getStringWidth(character)); } diff --git a/lib/internal/tls.js b/lib/internal/tls.js index da40f635286bfe..9cea780b91884c 100644 --- a/lib/internal/tls.js +++ b/lib/internal/tls.js @@ -3,6 +3,7 @@ const { ArrayIsArray, ArrayPrototypePush, + SafeStringIterator, StringPrototypeIndexOf, StringPrototypeSlice, StringPrototypeSplit, @@ -13,7 +14,7 @@ const { // C=US\nST=CA\nL=SF\nO=Joyent\nOU=Node.js\nCN=ca1\nemailAddress=ry@clouds.org function parseCertString(s) { const out = ObjectCreate(null); - for (const part of StringPrototypeSplit(s, '\n')) { + for (const part of new SafeStringIterator(StringPrototypeSplit(s, '\n'))) { const sepIndex = StringPrototypeIndexOf(part, '='); if (sepIndex > 0) { const key = StringPrototypeSlice(part, 0, sepIndex); diff --git a/lib/internal/util/inspect.js b/lib/internal/util/inspect.js index 17ca3f3d2b39ce..04b7b68c5d41c6 100644 --- a/lib/internal/util/inspect.js +++ b/lib/internal/util/inspect.js @@ -42,6 +42,7 @@ const { ReflectApply, RegExp, RegExpPrototypeToString, + SafeStringIterator, Set, SetPrototypeGetSize, SetPrototypeValues, @@ -2005,7 +2006,7 @@ if (internalBinding('config').hasIntl) { if (removeControlChars) str = stripVTControlCharacters(str); str = str.normalize('NFC'); - for (const char of str) { + for (const char of new SafeStringIterator(str)) { const code = char.codePointAt(0); if (isFullWidthCodePoint(code)) { width += 2; diff --git a/lib/readline.js b/lib/readline.js index 352b7ed64f06ba..598f9349bb3c0b 100644 --- a/lib/readline.js +++ b/lib/readline.js @@ -59,6 +59,7 @@ const { StringPrototypeTrim, Symbol, SymbolAsyncIterator, + SafeStringIterator, } = primordials; const { @@ -760,7 +761,7 @@ Interface.prototype._getDisplayPos = function(str) { const col = this.columns; let rows = 0; str = stripVTControlCharacters(str); - for (const char of str) { + for (const char of new SafeStringIterator(str)) { if (char === '\n') { // Rows must be incremented by 1 even if offset = 0 or col = +Infinity. rows += MathCeil(offset / col) || 1; @@ -1181,7 +1182,7 @@ function emitKeypressEvents(stream, iface = {}) { iface.isCompletionEnabled = false; let length = 0; - for (const character of string) { + for (const character of new SafeStringIterator(string)) { length += character.length; if (length === string.length) { iface.isCompletionEnabled = true; diff --git a/lib/tls.js b/lib/tls.js index 7ee9ae49f03a68..1e3cf9d67f8e4c 100644 --- a/lib/tls.js +++ b/lib/tls.js @@ -32,6 +32,7 @@ const { ObjectDefineProperty, ObjectFreeze, RegExpPrototypeTest, + SafeStringIterator, StringFromCharCode, StringPrototypeCharCodeAt, StringPrototypeEndsWith, @@ -239,7 +240,8 @@ exports.checkServerIdentity = function checkServerIdentity(hostname, cert) { hostname = '' + hostname; if (altNames) { - for (const name of StringPrototypeSplit(altNames, ', ')) { + for (const name of new SafeStringIterator(StringPrototypeSplit(altNames, + ', '))) { if (StringPrototypeStartsWith(name, 'DNS:')) { ArrayPrototypePush(dnsNames, StringPrototypeSlice(name, 4)); } else if (StringPrototypeStartsWith(name, 'URI:')) { From 24fb6c4a364fd0a4d0c7b03ec75c4e1479031a72 Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Tue, 15 Dec 2020 15:24:41 +0100 Subject: [PATCH 2/2] fixup! lib: add primordials.SafeStringIterator --- lib/internal/tls.js | 3 +-- lib/tls.js | 4 +--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/lib/internal/tls.js b/lib/internal/tls.js index 9cea780b91884c..da40f635286bfe 100644 --- a/lib/internal/tls.js +++ b/lib/internal/tls.js @@ -3,7 +3,6 @@ const { ArrayIsArray, ArrayPrototypePush, - SafeStringIterator, StringPrototypeIndexOf, StringPrototypeSlice, StringPrototypeSplit, @@ -14,7 +13,7 @@ const { // C=US\nST=CA\nL=SF\nO=Joyent\nOU=Node.js\nCN=ca1\nemailAddress=ry@clouds.org function parseCertString(s) { const out = ObjectCreate(null); - for (const part of new SafeStringIterator(StringPrototypeSplit(s, '\n'))) { + for (const part of StringPrototypeSplit(s, '\n')) { const sepIndex = StringPrototypeIndexOf(part, '='); if (sepIndex > 0) { const key = StringPrototypeSlice(part, 0, sepIndex); diff --git a/lib/tls.js b/lib/tls.js index 1e3cf9d67f8e4c..7ee9ae49f03a68 100644 --- a/lib/tls.js +++ b/lib/tls.js @@ -32,7 +32,6 @@ const { ObjectDefineProperty, ObjectFreeze, RegExpPrototypeTest, - SafeStringIterator, StringFromCharCode, StringPrototypeCharCodeAt, StringPrototypeEndsWith, @@ -240,8 +239,7 @@ exports.checkServerIdentity = function checkServerIdentity(hostname, cert) { hostname = '' + hostname; if (altNames) { - for (const name of new SafeStringIterator(StringPrototypeSplit(altNames, - ', '))) { + for (const name of StringPrototypeSplit(altNames, ', ')) { if (StringPrototypeStartsWith(name, 'DNS:')) { ArrayPrototypePush(dnsNames, StringPrototypeSlice(name, 4)); } else if (StringPrototypeStartsWith(name, 'URI:')) {