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
This commit is contained in:
Charlie Gordon 2024-04-08 21:25:01 +02:00 committed by GitHub
parent 56593f419b
commit 97c918662b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -3012,19 +3012,22 @@ static const char *JS_AtomGetStrRT(JSRuntime *rt, char *buf, int buf_size,
{ {
if (__JS_AtomIsTaggedInt(atom)) { if (__JS_AtomIsTaggedInt(atom)) {
snprintf(buf, buf_size, "%u", __JS_AtomToUInt32(atom)); snprintf(buf, buf_size, "%u", __JS_AtomToUInt32(atom));
} else { } else if (atom == JS_ATOM_NULL) {
JSAtomStruct *p; snprintf(buf, buf_size, "<null>");
} else if (atom >= rt->atom_size) {
assert(atom < rt->atom_size); assert(atom < rt->atom_size);
if (atom == JS_ATOM_NULL) { snprintf(buf, buf_size, "<invalid %x>", atom);
snprintf(buf, buf_size, "<null>"); } else {
JSAtomStruct *p = rt->atom_array[atom];
if (atom_is_free(p)) {
assert(!atom_is_free(p));
snprintf(buf, buf_size, "<free %x>", atom);
} else { } else {
int i, c; int i, c;
char *q; char *q;
JSString *str; JSString *str;
q = buf; q = buf;
p = rt->atom_array[atom];
assert(!atom_is_free(p));
str = p; str = p;
if (str) { if (str) {
if (!str->is_wide_char) { if (!str->is_wide_char) {
@ -5454,12 +5457,16 @@ void __JS_FreeValueRT(JSRuntime *rt, JSValue v)
#ifdef DUMP_FREE #ifdef DUMP_FREE
{ {
printf("Freeing "); /* Prevent invalid object access during GC */
if (tag == JS_TAG_OBJECT) { if ((rt->gc_phase != JS_GC_PHASE_REMOVE_CYCLES)
JS_DumpObject(rt, JS_VALUE_GET_OBJ(v)); || (tag != JS_TAG_OBJECT && tag != JS_TAG_FUNCTION_BYTECODE)) {
} else { printf("Freeing ");
JS_DumpValue(rt, v); if (tag == JS_TAG_OBJECT) {
printf("\n"); JS_DumpObject(rt, JS_VALUE_GET_OBJ(v));
} else {
JS_DumpValue(rt, v);
printf("\n");
}
} }
} }
#endif #endif
@ -11708,7 +11715,11 @@ static __maybe_unused void JS_DumpValue(JSRuntime *rt, JSValue val)
{ {
JSFunctionBytecode *b = JS_VALUE_GET_PTR(val); JSFunctionBytecode *b = JS_VALUE_GET_PTR(val);
char buf[ATOM_GET_STR_BUF_SIZE]; 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; break;
case JS_TAG_OBJECT: case JS_TAG_OBJECT:
@ -27476,7 +27487,7 @@ static void js_free_function_def(JSContext *ctx, JSFunctionDef *fd)
#ifdef DUMP_BYTECODE #ifdef DUMP_BYTECODE
static const char *skip_lines(const char *p, int n) { static const char *skip_lines(const char *p, int n) {
while (n-- > 0 && *p) { while (p && n-- > 0 && *p) {
while (*p && *p++ != '\n') while (*p && *p++ != '\n')
continue; 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) { static void print_lines(const char *source, int line, int line1) {
const char *s = source; const char *s = source;
const char *p = skip_lines(s, line); const char *p = skip_lines(s, line);
if (*p) { if (p && *p) {
while (line++ < line1) { while (line++ < line1) {
p = skip_lines(s = p, 1); p = skip_lines(s = p, 1);
printf(";; %.*s", (int)(p - s), s); printf(";; %.*s", (int)(p - s), s);