mirror of
https://github.com/ashinn/chibi-scheme.git
synced 2025-07-08 21:47:33 +02:00
Apply checks for stack overflow.
This commit is contained in:
parent
1dd61a26f3
commit
8e6927001c
4 changed files with 47 additions and 18 deletions
2
eval.c
2
eval.c
|
@ -293,7 +293,7 @@ sexp sexp_make_procedure_op (sexp ctx, sexp self, sexp_sint_t n, sexp flags,
|
||||||
sexp num_args, sexp bc, sexp vars) {
|
sexp num_args, sexp bc, sexp vars) {
|
||||||
sexp proc = sexp_alloc_type(ctx, procedure, SEXP_PROCEDURE);
|
sexp proc = sexp_alloc_type(ctx, procedure, SEXP_PROCEDURE);
|
||||||
sexp_procedure_flags(proc) = (char) (sexp_uint_t) flags;
|
sexp_procedure_flags(proc) = (char) (sexp_uint_t) flags;
|
||||||
sexp_procedure_num_args(proc) = (unsigned short) (sexp_uint_t) num_args;
|
sexp_procedure_num_args(proc) = sexp_unbox_fixnum(num_args);
|
||||||
sexp_procedure_code(proc) = bc;
|
sexp_procedure_code(proc) = bc;
|
||||||
sexp_procedure_vars(proc) = vars;
|
sexp_procedure_vars(proc) = vars;
|
||||||
return proc;
|
return proc;
|
||||||
|
|
|
@ -183,6 +183,12 @@
|
||||||
/* this enabled. */
|
/* this enabled. */
|
||||||
/* #define SEXP_USE_CHECK_STACK 0 */
|
/* #define SEXP_USE_CHECK_STACK 0 */
|
||||||
|
|
||||||
|
/* uncomment this to disable growing the stack on overflow */
|
||||||
|
/* If enabled, chibi attempts to grow the stack on overflow, */
|
||||||
|
/* up to SEXP_MAX_STACK_SIZE, otherwise a failed stack check */
|
||||||
|
/* will just raise an error immediately. */
|
||||||
|
/* #define SEXP_USE_GROW_STACK 0 */
|
||||||
|
|
||||||
/* #define SEXP_USE_DEBUG_VM 0 */
|
/* #define SEXP_USE_DEBUG_VM 0 */
|
||||||
/* Experts only. */
|
/* Experts only. */
|
||||||
/* For *very* verbose output on every VM operation. */
|
/* For *very* verbose output on every VM operation. */
|
||||||
|
@ -530,6 +536,14 @@
|
||||||
#define SEXP_USE_CHECK_STACK ! SEXP_USE_NO_FEATURES
|
#define SEXP_USE_CHECK_STACK ! SEXP_USE_NO_FEATURES
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef SEXP_USE_GROW_STACK
|
||||||
|
#define SEXP_USE_GROW_STACK SEXP_USE_CHECK_STACK && ! SEXP_USE_NO_FEATURES
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SEXP_USE_LONG_PROCEDURE_ARGS
|
||||||
|
#define SEXP_USE_LONG_PROCEDURE_ARGS ! SEXP_USE_NO_FEATURES
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef SEXP_INIT_BCODE_SIZE
|
#ifndef SEXP_INIT_BCODE_SIZE
|
||||||
#define SEXP_INIT_BCODE_SIZE 128
|
#define SEXP_INIT_BCODE_SIZE 128
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -184,6 +184,12 @@ typedef int sexp_sint_t;
|
||||||
#define sexp_heap_align(n) sexp_align(n, 4)
|
#define sexp_heap_align(n) sexp_align(n, 4)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if SEXP_USE_LONG_PROCEDURE_ARGS
|
||||||
|
typedef int sexp_proc_num_args_t;
|
||||||
|
#else
|
||||||
|
typedef short sexp_proc_num_args_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct sexp_struct *sexp;
|
typedef struct sexp_struct *sexp;
|
||||||
|
|
||||||
#define sexp_heap_pad_size(s) (sizeof(struct sexp_heap_t) + (s) + sexp_heap_align(1))
|
#define sexp_heap_pad_size(s) (sizeof(struct sexp_heap_t) + (s) + sexp_heap_align(1))
|
||||||
|
@ -355,7 +361,7 @@ struct sexp_struct {
|
||||||
} bytecode;
|
} bytecode;
|
||||||
struct {
|
struct {
|
||||||
char flags;
|
char flags;
|
||||||
unsigned short num_args;
|
sexp_proc_num_args_t num_args;
|
||||||
sexp bc, vars;
|
sexp bc, vars;
|
||||||
} procedure;
|
} procedure;
|
||||||
struct {
|
struct {
|
||||||
|
|
41
vm.c
41
vm.c
|
@ -1,5 +1,5 @@
|
||||||
/* vm.c -- stack-based virtual machine backend */
|
/* vm.c -- stack-based virtual machine backend */
|
||||||
/* Copyright (c) 2009-2011 Alex Shinn. All rights reserved. */
|
/* Copyright (c) 2009-2012 Alex Shinn. All rights reserved. */
|
||||||
/* BSD-style license: http://synthcode.com/license.txt */
|
/* BSD-style license: http://synthcode.com/license.txt */
|
||||||
|
|
||||||
#if SEXP_USE_DEBUG_VM > 1
|
#if SEXP_USE_DEBUG_VM > 1
|
||||||
|
@ -652,11 +652,12 @@ static sexp make_opcode_procedure (sexp ctx, sexp op, sexp_uint_t i) {
|
||||||
|
|
||||||
/*********************** the virtual machine **************************/
|
/*********************** the virtual machine **************************/
|
||||||
|
|
||||||
#if SEXP_USE_CHECK_STACK
|
#if SEXP_USE_GROW_STACK
|
||||||
static int sexp_grow_stack (sexp ctx) {
|
static int sexp_grow_stack (sexp ctx, int min_size) {
|
||||||
sexp stack, old_stack = sexp_context_stack(ctx), *from, *to;
|
sexp stack, old_stack = sexp_context_stack(ctx), *from, *to;
|
||||||
int i, size = sexp_stack_length(old_stack), new_size;
|
int i, size = sexp_stack_length(old_stack), new_size;
|
||||||
new_size = size * 2;
|
new_size = size * 2;
|
||||||
|
if (new_size < min_size) new_size = min_size;
|
||||||
if (new_size > SEXP_MAX_STACK_SIZE) {
|
if (new_size > SEXP_MAX_STACK_SIZE) {
|
||||||
if (size == SEXP_MAX_STACK_SIZE)
|
if (size == SEXP_MAX_STACK_SIZE)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -677,6 +678,8 @@ static int sexp_grow_stack (sexp ctx) {
|
||||||
sexp_context_stack(ctx) = stack;
|
sexp_context_stack(ctx) = stack;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
#define sexp_grow_stack(ctx, min_size) 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static sexp sexp_save_stack (sexp ctx, sexp *stack, sexp_uint_t to) {
|
static sexp sexp_save_stack (sexp ctx, sexp *stack, sexp_uint_t to) {
|
||||||
|
@ -694,7 +697,7 @@ static sexp sexp_restore_stack (sexp ctx, sexp saved) {
|
||||||
sexp *from = sexp_vector_data(saved), *to;
|
sexp *from = sexp_vector_data(saved), *to;
|
||||||
#if SEXP_USE_CHECK_STACK
|
#if SEXP_USE_CHECK_STACK
|
||||||
if ((len+64 >= sexp_stack_length(sexp_context_stack(ctx)))
|
if ((len+64 >= sexp_stack_length(sexp_context_stack(ctx)))
|
||||||
&& !sexp_grow_stack(ctx))
|
&& !sexp_grow_stack(ctx, len+64))
|
||||||
return sexp_global(ctx, SEXP_G_OOS_ERROR);
|
return sexp_global(ctx, SEXP_G_OOS_ERROR);
|
||||||
#endif
|
#endif
|
||||||
to = sexp_stack_data(sexp_context_stack(ctx));
|
to = sexp_stack_data(sexp_context_stack(ctx));
|
||||||
|
@ -812,6 +815,21 @@ static sexp sexp_print_vm_profile (sexp ctx, sexp self, sexp_sint_t n) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if SEXP_USE_CHECK_STACK
|
||||||
|
#define sexp_ensure_stack(n) \
|
||||||
|
if (top+n >= sexp_stack_length(sexp_context_stack(ctx))) { \
|
||||||
|
sexp_context_top(ctx) = top; \
|
||||||
|
if (sexp_grow_stack(ctx, n)) { \
|
||||||
|
stack = sexp_stack_data(sexp_context_stack(ctx)); \
|
||||||
|
} else { \
|
||||||
|
_ARG1 = sexp_global(ctx, SEXP_G_OOS_ERROR); \
|
||||||
|
goto end_loop; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define sexp_ensure_stack(n)
|
||||||
|
#endif
|
||||||
|
|
||||||
sexp sexp_apply (sexp ctx, sexp proc, sexp args) {
|
sexp sexp_apply (sexp ctx, sexp proc, sexp args) {
|
||||||
unsigned char *ip;
|
unsigned char *ip;
|
||||||
sexp bc, cp, *stack = sexp_stack_data(sexp_context_stack(ctx));
|
sexp bc, cp, *stack = sexp_stack_data(sexp_context_stack(ctx));
|
||||||
|
@ -938,6 +956,7 @@ sexp sexp_apply (sexp ctx, sexp proc, sexp args) {
|
||||||
top -= 2;
|
top -= 2;
|
||||||
apply1:
|
apply1:
|
||||||
i = sexp_unbox_fixnum(sexp_length(ctx, tmp2));
|
i = sexp_unbox_fixnum(sexp_length(ctx, tmp2));
|
||||||
|
sexp_ensure_stack(i + 64);
|
||||||
top += i;
|
top += i;
|
||||||
for ( ; sexp_pairp(tmp2); tmp2=sexp_cdr(tmp2), top--)
|
for ( ; sexp_pairp(tmp2); tmp2=sexp_cdr(tmp2), top--)
|
||||||
_ARG1 = sexp_car(tmp2);
|
_ARG1 = sexp_car(tmp2);
|
||||||
|
@ -962,17 +981,7 @@ sexp sexp_apply (sexp ctx, sexp proc, sexp args) {
|
||||||
fp = sexp_unbox_fixnum(tmp2);
|
fp = sexp_unbox_fixnum(tmp2);
|
||||||
goto make_call;
|
goto make_call;
|
||||||
case SEXP_OP_CALL:
|
case SEXP_OP_CALL:
|
||||||
#if SEXP_USE_CHECK_STACK
|
sexp_ensure_stack(64); /* TODO: pre-compute stack needed for each proc */
|
||||||
if (top+64 >= sexp_stack_length(sexp_context_stack(ctx))) {
|
|
||||||
sexp_context_top(ctx) = top;
|
|
||||||
if (sexp_grow_stack(ctx)) {
|
|
||||||
stack = sexp_stack_data(sexp_context_stack(ctx));
|
|
||||||
} else {
|
|
||||||
_ARG1 = sexp_global(ctx, SEXP_G_OOS_ERROR);
|
|
||||||
goto end_loop;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
_ALIGN_IP();
|
_ALIGN_IP();
|
||||||
i = sexp_unbox_fixnum(_WORD0);
|
i = sexp_unbox_fixnum(_WORD0);
|
||||||
tmp1 = _ARG1;
|
tmp1 = _ARG1;
|
||||||
|
@ -988,7 +997,7 @@ sexp sexp_apply (sexp ctx, sexp proc, sexp args) {
|
||||||
}
|
}
|
||||||
if (! sexp_procedurep(tmp1))
|
if (! sexp_procedurep(tmp1))
|
||||||
sexp_raise("non procedure application", sexp_list1(ctx, tmp1));
|
sexp_raise("non procedure application", sexp_list1(ctx, tmp1));
|
||||||
j = i - sexp_unbox_fixnum(sexp_procedure_num_args(tmp1));
|
j = i - sexp_procedure_num_args(tmp1);
|
||||||
if (j < 0)
|
if (j < 0)
|
||||||
sexp_raise("not enough args",
|
sexp_raise("not enough args",
|
||||||
sexp_list2(ctx, tmp1, sexp_make_fixnum(i)));
|
sexp_list2(ctx, tmp1, sexp_make_fixnum(i)));
|
||||||
|
|
Loading…
Add table
Reference in a new issue