From 80f24e131f9ef286c1d7e6267c0e4c34595ef656 Mon Sep 17 00:00:00 2001 From: John Alanbrook Date: Sat, 7 Feb 2026 16:15:58 -0600 Subject: [PATCH] all suite asan errors fixed for mcode --- Makefile | 2 +- source/quickjs.c | 163 ++--------------------------------------------- 2 files changed, 6 insertions(+), 159 deletions(-) diff --git a/Makefile b/Makefile index 261bd62a..287f1cdc 100755 --- a/Makefile +++ b/Makefile @@ -58,7 +58,7 @@ static: # Bootstrap: build cell from scratch using meson (only needed once) # Also installs core scripts to ~/.cell/core bootstrap: - meson setup build_bootstrap -Dbuildtype=debugoptimized + meson setup build_bootstrap -Dbuildtype=debug -Db_sanitize=address meson compile -C build_bootstrap cp build_bootstrap/cell . cp build_bootstrap/libcell_runtime.dylib . diff --git a/source/quickjs.c b/source/quickjs.c index 701b01ba..c04f43e2 100644 --- a/source/quickjs.c +++ b/source/quickjs.c @@ -2972,36 +2972,6 @@ static int ctx_gc (JSContext *ctx, int allow_grow, size_t alloc_size) { scan += obj_size; } - /* Post-GC verify: check all arrays have valid internal pointers */ - { - uint8_t *vp = to_base; - while (vp < to_free) { - objhdr_t vh = *(objhdr_t *)vp; - uint8_t vt = objhdr_type(vh); - if (vt == OBJ_ARRAY) { - JSArray *va = (JSArray *)vp; - for (uint32_t vi = 0; vi < va->len; vi++) { - JSValue ev = va->values[vi]; - if (JS_IsPtr(ev)) { - void *ep = JS_VALUE_GET_PTR(ev); - int in_to = ((uint8_t*)ep >= to_base && (uint8_t*)ep < to_free); - int is_st = is_stone_ptr(ctx, ep); - if (!in_to && !is_st) { - fprintf(stderr, "GC VERIFY FAIL: array@%p values[%u]=%p not in to-space [%p,%p) or stone\n", - (void*)va, vi, ep, (void*)to_base, (void*)to_free); - /* Check if it's in from-space (stale) */ - int in_from = ((uint8_t*)ep >= from_base && (uint8_t*)ep < from_end); - fprintf(stderr, " in_from=%d\n", in_from); - fflush(stderr); - } - } - } - } - size_t sz = gc_object_size(vp); - vp += sz; - } - } - /* Return old block (in poison mode, just poison it and leak) */ heap_block_free (rt, from_base, old_heap_size); @@ -4215,20 +4185,6 @@ static int js_intrinsic_array_set (JSContext *ctx, JSValue *arr_ptr, word_t idx, } arr->values[idx] = val; - /* DEBUG: check for stale values being stored */ - if (JS_IsPtr(val)) { - void *vp = JS_VALUE_GET_PTR(val); - int in_h = ((uint8_t*)vp >= ctx->heap_base && (uint8_t*)vp < ctx->heap_base + ctx->current_block_size); - int is_s = is_stone_ptr(ctx, vp); - if (!in_h && !is_s) { - fprintf(stderr, "STALE STORE into array[%lu]: ptr=%p heap=[%p,%p)\n", - (unsigned long)idx, vp, (void*)ctx->heap_base, (void*)(ctx->heap_base + ctx->current_block_size)); - fflush(stderr); - /* Deliberately trigger ASAN to get a stack trace */ - volatile uint8_t x = *(uint8_t*)vp; - (void)x; - } - } return 0; } @@ -22897,6 +22853,7 @@ static JSValue js_cell_text_extract (JSContext *ctx, JSValue this_val, int argc, /* Literal text path */ JSValue needle_val = JS_ToString (ctx, argv[1]); if (JS_IsException (needle_val)) return JS_EXCEPTION; + str = argv[0]; /* refresh after potential GC */ int needle_len = js_string_value_len (needle_val); @@ -22922,6 +22879,7 @@ static JSValue js_cell_text_extract (JSContext *ctx, JSValue this_val, int argc, JS_PushGCRef (ctx, &arr_ref); arr_ref.val = JS_NewArrayLen (ctx, 1); if (JS_IsException (arr_ref.val)) { JS_PopGCRef (ctx, &arr_ref); return JS_EXCEPTION; } + str = argv[0]; /* refresh after potential GC */ JSValue match = js_sub_string_val (ctx, str, pos, pos + needle_len); if (JS_IsException (match)) { JS_PopGCRef (ctx, &arr_ref); return JS_EXCEPTION; } @@ -23071,35 +23029,6 @@ static JSValue js_cell_text_format (JSContext *ctx, JSValue this_val, int argc, } if (valid && idx >= 0) { cv_ref.val = JS_GetPropertyUint32 (ctx, coll_ref.val, (uint32_t)idx); - if (JS_IsPtr(cv_ref.val)) { - void *dp = JS_VALUE_GET_PTR(cv_ref.val); - int in_h = ((uint8_t*)dp >= ctx->heap_base && (uint8_t*)dp < ctx->heap_base + ctx->current_block_size); - int is_s = is_stone_ptr(ctx, dp); - if (!in_h && !is_s) { - fprintf(stderr, "STALE right after GetPropertyUint32: ptr=%p idx=%d heap=[%p,%p)\n", - dp, idx, (void*)ctx->heap_base, (void*)(ctx->heap_base + ctx->current_block_size)); - /* Check the array and all its elements */ - JSArray *dbg_a = (JSArray *)chase(coll_ref.val); - void *ap = (void*)dbg_a; - int arr_in_h = ((uint8_t*)ap >= ctx->heap_base && (uint8_t*)ap < ctx->heap_base + ctx->current_block_size); - fprintf(stderr, " array ptr=%p in_heap=%d arr->len=%u hdr=0x%llx\n", ap, arr_in_h, (unsigned)dbg_a->len, (unsigned long long)dbg_a->mist_hdr); - for (uint32_t di = 0; di < dbg_a->len && di < 5; di++) { - JSValue ev = dbg_a->values[di]; - if (JS_IsPtr(ev)) { - void *evp = JS_VALUE_GET_PTR(ev); - int ev_in = ((uint8_t*)evp >= ctx->heap_base && (uint8_t*)evp < ctx->heap_base + ctx->current_block_size); - int ev_st = is_stone_ptr(ctx, evp); - fprintf(stderr, " arr[%u]=%p in_heap=%d stone=%d\n", di, evp, ev_in, ev_st); - } - } - /* Check the raw coll_ref.val pointer (before chase) */ - void *raw_arr = JS_VALUE_GET_PTR(coll_ref.val); - objhdr_t raw_hdr = *(objhdr_t*)raw_arr; - fprintf(stderr, " raw coll_ref ptr=%p hdr_type=%u is_fwd=%d\n", - raw_arr, objhdr_type(raw_hdr), objhdr_type(raw_hdr) == OBJ_FORWARD); - fflush(stderr); - } - } } } else { cv_ref.val = JS_GetProperty (ctx, coll_ref.val, name_val); @@ -23141,16 +23070,6 @@ static JSValue js_cell_text_format (JSContext *ctx, JSValue this_val, int argc, } if (!made_substitution && !JS_IsNull (cv_ref.val)) { - if (JS_IsPtr(cv_ref.val)) { - void *dbg_ptr = JS_VALUE_GET_PTR(cv_ref.val); - uint8_t *cur_base = ctx->heap_base; - uint8_t *cur_end = cur_base + ctx->current_block_size; - int in_cur = ((uint8_t*)dbg_ptr >= cur_base && (uint8_t*)dbg_ptr < cur_end); - int is_stone = is_stone_ptr(ctx, dbg_ptr); - fprintf(stderr, "DEBUG format: cv_ref.val=%p in_current=%d is_stone=%d is_array=%d top_gc=%p cv_ref_addr=%p heap=[%p,%p)\n", - dbg_ptr, in_cur, is_stone, is_array, (void*)ctx->top_gc_ref, (void*)&cv_ref, (void*)cur_base, (void*)cur_end); - fflush(stderr); - } JSValue conv_text_val = JS_ToString (ctx, cv_ref.val); if (JS_IsText (conv_text_val)) { substitution = conv_text_val; @@ -36050,27 +35969,6 @@ static JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj, cJSON *op_item = cJSON_GetArrayItem(instr, 0); const char *op = op_item->valuestring; - /* DEBUG: check all frame slots for stale pointers before each instruction */ - { - static const char *prev_op = "(start)"; - static int prev_pc = -1; - for (int si = 0; si < code->nr_slots; si++) { - JSValue sv = frame->slots[si]; - if (JS_IsPtr(sv)) { - void *sp = JS_VALUE_GET_PTR(sv); - int in_heap = ((uint8_t*)sp >= ctx->heap_base && (uint8_t*)sp < ctx->heap_base + ctx->current_block_size); - int in_stone = is_stone_ptr(ctx, sp); - if (!in_heap && !in_stone) { - fprintf(stderr, "STALE SLOT[%d]=%p before op '%s' pc=%d (prev='%s' pc=%d) heap=[%p,%p)\n", - si, sp, op, pc-1, prev_op, prev_pc, - (void*)ctx->heap_base, (void*)(ctx->heap_base + ctx->current_block_size)); - } - } - } - prev_op = op; - prev_pc = pc - 1; - } - /* Operand extraction helpers — items 1,2,3 */ cJSON *a1 = cJSON_GetArrayItem(instr, 1); cJSON *a2 = cJSON_GetArrayItem(instr, 2); @@ -37020,18 +36918,6 @@ static JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj, int vs_base = ctx->value_stack_top; for (int i = 0; i < c_argc; i++) { ctx->value_stack[vs_base + i] = new_frame->slots[i + 1]; - /* DEBUG: check for stale values */ - JSValue dbg_v = new_frame->slots[i + 1]; - if (JS_IsPtr(dbg_v)) { - void *dp = JS_VALUE_GET_PTR(dbg_v); - int in_h = ((uint8_t*)dp >= ctx->heap_base && (uint8_t*)dp < ctx->heap_base + ctx->current_block_size); - int is_s = is_stone_ptr(ctx, dp); - if (!in_h && !is_s) { - fprintf(stderr, "STALE invoke arg[%d]: ptr=%p heap=[%p,%p)\n", - i, dp, (void*)ctx->heap_base, (void*)(ctx->heap_base + ctx->current_block_size)); - fflush(stderr); - } - } } ctx->value_stack_top = vs_base + c_argc; ctx->reg_current_frame = frame_ref.val; @@ -37065,6 +36951,7 @@ static JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj, int vs_base = ctx->value_stack_top; ctx->value_stack[vs_base] = JS_NewString(ctx, method_name); frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val); + ctx->value_stack_top = vs_base + 1; /* protect key from GC */ JSValue arr = JS_NewArray(ctx); frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val); if (JS_IsException(arr)) goto disrupt; @@ -37161,6 +37048,7 @@ static JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj, /* Proxy call: obj(key, [args...]) */ int vs_base = ctx->value_stack_top; ctx->value_stack[vs_base] = key; /* protect key on value stack */ + ctx->value_stack_top = vs_base + 1; /* protect key from GC */ JSValue arr = JS_NewArray(ctx); frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val); if (JS_IsException(arr)) goto disrupt; @@ -37168,41 +37056,11 @@ static JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj, cJSON *p = a3->next; for (int i = 0; i < nargs; i++, p = p->next) { int areg = (int)p->valuedouble; - /* DEBUG: check if the value we're about to store is stale */ - JSValue dbg_val = frame->slots[areg]; - if (JS_IsPtr(dbg_val)) { - void *dvp = JS_VALUE_GET_PTR(dbg_val); - int dv_in = ((uint8_t*)dvp >= ctx->heap_base && (uint8_t*)dvp < ctx->heap_base + ctx->current_block_size); - int dv_st = is_stone_ptr(ctx, dvp); - if (!dv_in && !dv_st) { - fprintf(stderr, "STALE callmethod_dyn arg frame->slots[%d]=%p heap=[%p,%p)\n", - areg, dvp, (void*)ctx->heap_base, (void*)(ctx->heap_base + ctx->current_block_size)); - fflush(stderr); - } - } JS_SetPropertyUint32(ctx, frame->slots[dest], i, frame->slots[areg]); frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val); } ctx->value_stack[vs_base + 1] = frame->slots[dest]; ctx->value_stack_top = vs_base + 2; - /* DEBUG: verify array elements are in current heap */ - { - JSValue dbg_arr_v = ctx->value_stack[vs_base + 1]; - JSArray *dbg_arr = (JSArray *)chase(dbg_arr_v); - for (uint32_t di = 0; di < dbg_arr->len; di++) { - JSValue ev = dbg_arr->values[di]; - if (JS_IsPtr(ev)) { - void *ep = JS_VALUE_GET_PTR(ev); - int in_heap = ((uint8_t*)ep >= ctx->heap_base && (uint8_t*)ep < ctx->heap_base + ctx->current_block_size); - int is_st = is_stone_ptr(ctx, ep); - if (!in_heap && !is_st) { - fprintf(stderr, "STALE in callmethod_dyn array[%u]: ptr=%p heap=[%p,%p) nargs=%d\n", - di, ep, (void*)ctx->heap_base, (void*)(ctx->heap_base + ctx->current_block_size), nargs); - fflush(stderr); - } - } - } - } ctx->reg_current_frame = frame_ref.val; ctx->rt->current_register_pc = pc > 0 ? pc - 1 : 0; JSValue ret = JS_CallInternal(ctx, frame->slots[obj_reg], JS_NULL, 2, &ctx->value_stack[vs_base], 0); @@ -37380,18 +37238,6 @@ static JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj, cJSON *elem = cJSON_GetArrayItem(instr, 3 + i); if (elem) { int elem_slot = (int)elem->valuedouble; - /* DEBUG: check if elem is stale before SetProperty */ - JSValue dbg_ev = frame->slots[elem_slot]; - if (JS_IsPtr(dbg_ev)) { - void *ep = JS_VALUE_GET_PTR(dbg_ev); - int in_h = ((uint8_t*)ep >= ctx->heap_base && (uint8_t*)ep < ctx->heap_base + ctx->current_block_size); - int is_s = is_stone_ptr(ctx, ep); - if (!in_h && !is_s) { - fprintf(stderr, "STALE ELEM in array op: slot[%d]=%p heap=[%p,%p) i=%d nr_elems=%d\n", - elem_slot, ep, (void*)ctx->heap_base, (void*)(ctx->heap_base + ctx->current_block_size), i, nr_elems); - fflush(stderr); - } - } JS_SetPropertyUint32(ctx, frame->slots[dest], i, frame->slots[elem_slot]); frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val); } @@ -37470,6 +37316,7 @@ static JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj, int vs_base = ctx->value_stack_top; ctx->value_stack[vs_base] = JS_NewString(ctx, pattern); /* pat_val */ frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val); + ctx->value_stack_top = vs_base + 1; /* protect pattern from GC */ ctx->value_stack[vs_base + 1] = *flags_str ? JS_NewString(ctx, flags_str) : JS_NULL; /* flags_val */ frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val); ctx->value_stack_top = vs_base + 2;