From fc9fa66b0d84c2cece57a9ff126c629ec81beefa Mon Sep 17 00:00:00 2001 From: Nikita Skovoroda Date: Wed, 31 Jul 2024 14:42:51 +0300 Subject: [PATCH] module: validate that strip-types does not insert any code --- lib/internal/modules/helpers.js | 49 +++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/lib/internal/modules/helpers.js b/lib/internal/modules/helpers.js index d466cec51cfbf7..0f2b38575a1258 100644 --- a/lib/internal/modules/helpers.js +++ b/lib/internal/modules/helpers.js @@ -24,6 +24,7 @@ const internalFS = require('internal/fs/utils'); const path = require('path'); const { pathToFileURL, fileURLToPath } = require('internal/url'); const assert = require('internal/assert'); +const { Buffer: { from: BufferFrom } } = require('buffer'); const { getOptionValue } = require('internal/options'); const { setOwnProperty } = require('internal/util'); @@ -307,10 +308,58 @@ function lazyLoadTSParser() { return parseTS; } +function doesTSStripTypesResultMatchSource(code, source) { + const sourceBuf = BufferFrom(source); + const codeBuf = BufferFrom(code); + if (sourceBuf.length !== codeBuf.length) { return false; } + for (let i = 0; i < codeBuf.length; i++) { + // Should match either the source buffer or spaces (sometimes multi-byte) or semicolon + const val = codeBuf[i]; + if (val === sourceBuf[i]) { + // Source match + continue; + } + // https://github.com/nodejs/amaro/blob/e533394f576f946add41dd8816816435e8100c3b/deps/swc/crates/swc_fast_ts_strip/src/lib.rs#L400-L414 + if (val === 0x3b) { + // Semicolon 3b + continue; + } + // https://github.com/nodejs/amaro/blob/e533394f576f946add41dd8816816435e8100c3b/deps/swc/crates/swc_fast_ts_strip/src/lib.rs#L200-L226 + if (val === 0x20) { + // Space 20 + continue; + } + if (val === 0xe2) { + // No-Break Space 00A0 + if (i + 1 >= codeBuf.length) { return false; } + if (codeBuf[++i] !== 0xa0) { return false; } + continue; + } + if (val === 0xc2) { + // En Space 2002 + if (i + 2 >= codeBuf.length) { return false; } + if (codeBuf[++i] !== 0x80) { return false; } + if (codeBuf[++i] !== 0x82) { return false; } + continue; + } + if (val === 0xef) { + // ZWNBSP FEFF + if (i < 1 || codeBuf[i - 1] !== 0x20) { return false; } // Only can get insterted after a space + if (i + 2 >= codeBuf.length) { return false; } + if (codeBuf[++i] !== 0xbb) { return false; } + if (codeBuf[++i] !== 0xbf) { return false; } + continue; + } + return false; + } + return true; +} + function tsParse(source) { if (!source || typeof source !== 'string') { return; } const transformSync = lazyLoadTSParser(); const { code } = transformSync(source, { mode: 'strip-only' }); + assert(doesTSStripTypesResultMatchSource(code, source), 'Unexpected strip-types result'); return code; }