Files
orca/config/scripts/verify-linux-glibc-payloads.test.mjs
T
OrcaWin 6fc3cdcad6 Bundle Bun for headless Orca and profile persistence (#22635)
Bundle a pinned, verified Bun runtime for headless Orca so existing Node launch commands can hand off before opening a profile. Keep desktop execution on Electron.

Add the Bun SQLite adapter and terminal backend, bounded shutdown, process inspection and cross-platform artifact qualification. Keep future managed SSH deployment separate from current production launch paths.
2026-09-25 22:49:06 -07:00

125 lines
4.8 KiB
JavaScript

import { mkdtemp, mkdir, writeFile, rm } from 'node:fs/promises'
import { createRequire } from 'node:module'
import { tmpdir } from 'node:os'
import { dirname, join } from 'node:path'
import { afterEach, describe, expect, it } from 'vitest'
const require = createRequire(import.meta.url)
const { verifyLinuxGlibcFloor } = require('./verify-linux-glibc-floor.cjs')
const roots = []
const STATIC_HEADERS = 'Program Header:\n LOAD off 0x0000000000000000\n'
const MUSL_TARGET = 'orcad-template/targets/linux-arm64-musl/watcher.node'
afterEach(async () => {
await Promise.all(roots.splice(0).map((root) => rm(root, { recursive: true, force: true })))
})
async function writeObjdumpFixture(
headers,
{ filename = 'browser', symbolTableError = false } = {}
) {
const root = await mkdtemp(join(tmpdir(), 'orca-glibc-payload-'))
roots.push(root)
const app = join(root, 'app')
const binary = join(app, ...filename.split('/'))
await mkdir(dirname(binary), { recursive: true })
const elf = Buffer.alloc(64)
elf.write('\x7fELF', 0, 'latin1')
elf[4] = 2
elf[5] = 1
elf[6] = 1
elf.writeUInt16LE(0xb7, 18)
await writeFile(binary, elf)
await writeFile(join(root, 'private-headers.txt'), headers)
const objdumpPath = join(root, 'objdump-stub.sh')
await writeFile(
objdumpPath,
[
'#!/bin/sh',
'case "$1" in',
' --version) echo "GNU objdump (fixture)" ;;',
' -p) cat "$(dirname "$0")/private-headers.txt" ;;',
symbolTableError
? ' -T) echo "not a dynamic object" >&2; exit 1 ;;'
: ' -T) echo "0000 DF *UND* 0000 openpty" ;;',
'esac'
].join('\n'),
{ mode: 0o755 }
)
return () => verifyLinuxGlibcFloor(app, { objdumpPath, targetArch: 'arm64' })
}
describe.skipIf(process.platform === 'win32')('static ELF and remote musl payloads', () => {
it.each(['', '\nDynamic Section:\n'])(
'accepts static LOAD segments with no dynamic imports (section suffix %j)',
async (suffix) => {
const verify = await writeObjdumpFixture(STATIC_HEADERS + suffix, { symbolTableError: true })
expect(verify).not.toThrow()
}
)
it.each([
['missing program headers', 'Dynamic Section:\n'],
['dynamic segment', `${STATIC_HEADERS} DYNAMIC off 0x0000000000001000\n`],
['interpreter segment', `${STATIC_HEADERS} INTERP off 0x0000000000001000\n`],
['dependency without a dynamic segment', `${STATIC_HEADERS} NEEDED libc.so.6\n`]
])('preserves symbol-table failures for %s', async (_label, headers) => {
const verify = await writeObjdumpFixture(headers, { symbolTableError: true })
expect(verify).toThrow(/objdump -T failed/)
})
it.each(['libc.so', 'libc.musl-aarch64.so.1'])(
'does not apply Ubuntu C++ or libutil requirements to a remote payload linked to %s',
async (libc) => {
const verify = await writeObjdumpFixture(
`Dynamic Section:\n NEEDED ${libc}\n NEEDED libstdc++.so.6\n` +
'Version References:\n required from libstdc++.so.6:\n 0x0 0x00 02 GLIBCXX_3.4.29\n',
{ filename: MUSL_TARGET }
)
expect(verify).not.toThrow()
}
)
it.each([
['desktop addon', 'watcher.node', 'libc.so'],
['glibc target', 'orcad-template/targets/linux-arm64-glibc/watcher.node', 'libc.so'],
['mislabeled glibc target', MUSL_TARGET, 'libc.so.6'],
['mixed libc dependencies', MUSL_TARGET, 'libc.so\n NEEDED libc.so.6']
])('retains Ubuntu floor and provider checks for %s', async (_label, filename, libc) => {
const verify = await writeObjdumpFixture(
`Dynamic Section:\n NEEDED ${libc}\n NEEDED libstdc++.so.6\n` +
'Version References:\n required from libstdc++.so.6:\n 0x0 0x00 02 GLIBCXX_3.4.29\n',
{ filename }
)
expect(verify).toThrow(
/needs GLIBCXX_3.4.29.*imports openpty but libutil.so.1 is not in DT_NEEDED/
)
})
it('still rejects too-new glibc version needs in a musl payload', async () => {
const verify = await writeObjdumpFixture(
'Dynamic Section:\n NEEDED libc.so\nVersion References:\n' +
' required from libc.so:\n 0x0 0x00 02 GLIBC_2.34\n',
{ filename: MUSL_TARGET }
)
expect(verify).toThrow(/needs GLIBC_2.34/)
})
it('retains the provider check when version references disclose a glibc dependency', async () => {
const verify = await writeObjdumpFixture(
'Dynamic Section:\n NEEDED libc.so\nVersion References:\n' +
' required from libc.so.6:\n 0x0 0x00 02 GLIBC_2.17\n',
{ filename: MUSL_TARGET }
)
expect(verify).toThrow(/imports openpty but libutil.so.1 is not in DT_NEEDED/)
})
it('preserves objdump failures for a musl-labeled file without proven musl dependencies', async () => {
const verify = await writeObjdumpFixture('Dynamic Section:\n', {
filename: MUSL_TARGET,
symbolTableError: true
})
expect(verify).toThrow(/objdump -T failed/)
})
})