[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]