From 97c918662b99ed89f4162b0f952bccfcff1cc2ae Mon Sep 17 00:00:00 2001 From: Charlie Gordon Date: Mon, 8 Apr 2024 21:25:01 +0200 Subject: [PATCH] Fix crashes in DUMP output (#350) - avoid crashing on invalid atoms in `JS_AtomGetStrRT` - do not dump objects and function_bytecode during `JS_GC_PHASE_REMOVE_CYCLES` phase - fix crash in `print_lines` on null source --- quickjs.c | 41 ++++++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/quickjs.c b/quickjs.c index a918691..94604cf 100644 --- a/quickjs.c +++ b/quickjs.c @@ -3012,19 +3012,22 @@ static const char *JS_AtomGetStrRT(JSRuntime *rt, char *buf, int buf_size, { if (__JS_AtomIsTaggedInt(atom)) { snprintf(buf, buf_size, "%u", __JS_AtomToUInt32(atom)); - } else { - JSAtomStruct *p; + } else if (atom == JS_ATOM_NULL) { + snprintf(buf, buf_size, ""); + } else if (atom >= rt->atom_size) { assert(atom < rt->atom_size); - if (atom == JS_ATOM_NULL) { - snprintf(buf, buf_size, ""); + snprintf(buf, buf_size, "", atom); + } else { + JSAtomStruct *p = rt->atom_array[atom]; + if (atom_is_free(p)) { + assert(!atom_is_free(p)); + snprintf(buf, buf_size, "", atom); } else { int i, c; char *q; JSString *str; q = buf; - p = rt->atom_array[atom]; - assert(!atom_is_free(p)); str = p; if (str) { if (!str->is_wide_char) { @@ -5454,12 +5457,16 @@ void __JS_FreeValueRT(JSRuntime *rt, JSValue v) #ifdef DUMP_FREE { - printf("Freeing "); - if (tag == JS_TAG_OBJECT) { - JS_DumpObject(rt, JS_VALUE_GET_OBJ(v)); - } else { - JS_DumpValue(rt, v); - printf("\n"); + /* Prevent invalid object access during GC */ + if ((rt->gc_phase != JS_GC_PHASE_REMOVE_CYCLES) + || (tag != JS_TAG_OBJECT && tag != JS_TAG_FUNCTION_BYTECODE)) { + printf("Freeing "); + if (tag == JS_TAG_OBJECT) { + JS_DumpObject(rt, JS_VALUE_GET_OBJ(v)); + } else { + JS_DumpValue(rt, v); + printf("\n"); + } } } #endif @@ -11708,7 +11715,11 @@ static __maybe_unused void JS_DumpValue(JSRuntime *rt, JSValue val) { JSFunctionBytecode *b = JS_VALUE_GET_PTR(val); char buf[ATOM_GET_STR_BUF_SIZE]; - printf("[bytecode %s]", JS_AtomGetStrRT(rt, buf, sizeof(buf), b->func_name)); + if (b->func_name) { + printf("[bytecode %s]", JS_AtomGetStrRT(rt, buf, sizeof(buf), b->func_name)); + } else { + printf("[bytecode (anonymous)]"); + } } break; case JS_TAG_OBJECT: @@ -27476,7 +27487,7 @@ static void js_free_function_def(JSContext *ctx, JSFunctionDef *fd) #ifdef DUMP_BYTECODE static const char *skip_lines(const char *p, int n) { - while (n-- > 0 && *p) { + while (p && n-- > 0 && *p) { while (*p && *p++ != '\n') continue; } @@ -27486,7 +27497,7 @@ static const char *skip_lines(const char *p, int n) { static void print_lines(const char *source, int line, int line1) { const char *s = source; const char *p = skip_lines(s, line); - if (*p) { + if (p && *p) { while (line++ < line1) { p = skip_lines(s = p, 1); printf(";; %.*s", (int)(p - s), s);