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 '/tmp': process.argv[5] 19 } 20 }); 21 const importObject = { wasi_snapshot_preview1: wasi.wasiImport }; 22 const modulePath = path.join(wasmDir, `${process.argv[3]}.wasm`); 23 const buffer = fs.readFileSync(modulePath); 24 25 (async () => { 26 const { instance } = await WebAssembly.instantiate(buffer, importObject); 27 28 wasi.start(instance); 29 })().then(common.mustCall()); 30} else { 31 if (!common.canCreateSymLink()) { 32 common.skip('insufficient privileges'); 33 } 34 35 const assert = require('assert'); 36 const cp = require('child_process'); 37 const tmpdir = require('../common/tmpdir'); 38 39 // Setup the sandbox environment. 40 tmpdir.refresh(); 41 const sandbox = path.join(tmpdir.path, 'sandbox'); 42 const sandboxedFile = path.join(sandbox, 'input.txt'); 43 const externalFile = path.join(tmpdir.path, 'outside.txt'); 44 const sandboxedDir = path.join(sandbox, 'subdir'); 45 const sandboxedSymlink = path.join(sandboxedDir, 'input_link.txt'); 46 const escapingSymlink = path.join(sandboxedDir, 'outside.txt'); 47 const loopSymlink1 = path.join(sandboxedDir, 'loop1'); 48 const loopSymlink2 = path.join(sandboxedDir, 'loop2'); 49 const sandboxedTmp = path.join(tmpdir.path, 'tmp'); 50 51 fs.mkdirSync(sandbox); 52 fs.mkdirSync(sandboxedDir); 53 fs.mkdirSync(sandboxedTmp); 54 fs.writeFileSync(sandboxedFile, 'hello from input.txt', 'utf8'); 55 fs.writeFileSync(externalFile, 'this should be inaccessible', 'utf8'); 56 fs.symlinkSync(path.join('.', 'input.txt'), sandboxedSymlink, 'file'); 57 fs.symlinkSync(path.join('..', 'outside.txt'), escapingSymlink, 'file'); 58 fs.symlinkSync(path.join('subdir', 'loop2'), 59 loopSymlink1, 'file'); 60 fs.symlinkSync(path.join('subdir', 'loop1'), 61 loopSymlink2, 'file'); 62 63 function runWASI(options) { 64 console.log('executing', options.test); 65 const opts = { env: { ...process.env, NODE_DEBUG_NATIVE: 'wasi' } }; 66 const child = cp.spawnSync(process.execPath, [ 67 '--experimental-wasi-unstable-preview1', 68 '--experimental-wasm-bigint', 69 __filename, 70 'wasi-child', 71 options.test, 72 sandbox, 73 sandboxedTmp, 74 ], opts); 75 console.log(child.stderr.toString()); 76 assert.strictEqual(child.status, 0); 77 assert.strictEqual(child.signal, null); 78 assert.strictEqual(child.stdout.toString(), options.stdout || ''); 79 } 80 81 runWASI({ test: 'create_symlink', stdout: 'hello from input.txt' }); 82 runWASI({ test: 'follow_symlink', stdout: 'hello from input.txt' }); 83 runWASI({ test: 'link' }); 84 runWASI({ test: 'symlink_escape' }); 85 runWASI({ test: 'symlink_loop' }); 86} 87