Skip to content

Commit 5c47676

Browse files
authored
Check for NULL object references in deserializer (#1327)
JS_ReadTypedArray contains a hack where it briefly puts a NULL object pointer in the object reference table to work around a chicken-and-egg problem. Malicious or corrupt BJSON could reference that entry while it was still NULL and trigger a segfault. Guard against that. Fixes: #1321
1 parent f470b8f commit 5c47676

File tree

2 files changed

+10
-9
lines changed

2 files changed

+10
-9
lines changed

quickjs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38649,7 +38649,7 @@ static JSValue JS_ReadObjectRec(BCReaderState *s)
3864938649
if (bc_get_leb128(s, &val))
3865038650
return JS_EXCEPTION;
3865138651
bc_read_trace(s, "%u\n", val);
38652-
if (val >= s->objects_count) {
38652+
if (val >= s->objects_count || !s->objects[val]) {
3865338653
return JS_ThrowSyntaxError(ctx, "invalid object reference (%u >= %u)",
3865438654
val, s->objects_count);
3865538655
}

tests/test_bjson.js

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -268,15 +268,15 @@ function bjson_test_bytecode()
268268
var buf, o, r, e, i;
269269

270270
o = std.evalScript(";(function f(o){ return o.i })", {compile_only: true});
271-
buf = bjson.write(o, /*JS_WRITE_OBJ_BYTECODE*/(1 << 0));
271+
buf = bjson.write(o, bjson.WRITE_OBJ_BYTECODE);
272272
try {
273273
bjson.read(buf, 0, buf.byteLength);
274274
} catch (_e) {
275275
e = _e;
276276
}
277277
assert(String(e), "SyntaxError: no bytecode allowed");
278278

279-
o = bjson.read(buf, 0, buf.byteLength, /*JS_READ_OBJ_BYTECODE*/(1 << 0));
279+
o = bjson.read(buf, 0, buf.byteLength, bjson.READ_OBJ_BYTECODE);
280280
assert(String(o), "[function bytecode]");
281281
o = std.evalScript(o, {eval_function: true});
282282
for (i = 0; i < 42; i++) o({i}); // exercise o.i IC
@@ -285,15 +285,16 @@ function bjson_test_bytecode()
285285
function bjson_test_fuzz()
286286
{
287287
var corpus = [
288-
"FxAAAAAABGA=",
289-
"F+bm5oIt",
290-
"FwARABMGBgYGBgYGBgYGBv////8QABEALxH/vy8R/78=",
291-
"FwAIfwAK/////3//////////////////////////////3/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAD5+fn5+fn5+fn5+fkAAAAAAAYAqw==",
288+
["FxAAAAAABGA="],
289+
["F+bm5oIt"],
290+
["FwARABMGBgYGBgYGBgYGBv////8QABEALxH/vy8R/78="],
291+
["FwAIfwAK/////3//////////////////////////////3/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAD5+fn5+fn5+fn5+fkAAAAAAAYAqw=="],
292+
["FwAOAAAAFAA=", bjson.READ_OBJ_REFERENCE],
292293
];
293-
for (var input of corpus) {
294+
for (var [input, flags] of corpus) {
294295
var buf = base64decode(input);
295296
try {
296-
bjson.read(buf, 0, buf.byteLength);
297+
bjson.read(buf, 0, buf.byteLength, flags);
297298
} catch (e) {
298299
if (/invalid version/.test(e.message)) throw e; // corpus needs update
299300
}

0 commit comments

Comments
 (0)