Files
orca/docs/audits/terminal-completed-spawn-inputs/spawn-source.cjs

115 lines
4.1 KiB
JavaScript

const assert = require('node:assert/strict')
const { createHash } = require('node:crypto')
const { readFileSync } = require('node:fs')
const path = require('node:path')
const Module = require('node:module')
const esbuild = require('esbuild')
const { applyPatch, parsePatch, reversePatch } = require('diff')
const versions = require('./source-versions.json')
const root = path.resolve(__dirname, '../../..')
const readText = (file) => readFileSync(file, 'utf8').replace(/\r\n/g, '\n')
const sha = (value) => createHash('sha256').update(value).digest('hex')
const patches = parsePatch(readText(path.join(__dirname, 'fix.patch')))
assert.equal(patches.length, versions.sources.length)
const fixedSources = new Map()
const baselineSources = new Map()
const evaluatedSourceHashes = {}
const sourceMapPath = process.env.ORCA_SPAWN_INPUT_PROOF_SOURCE_MAP
const sourceOverrides = sourceMapPath ? JSON.parse(readText(path.resolve(sourceMapPath))) : null
if (sourceMapPath) {
assert.equal(typeof sourceOverrides, 'object')
assert.notEqual(sourceOverrides, null)
assert.equal(Array.isArray(sourceOverrides), false)
assert.deepEqual(
Object.keys(sourceOverrides).sort(),
versions.sources.map((source) => source.sourcePath).sort()
)
}
for (const source of versions.sources) {
const file = path.join(root, source.sourcePath)
const fixed = sourceOverrides ? sourceOverrides[source.sourcePath] : readText(file)
assert.equal(typeof fixed, 'string')
const pair = [source, ...(source.alternatePairs ?? [])].find(
(entry) => entry.fixedSha256 === sha(fixed)
)
assert.ok(pair, `Unreviewed product source: ${source.sourcePath}`)
const patch = patches.find((entry) => entry.oldFileName === `a/${source.sourcePath}`)
assert.ok(patch)
const baseline = applyPatch(fixed, reversePatch(patch))
assert.notEqual(baseline, false)
assert.equal(sha(baseline), pair.baselineSha256, `Baseline changed: ${source.sourcePath}`)
fixedSources.set(file, fixed)
baselineSources.set(file, baseline)
evaluatedSourceHashes[source.sourcePath] = { baseline: sha(baseline), fixed: sha(fixed) }
}
const sourceMode = sourceMapPath
? 'mapped modules with working-tree dependencies'
: 'working-tree modules and dependencies'
const reportPrefix = sourceMapPath ? 'mapped-' : ''
async function loadExports(fixed) {
const sources = fixed ? fixedSources : baselineSources
const build = await esbuild.build({
stdin: {
contents: [
"export { TerminalHost } from './src/main/daemon/terminal-host'",
"export { DaemonTerminalAdmission } from './src/main/daemon/daemon-terminal-admission'",
"export { DaemonPtySpawnPreparations } from './src/main/daemon/daemon-pty-spawn-preparations'"
].join(';'),
resolveDir: root,
loader: 'ts'
},
platform: 'node',
format: 'cjs',
bundle: true,
packages: 'external',
write: false,
plugins: [
{
name: 'reviewed-spawn-input-sources',
setup(builder) {
builder.onLoad(
{ filter: /(?:terminal-host(?:-session-create)?|session-output-pipeline)\.ts$/ },
(args) => {
const contents = sources.get(args.path)
return contents === undefined ? undefined : { contents, loader: 'ts' }
}
)
builder.onResolve({ filter: /pty-descendant-termination$/ }, () => ({
path: 'no-os-signals',
namespace: 'fixture'
}))
builder.onLoad({ filter: /.*/, namespace: 'fixture' }, () => ({
contents:
"export function killWithDescendantSweep() { throw new Error('Unexpected real process teardown') }",
loader: 'js'
}))
}
}
]
})
const filename = path.join(__dirname, 'bundled-terminal-host.cjs')
const loaded = new Module(filename, module)
loaded.filename = filename
loaded.paths = Module._nodeModulePaths(__dirname)
loaded._compile(build.outputFiles[0].text, filename)
return loaded.exports
}
async function load(fixed) {
return (await loadExports(fixed)).TerminalHost
}
module.exports = {
load,
loadExports,
versions,
sha,
baselineSources,
evaluatedSourceHashes,
sourceMode,
reportPrefix
}