ruby-changes:38091
From: ko1 <ko1@a...>
Date: Mon, 6 Apr 2015 16:14:49 +0900 (JST)
Subject: [ruby-changes:38091] ko1:r50172 (trunk): * vm_args.c: protect value stack from calling other methods
ko1 2015-04-06 16:14:28 +0900 (Mon, 06 Apr 2015) New Revision: 50172 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=50172 Log: * vm_args.c: protect value stack from calling other methods during complex parameter setting process (splat, kw, and so on). [Bug #11027] * vm_core.h: remove rb_thead_t::mark_stack_len. With this modification, we don't need to use th->mark_stack_len. * test/ruby/test_keyword.rb: add a test. * cont.c (cont_capture): catch up this fix. * vm.c (rb_thread_mark): ditto. Modified files: trunk/ChangeLog trunk/cont.c trunk/test/ruby/test_keyword.rb trunk/vm.c trunk/vm_args.c trunk/vm_core.h Index: ChangeLog =================================================================== --- ChangeLog (revision 50171) +++ ChangeLog (revision 50172) @@ -1,3 +1,18 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Mon Apr 6 16:09:58 2015 Koichi Sasada <ko1@a...> + + * vm_args.c: protect value stack from calling other methods + during complex parameter setting process (splat, kw, and so on). + [Bug #11027] + + * vm_core.h: remove rb_thead_t::mark_stack_len. + With this modification, we don't need to use th->mark_stack_len. + + * test/ruby/test_keyword.rb: add a test. + + * cont.c (cont_capture): catch up this fix. + + * vm.c (rb_thread_mark): ditto. + Mon Apr 6 11:26:42 2015 NARUSE, Yui <naruse@r...> * tool/downloader.rb (http_options): prevent content auto decoding Index: vm_core.h =================================================================== --- vm_core.h (revision 50171) +++ vm_core.h (revision 50172) @@ -631,7 +631,6 @@ typedef struct rb_thread_struct { https://github.com/ruby/ruby/blob/trunk/vm_core.h#L631 enum rb_thread_status status; int to_kill; int priority; - int mark_stack_len; native_thread_data_t native_thread_data; void *blocking_region_buffer; Index: cont.c =================================================================== --- cont.c (revision 50171) +++ cont.c (revision 50172) @@ -490,7 +490,7 @@ cont_capture(volatile int *stat) https://github.com/ruby/ruby/blob/trunk/cont.c#L490 contval = cont->self; #ifdef CAPTURE_JUST_VALID_VM_STACK - cont->vm_stack_slen = th->cfp->sp + th->mark_stack_len - th->stack; + cont->vm_stack_slen = th->cfp->sp - th->stack; cont->vm_stack_clen = th->stack + th->stack_size - (VALUE*)th->cfp; cont->vm_stack = ALLOC_N(VALUE, cont->vm_stack_slen + cont->vm_stack_clen); MEMCPY(cont->vm_stack, th->stack, VALUE, cont->vm_stack_slen); Index: vm.c =================================================================== --- vm.c (revision 50171) +++ vm.c (revision 50172) @@ -2048,7 +2048,6 @@ rb_thread_mark(void *ptr) https://github.com/ruby/ruby/blob/trunk/vm.c#L2048 rb_control_frame_t *limit_cfp = (void *)(th->stack + th->stack_size); rb_gc_mark_values((long)(sp - p), p); - rb_gc_mark_locations(sp, sp + th->mark_stack_len); while (cfp != limit_cfp) { rb_iseq_t *iseq = cfp->iseq; Index: test/ruby/test_keyword.rb =================================================================== --- test/ruby/test_keyword.rb (revision 50171) +++ test/ruby/test_keyword.rb (revision 50172) @@ -566,4 +566,14 @@ class TestKeywordArguments < Test::Unit: https://github.com/ruby/ruby/blob/trunk/test/ruby/test_keyword.rb#L566 result = m(["a" => 10]) { |a = nil, **b| [a, b] } assert_equal([{"a" => 10}, {}], result) end + + def method_for_test_to_hash_call_during_setup_complex_parameters k1:, k2:, **rest_kw + [k1, k2, rest_kw] + end + + def test_to_hash_call_during_setup_complex_parameters + sym = "sym_#{Time.now}".to_sym + h = method_for_test_to_hash_call_during_setup_complex_parameters k1: "foo", k2: "bar", sym => "baz" + assert_equal ["foo", "bar", {sym => "baz"}], h, '[Bug #11027]' + end end Index: vm_args.c =================================================================== --- vm_args.c (revision 50171) +++ vm_args.c (revision 50172) @@ -83,19 +83,17 @@ args_reduce(struct args_info *args, int https://github.com/ruby/ruby/blob/trunk/vm_args.c#L83 } static inline int -args_check_block_arg0(struct args_info *args, rb_thread_t *th, const int msl) +args_check_block_arg0(struct args_info *args, rb_thread_t *th) { VALUE ary = Qnil; if (args->rest && RARRAY_LEN(args->rest) == 1) { VALUE arg0 = RARRAY_AREF(args->rest, 0); ary = rb_check_array_type(arg0); - th->mark_stack_len = msl; } else if (args->argc == 1) { VALUE arg0 = args->argv[0]; ary = rb_check_array_type(arg0); - th->mark_stack_len = msl; args->argv[0] = arg0; /* see: https://bugs.ruby-lang.org/issues/8484 */ } @@ -173,10 +171,9 @@ args_rest_array(struct args_info *args) https://github.com/ruby/ruby/blob/trunk/vm_args.c#L171 } static int -keyword_hash_p(VALUE *kw_hash_ptr, VALUE *rest_hash_ptr, rb_thread_t *th, const int msl) +keyword_hash_p(VALUE *kw_hash_ptr, VALUE *rest_hash_ptr, rb_thread_t *th) { *rest_hash_ptr = rb_check_hash_type(*kw_hash_ptr); - th->mark_stack_len = msl; if (!NIL_P(*rest_hash_ptr)) { VALUE hash = rb_extract_keywords(rest_hash_ptr); @@ -191,7 +188,7 @@ keyword_hash_p(VALUE *kw_hash_ptr, VALUE https://github.com/ruby/ruby/blob/trunk/vm_args.c#L188 } static VALUE -args_pop_keyword_hash(struct args_info *args, VALUE *kw_hash_ptr, rb_thread_t *th, const int msl) +args_pop_keyword_hash(struct args_info *args, VALUE *kw_hash_ptr, rb_thread_t *th) { VALUE rest_hash; @@ -200,7 +197,7 @@ args_pop_keyword_hash(struct args_info * https://github.com/ruby/ruby/blob/trunk/vm_args.c#L197 assert(args->argc > 0); *kw_hash_ptr = args->argv[args->argc-1]; - if (keyword_hash_p(kw_hash_ptr, &rest_hash, th, msl)) { + if (keyword_hash_p(kw_hash_ptr, &rest_hash, th)) { if (rest_hash) { args->argv[args->argc-1] = rest_hash; } @@ -216,7 +213,7 @@ args_pop_keyword_hash(struct args_info * https://github.com/ruby/ruby/blob/trunk/vm_args.c#L213 if (len > 0) { *kw_hash_ptr = RARRAY_AREF(args->rest, len - 1); - if (keyword_hash_p(kw_hash_ptr, &rest_hash, th, msl)) { + if (keyword_hash_p(kw_hash_ptr, &rest_hash, th)) { if (rest_hash) { RARRAY_ASET(args->rest, len - 1, rest_hash); } @@ -511,9 +508,27 @@ setup_parameters_complex(rb_thread_t * c https://github.com/ruby/ruby/blob/trunk/vm_args.c#L508 int given_argc; struct args_info args_body, *args; VALUE keyword_hash = Qnil; - const int msl = ci->argc + iseq->param.size; + VALUE * const orig_sp = th->cfp->sp; + int i; - th->mark_stack_len = msl; + /* + * Extend SP for GC. + * + * [pushed values] [uninitialized values] + * <- ci->argc --> + * <- iseq->param.size------------------> + * ^ locals ^ sp + * + * => + * [pushed values] [initialized values ] + * <- ci->argc --> + * <- iseq->param.size------------------> + * ^ locals ^ sp + */ + for (i=ci->argc; i<iseq->param.size; i++) { + locals[i] = Qnil; + } + th->cfp->sp = &locals[i]; /* setup args */ args = &args_body; @@ -556,7 +571,7 @@ setup_parameters_complex(rb_thread_t * c https://github.com/ruby/ruby/blob/trunk/vm_args.c#L571 (min_argc > 0 || iseq->param.opt_num > 1 || iseq->param.flags.has_kw || iseq->param.flags.has_kwrest) && !iseq->param.flags.ambiguous_param0 && - args_check_block_arg0(args, th, msl)) { + args_check_block_arg0(args, th)) { given_argc = RARRAY_LENINT(args->rest); } break; @@ -564,7 +579,7 @@ setup_parameters_complex(rb_thread_t * c https://github.com/ruby/ruby/blob/trunk/vm_args.c#L579 if (given_argc == 1 && given_argc != iseq->param.lead_num && !iseq->param.flags.has_rest && - args_check_block_arg0(args, th, msl)) { + args_check_block_arg0(args, th)) { given_argc = RARRAY_LENINT(args->rest); } } @@ -590,7 +605,7 @@ setup_parameters_complex(rb_thread_t * c https://github.com/ruby/ruby/blob/trunk/vm_args.c#L605 if (given_argc > min_argc && (iseq->param.flags.has_kw || iseq->param.flags.has_kwrest) && args->kw_argv == NULL) { - if (args_pop_keyword_hash(args, &keyword_hash, th, msl)) { + if (args_pop_keyword_hash(args, &keyword_hash, th)) { given_argc--; } } @@ -662,8 +677,7 @@ setup_parameters_complex(rb_thread_t * c https://github.com/ruby/ruby/blob/trunk/vm_args.c#L677 } #endif - th->mark_stack_len = 0; - + th->cfp->sp = orig_sp; return opt_pc; } -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/