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 and might change at any time'); 9 10 const { WASI } = require('wasi'); 11 const wasmDir = path.join(__dirname, 'wasm'); 12 const wasi = new WASI({ 13 args: [], 14 env: process.env, 15 preopens: { 16 '/sandbox': process.argv[4], 17 '/tmp': process.argv[5], 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 })().then(common.mustCall()); 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 const sandboxedTmp = path.join(tmpdir.path, 'tmp'); 49 50 fs.mkdirSync(sandbox); 51 fs.mkdirSync(sandboxedDir); 52 fs.mkdirSync(sandboxedTmp); 53 fs.writeFileSync(sandboxedFile, 'hello from input.txt', 'utf8'); 54 fs.writeFileSync(externalFile, 'this should be inaccessible', 'utf8'); 55 fs.symlinkSync(path.join('.', 'input.txt'), sandboxedSymlink, 'file'); 56 fs.symlinkSync(path.join('..', 'outside.txt'), escapingSymlink, 'file'); 57 fs.symlinkSync(path.join('subdir', 'loop2'), 58 loopSymlink1, 'file'); 59 fs.symlinkSync(path.join('subdir', 'loop1'), 60 loopSymlink2, 'file'); 61 62 function runWASI(options) { 63 console.log('executing', options.test); 64 const opts = { env: { ...process.env, NODE_DEBUG_NATIVE: 'wasi' } }; 65 const child = cp.spawnSync(process.execPath, [ 66 __filename, 67 'wasi-child', 68 options.test, 69 sandbox, 70 sandboxedTmp, 71 ], opts); 72 console.log(child.stderr.toString()); 73 assert.strictEqual(child.status, 0); 74 assert.strictEqual(child.signal, null); 75 assert.strictEqual(child.stdout.toString(), options.stdout || ''); 76 } 77 78 runWASI({ test: 'create_symlink', stdout: 'hello from input.txt' }); 79 runWASI({ test: 'follow_symlink', stdout: 'hello from input.txt' }); 80 runWASI({ test: 'link' }); 81 runWASI({ test: 'symlink_escape' }); 82 runWASI({ test: 'symlink_loop' }); 83} 84