From afc6a96d685e3e8dce0abaee9e82dd54aa506f2b Mon Sep 17 00:00:00 2001 From: Alex Shinn Date: Sun, 27 Feb 2011 20:53:12 +0900 Subject: [PATCH] Adding more OOM checks (issue #59), thanks rotty. --- eval.c | 7 ++- gc.c | 9 ++++ include/chibi/sexp.h | 2 + main.c | 11 ++-- sexp.c | 124 ++++++++++++++++++++++++------------------- 5 files changed, 92 insertions(+), 61 deletions(-) diff --git a/eval.c b/eval.c index 1e166c48..7b2d207a 100644 --- a/eval.c +++ b/eval.c @@ -1,5 +1,5 @@ /* eval.c -- evaluator library implementation */ -/* Copyright (c) 2009-2010 Alex Shinn. All rights reserved. */ +/* Copyright (c) 2009-2011 Alex Shinn. All rights reserved. */ /* BSD-style license: http://synthcode.com/license.txt */ #include "chibi/eval.h" @@ -365,8 +365,10 @@ void sexp_init_eval_context_globals (sexp ctx) { sexp sexp_make_eval_context (sexp ctx, sexp stack, sexp env, sexp_uint_t size, sexp_uint_t max_size) { sexp_gc_var1(res); - if (ctx) sexp_gc_preserve1(ctx, res); res = sexp_make_context(ctx, size, max_size); + if (!res || sexp_exceptionp(res)) + return res; + if (ctx) sexp_gc_preserve1(ctx, res); sexp_context_bc(res) = sexp_alloc_bytecode(res, SEXP_INIT_BCODE_SIZE); sexp_bytecode_name(sexp_context_bc(res)) = SEXP_FALSE; sexp_bytecode_length(sexp_context_bc(res)) = SEXP_INIT_BCODE_SIZE; @@ -1530,6 +1532,7 @@ sexp sexp_find_module_file (sexp ctx, const char *file) { slash = dir[dirlen-1] == '/'; len = dirlen+filelen+2-slash; path = (char*) malloc(len); + if (! path) return sexp_global(ctx, SEXP_G_OOM_ERROR); memcpy(path, dir, dirlen); if (! slash) path[dirlen] = '/'; memcpy(path+len-filelen-1, file, filelen); diff --git a/gc.c b/gc.c index c912d369..5d98de1d 100644 --- a/gc.c +++ b/gc.c @@ -38,6 +38,14 @@ static size_t sexp_heap_total_size (sexp_heap h) { return total_size; } +void sexp_free_heap (sexp_heap heap) { +#if SEXP_USE_MMAP_GC + munmap(heap, sexp_heap_pad_size(heap->size)); +#else + free(heap); +#endif +} + sexp_uint_t sexp_allocated_bytes (sexp ctx, sexp x) { sexp_uint_t res; sexp t; @@ -451,6 +459,7 @@ sexp sexp_copy_context (sexp ctx, sexp dst, sexp flags) { return sexp_user_exception(ctx, NULL, "can't copy a non-contiguous heap", ctx); } else if (! dst || sexp_not(dst)) { to = sexp_make_heap(from->size, from->max_size); + if (!to) return sexp_global(ctx, SEXP_G_OOM_ERROR); dst = (sexp) ((char*)ctx + ((char*)to - (char*)from)); } else if (! sexp_contextp(dst)) { return sexp_type_exception(ctx, NULL, SEXP_CONTEXT, dst); diff --git a/include/chibi/sexp.h b/include/chibi/sexp.h index 4c4a1217..02a35cc4 100644 --- a/include/chibi/sexp.h +++ b/include/chibi/sexp.h @@ -1105,8 +1105,10 @@ SEXP_API void sexp_maybe_unblock_port (sexp ctx, sexp in); #define SEXP_COPY_FREEP SEXP_ONE #if SEXP_USE_GLOBAL_HEAP +#define sexp_free_heap(heap) #define sexp_destroy_context(ctx) #else +SEXP_API void sexp_free_heap (sexp_heap heap); SEXP_API void sexp_destroy_context (sexp ctx); SEXP_API sexp sexp_copy_context (sexp ctx, sexp dst, sexp flags); #endif diff --git a/main.c b/main.c index 4cb623ca..592e3df9 100644 --- a/main.c +++ b/main.c @@ -1,5 +1,5 @@ /* main.c -- chibi-scheme command-line app */ -/* Copyright (c) 2009-2010 Alex Shinn. All rights reserved. */ +/* Copyright (c) 2009-2011 Alex Shinn. All rights reserved. */ /* BSD-style license: http://synthcode.com/license.txt */ #include "chibi/eval.h" @@ -95,9 +95,10 @@ static sexp check_exception (sexp ctx, sexp res) { } static sexp sexp_load_standard_repl_env (sexp ctx, sexp env, sexp k) { - sexp e = sexp_load_standard_env(ctx, env, k), res; + sexp e = sexp_load_standard_env(ctx, env, k), p, res; + if (sexp_exceptionp(e)) return e; #if SEXP_USE_GREEN_THREADS - sexp p = sexp_param_ref(ctx, e, sexp_global(ctx, SEXP_G_CUR_IN_SYMBOL)); + p = sexp_param_ref(ctx, e, sexp_global(ctx, SEXP_G_CUR_IN_SYMBOL)); if (sexp_portp(p)) sexp_maybe_block_port(ctx, p, 1); #endif res = sexp_make_env(ctx); @@ -107,6 +108,10 @@ static sexp sexp_load_standard_repl_env (sexp ctx, sexp env, sexp k) { #define init_context() if (! ctx) do { \ ctx = sexp_make_eval_context(NULL, NULL, NULL, heap_size, heap_max_size); \ + if (! ctx) { \ + fprintf(stderr, "chibi-scheme: out of memory\n"); \ + exit_failure(); \ + } \ env = sexp_context_env(ctx); \ sexp_gc_preserve2(ctx, tmp, args); \ } while (0) diff --git a/sexp.c b/sexp.c index f08ec769..e5e40c03 100644 --- a/sexp.c +++ b/sexp.c @@ -1,5 +1,5 @@ /* sexp.c -- standalone sexp library implementation */ -/* Copyright (c) 2009-2010 Alex Shinn. All rights reserved. */ +/* Copyright (c) 2009-2011 Alex Shinn. All rights reserved. */ /* BSD-style license: http://synthcode.com/license.txt */ #include "chibi/sexp.h" @@ -166,6 +166,10 @@ sexp sexp_register_type_op (sexp ctx sexp_api_params(self, n), sexp name, sexp_type_array_size = len; #else res = sexp_make_vector(ctx, sexp_make_fixnum(len), SEXP_VOID); + if (sexp_exceptionp(res)) { + sexp_gc_release2(ctx); + return res; + } v1 = sexp_vector_data(res); v2 = sexp_vector_data(sexp_global(ctx, SEXP_G_TYPES)); for (i=0; inext; -#if SEXP_USE_MMAP_GC - munmap(heap, sexp_heap_pad_size(heap->size)); -#else - free(heap); -#endif + sexp_free_heap(heap); } } } @@ -1206,9 +1214,13 @@ sexp sexp_make_output_string_port_op (sexp ctx sexp_api_params(self, n)) { sexp res = sexp_make_output_port(ctx, NULL, SEXP_FALSE); if (sexp_exceptionp(res)) return res; sexp_port_buf(res) = (char*) malloc(SEXP_PORT_BUFFER_SIZE); - sexp_port_size(res) = SEXP_PORT_BUFFER_SIZE; - sexp_port_offset(res) = 0; - sexp_port_cookie(res) = SEXP_NULL; + if (!sexp_port_buf(res)) { + res = sexp_global(ctx, SEXP_G_OOM_ERROR); + } else { + sexp_port_size(res) = SEXP_PORT_BUFFER_SIZE; + sexp_port_offset(res) = 0; + sexp_port_cookie(res) = SEXP_NULL; + } return res; }