diff options
| author | 2026-10-12 08:46:23 +0330 | |
|---|---|---|
| committer | 2026-10-12 08:46:23 +0330 | |
| commit | ecc350ca5c2eb50be8309c5f14f8bf0d87db9a02 (patch) | |
| tree | 70e0af76a1b13affff7c6cc8aac7b3e6ef960478 /tests/drivers/lsp_sandbox.js | |
a
Diffstat (limited to 'tests/drivers/lsp_sandbox.js')
| -rw-r--r-- | tests/drivers/lsp_sandbox.js | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/tests/drivers/lsp_sandbox.js b/tests/drivers/lsp_sandbox.js new file mode 100644 index 0000000..14bc1e3 --- /dev/null +++ b/tests/drivers/lsp_sandbox.js @@ -0,0 +1,22 @@ +// opening a file in the editor checks it, and a check runs the file's compile-time code +// (immediate functions). the server must not let that code write files, so a file that +// tries to leaves nothing behind and the server still answers. +// usage: node tests/drivers/lsp_sandbox.js path/to/zclsp +const cp = require('child_process'), fs = require('fs'), os = require('os'), path = require('path'); +const target = path.join(os.tmpdir(), 'zc-sandbox-' + process.pid); +try { fs.unlinkSync(target); } catch (e) {} +const src = 'immediate fn evil() { let fd = syscall(1, "' + target + '", 1, 0); syscall(4, fd, 65, 1); syscall(2, fd, 0, 0); return 0; }\nevil\nfn main() { return 0; }\n'; +const frame = m => { const b = Buffer.from(JSON.stringify(m)); return Buffer.concat([Buffer.from('Content-Length: ' + b.length + '\r\n\r\n'), b]); }; +const input = Buffer.concat([ + frame({ jsonrpc: '2.0', id: 1, method: 'initialize', params: { processId: 1, capabilities: {} } }), + frame({ jsonrpc: '2.0', method: 'textDocument/didOpen', params: { textDocument: { uri: 'file:///evil.zc', languageId: 'zc', version: 1, text: src } } }), + frame({ jsonrpc: '2.0', id: 3, method: 'textDocument/semanticTokens/full', params: { textDocument: { uri: 'file:///evil.zc' } } }), + frame({ jsonrpc: '2.0', method: 'exit' }), +]); +const r = cp.spawnSync(process.argv[2], [], { input, timeout: 20000 }); +const wrote = fs.existsSync(target); +if (wrote) fs.unlinkSync(target); +const answered = r.stdout && r.stdout.includes('"id":3'); +const ok = !wrote && answered; +console.log((ok ? 'ok ' : 'FAIL ') + 'lsp sandbox: compile-time code cannot write files' + (ok ? '' : ' (wrote: ' + wrote + ', answered: ' + !!answered + ')')); +process.exit(ok ? 0 : 1); |
