1'use strict'; 2const common = require('../common'); 3const fs = require('fs'); 4const path = require('path'); 5 6if (process.argv[2] === 'wasi-child') { 7 common.expectWarning('ExperimentalWarning', 8 'WASI is an experimental feature. This feature could ' + 9 'change at any time'); 10 11 const { WASI } = require('wasi'); 12 const wasmDir = path.join(__dirname, 'wasm'); 13 const wasi = new WASI({ 14 args: [], 15 env: process.env, 16 preopens: { 17 '/sandbox': process.argv[4] 18 } 19 }); 20 const importObject = { wasi_snapshot_preview1: wasi.wasiImport }; 21 const modulePath = path.join(wasmDir, `${process.argv[3]}.wasm`); 22 const buffer = fs.readFileSync(modulePath); 23 24 (async () => { 25 const { instance } = await WebAssembly.instantiate(buffer, importObject); 26 27 wasi.start(instance); 28 })(); 29} else { 30 if (!common.canCreateSymLink()) { 31 common.skip('insufficient privileges'); 32 } 33 34 const assert = require('assert'); 35 const cp = require('child_process'); 36 const tmpdir = require('../common/tmpdir'); 37 38 // Setup the sandbox environment. 39 tmpdir.refresh(); 40 const sandbox = path.join(tmpdir.path, 'sandbox'); 41 const sandboxedFile = path.join(sandbox, 'input.txt'); 42 const externalFile = path.join(tmpdir.path, 'outside.txt'); 43 const sandboxedDir = path.join(sandbox, 'subdir'); 44 const sandboxedSymlink = path.join(sandboxedDir, 'input_link.txt'); 45 const escapingSymlink = path.join(sandboxedDir, 'outside.txt'); 46 const loopSymlink1 = path.join(sandboxedDir, 'loop1'); 47 const loopSymlink2 = path.join(sandboxedDir, 'loop2'); 48 49 fs.mkdirSync(sandbox); 50 fs.mkdirSync(sandboxedDir); 51 fs.writeFileSync(sandboxedFile, 'hello from input.txt', 'utf8'); 52 fs.writeFileSync(externalFile, 'this should be inaccessible', 'utf8'); 53 fs.symlinkSync(path.join('.', 'input.txt'), sandboxedSymlink, 'file'); 54 fs.symlinkSync(path.join('..', 'outside.txt'), escapingSymlink, 'file'); 55 fs.symlinkSync(path.join('subdir', 'loop2'), 56 loopSymlink1, 'file'); 57 fs.symlinkSync(path.join('subdir', 'loop1'), 58 loopSymlink2, 'file'); 59 60 function runWASI(options) { 61 console.log('executing', options.test); 62 const opts = { env: { ...process.env, NODE_DEBUG_NATIVE: 'wasi' } }; 63 const child = cp.spawnSync(process.execPath, [ 64 '--experimental-wasi-unstable-preview1', 65 '--experimental-wasm-bigint', 66 __filename, 67 'wasi-child', 68 options.test, 69 sandbox 70 ], opts); 71 console.log(child.stderr.toString()); 72 assert.strictEqual(child.status, 0); 73 assert.strictEqual(child.signal, null); 74 assert.strictEqual(child.stdout.toString(), options.stdout || ''); 75 } 76 77 runWASI({ test: 'create_symlink', stdout: 'hello from input.txt' }); 78 runWASI({ test: 'follow_symlink', stdout: 'hello from input.txt' }); 79 runWASI({ test: 'symlink_escape' }); 80 runWASI({ test: 'symlink_loop' }); 81} 82