mirror of
https://github.com/ashinn/chibi-scheme.git
synced 2025-05-19 13:49:17 +02:00
Merge pull request #640 from Donaim/601
Prevent stack overflow in sexp_mark_one (issue #601)
This commit is contained in:
commit
af7189e895
4 changed files with 65 additions and 6 deletions
56
gc.c
56
gc.c
|
@ -225,7 +225,35 @@ int sexp_valid_object_p (sexp ctx, sexp x) {
|
||||||
#define sexp_gc_pass_ctx(x)
|
#define sexp_gc_pass_ctx(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void sexp_mark_one (sexp_gc_pass_ctx(sexp ctx) sexp* types, sexp x) {
|
static void sexp_mark_stack_push (sexp ctx, sexp *start, sexp *end) {
|
||||||
|
struct sexp_mark_stack_ptr_t *stack = sexp_context_mark_stack(ctx);
|
||||||
|
struct sexp_mark_stack_ptr_t **ptr = &sexp_context_mark_stack_ptr(ctx);
|
||||||
|
struct sexp_mark_stack_ptr_t *old = *ptr;
|
||||||
|
|
||||||
|
if (old == NULL) {
|
||||||
|
*ptr = stack;
|
||||||
|
} else if (old >= stack && old + 1 < stack + SEXP_MARK_STACK_COUNT) {
|
||||||
|
(*ptr)++;
|
||||||
|
} else {
|
||||||
|
*ptr = malloc(sizeof(**ptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
(*ptr)->start = start;
|
||||||
|
(*ptr)->end = end;
|
||||||
|
(*ptr)->prev = old;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sexp_mark_stack_pop (sexp ctx) {
|
||||||
|
struct sexp_mark_stack_ptr_t *stack = sexp_context_mark_stack(ctx);
|
||||||
|
struct sexp_mark_stack_ptr_t *old = sexp_context_mark_stack_ptr(ctx);
|
||||||
|
|
||||||
|
sexp_context_mark_stack_ptr(ctx) = old->prev;
|
||||||
|
if (!(old >= stack && old < stack + SEXP_MARK_STACK_COUNT)) {
|
||||||
|
free(old);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sexp_mark_one (sexp ctx, sexp* types, sexp x) {
|
||||||
sexp_sint_t len;
|
sexp_sint_t len;
|
||||||
sexp t, *p, *q;
|
sexp t, *p, *q;
|
||||||
struct sexp_gc_var_t *saves;
|
struct sexp_gc_var_t *saves;
|
||||||
|
@ -235,7 +263,7 @@ void sexp_mark_one (sexp_gc_pass_ctx(sexp ctx) sexp* types, sexp x) {
|
||||||
sexp_markedp(x) = 1;
|
sexp_markedp(x) = 1;
|
||||||
if (sexp_contextp(x)) {
|
if (sexp_contextp(x)) {
|
||||||
for (saves=sexp_context_saves(x); saves; saves=saves->next)
|
for (saves=sexp_context_saves(x); saves; saves=saves->next)
|
||||||
if (saves->var) sexp_mark_one(sexp_gc_pass_ctx(ctx) types, *(saves->var));
|
if (saves->var) sexp_mark_one(ctx, types, *(saves->var));
|
||||||
}
|
}
|
||||||
t = types[sexp_pointer_tag(x)];
|
t = types[sexp_pointer_tag(x)];
|
||||||
len = sexp_type_num_slots_of_object(t, x) - 1;
|
len = sexp_type_num_slots_of_object(t, x) - 1;
|
||||||
|
@ -246,15 +274,31 @@ void sexp_mark_one (sexp_gc_pass_ctx(sexp ctx) sexp* types, sexp x) {
|
||||||
q--; /* skip trailing immediates */
|
q--; /* skip trailing immediates */
|
||||||
while (p < q && *q == q[-1])
|
while (p < q && *q == q[-1])
|
||||||
q--; /* skip trailing duplicates */
|
q--; /* skip trailing duplicates */
|
||||||
while (p < q)
|
if (p < q) {
|
||||||
sexp_mark_one(sexp_gc_pass_ctx(ctx) types, *p++);
|
sexp_mark_stack_push(ctx, p, q);
|
||||||
x = *p;
|
}
|
||||||
|
x = *q;
|
||||||
goto loop;
|
goto loop;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void sexp_mark_one_start (sexp ctx, sexp* types, sexp x) {
|
||||||
|
struct sexp_mark_stack_ptr_t **ptr = &sexp_context_mark_stack_ptr(ctx);
|
||||||
|
sexp *p, *q;
|
||||||
|
sexp_mark_one(ctx, types, x);
|
||||||
|
|
||||||
|
while (*ptr) {
|
||||||
|
p = (*ptr)->start;
|
||||||
|
q = (*ptr)->end;
|
||||||
|
sexp_mark_stack_pop(ctx);
|
||||||
|
while (p < q) {
|
||||||
|
sexp_mark_one(ctx, types, *p++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void sexp_mark (sexp ctx, sexp x) {
|
void sexp_mark (sexp ctx, sexp x) {
|
||||||
sexp_mark_one(sexp_gc_pass_ctx(ctx) sexp_vector_data(sexp_global(ctx, SEXP_G_TYPES)), x);
|
sexp_mark_one_start(ctx, sexp_vector_data(sexp_global(ctx, SEXP_G_TYPES)), x);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SEXP_USE_CONSERVATIVE_GC
|
#if SEXP_USE_CONSERVATIVE_GC
|
||||||
|
|
|
@ -278,6 +278,10 @@
|
||||||
#define SEXP_GROW_HEAP_FACTOR 2 /* 1.6180339887498948482 */
|
#define SEXP_GROW_HEAP_FACTOR 2 /* 1.6180339887498948482 */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* size of per-context stack that is used during gc cycles
|
||||||
|
* increase if you can affort extra unused memory */
|
||||||
|
#define SEXP_MARK_STACK_COUNT 1024
|
||||||
|
|
||||||
/* the default number of opcodes to run each thread for */
|
/* the default number of opcodes to run each thread for */
|
||||||
#ifndef SEXP_DEFAULT_QUANTUM
|
#ifndef SEXP_DEFAULT_QUANTUM
|
||||||
#define SEXP_DEFAULT_QUANTUM 500
|
#define SEXP_DEFAULT_QUANTUM 500
|
||||||
|
|
|
@ -393,6 +393,11 @@ struct sexp_core_form_struct {
|
||||||
sexp name;
|
sexp name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct sexp_mark_stack_ptr_t {
|
||||||
|
sexp *start, *end;
|
||||||
|
struct sexp_mark_stack_ptr_t *prev; /* TODO: remove for allocations on stack */
|
||||||
|
};
|
||||||
|
|
||||||
struct sexp_struct {
|
struct sexp_struct {
|
||||||
sexp_tag_t tag;
|
sexp_tag_t tag;
|
||||||
char markedp;
|
char markedp;
|
||||||
|
@ -538,6 +543,8 @@ struct sexp_struct {
|
||||||
} stack;
|
} stack;
|
||||||
struct {
|
struct {
|
||||||
sexp_heap heap;
|
sexp_heap heap;
|
||||||
|
struct sexp_mark_stack_ptr_t mark_stack[SEXP_MARK_STACK_COUNT];
|
||||||
|
struct sexp_mark_stack_ptr_t *mark_stack_ptr;
|
||||||
struct sexp_gc_var_t *saves;
|
struct sexp_gc_var_t *saves;
|
||||||
#if SEXP_USE_GREEN_THREADS
|
#if SEXP_USE_GREEN_THREADS
|
||||||
sexp_sint_t refuel;
|
sexp_sint_t refuel;
|
||||||
|
@ -1305,6 +1312,8 @@ enum sexp_uniform_vector_type {
|
||||||
#define sexp_context_stack(x) (sexp_field(x, context, SEXP_CONTEXT, stack))
|
#define sexp_context_stack(x) (sexp_field(x, context, SEXP_CONTEXT, stack))
|
||||||
#define sexp_context_parent(x) (sexp_field(x, context, SEXP_CONTEXT, parent))
|
#define sexp_context_parent(x) (sexp_field(x, context, SEXP_CONTEXT, parent))
|
||||||
#define sexp_context_child(x) (sexp_field(x, context, SEXP_CONTEXT, child))
|
#define sexp_context_child(x) (sexp_field(x, context, SEXP_CONTEXT, child))
|
||||||
|
#define sexp_context_mark_stack(x) (sexp_field(x, context, SEXP_CONTEXT, mark_stack))
|
||||||
|
#define sexp_context_mark_stack_ptr(x) (sexp_field(x, context, SEXP_CONTEXT, mark_stack_ptr))
|
||||||
#define sexp_context_saves(x) (sexp_field(x, context, SEXP_CONTEXT, saves))
|
#define sexp_context_saves(x) (sexp_field(x, context, SEXP_CONTEXT, saves))
|
||||||
#define sexp_context_tailp(x) (sexp_field(x, context, SEXP_CONTEXT, tailp))
|
#define sexp_context_tailp(x) (sexp_field(x, context, SEXP_CONTEXT, tailp))
|
||||||
#define sexp_context_tracep(x) (sexp_field(x, context, SEXP_CONTEXT, tracep))
|
#define sexp_context_tracep(x) (sexp_field(x, context, SEXP_CONTEXT, tracep))
|
||||||
|
|
2
sexp.c
2
sexp.c
|
@ -611,6 +611,7 @@ sexp sexp_bootstrap_context (sexp_uint_t size, sexp_uint_t max_size) {
|
||||||
heap = sexp_make_heap(size, max_size, 0);
|
heap = sexp_make_heap(size, max_size, 0);
|
||||||
if (!heap) return 0;
|
if (!heap) return 0;
|
||||||
sexp_pointer_tag(&dummy_ctx) = SEXP_CONTEXT;
|
sexp_pointer_tag(&dummy_ctx) = SEXP_CONTEXT;
|
||||||
|
sexp_context_mark_stack_ptr(&dummy_ctx) = NULL;
|
||||||
sexp_context_saves(&dummy_ctx) = NULL;
|
sexp_context_saves(&dummy_ctx) = NULL;
|
||||||
sexp_context_heap(&dummy_ctx) = heap;
|
sexp_context_heap(&dummy_ctx) = heap;
|
||||||
ctx = sexp_alloc_type(&dummy_ctx, context, SEXP_CONTEXT);
|
ctx = sexp_alloc_type(&dummy_ctx, context, SEXP_CONTEXT);
|
||||||
|
@ -653,6 +654,7 @@ sexp sexp_make_context (sexp ctx, size_t size, size_t max_size) {
|
||||||
if (!res || sexp_exceptionp(res)) return res;
|
if (!res || sexp_exceptionp(res)) return res;
|
||||||
sexp_context_parent(res) = ctx;
|
sexp_context_parent(res) = ctx;
|
||||||
sexp_context_name(res) = sexp_context_specific(res) = SEXP_FALSE;
|
sexp_context_name(res) = sexp_context_specific(res) = SEXP_FALSE;
|
||||||
|
sexp_context_mark_stack_ptr(res) = NULL;
|
||||||
sexp_context_saves(res) = NULL;
|
sexp_context_saves(res) = NULL;
|
||||||
sexp_context_params(res) = SEXP_NULL;
|
sexp_context_params(res) = SEXP_NULL;
|
||||||
sexp_context_last_fp(res) = 0;
|
sexp_context_last_fp(res) = 0;
|
||||||
|
|
Loading…
Add table
Reference in a new issue