From 0a79b84ef937269031af563871812aab63e41b20 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Thu, 24 Oct 2024 09:09:40 +0200 Subject: [PATCH] Improve deserializer error message for bytecode Don't raise a "invalid tag 12" exception when encountering bytecode and JS_READ_OBJ_BYTECODE is not set, because no one knows what "tag 12" means without looking it up, not even quickjs maintainers. --- quickjs-libc.c | 6 ++++++ quickjs.c | 8 +++++--- tests/test_bjson.js | 21 +++++++++++++++++++++ 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/quickjs-libc.c b/quickjs-libc.c index e930ff8b..3dcb4ebc 100644 --- a/quickjs-libc.c +++ b/quickjs-libc.c @@ -837,6 +837,7 @@ static JSValue js_evalScript(JSContext *ctx, JSValue this_val, JSValue ret; JSValue options_obj; BOOL backtrace_barrier = FALSE; + BOOL compile_only = FALSE; BOOL is_async = FALSE; int flags; @@ -845,6 +846,9 @@ static JSValue js_evalScript(JSContext *ctx, JSValue this_val, if (get_bool_option(ctx, &backtrace_barrier, options_obj, "backtrace_barrier")) return JS_EXCEPTION; + if (get_bool_option(ctx, &compile_only, options_obj, + "compile_only")) + return JS_EXCEPTION; if (get_bool_option(ctx, &is_async, options_obj, "async")) return JS_EXCEPTION; @@ -860,6 +864,8 @@ static JSValue js_evalScript(JSContext *ctx, JSValue this_val, flags = JS_EVAL_TYPE_GLOBAL; if (backtrace_barrier) flags |= JS_EVAL_FLAG_BACKTRACE_BARRIER; + if (compile_only) + flags |= JS_EVAL_FLAG_COMPILE_ONLY; if (is_async) flags |= JS_EVAL_FLAG_ASYNC; ret = JS_Eval(ctx, str, len, "", flags); diff --git a/quickjs.c b/quickjs.c index 892a05cc..a998afec 100644 --- a/quickjs.c +++ b/quickjs.c @@ -35473,12 +35473,14 @@ static JSValue JS_ReadObjectRec(BCReaderState *s) break; case BC_TAG_FUNCTION_BYTECODE: if (!s->allow_bytecode) - goto invalid_tag; + goto no_allow_bytecode; obj = JS_ReadFunctionTag(s); break; case BC_TAG_MODULE: - if (!s->allow_bytecode) - goto invalid_tag; + if (!s->allow_bytecode) { + no_allow_bytecode: + return JS_ThrowSyntaxError(ctx, "no bytecode allowed"); + } obj = JS_ReadModule(s); break; case BC_TAG_OBJECT: diff --git a/tests/test_bjson.js b/tests/test_bjson.js index 6a2ee2cb..989310d2 100644 --- a/tests/test_bjson.js +++ b/tests/test_bjson.js @@ -1,3 +1,4 @@ +import * as std from "std"; import * as bjson from "bjson"; import { assert } from "./assert.js"; @@ -227,6 +228,25 @@ function bjson_test_symbol() assert(o, r); } +function bjson_test_bytecode() +{ + var buf, o, r, e; + + o = std.evalScript(";(function f(o){ return o.i })", {compile_only: true}); + buf = bjson.write(o, /*JS_WRITE_OBJ_BYTECODE*/(1 << 0)); + try { + bjson.read(buf, 0, buf.byteLength); + } catch (_e) { + e = _e; + } + assert(String(e), "SyntaxError: no bytecode allowed"); + + // can't really do anything with |o| at the moment, + // no way to pass it to JS_EvalFunction + o = bjson.read(buf, 0, buf.byteLength, /*JS_READ_OBJ_BYTECODE*/(1 << 0)); + assert(String(o), "[function bytecode]"); +} + function bjson_test_fuzz() { var corpus = [ @@ -277,6 +297,7 @@ function bjson_test_all() bjson_test_map(); bjson_test_set(); bjson_test_symbol(); + bjson_test_bytecode(); bjson_test_fuzz(); }