From e2d6896ebad13694800af49c2625e106b8440ddf Mon Sep 17 00:00:00 2001 From: dearblue Date: Sat, 19 Jan 2019 12:54:19 +0900 Subject: [PATCH] Fix memory leak for irep when out of memory by `mrb_proc_new()` --- src/proc.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/proc.c b/src/proc.c index dcbeb4f62..acc21fc3c 100644 --- a/src/proc.c +++ b/src/proc.c @@ -8,6 +8,7 @@ #include #include #include +#include static mrb_code call_iseq[] = { OP_CALL, @@ -287,14 +288,25 @@ proc_lambda(mrb_state *mrb, mrb_value self) return blk; } +static void +tempirep_free(mrb_state *mrb, void *p) +{ + if (p) mrb_irep_free(mrb, (mrb_irep *)p); +} + +static const mrb_data_type tempirep_type = { "temporary irep", tempirep_free }; + void mrb_init_proc(mrb_state *mrb) { struct RProc *p; mrb_method_t m; - mrb_irep *call_irep = (mrb_irep *)mrb_malloc(mrb, sizeof(mrb_irep)); + struct RData *irep_obj = mrb_data_object_alloc(mrb, mrb->object_class, NULL, &tempirep_type); + mrb_irep *call_irep; static const mrb_irep mrb_irep_zero = { 0 }; + call_irep = (mrb_irep *)mrb_malloc(mrb, sizeof(mrb_irep)); + irep_obj->data = call_irep; *call_irep = mrb_irep_zero; call_irep->flags = MRB_ISEQ_NO_FREE; call_irep->iseq = call_iseq; @@ -306,6 +318,7 @@ mrb_init_proc(mrb_state *mrb) mrb_define_method(mrb, mrb->proc_class, "arity", mrb_proc_arity, MRB_ARGS_NONE()); p = mrb_proc_new(mrb, call_irep); + irep_obj->data = NULL; MRB_METHOD_FROM_PROC(m, p); mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern_lit(mrb, "call"), m); mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern_lit(mrb, "[]"), m);