ruby-changes:38481
From: nagachika <ko1@a...>
Date: Thu, 21 May 2015 01:04:50 +0900 (JST)
Subject: [ruby-changes:38481] nagachika:r50562 (ruby_2_2): merge revision(s) 50172, 50173: [Backport #11027]
nagachika 2015-05-21 01:04:34 +0900 (Thu, 21 May 2015) New Revision: 50562 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=50562 Log: merge revision(s) 50172,50173: [Backport #11027] * 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 directories: branches/ruby_2_2/ Modified files: branches/ruby_2_2/ChangeLog branches/ruby_2_2/cont.c branches/ruby_2_2/test/ruby/test_keyword.rb branches/ruby_2_2/version.h branches/ruby_2_2/vm.c branches/ruby_2_2/vm_args.c branches/ruby_2_2/vm_core.h Index: ruby_2_2/ChangeLog =================================================================== --- ruby_2_2/ChangeLog (revision 50561) +++ ruby_2_2/ChangeLog (revision 50562) @@ -1,3 +1,18 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_2/ChangeLog#L1 +Thu May 21 00:55:45 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. + Thu May 21 00:07:54 2015 Nobuyoshi Nakada <nobu@r...> * vm_eval.c (rb_obj_instance_eval, rb_obj_instance_exec): allow Index: ruby_2_2/vm_core.h =================================================================== --- ruby_2_2/vm_core.h (revision 50561) +++ ruby_2_2/vm_core.h (revision 50562) @@ -642,7 +642,6 @@ typedef struct rb_thread_struct { https://github.com/ruby/ruby/blob/trunk/ruby_2_2/vm_core.h#L642 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: ruby_2_2/cont.c =================================================================== --- ruby_2_2/cont.c (revision 50561) +++ ruby_2_2/cont.c (revision 50562) @@ -490,7 +490,7 @@ cont_capture(volatile int *stat) https://github.com/ruby/ruby/blob/trunk/ruby_2_2/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: ruby_2_2/vm.c =================================================================== --- ruby_2_2/vm.c (revision 50561) +++ ruby_2_2/vm.c (revision 50562) @@ -2015,7 +2015,6 @@ rb_thread_mark(void *ptr) https://github.com/ruby/ruby/blob/trunk/ruby_2_2/vm.c#L2015 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: ruby_2_2/version.h =================================================================== --- ruby_2_2/version.h (revision 50561) +++ ruby_2_2/version.h (revision 50562) @@ -1,6 +1,6 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_2/version.h#L1 #define RUBY_VERSION "2.2.3" #define RUBY_RELEASE_DATE "2015-05-21" -#define RUBY_PATCHLEVEL 111 +#define RUBY_PATCHLEVEL 112 #define RUBY_RELEASE_YEAR 2015 #define RUBY_RELEASE_MONTH 5 Index: ruby_2_2/test/ruby/test_keyword.rb =================================================================== --- ruby_2_2/test/ruby/test_keyword.rb (revision 50561) +++ ruby_2_2/test/ruby/test_keyword.rb (revision 50562) @@ -566,4 +566,14 @@ class TestKeywordArguments < Test::Unit: https://github.com/ruby/ruby/blob/trunk/ruby_2_2/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: ruby_2_2/vm_args.c =================================================================== --- ruby_2_2/vm_args.c (revision 50561) +++ ruby_2_2/vm_args.c (revision 50562) @@ -83,19 +83,17 @@ args_reduce(struct args_info *args, int https://github.com/ruby/ruby/blob/trunk/ruby_2_2/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/ruby_2_2/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/ruby_2_2/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/ruby_2_2/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/ruby_2_2/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/ruby_2_2/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/ruby_2_2/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/ruby_2_2/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/ruby_2_2/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/ruby_2_2/vm_args.c#L677 } #endif - th->mark_stack_len = 0; - + th->cfp->sp = orig_sp; return opt_pc; } Property changes on: ruby_2_2 ___________________________________________________________________ Modified: svn:mergeinfo Merged /trunk:r50172-50173 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/