-
Notifications
You must be signed in to change notification settings - Fork 212
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
test(xsnap): size limits #2681
test(xsnap): size limits #2681
Changes from all commits
732aaba
8b3c3f8
2a033f2
a68d0f9
a04b9d5
31cbb89
1cf1329
38167e5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
/* global setTimeout, __filename */ | ||
// eslint-disable-next-line import/no-extraneous-dependencies | ||
import test from 'ava'; | ||
import * as childProcess from 'child_process'; | ||
import * as os from 'os'; | ||
|
@@ -48,18 +50,19 @@ test('evaluate until idle', async t => { | |
test('evaluate infinite loop', async t => { | ||
const opts = options(); | ||
const vat = xsnap(opts); | ||
t.teardown(vat.terminate); | ||
await t.throwsAsync(vat.evaluate(`for (;;) {}`), { | ||
message: 'xsnap test worker exited', | ||
message: /xsnap test worker exited with code 7/, | ||
instanceOf: Error, | ||
}); | ||
await vat.close(); | ||
t.deepEqual([], opts.messages); | ||
}); | ||
|
||
// TODO: Reenable when this doesn't take 3.6 seconds. | ||
test.skip('evaluate promise loop', async t => { | ||
test('evaluate promise loop', async t => { | ||
const opts = options(); | ||
const vat = xsnap(opts); | ||
t.teardown(vat.terminate); | ||
await t.throwsAsync( | ||
vat.evaluate(` | ||
function f() { | ||
|
@@ -68,11 +71,10 @@ test.skip('evaluate promise loop', async t => { | |
f(); | ||
`), | ||
{ | ||
message: 'xsnap test worker exited', | ||
message: /exited with code 7/, | ||
instanceOf: Error, | ||
}, | ||
); | ||
await vat.close(); | ||
t.deepEqual([], opts.messages); | ||
}); | ||
|
||
|
@@ -400,6 +402,103 @@ test('heap exhaustion: orderly fail-stop', async t => { | |
const vat = xsnap({ ...xsnapOptions, meteringLimit: 0, debug }); | ||
t.teardown(() => vat.terminate()); | ||
// eslint-disable-next-line no-await-in-loop | ||
await t.throwsAsync(vat.evaluate(grow)); | ||
await t.throwsAsync(vat.evaluate(grow), { message: /exited with code 1$/ }); | ||
} | ||
}); | ||
|
||
test('property name space exhaustion: orderly fail-stop', async t => { | ||
const grow = qty => ` | ||
const objmap = {}; | ||
try { | ||
for (let ix = 0; ix < ${qty}; ix += 1) { | ||
const key = \`k\${ix}\`; | ||
objmap[key] = 1; | ||
if (!(key in objmap)) { | ||
throw Error(key); | ||
} | ||
} | ||
} catch (err) { | ||
// name space exhaustion should not be catchable! | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good, but if this managed to catch the first few times, and then stopped catching it, we'd not be able to distinguish that failure mode from the intended one. Would it be possible to have the If that's too much hassle, just having it print a "wait a minute I shouldn't be printed" and manually eyeball it once should be sufficient. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't understand your point. The In any case, I put a for-ever loop in the catch block to exit with "too much computation" in 0b4501f . |
||
// spin and fail with "too much computation" | ||
for (;;) {} | ||
} | ||
`; | ||
for (const debug of [false, true]) { | ||
const vat = xsnap({ ...xsnapOptions, meteringLimit: 0, debug }); | ||
t.teardown(() => vat.terminate()); | ||
console.log({ debug, qty: 31000 }); | ||
// eslint-disable-next-line no-await-in-loop | ||
await t.notThrowsAsync(vat.evaluate(grow(31000))); | ||
console.log({ debug, qty: 4000000000 }); | ||
// eslint-disable-next-line no-await-in-loop | ||
await t.throwsAsync(vat.evaluate(grow(4000000000)), { | ||
message: /exited with code 6/, | ||
}); | ||
} | ||
}); | ||
|
||
(() => { | ||
const grow = qty => ` | ||
const send = it => issueCommand(ArrayBuffer.fromString(JSON.stringify(it))); | ||
let expr = \`"\${Array(${qty}).fill('abcd').join('')}"\`; | ||
try { | ||
eval(expr); | ||
send(expr.length); | ||
} catch (err) { | ||
send(err.message); | ||
} | ||
`; | ||
for (const debug of [false, true]) { | ||
for (const [parserBufferSize, qty, failure] of [ | ||
[undefined, 100, null], | ||
[undefined, 8192 * 1024 + 100, 'buffer overflow'], | ||
[2, 10, null], | ||
[2, 50000, 'buffer overflow'], | ||
]) { | ||
test(`parser buffer size ${parserBufferSize || | ||
'default'}k; rep ${qty}; debug ${debug}`, async t => { | ||
const opts = options(); | ||
const vat = xsnap({ ...opts, debug, parserBufferSize }); | ||
t.teardown(() => vat.terminate()); | ||
const expected = failure ? [failure] : [qty * 4 + 2]; | ||
// eslint-disable-next-line no-await-in-loop | ||
await t.notThrowsAsync(vat.evaluate(grow(qty))); | ||
t.deepEqual( | ||
expected, | ||
opts.messages.map(txt => JSON.parse(txt)), | ||
); | ||
}); | ||
} | ||
} | ||
})(); | ||
|
||
(() => { | ||
const challenges = [ | ||
'new Uint8Array(2_130_706_417)', | ||
'new Uint16Array(1_065_353_209)', | ||
'new Uint32Array(532_676_605)', | ||
'new BigUint64Array(266_338_303);', | ||
'new Array(66_584_576).fill(0)', | ||
'(new Array(66_584_575).fill(0))[66_584_575] = 0;', | ||
]; | ||
|
||
for (const statement of challenges) { | ||
test(`large sizes - abort cluster: ${statement}`, async t => { | ||
const vat = xsnap(xsnapOptions); | ||
t.teardown(() => vat.terminate()); | ||
// eslint-disable-next-line no-await-in-loop | ||
await t.throwsAsync( | ||
vat.evaluate(` | ||
(() => { | ||
try { | ||
// can't catch memory full | ||
${statement}\n | ||
} catch (ignore) { | ||
// ignore | ||
} | ||
})()`), | ||
{ message: /exited with code 1$/ }, | ||
); | ||
}); | ||
} | ||
})(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe let's make that an
unsigned int
? Sinceatoi
accepts-1234
, it might be an extra safety belt.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you want it to underflow and wrap around? I don't understand why.