mirror of https://github.com/svaarala/duktape.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
134 lines
3.5 KiB
134 lines
3.5 KiB
/*
|
|
* Test memory safety of decoding a JSON document clipped at all possible
|
|
* offsets, and any possible byte (or none) appended.
|
|
*
|
|
* The JSON document should exercise all (or as many as possible) code paths
|
|
* of JSON parsing. This is especially important after the change to remove
|
|
* an explicit end-of-input check and rely on a SyntaxError caused by (a
|
|
* guaranteed) NUL instead.
|
|
*
|
|
* We don't care about correct parsing in this test -- except to test that
|
|
* the full document with no trailing bytes parses correctly.
|
|
*/
|
|
|
|
/*---
|
|
{
|
|
"custom": true
|
|
}
|
|
---*/
|
|
|
|
/*===
|
|
input length: 195
|
|
input length: 195
|
|
input length: 195
|
|
input length: 627
|
|
input length: 627
|
|
input length: 627
|
|
input length: 6
|
|
6 -1 SyntaxError
|
|
input length: 6
|
|
6 -1 SyntaxError
|
|
input length: 6
|
|
6 -1 SyntaxError
|
|
input length: 26
|
|
input length: 116
|
|
28 124 TypeError
|
|
30 124 TypeError
|
|
32 124 TypeError
|
|
34 124 TypeError
|
|
===*/
|
|
|
|
function jsonClipTest(input, parser) {
|
|
var i, j;
|
|
var t, buf;
|
|
|
|
print('input length: ' + input.length);
|
|
|
|
for (i = 0; i <= input.length; i++) {
|
|
for (j = -1; j < 256; j++) {
|
|
try {
|
|
t = input.substring(0, i);
|
|
if (j >= 0) {
|
|
buf = Duktape.Buffer(1);
|
|
buf[0] = j;
|
|
t = t + buf;
|
|
}
|
|
if (parser === 'json') {
|
|
t = JSON.parse(t);
|
|
} else if (parser === 'jx') {
|
|
t = Duktape.dec('jx', t);
|
|
} else if (parser === 'jc') {
|
|
t = Duktape.dec('jc', t);
|
|
} else {
|
|
throw new Error('invalid parser: ' + parser);
|
|
}
|
|
} catch (e) {
|
|
// print error if original input doesn't parse (expected for some tests)
|
|
if ((i == input.length && j == -1) || e.name !== 'SyntaxError') {
|
|
print(i, j, e.name);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function test() {
|
|
var inp;
|
|
var i, j;
|
|
|
|
// Exercise:
|
|
// - all types
|
|
// - all escapes
|
|
inp = '{ ' +
|
|
'"types": [ null, true, false, 123, 123.456, 123e3, "", "val", { "foo": "bar" }, [ 1, 2, 3 ] ], ' +
|
|
'"escapes": "foo\\t\\n\\r\\f\\b\\u1234\\ubeef\\u0000bar", ' +
|
|
'"emptyobj": {}, ' +
|
|
'"emptyarr": [], ' +
|
|
'"dummy":"value" ' +
|
|
'}';
|
|
jsonClipTest(inp, 'json');
|
|
jsonClipTest(inp, 'jx');
|
|
jsonClipTest(inp, 'jc');
|
|
|
|
// Exercise:
|
|
// - All codepoints 0x00...0xff
|
|
// - All UTF-8 encoding lengths
|
|
|
|
for (i = 0; i < 256; i++) {
|
|
inp += String.fromCharCode(i);
|
|
}
|
|
inp += '\u0123\ubeef'; // 2 and 3 byte
|
|
inp = JSON.stringify(inp);
|
|
jsonClipTest(inp, 'json');
|
|
jsonClipTest(inp, 'jx');
|
|
jsonClipTest(inp, 'jc');
|
|
|
|
// Exercise:
|
|
// - Control character (< 0x20) unescaped in the middle of a string
|
|
inp = '"foo\u0013"';
|
|
jsonClipTest(inp, 'json'); // won't parse
|
|
jsonClipTest(inp, 'jx');
|
|
jsonClipTest(inp, 'jc');
|
|
|
|
// Exercise:
|
|
// - JX escapes
|
|
inp = '"foo\\x00\\xff\\Udeadbeefbar"';
|
|
jsonClipTest(inp, 'jx');
|
|
|
|
// Exercise:
|
|
// - JX custom syntax
|
|
inp = '{ ' +
|
|
'plainkey: true, ' +
|
|
'buffer: |deadbeef|, ' +
|
|
'pointer: (0xdeadbeef), ' +
|
|
'numbers: [ Infinity, -Infinity, NaN ], ' +
|
|
'dummy: "value" ' +
|
|
'}';
|
|
jsonClipTest(inp, 'jx'); // causes TypeErrors for decode failures
|
|
}
|
|
|
|
try {
|
|
test();
|
|
} catch (e) {
|
|
print(e.stack || e);
|
|
}
|
|
|