From 8263459627b20d4383978b3d1471298bf52bde05 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Sat, 14 Sep 2019 21:36:41 +0900 Subject: Keep the reference of imemo while argv may be used To prevent the `v` reference from being eliminated before argv is used, calling `rb_free_tmp_buffer` against `v` explicitly. --- vm_eval.c | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) (limited to 'vm_eval.c') diff --git a/vm_eval.c b/vm_eval.c index f128e8dd8e..b5d6dcca13 100644 --- a/vm_eval.c +++ b/vm_eval.c @@ -235,25 +235,27 @@ vm_call0_body(rb_execution_context_t *ec, struct rb_calling_info *calling, const return ret; } -static void +/* Caller should keep the reference to the return value until argv becomes useless. */ +static VALUE add_empty_keyword(int *argc, const VALUE **argv, int *kw_splat) { if (*kw_splat == RB_PASS_CALLED_KEYWORDS || *kw_splat == RB_PASS_EMPTY_KEYWORDS) { if (*kw_splat == RB_PASS_EMPTY_KEYWORDS || rb_empty_keyword_given_p()) { int n = *argc; VALUE v; - VALUE *ptr; - ptr = rb_alloc_tmp_buffer2(&v, n+1, sizeof(VALUE)); + VALUE *ptr = rb_alloc_tmp_buffer2(&v, n+1, sizeof(VALUE)); memcpy(ptr, *argv, sizeof(VALUE)*n); ptr[n] = rb_hash_new(); *argc = ++n; *argv = ptr; *kw_splat = 1; + return v; } else { *kw_splat = rb_keyword_given_p(); } } + return 0; } VALUE @@ -265,8 +267,10 @@ rb_vm_call(rb_execution_context_t *ec, VALUE recv, VALUE id, int argc, const VAL VALUE rb_vm_call_kw(rb_execution_context_t *ec, VALUE recv, VALUE id, int argc, const VALUE *argv, const rb_callable_method_entry_t *me, int kw_splat) { - add_empty_keyword(&argc, &argv, &kw_splat); - return rb_vm_call0(ec, recv, id, argc, argv, me, kw_splat); + VALUE v = add_empty_keyword(&argc, &argv, &kw_splat); + VALUE ret = rb_vm_call0(ec, recv, id, argc, argv, me, kw_splat); + rb_free_tmp_buffer(&v); + return ret; } static inline VALUE @@ -291,8 +295,10 @@ vm_call_super(rb_execution_context_t *ec, int argc, const VALUE *argv, int kw_sp return method_missing(recv, id, argc, argv, MISSING_SUPER); } else { - add_empty_keyword(&argc, &argv, &kw_splat); - return rb_vm_call0(ec, recv, id, argc, argv, me, kw_splat); + VALUE v = add_empty_keyword(&argc, &argv, &kw_splat); + VALUE ret = rb_vm_call0(ec, recv, id, argc, argv, me, kw_splat); + rb_free_tmp_buffer(&v); + return ret; } } @@ -940,8 +946,10 @@ rb_funcallv(VALUE recv, ID mid, int argc, const VALUE *argv) VALUE rb_funcallv_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat) { - add_empty_keyword(&argc, &argv, &kw_splat); - return rb_call(recv, mid, argc, argv, kw_splat ? CALL_FCALL_KW : CALL_FCALL); + VALUE v = add_empty_keyword(&argc, &argv, &kw_splat); + VALUE ret = rb_call(recv, mid, argc, argv, kw_splat ? CALL_FCALL_KW : CALL_FCALL); + rb_free_tmp_buffer(&v); + return ret; } /*! @@ -1008,8 +1016,10 @@ rb_funcall_with_block_kw(VALUE recv, ID mid, int argc, const VALUE *argv, VALUE vm_passed_block_handler_set(GET_EC(), passed_procval); } - add_empty_keyword(&argc, &argv, &kw_splat); - return rb_call(recv, mid, argc, argv, kw_splat ? CALL_PUBLIC_KW : CALL_PUBLIC); + VALUE v = add_empty_keyword(&argc, &argv, &kw_splat); + VALUE ret = rb_call(recv, mid, argc, argv, kw_splat ? CALL_PUBLIC_KW : CALL_PUBLIC); + rb_free_tmp_buffer(&v); + return ret; } static VALUE * @@ -1373,13 +1383,15 @@ rb_block_call_kw(VALUE obj, ID mid, int argc, const VALUE * argv, { struct iter_method_arg arg; - add_empty_keyword(&argc, &argv, &kw_splat); + VALUE v = add_empty_keyword(&argc, &argv, &kw_splat); arg.obj = obj; arg.mid = mid; arg.argc = argc; arg.argv = argv; arg.kw_splat = kw_splat; - return rb_iterate(iterate_method, (VALUE)&arg, bl_proc, data2); + VALUE ret = rb_iterate(iterate_method, (VALUE)&arg, bl_proc, data2); + rb_free_tmp_buffer(&v); + return ret; } VALUE -- cgit v1.2.3