From 9fc62d28d0e5738368571d70f1be191876e91d8b Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 28 Nov 2016 09:52:57 +0900 Subject: pre-allocate arena overflow error --- src/gc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/gc.c') diff --git a/src/gc.c b/src/gc.c index b29df1f02..ecc09374e 100644 --- a/src/gc.c +++ b/src/gc.c @@ -403,7 +403,7 @@ gc_protect(mrb_state *mrb, mrb_gc *gc, struct RBasic *p) if (gc->arena_idx >= MRB_GC_ARENA_SIZE) { /* arena overflow error */ gc->arena_idx = MRB_GC_ARENA_SIZE - 4; /* force room in arena */ - mrb_raise(mrb, E_RUNTIME_ERROR, "arena overflow error"); + mrb_exc_raise(mrb, mrb_obj_value(mrb->arena_err)); } #else if (gc->arena_idx >= gc->arena_capa) { @@ -816,6 +816,9 @@ root_scan_phase(mrb_state *mrb, mrb_gc *gc) mrb_gc_mark(mrb, (struct RBasic*)mrb->exc); /* mark pre-allocated exception */ mrb_gc_mark(mrb, (struct RBasic*)mrb->nomem_err); +#ifdef MRB_GC_FIXED_ARENA + mrb_gc_mark(mrb, (struct RBasic*)mrb->arena_err); +#endif mark_context(mrb, mrb->root_c); if (mrb->root_c->fib) { -- cgit v1.2.3 From 630733f34698047e3b7b4e66cf929f626123b14e Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 30 Nov 2016 03:38:55 +0900 Subject: check ttype before object allocation; fix #3294 --- src/gc.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src/gc.c') diff --git a/src/gc.c b/src/gc.c index ecc09374e..69708e40b 100644 --- a/src/gc.c +++ b/src/gc.c @@ -479,6 +479,17 @@ mrb_obj_alloc(mrb_state *mrb, enum mrb_vtype ttype, struct RClass *cls) static const RVALUE RVALUE_zero = { { { MRB_TT_FALSE } } }; mrb_gc *gc = &mrb->gc; + if (cls) { + enum mrb_vtype tt = MRB_INSTANCE_TT(cls); + if (tt != MRB_TT_FALSE && + ttype != MRB_TT_SCLASS && + ttype != MRB_TT_ICLASS && + ttype != MRB_TT_ENV && + ttype != tt) { + mrb_raisef(mrb, E_TYPE_ERROR, "allocation failure of %S", mrb_obj_value(cls)); + } + } + #ifdef MRB_GC_STRESS mrb_full_gc(mrb); #endif -- cgit v1.2.3 From dffb4d82dc83054eade20679f069979d242d9745 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 6 Dec 2016 11:40:49 +0900 Subject: Add type check for cls before allocation --- src/gc.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'src/gc.c') diff --git a/src/gc.c b/src/gc.c index 69708e40b..470fffc5f 100644 --- a/src/gc.c +++ b/src/gc.c @@ -480,7 +480,18 @@ mrb_obj_alloc(mrb_state *mrb, enum mrb_vtype ttype, struct RClass *cls) mrb_gc *gc = &mrb->gc; if (cls) { - enum mrb_vtype tt = MRB_INSTANCE_TT(cls); + enum mrb_vtype tt; + + switch (cls->tt) { + case MRB_TT_CLASS: + case MRB_TT_SCLASS: + case MRB_TT_MODULE: + case MRB_TT_ENV: + break; + default: + mrb_raise(mrb, E_TYPE_ERROR, "allocation failure"); + } + tt = MRB_INSTANCE_TT(cls); if (tt != MRB_TT_FALSE && ttype != MRB_TT_SCLASS && ttype != MRB_TT_ICLASS && -- cgit v1.2.3 From f7a891fa8979bdb82410e1adc98765013cc29a79 Mon Sep 17 00:00:00 2001 From: Bouke van der Bijl Date: Tue, 6 Dec 2016 10:30:08 -0500 Subject: Mark all the built-in classes during GC sweep Reported by https://hackerone.com/haquaman --- mrbgems/mruby-bin-mruby/bintest/mruby.rb | 14 ++++++++++++++ src/gc.c | 20 ++++++++++++++++++++ 2 files changed, 34 insertions(+) (limited to 'src/gc.c') diff --git a/mrbgems/mruby-bin-mruby/bintest/mruby.rb b/mrbgems/mruby-bin-mruby/bintest/mruby.rb index 01fc94632..ad8ec3a0f 100644 --- a/mrbgems/mruby-bin-mruby/bintest/mruby.rb +++ b/mrbgems/mruby-bin-mruby/bintest/mruby.rb @@ -44,3 +44,17 @@ EOS script.flush assert_equal "\"test\"\n\"fin\"\n", `#{cmd('mruby')} #{script.path}` end + +assert('garbage collecting built-in classes') do + script = Tempfile.new('test.rb') + + script.write <object_class); + + /* mark built-in classes */ + mrb_gc_mark(mrb, (struct RBasic*)mrb->class_class); + mrb_gc_mark(mrb, (struct RBasic*)mrb->module_class); + mrb_gc_mark(mrb, (struct RBasic*)mrb->proc_class); + mrb_gc_mark(mrb, (struct RBasic*)mrb->string_class); + mrb_gc_mark(mrb, (struct RBasic*)mrb->array_class); + mrb_gc_mark(mrb, (struct RBasic*)mrb->hash_class); + + mrb_gc_mark(mrb, (struct RBasic*)mrb->float_class); + mrb_gc_mark(mrb, (struct RBasic*)mrb->fixnum_class); + mrb_gc_mark(mrb, (struct RBasic*)mrb->true_class); + mrb_gc_mark(mrb, (struct RBasic*)mrb->false_class); + mrb_gc_mark(mrb, (struct RBasic*)mrb->nil_class); + mrb_gc_mark(mrb, (struct RBasic*)mrb->symbol_class); + mrb_gc_mark(mrb, (struct RBasic*)mrb->kernel_module); + + mrb_gc_mark(mrb, (struct RBasic*)mrb->eException_class); + mrb_gc_mark(mrb, (struct RBasic*)mrb->eStandardError_class); + /* mark top_self */ mrb_gc_mark(mrb, (struct RBasic*)mrb->top_self); /* mark exception */ -- cgit v1.2.3 From c2e749f878049204239ad63ac9546253aeb6ceeb Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Thu, 8 Dec 2016 10:22:14 +0900 Subject: fix issues of mrb_gc_unregister introduced in 09b1185 * fixes partial copy of objects in GC root array (due to missing `* sizeof(mrb_value)`) * restores the behavior that permitted an unregistered object to be used as an argument --- src/gc.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src/gc.c') diff --git a/src/gc.c b/src/gc.c index 470fffc5f..f928cc49b 100644 --- a/src/gc.c +++ b/src/gc.c @@ -453,7 +453,7 @@ mrb_gc_unregister(mrb_state *mrb, mrb_value obj) mrb_sym root = mrb_intern_lit(mrb, GC_ROOT_NAME); mrb_value table = mrb_gv_get(mrb, root); struct RArray *a; - mrb_int i, len; + mrb_int i; if (mrb_nil_p(table)) return; if (mrb_type(table) != MRB_TT_ARRAY) { @@ -462,14 +462,13 @@ mrb_gc_unregister(mrb_state *mrb, mrb_value obj) } a = mrb_ary_ptr(table); mrb_ary_modify(mrb, a); - len = a->len-1; - for (i=0; ilen; i++) { if (mrb_obj_eq(mrb, a->ptr[i], obj)) { - memmove(&a->ptr[i], &a->ptr[i+1], len-i); + a->len--; + memmove(&a->ptr[i], &a->ptr[i + 1], (a->len - i) * sizeof(a->ptr[i])); break; } } - a->len--; } MRB_API struct RBasic* -- cgit v1.2.3 From 2ef634edb5ce70331a6a66d1c36726db904492bf Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Sat, 10 Dec 2016 15:11:07 +0900 Subject: do not destroy a page with an active TT_ENV (e.g. an env referred from TT_FIBER) --- src/gc.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'src/gc.c') diff --git a/src/gc.c b/src/gc.c index f928cc49b..5525f0593 100644 --- a/src/gc.c +++ b/src/gc.c @@ -741,10 +741,12 @@ obj_free(mrb_state *mrb, struct RBasic *obj) { struct REnv *e = (struct REnv*)obj; - if (!MRB_ENV_STACK_SHARED_P(e)) { - mrb_free(mrb, e->stack); - e->stack = NULL; + if (MRB_ENV_STACK_SHARED_P(e)) { + /* cannot be freed */ + return; } + mrb_free(mrb, e->stack); + e->stack = NULL; } break; @@ -998,9 +1000,13 @@ incremental_sweep_phase(mrb_state *mrb, mrb_gc *gc, size_t limit) if (is_dead(gc, &p->as.basic)) { if (p->as.basic.tt != MRB_TT_FREE) { obj_free(mrb, &p->as.basic); - p->as.free.next = page->freelist; - page->freelist = (struct RBasic*)p; - freed++; + if (p->as.basic.tt == MRB_TT_FREE) { + p->as.free.next = page->freelist; + page->freelist = (struct RBasic*)p; + freed++; + } else { + dead_slot = 0; + } } } else { -- cgit v1.2.3 From 0af170fbec1bbf412b009117736d22e6f5c39b03 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 10 Dec 2016 15:34:32 +0900 Subject: gc.c: dead_slot is boolean; ref #3339 --- src/gc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src/gc.c') diff --git a/src/gc.c b/src/gc.c index 5525f0593..e8523af79 100644 --- a/src/gc.c +++ b/src/gc.c @@ -1004,15 +1004,16 @@ incremental_sweep_phase(mrb_state *mrb, mrb_gc *gc, size_t limit) p->as.free.next = page->freelist; page->freelist = (struct RBasic*)p; freed++; - } else { - dead_slot = 0; + } + else { + dead_slot = FALSE; } } } else { if (!is_generational(gc)) paint_partial_white(gc, &p->as.basic); /* next gc target */ - dead_slot = 0; + dead_slot = FALSE; } p++; } -- cgit v1.2.3 From 8e0f2313302871ddd713c3e8e6a9d4731426f308 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 4 Feb 2017 12:59:08 +0900 Subject: Mark `mrb->backtrace.exc` as GC root; fix #3388 --- src/gc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/gc.c') diff --git a/src/gc.c b/src/gc.c index c75a0f9aa..225ca095c 100644 --- a/src/gc.c +++ b/src/gc.c @@ -857,6 +857,7 @@ root_scan_phase(mrb_state *mrb, mrb_gc *gc) mrb_gc_mark(mrb, (struct RBasic*)mrb->top_self); /* mark exception */ mrb_gc_mark(mrb, (struct RBasic*)mrb->exc); + mrb_gc_mark(mrb, (struct RBasic*)mrb->backtrace.exc); /* mark pre-allocated exception */ mrb_gc_mark(mrb, (struct RBasic*)mrb->nomem_err); #ifdef MRB_GC_FIXED_ARENA -- cgit v1.2.3 From 8f52b88ee75fb3ca62931a1d3975c9cd78eae2d8 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 4 Feb 2017 13:48:23 +0900 Subject: No need to make env unshared in the finalization; fix #3425 --- src/gc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/gc.c') diff --git a/src/gc.c b/src/gc.c index 225ca095c..88d157d9c 100644 --- a/src/gc.c +++ b/src/gc.c @@ -367,7 +367,7 @@ mrb_gc_init(mrb_state *mrb, mrb_gc *gc) #endif } -static void obj_free(mrb_state *mrb, struct RBasic *obj); +static void obj_free(mrb_state *mrb, struct RBasic *obj, int end); void free_heap(mrb_state *mrb, mrb_gc *gc) @@ -381,7 +381,7 @@ free_heap(mrb_state *mrb, mrb_gc *gc) page = page->next; for (p = objects(tmp), e=p+MRB_HEAP_PAGE_SIZE; pas.free.tt != MRB_TT_FREE) - obj_free(mrb, &p->as.basic); + obj_free(mrb, &p->as.basic, TRUE); } mrb_free(mrb, tmp); } @@ -699,7 +699,7 @@ mrb_gc_mark(mrb_state *mrb, struct RBasic *obj) } static void -obj_free(mrb_state *mrb, struct RBasic *obj) +obj_free(mrb_state *mrb, struct RBasic *obj, int end) { DEBUG(printf("obj_free(%p,tt=%d)\n",obj,obj->tt)); switch (obj->tt) { @@ -753,7 +753,7 @@ obj_free(mrb_state *mrb, struct RBasic *obj) case MRB_TT_FIBER: { struct mrb_context *c = ((struct RFiber*)obj)->cxt; - if (c && c != mrb->root_c) { + if (!end && c && c != mrb->root_c) { mrb_callinfo *ci = c->ci; mrb_callinfo *ce = c->cibase; @@ -1020,7 +1020,7 @@ incremental_sweep_phase(mrb_state *mrb, mrb_gc *gc, size_t limit) while (pas.basic)) { if (p->as.basic.tt != MRB_TT_FREE) { - obj_free(mrb, &p->as.basic); + obj_free(mrb, &p->as.basic, FALSE); if (p->as.basic.tt == MRB_TT_FREE) { p->as.free.next = page->freelist; page->freelist = (struct RBasic*)p; -- cgit v1.2.3 From b277c58e783f187cfff1b7bb5843d2e95d3c3b0b Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 8 Feb 2017 16:31:37 +0900 Subject: Mark classes referenced from saved backtrace. Maybe related to #3438 --- src/gc.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/gc.c') diff --git a/src/gc.c b/src/gc.c index 88d157d9c..1608dbcb2 100644 --- a/src/gc.c +++ b/src/gc.c @@ -857,7 +857,12 @@ root_scan_phase(mrb_state *mrb, mrb_gc *gc) mrb_gc_mark(mrb, (struct RBasic*)mrb->top_self); /* mark exception */ mrb_gc_mark(mrb, (struct RBasic*)mrb->exc); + /* mark backtrace */ mrb_gc_mark(mrb, (struct RBasic*)mrb->backtrace.exc); + e = (size_t)mrb->backtrace.n; + for (i=0; ibacktrace.entries[i].klass); + } /* mark pre-allocated exception */ mrb_gc_mark(mrb, (struct RBasic*)mrb->nomem_err); #ifdef MRB_GC_FIXED_ARENA -- cgit v1.2.3 From 8efa7b00df2842eaff31cdabc95651a856e40549 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 15 Feb 2017 11:59:47 +0900 Subject: Preallocate SystemStackError; ref #3421 --- include/mruby.h | 2 +- src/backtrace.c | 2 +- src/error.c | 5 +++-- src/gc.c | 1 + src/vm.c | 2 +- 5 files changed, 7 insertions(+), 5 deletions(-) (limited to 'src/gc.c') diff --git a/include/mruby.h b/include/mruby.h index 6950cf904..8adce289b 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -221,6 +221,7 @@ typedef struct mrb_state { struct RClass *eException_class; struct RClass *eStandardError_class; struct RObject *nomem_err; /* pre-allocated NoMemoryError */ + struct RObject *stack_err; /* pre-allocated SysStackError */ #ifdef MRB_GC_FIXED_ARENA struct RObject *arena_err; /* pre-allocated arena overfow error */ #endif @@ -1110,7 +1111,6 @@ MRB_API void mrb_print_error(mrb_state *mrb); #define E_SYNTAX_ERROR (mrb_exc_get(mrb, "SyntaxError")) #define E_LOCALJUMP_ERROR (mrb_exc_get(mrb, "LocalJumpError")) #define E_REGEXP_ERROR (mrb_exc_get(mrb, "RegexpError")) -#define E_SYSSTACK_ERROR (mrb_exc_get(mrb, "SystemStackError")) #define E_NOTIMP_ERROR (mrb_exc_get(mrb, "NotImplementedError")) #define E_FLOATDOMAIN_ERROR (mrb_exc_get(mrb, "FloatDomainError")) diff --git a/src/backtrace.c b/src/backtrace.c index 051d5d4e0..529b0b1c9 100644 --- a/src/backtrace.c +++ b/src/backtrace.c @@ -263,7 +263,7 @@ mrb_print_backtrace(mrb_state *mrb) { mrb_value backtrace; - if (!mrb->exc || mrb_obj_is_kind_of(mrb, mrb_obj_value(mrb->exc), E_SYSSTACK_ERROR)) { + if (!mrb->exc) { return; } diff --git a/src/error.c b/src/error.c index a71ee548f..7916ca65b 100644 --- a/src/error.c +++ b/src/error.c @@ -532,7 +532,7 @@ mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_value args, char const* fmt, void mrb_init_exception(mrb_state *mrb) { - struct RClass *exception, *runtime_error, *script_error; + struct RClass *exception, *runtime_error, *script_error, *stack_error; mrb->eException_class = exception = mrb_define_class(mrb, "Exception", mrb->object_class); /* 15.2.22 */ MRB_SET_INSTANCE_TT(exception, MRB_TT_EXCEPTION); @@ -553,5 +553,6 @@ mrb_init_exception(mrb_state *mrb) #endif script_error = mrb_define_class(mrb, "ScriptError", mrb->eException_class); /* 15.2.37 */ mrb_define_class(mrb, "SyntaxError", script_error); /* 15.2.38 */ - mrb_define_class(mrb, "SystemStackError", exception); + stack_error = mrb_define_class(mrb, "SystemStackError", exception); + mrb->stack_err = mrb_obj_ptr(mrb_exc_new_str_lit(mrb, stack_error, "stack level too deep")); } diff --git a/src/gc.c b/src/gc.c index 1608dbcb2..63eab8e00 100644 --- a/src/gc.c +++ b/src/gc.c @@ -865,6 +865,7 @@ root_scan_phase(mrb_state *mrb, mrb_gc *gc) } /* mark pre-allocated exception */ mrb_gc_mark(mrb, (struct RBasic*)mrb->nomem_err); + mrb_gc_mark(mrb, (struct RBasic*)mrb->stack_err); #ifdef MRB_GC_FIXED_ARENA mrb_gc_mark(mrb, (struct RBasic*)mrb->arena_err); #endif diff --git a/src/vm.c b/src/vm.c index 8bb446fa9..91612a0da 100644 --- a/src/vm.c +++ b/src/vm.c @@ -162,7 +162,7 @@ stack_extend_alloc(mrb_state *mrb, int room, int keep) to prevent infinite recursion. However, do this only after resizing the stack, so mrb_raise has stack space to work with. */ if (size > MRB_STACK_MAX) { init_new_stack_space(mrb, room, keep); - mrb_raise(mrb, E_SYSSTACK_ERROR, "stack level too deep. (limit=" MRB_STRINGIZE(MRB_STACK_MAX) ")"); + mrb_exc_raise(mrb, mrb_obj_value(mrb->stack_err)); } } -- cgit v1.2.3