fix mem errors for mcode
This commit is contained in:
121
source/quickjs.c
121
source/quickjs.c
@@ -22264,7 +22264,8 @@ static JSValue js_cell_text_replace (JSContext *ctx, JSValue this_val, int argc,
|
||||
b_ref.val = JS_MKPTR (b);
|
||||
|
||||
/* Macro to re-chase b from GC ref before use */
|
||||
#define B_RECHASE() b = (JSText *)JS_VALUE_GET_PTR (chase (b_ref.val))
|
||||
#define B_RECHASE() b = (JSText *)chase (b_ref.val)
|
||||
|
||||
/* Macro to update b_ref after b changes */
|
||||
#define B_UPDATE(new_b) do { b = (new_b); b_ref.val = JS_MKPTR (b); } while(0)
|
||||
#define B_CLEANUP() JS_PopGCRef (ctx, &b_ref)
|
||||
@@ -22896,8 +22897,10 @@ static JSValue js_cell_text_format (JSContext *ctx, JSValue this_val, int argc,
|
||||
format_spec = JS_KEY_empty;
|
||||
}
|
||||
|
||||
/* Get value from collection */
|
||||
JSValue coll_value = JS_NULL;
|
||||
/* Get value from collection — protect with GCRef since JS_Call below can trigger GC */
|
||||
JSGCRef cv_ref;
|
||||
JS_PushGCRef (ctx, &cv_ref);
|
||||
cv_ref.val = JS_NULL;
|
||||
if (is_array) {
|
||||
int name_len = js_string_value_len (name_val);
|
||||
int32_t idx = 0;
|
||||
@@ -22910,10 +22913,10 @@ static JSValue js_cell_text_format (JSContext *ctx, JSValue this_val, int argc,
|
||||
valid = 0;
|
||||
}
|
||||
if (valid && idx >= 0) {
|
||||
coll_value = JS_GetPropertyUint32 (ctx, coll_ref.val, (uint32_t)idx);
|
||||
cv_ref.val = JS_GetPropertyUint32 (ctx, coll_ref.val, (uint32_t)idx);
|
||||
}
|
||||
} else {
|
||||
coll_value = JS_GetProperty (ctx, coll_ref.val, name_val);
|
||||
cv_ref.val = JS_GetProperty (ctx, coll_ref.val, name_val);
|
||||
}
|
||||
|
||||
/* Try to get substitution */
|
||||
@@ -22922,7 +22925,7 @@ static JSValue js_cell_text_format (JSContext *ctx, JSValue this_val, int argc,
|
||||
|
||||
if (!JS_IsNull (xform_ref.val)) {
|
||||
if (JS_IsFunction (xform_ref.val)) {
|
||||
JSValue args[2] = { coll_value, format_spec };
|
||||
JSValue args[2] = { cv_ref.val, format_spec };
|
||||
JSValue result_val = JS_Call (ctx, xform_ref.val, JS_NULL, 2, args);
|
||||
if (JS_IsText (result_val)) {
|
||||
substitution = result_val;
|
||||
@@ -22931,7 +22934,7 @@ static JSValue js_cell_text_format (JSContext *ctx, JSValue this_val, int argc,
|
||||
} else if (JS_IsRecord (xform_ref.val)) {
|
||||
JSValue func = JS_GetProperty (ctx, xform_ref.val, format_spec);
|
||||
if (JS_IsFunction (func)) {
|
||||
JSValue result_val = JS_Call (ctx, func, JS_NULL, 1, &coll_value);
|
||||
JSValue result_val = JS_Call (ctx, func, JS_NULL, 1, &cv_ref.val);
|
||||
if (JS_IsText (result_val)) {
|
||||
substitution = result_val;
|
||||
made_substitution = 1;
|
||||
@@ -22940,10 +22943,10 @@ static JSValue js_cell_text_format (JSContext *ctx, JSValue this_val, int argc,
|
||||
}
|
||||
}
|
||||
|
||||
if (!made_substitution && JS_IsNumber (coll_value) && !JS_IsNull (format_spec)) {
|
||||
JSValue text_method = JS_GetPropertyStr (ctx, coll_value, "text");
|
||||
if (!made_substitution && JS_IsNumber (cv_ref.val) && !JS_IsNull (format_spec)) {
|
||||
JSValue text_method = JS_GetPropertyStr (ctx, cv_ref.val, "text");
|
||||
if (JS_IsFunction (text_method)) {
|
||||
JSValue result_val = JS_Call (ctx, text_method, coll_value, 1, &format_spec);
|
||||
JSValue result_val = JS_Call (ctx, text_method, cv_ref.val, 1, &format_spec);
|
||||
if (JS_IsText (result_val)) {
|
||||
substitution = result_val;
|
||||
made_substitution = 1;
|
||||
@@ -22951,13 +22954,14 @@ static JSValue js_cell_text_format (JSContext *ctx, JSValue this_val, int argc,
|
||||
}
|
||||
}
|
||||
|
||||
if (!made_substitution && !JS_IsNull (coll_value)) {
|
||||
JSValue conv_text_val = JS_ToString (ctx, coll_value);
|
||||
if (!made_substitution && !JS_IsNull (cv_ref.val)) {
|
||||
JSValue conv_text_val = JS_ToString (ctx, cv_ref.val);
|
||||
if (JS_IsText (conv_text_val)) {
|
||||
substitution = conv_text_val;
|
||||
made_substitution = 1;
|
||||
}
|
||||
}
|
||||
JS_PopGCRef (ctx, &cv_ref);
|
||||
|
||||
result = (JSText *)chase (res_ref.val);
|
||||
if (made_substitution) {
|
||||
@@ -36107,12 +36111,16 @@ static JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj,
|
||||
}
|
||||
else if (strcmp(op, "concat_space") == 0) {
|
||||
int dest = (int)a1->valuedouble;
|
||||
JSValue left = frame->slots[(int)a2->valuedouble];
|
||||
JSValue right = frame->slots[(int)a3->valuedouble];
|
||||
int left_slot = (int)a2->valuedouble;
|
||||
int right_slot = (int)a3->valuedouble;
|
||||
JSValue left = frame->slots[left_slot];
|
||||
JSValue right = frame->slots[right_slot];
|
||||
if (!JS_IsText(left) || !JS_IsText(right)) { goto disrupt; }
|
||||
JSValue space = JS_ConcatString(ctx, left, JS_NewString(ctx, " "));
|
||||
JSValue space_str = JS_NewString(ctx, " ");
|
||||
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
||||
JSValue res = JS_ConcatString(ctx, space, right);
|
||||
JSValue space = JS_ConcatString(ctx, frame->slots[left_slot], space_str);
|
||||
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
||||
JSValue res = JS_ConcatString(ctx, space, frame->slots[right_slot]);
|
||||
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
||||
frame->slots[dest] = res;
|
||||
}
|
||||
@@ -36126,7 +36134,11 @@ static JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj,
|
||||
int dest = (int)a1->valuedouble;
|
||||
JSValue v = frame->slots[(int)a2->valuedouble];
|
||||
if (!JS_IsText(v)) { goto disrupt; }
|
||||
JSValue res = js_cell_text_lower(ctx, JS_NULL, 1, &v);
|
||||
int vs_base = ctx->value_stack_top;
|
||||
ctx->value_stack[vs_base] = v;
|
||||
ctx->value_stack_top = vs_base + 1;
|
||||
JSValue res = js_cell_text_lower(ctx, JS_NULL, 1, &ctx->value_stack[vs_base]);
|
||||
ctx->value_stack_top = vs_base;
|
||||
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
||||
frame->slots[dest] = res;
|
||||
}
|
||||
@@ -36134,7 +36146,11 @@ static JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj,
|
||||
int dest = (int)a1->valuedouble;
|
||||
JSValue v = frame->slots[(int)a2->valuedouble];
|
||||
if (!JS_IsText(v)) { goto disrupt; }
|
||||
JSValue res = js_cell_text_upper(ctx, JS_NULL, 1, &v);
|
||||
int vs_base = ctx->value_stack_top;
|
||||
ctx->value_stack[vs_base] = v;
|
||||
ctx->value_stack_top = vs_base + 1;
|
||||
JSValue res = js_cell_text_upper(ctx, JS_NULL, 1, &ctx->value_stack[vs_base]);
|
||||
ctx->value_stack_top = vs_base;
|
||||
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
||||
frame->slots[dest] = res;
|
||||
}
|
||||
@@ -36142,7 +36158,11 @@ static JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj,
|
||||
int dest = (int)a1->valuedouble;
|
||||
JSValue v = frame->slots[(int)a2->valuedouble];
|
||||
if (!JS_IsNumber(v)) { goto disrupt; }
|
||||
JSValue res = js_cell_character(ctx, JS_NULL, 1, &v);
|
||||
int vs_base = ctx->value_stack_top;
|
||||
ctx->value_stack[vs_base] = v;
|
||||
ctx->value_stack_top = vs_base + 1;
|
||||
JSValue res = js_cell_character(ctx, JS_NULL, 1, &ctx->value_stack[vs_base]);
|
||||
ctx->value_stack_top = vs_base;
|
||||
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
||||
frame->slots[dest] = res;
|
||||
}
|
||||
@@ -36150,7 +36170,11 @@ static JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj,
|
||||
int dest = (int)a1->valuedouble;
|
||||
JSValue v = frame->slots[(int)a2->valuedouble];
|
||||
if (!JS_IsText(v)) { goto disrupt; }
|
||||
JSValue res = js_cell_text_codepoint(ctx, JS_NULL, 1, &v);
|
||||
int vs_base = ctx->value_stack_top;
|
||||
ctx->value_stack[vs_base] = v;
|
||||
ctx->value_stack_top = vs_base + 1;
|
||||
JSValue res = js_cell_text_codepoint(ctx, JS_NULL, 1, &ctx->value_stack[vs_base]);
|
||||
ctx->value_stack_top = vs_base;
|
||||
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
||||
frame->slots[dest] = res;
|
||||
}
|
||||
@@ -36772,12 +36796,15 @@ static JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj,
|
||||
JSFunction *fn = JS_VALUE_GET_FUNCTION(method);
|
||||
if (fn->kind == JS_FUNC_KIND_MCODE) {
|
||||
/* mcode function — set up frame and jump */
|
||||
frame->slots[dest] = method; /* protect from GC */
|
||||
JSFrameRegister *new_frame = alloc_frame_register(ctx, fn->u.mcode.code->nr_slots);
|
||||
if (!new_frame) {
|
||||
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
||||
goto disrupt;
|
||||
}
|
||||
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
||||
method = frame->slots[dest]; /* re-read after GC */
|
||||
fn = JS_VALUE_GET_FUNCTION(method);
|
||||
new_frame->function = method;
|
||||
new_frame->slots[0] = frame->slots[obj_reg]; /* this */
|
||||
cJSON *p = a3->next;
|
||||
@@ -36982,21 +37009,21 @@ static JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj,
|
||||
else if (strcmp(op, "apply") == 0) {
|
||||
int func_slot = (int)a1->valuedouble;
|
||||
int arr_slot = (int)a2->valuedouble;
|
||||
JSValue func_val = frame->slots[func_slot];
|
||||
JSValue arr_val = frame->slots[arr_slot];
|
||||
if (!JS_IsFunction(func_val) || !JS_IsArray(arr_val)) { goto disrupt; }
|
||||
JSValue len_val = JS_GetProperty(ctx, arr_val, JS_KEY_length);
|
||||
if (!JS_IsFunction(frame->slots[func_slot]) || !JS_IsArray(frame->slots[arr_slot])) { goto disrupt; }
|
||||
JSValue len_val = JS_GetProperty(ctx, frame->slots[arr_slot], JS_KEY_length);
|
||||
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
||||
int len = JS_IsNumber(len_val) ? (int)JS_VALUE_GET_INT(len_val) : 0;
|
||||
JSValue argv[256];
|
||||
if (len > 256) len = 256;
|
||||
int vs_base = ctx->value_stack_top;
|
||||
for (int i = 0; i < len; i++) {
|
||||
argv[i] = JS_GetPropertyUint32(ctx, arr_val, i);
|
||||
ctx->value_stack[vs_base + i] = JS_GetPropertyUint32(ctx, frame->slots[arr_slot], i);
|
||||
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
||||
}
|
||||
ctx->value_stack_top = vs_base + len;
|
||||
ctx->reg_current_frame = frame_ref.val;
|
||||
ctx->rt->current_register_pc = pc > 0 ? pc - 1 : 0;
|
||||
result = JS_Call(ctx, func_val, JS_NULL, len, argv);
|
||||
result = JS_Call(ctx, frame->slots[func_slot], JS_NULL, len, &ctx->value_stack[vs_base]);
|
||||
ctx->value_stack_top = vs_base;
|
||||
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
||||
if (JS_IsException(result)) { goto disrupt; }
|
||||
}
|
||||
@@ -37064,11 +37091,15 @@ static JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj,
|
||||
/* ---- Append (to pretext) ---- */
|
||||
else if (strcmp(op, "append") == 0) {
|
||||
int pt_slot = (int)a1->valuedouble;
|
||||
JSValue right = frame->slots[(int)a2->valuedouble];
|
||||
JSValue pt_val = frame->slots[pt_slot];
|
||||
if (!JS_IsText(pt_val) || !JS_IsText(right)) { goto disrupt; }
|
||||
JSText *s = JS_VALUE_GET_PTR(pt_val);
|
||||
s = pretext_concat_value(ctx, s, right);
|
||||
int right_slot = (int)a2->valuedouble;
|
||||
if (!JS_IsText(frame->slots[pt_slot]) || !JS_IsText(frame->slots[right_slot])) { goto disrupt; }
|
||||
int vs_base = ctx->value_stack_top;
|
||||
ctx->value_stack[vs_base] = frame->slots[pt_slot];
|
||||
ctx->value_stack[vs_base + 1] = frame->slots[right_slot];
|
||||
ctx->value_stack_top = vs_base + 2;
|
||||
JSText *s = JS_VALUE_GET_PTR(ctx->value_stack[vs_base]);
|
||||
s = pretext_concat_value(ctx, s, ctx->value_stack[vs_base + 1]);
|
||||
ctx->value_stack_top = vs_base;
|
||||
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
||||
if (!s) { goto disrupt; }
|
||||
frame->slots[pt_slot] = JS_MKPTR(s);
|
||||
@@ -37091,15 +37122,18 @@ static JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj,
|
||||
const char *flags_str = a3 ? a3->valuestring : "";
|
||||
if (!pattern) pattern = "";
|
||||
if (!flags_str) flags_str = "";
|
||||
JSValue pat_val = JS_NewString(ctx, pattern);
|
||||
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);
|
||||
JSValue flags_val = *flags_str ? JS_NewString(ctx, flags_str) : JS_NULL;
|
||||
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);
|
||||
JSValue bc = js_compile_regexp(ctx, pat_val, flags_val);
|
||||
ctx->value_stack_top = vs_base + 2;
|
||||
JSValue bc = js_compile_regexp(ctx, ctx->value_stack[vs_base], ctx->value_stack[vs_base + 1]);
|
||||
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
||||
if (JS_IsException(bc)) { goto disrupt; }
|
||||
JSValue re_obj = js_regexp_constructor_internal(ctx, pat_val, bc);
|
||||
if (JS_IsException(bc)) { ctx->value_stack_top = vs_base; goto disrupt; }
|
||||
JSValue re_obj = js_regexp_constructor_internal(ctx, ctx->value_stack[vs_base], bc);
|
||||
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
||||
ctx->value_stack_top = vs_base;
|
||||
if (JS_IsException(re_obj)) { goto disrupt; }
|
||||
frame->slots[dest] = re_obj;
|
||||
}
|
||||
@@ -37108,22 +37142,19 @@ static JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj,
|
||||
else if (strcmp(op, "push") == 0) {
|
||||
int arr_slot = (int)a1->valuedouble;
|
||||
int val_slot = (int)a2->valuedouble;
|
||||
JSValue val = frame->slots[val_slot];
|
||||
if (!JS_IsArray(frame->slots[arr_slot])) { goto disrupt; }
|
||||
JSGCRef arr_gc;
|
||||
JS_PushGCRef(ctx, &arr_gc);
|
||||
arr_gc.val = frame->slots[arr_slot];
|
||||
int rc = JS_ArrayPush(ctx, &arr_gc.val, val);
|
||||
JSGCRef val_gc;
|
||||
JS_PushGCRef(ctx, &val_gc);
|
||||
val_gc.val = frame->slots[val_slot];
|
||||
int rc = JS_ArrayPush(ctx, &arr_gc.val, val_gc.val);
|
||||
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
||||
JS_PopGCRef(ctx, &val_gc);
|
||||
JS_PopGCRef(ctx, &arr_gc);
|
||||
if (rc < 0) goto disrupt;
|
||||
frame->slots[arr_slot] = arr_gc.val;
|
||||
/* If we pushed the array onto itself, the stored val may be stale
|
||||
(val was passed by value to JS_ArrayPush before GC could update it) */
|
||||
if (val_slot == arr_slot) {
|
||||
JSArray *a = JS_VALUE_GET_ARRAY(arr_gc.val);
|
||||
a->values[a->len - 1] = arr_gc.val;
|
||||
}
|
||||
}
|
||||
|
||||
/* ---- Pop (remove last from array) ---- */
|
||||
|
||||
Reference in New Issue
Block a user