More complete fix with some debugging tools.

This commit is contained in:
Calvin Rose 2023-07-02 13:04:42 -05:00
parent a5f4e4d328
commit 9bc5bec9f1
3 changed files with 58 additions and 27 deletions

View File

@ -405,7 +405,7 @@ static void janet_stream_marshal(void *p, JanetMarshalContext *ctx) {
#ifdef JANET_WINDOWS #ifdef JANET_WINDOWS
/* TODO - ref counting to avoid situation where a handle is closed or GCed /* TODO - ref counting to avoid situation where a handle is closed or GCed
* while in transit, and it's value gets reused. DuplicateHandle does not work * while in transit, and it's value gets reused. DuplicateHandle does not work
* for network sockets, and in general for winsock it is better to nipt duplicate * for network sockets, and in general for winsock it is better to not duplicate
* unless there is a need to. */ * unless there is a need to. */
HANDLE duph = INVALID_HANDLE_VALUE; HANDLE duph = INVALID_HANDLE_VALUE;
if (s->flags & JANET_STREAM_SOCKET) { if (s->flags & JANET_STREAM_SOCKET) {

View File

@ -246,6 +246,7 @@ static void marshal_one_def(MarshalState *st, JanetFuncDef *def, int flags) {
} }
/* Add to lookup */ /* Add to lookup */
janet_v_push(st->seen_defs, def); janet_v_push(st->seen_defs, def);
pushint(st, def->flags); pushint(st, def->flags);
pushint(st, def->slotcount); pushint(st, def->slotcount);
pushint(st, def->arity); pushint(st, def->arity);
@ -266,14 +267,14 @@ static void marshal_one_def(MarshalState *st, JanetFuncDef *def, int flags) {
/* marshal constants */ /* marshal constants */
for (int32_t i = 0; i < def->constants_length; i++) for (int32_t i = 0; i < def->constants_length; i++)
marshal_one(st, def->constants[i], flags); marshal_one(st, def->constants[i], flags + 1);
/* Marshal symbol map, if needed */ /* Marshal symbol map, if needed */
for (int32_t i = 0; i < def->symbolmap_length; i++) { for (int32_t i = 0; i < def->symbolmap_length; i++) {
pushint(st, (int32_t) def->symbolmap[i].birth_pc); pushint(st, (int32_t) def->symbolmap[i].birth_pc);
pushint(st, (int32_t) def->symbolmap[i].death_pc); pushint(st, (int32_t) def->symbolmap[i].death_pc);
pushint(st, (int32_t) def->symbolmap[i].slot_index); pushint(st, (int32_t) def->symbolmap[i].slot_index);
marshal_one(st, janet_wrap_symbol(def->symbolmap[i].symbol), flags); marshal_one(st, janet_wrap_symbol(def->symbolmap[i].symbol), flags + 1);
} }
/* marshal the bytecode */ /* marshal the bytecode */
@ -387,18 +388,27 @@ void janet_marshal_janet(JanetMarshalContext *ctx, Janet x) {
marshal_one(st, x, ctx->flags + 1); marshal_one(st, x, ctx->flags + 1);
} }
#ifdef JANET_MARSHAL_DEBUG
#define MARK_SEEN() \
do { if (st->maybe_cycles) { \
Janet _check = janet_table_get(&st->seen, x); \
if (!janet_checktype(_check, JANET_NIL)) janet_eprintf("double MARK_SEEN on %v\n", x); \
janet_eprintf("made reference %d (%t) to %v\n", st->nextid, x, x); \
janet_table_put(&st->seen, x, janet_wrap_integer(st->nextid++)); \
} } while (0)
#else
#define MARK_SEEN() \
do { if (st->maybe_cycles) { \
janet_table_put(&st->seen, x, janet_wrap_integer(st->nextid++)); \
} } while (0)
#endif
void janet_marshal_abstract(JanetMarshalContext *ctx, void *abstract) { void janet_marshal_abstract(JanetMarshalContext *ctx, void *abstract) {
MarshalState *st = (MarshalState *)(ctx->m_state); MarshalState *st = (MarshalState *)(ctx->m_state);
if (st->maybe_cycles) { Janet x = janet_wrap_abstract(abstract);
janet_table_put(&st->seen, MARK_SEEN();
janet_wrap_abstract(abstract),
janet_wrap_integer(st->nextid++));
}
} }
#define MARK_SEEN() \
do { if (st->maybe_cycles) janet_table_put(&st->seen, x, janet_wrap_integer(st->nextid++)); } while (0)
static void marshal_one_abstract(MarshalState *st, Janet x, int flags) { static void marshal_one_abstract(MarshalState *st, Janet x, int flags) {
void *abstract = janet_unwrap_abstract(x); void *abstract = janet_unwrap_abstract(x);
#ifdef JANET_EV #ifdef JANET_EV
@ -420,9 +430,8 @@ static void marshal_one_abstract(MarshalState *st, Janet x, int flags) {
if (at->marshal) { if (at->marshal) {
pushbyte(st, LB_ABSTRACT); pushbyte(st, LB_ABSTRACT);
marshal_one(st, janet_csymbolv(at->name), flags + 1); marshal_one(st, janet_csymbolv(at->name), flags + 1);
JanetMarshalContext context = {st, NULL, flags, NULL, at}; JanetMarshalContext context = {st, NULL, flags + 1, NULL, at};
at->marshal(abstract, &context); at->marshal(abstract, &context);
MARK_SEEN();
} else { } else {
janet_panicf("cannot marshal %p", x); janet_panicf("cannot marshal %p", x);
} }
@ -738,9 +747,22 @@ static uint64_t read64(UnmarshalState *st, const uint8_t **atdata) {
return ret; return ret;
} }
#ifdef JANET_MARSHAL_DEBUG
static void dump_reference_table(UnmarshalState *st) {
for (int32_t i = 0; i < janet_v_count(st->lookup); i++) {
janet_eprintf(" reference %d (%t) = %v\n", i, st->lookup[i], st->lookup[i]);
}
}
#endif
/* Assert a janet type */ /* Assert a janet type */
static void janet_asserttype(Janet x, JanetType t) { static void janet_asserttype(Janet x, JanetType t, UnmarshalState *st) {
if (!janet_checktype(x, t)) { if (!janet_checktype(x, t)) {
#ifdef JANET_MARSHAL_DEBUG
dump_reference_table(st);
#else
(void) st;
#endif
janet_panicf("expected type %T, got %v", 1 << t, x); janet_panicf("expected type %T, got %v", 1 << t, x);
} }
} }
@ -792,7 +814,7 @@ static const uint8_t *unmarshal_one_env(
Janet fiberv; Janet fiberv;
/* On stack variant */ /* On stack variant */
data = unmarshal_one(st, data, &fiberv, flags); data = unmarshal_one(st, data, &fiberv, flags);
janet_asserttype(fiberv, JANET_FIBER); janet_asserttype(fiberv, JANET_FIBER, st);
env->as.fiber = janet_unwrap_fiber(fiberv); env->as.fiber = janet_unwrap_fiber(fiberv);
/* Negative offset indicates untrusted input */ /* Negative offset indicates untrusted input */
env->offset = -offset; env->offset = -offset;
@ -890,13 +912,13 @@ static const uint8_t *unmarshal_one_def(
if (def->flags & JANET_FUNCDEF_FLAG_HASNAME) { if (def->flags & JANET_FUNCDEF_FLAG_HASNAME) {
Janet x; Janet x;
data = unmarshal_one(st, data, &x, flags + 1); data = unmarshal_one(st, data, &x, flags + 1);
janet_asserttype(x, JANET_STRING); janet_asserttype(x, JANET_STRING, st);
def->name = janet_unwrap_string(x); def->name = janet_unwrap_string(x);
} }
if (def->flags & JANET_FUNCDEF_FLAG_HASSOURCE) { if (def->flags & JANET_FUNCDEF_FLAG_HASSOURCE) {
Janet x; Janet x;
data = unmarshal_one(st, data, &x, flags + 1); data = unmarshal_one(st, data, &x, flags + 1);
janet_asserttype(x, JANET_STRING); janet_asserttype(x, JANET_STRING, st);
def->source = janet_unwrap_string(x); def->source = janet_unwrap_string(x);
} }
@ -926,8 +948,9 @@ static const uint8_t *unmarshal_one_def(
def->symbolmap[i].slot_index = (uint32_t) readint(st, &data); def->symbolmap[i].slot_index = (uint32_t) readint(st, &data);
Janet value; Janet value;
data = unmarshal_one(st, data, &value, flags + 1); data = unmarshal_one(st, data, &value, flags + 1);
if (!janet_checktype(value, JANET_SYMBOL)) if (!janet_checktype(value, JANET_SYMBOL)) {
janet_panicf("expected symbol in unmarshal, got %v", value); janet_panicf("corrupted symbolmap when unmarshalling debug info, got %v", value);
}
def->symbolmap[i].symbol = janet_unwrap_symbol(value); def->symbolmap[i].symbol = janet_unwrap_symbol(value);
} }
def->symbolmap_length = (uint32_t) symbolmap_length; def->symbolmap_length = (uint32_t) symbolmap_length;
@ -1076,7 +1099,7 @@ static const uint8_t *unmarshal_one_fiber(
/* Get function */ /* Get function */
Janet funcv; Janet funcv;
data = unmarshal_one(st, data, &funcv, flags + 1); data = unmarshal_one(st, data, &funcv, flags + 1);
janet_asserttype(funcv, JANET_FUNCTION); janet_asserttype(funcv, JANET_FUNCTION, st);
func = janet_unwrap_function(funcv); func = janet_unwrap_function(funcv);
def = func->def; def = func->def;
@ -1122,7 +1145,7 @@ static const uint8_t *unmarshal_one_fiber(
Janet envv; Janet envv;
fiber_flags &= ~JANET_FIBER_FLAG_HASENV; fiber_flags &= ~JANET_FIBER_FLAG_HASENV;
data = unmarshal_one(st, data, &envv, flags + 1); data = unmarshal_one(st, data, &envv, flags + 1);
janet_asserttype(envv, JANET_TABLE); janet_asserttype(envv, JANET_TABLE, st);
fiber_env = janet_unwrap_table(envv); fiber_env = janet_unwrap_table(envv);
} }
@ -1131,7 +1154,7 @@ static const uint8_t *unmarshal_one_fiber(
Janet fiberv; Janet fiberv;
fiber_flags &= ~JANET_FIBER_FLAG_HASCHILD; fiber_flags &= ~JANET_FIBER_FLAG_HASCHILD;
data = unmarshal_one(st, data, &fiberv, flags + 1); data = unmarshal_one(st, data, &fiberv, flags + 1);
janet_asserttype(fiberv, JANET_FIBER); janet_asserttype(fiberv, JANET_FIBER, st);
fiber->child = janet_unwrap_fiber(fiberv); fiber->child = janet_unwrap_fiber(fiberv);
} }
@ -1229,11 +1252,12 @@ static const uint8_t *unmarshal_one_abstract(UnmarshalState *st, const uint8_t *
if (at == NULL) janet_panic("unknown abstract type"); if (at == NULL) janet_panic("unknown abstract type");
if (at->unmarshal) { if (at->unmarshal) {
JanetMarshalContext context = {NULL, st, flags, data, at}; JanetMarshalContext context = {NULL, st, flags, data, at};
*out = janet_wrap_abstract(at->unmarshal(&context)); void *abst = at->unmarshal(&context);
janet_assert(abst != NULL, "null pointer abstract");
*out = janet_wrap_abstract(abst);
if (context.at != NULL) { if (context.at != NULL) {
janet_panic("janet_unmarshal_abstract not called"); janet_panic("janet_unmarshal_abstract not called");
} }
janet_v_push(st->lookup, *out);
return context.data; return context.data;
} }
janet_panic("invalid abstract type - no unmarshal function pointer"); janet_panic("invalid abstract type - no unmarshal function pointer");
@ -1331,7 +1355,7 @@ static const uint8_t *unmarshal_one(
} }
case LB_FIBER: { case LB_FIBER: {
JanetFiber *fiber; JanetFiber *fiber;
data = unmarshal_one_fiber(st, data + 1, &fiber, flags); data = unmarshal_one_fiber(st, data + 1, &fiber, flags + 1);
*out = janet_wrap_fiber(fiber); *out = janet_wrap_fiber(fiber);
return data; return data;
} }
@ -1346,6 +1370,9 @@ static const uint8_t *unmarshal_one(
func = janet_gcalloc(JANET_MEMORY_FUNCTION, sizeof(JanetFunction) + func = janet_gcalloc(JANET_MEMORY_FUNCTION, sizeof(JanetFunction) +
len * sizeof(JanetFuncEnv)); len * sizeof(JanetFuncEnv));
func->def = NULL; func->def = NULL;
for (int32_t i = 0; i < len; i++) {
func->envs[i] = NULL;
}
*out = janet_wrap_function(func); *out = janet_wrap_function(func);
janet_v_push(st->lookup, *out); janet_v_push(st->lookup, *out);
data = unmarshal_one_def(st, data, &def, flags + 1); data = unmarshal_one_def(st, data, &def, flags + 1);
@ -1399,7 +1426,7 @@ static const uint8_t *unmarshal_one(
if (lead == LB_STRUCT_PROTO) { if (lead == LB_STRUCT_PROTO) {
Janet proto; Janet proto;
data = unmarshal_one(st, data, &proto, flags + 1); data = unmarshal_one(st, data, &proto, flags + 1);
janet_asserttype(proto, JANET_STRUCT); janet_asserttype(proto, JANET_STRUCT, st);
janet_struct_proto(struct_) = janet_unwrap_struct(proto); janet_struct_proto(struct_) = janet_unwrap_struct(proto);
} }
for (int32_t i = 0; i < len; i++) { for (int32_t i = 0; i < len; i++) {
@ -1422,7 +1449,7 @@ static const uint8_t *unmarshal_one(
if (lead == LB_TABLE_PROTO) { if (lead == LB_TABLE_PROTO) {
Janet proto; Janet proto;
data = unmarshal_one(st, data, &proto, flags + 1); data = unmarshal_one(st, data, &proto, flags + 1);
janet_asserttype(proto, JANET_TABLE); janet_asserttype(proto, JANET_TABLE, st);
t->proto = janet_unwrap_table(proto); t->proto = janet_unwrap_table(proto);
} }
for (int32_t i = 0; i < len; i++) { for (int32_t i = 0; i < len; i++) {

View File

@ -250,6 +250,10 @@ void janet_to_string_b(JanetBuffer *buffer, Janet x) {
case JANET_FUNCTION: { case JANET_FUNCTION: {
JanetFunction *fun = janet_unwrap_function(x); JanetFunction *fun = janet_unwrap_function(x);
JanetFuncDef *def = fun->def; JanetFuncDef *def = fun->def;
if (def == NULL) {
janet_buffer_push_cstring(buffer, "<incomplete function>");
break;
}
if (def->name) { if (def->name) {
const uint8_t *n = def->name; const uint8_t *n = def->name;
janet_buffer_push_cstring(buffer, "<function "); janet_buffer_push_cstring(buffer, "<function ");