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

ruby-changes:59360

From: Yusuke <ko1@a...>
Date: Sun, 22 Dec 2019 03:35:45 +0900 (JST)
Subject: [ruby-changes:59360] 75acbd5f00 (master): compile.c: avoid newarraykwsplat for arguments

https://git.ruby-lang.org/ruby.git/commit/?id=75acbd5f00

From 75acbd5f0076970d48bc423c2b058adbdb5da9e8 Mon Sep 17 00:00:00 2001
From: Yusuke Endoh <mame@r...>
Date: Sun, 22 Dec 2019 03:31:27 +0900
Subject: compile.c: avoid newarraykwsplat for arguments

`foo(*rest, post, **empty_kw)` is compiled like
`foo(*rest + [post, **empty_kw])`, and `**empty_kw` is removed by
"newarraykwsplat" instruction.
However, the method call still has a flag of KW_SPLAT, so "post" is
considered as a keyword hash, which caused a segfault.
Note that the flag cannot be removed if "empty_kw" is not always empty.

This change fixes the issue by compiling arguments with "newarray"
instead of "newarraykwsplat".

[Bug #16442]

diff --git a/compile.c b/compile.c
index 98ee34a..c19112c 100644
--- a/compile.c
+++ b/compile.c
@@ -5017,7 +5017,14 @@ setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn, https://github.com/ruby/ruby/blob/trunk/compile.c#L5017
           case NODE_ARGSPUSH: {
             int next_is_list = (nd_type(argn->nd_head) == NODE_LIST);
             VALUE argc = setup_args_core(iseq, args, argn->nd_head, 1, NULL, NULL);
-            NO_CHECK(COMPILE(args, "args (cat: splat)", argn->nd_body));
+            if (nd_type(argn->nd_body) == NODE_LIST) {
+                /* This branch is needed to avoid "newarraykwsplat" [Bug #16442] */
+                int rest_len = compile_args(iseq, args, argn->nd_body, NULL, NULL);
+                ADD_INSN1(args, nd_line(argn), newarray, INT2FIX(rest_len));
+            }
+            else {
+                NO_CHECK(COMPILE(args, "args (cat: splat)", argn->nd_body));
+            }
             if (flag) {
                 *flag |= VM_CALL_ARGS_SPLAT;
                 /* This is a dirty hack.  It traverses the AST twice.
diff --git a/test/ruby/test_keyword.rb b/test/ruby/test_keyword.rb
index 3d5cb2d..bfdec6f 100644
--- a/test/ruby/test_keyword.rb
+++ b/test/ruby/test_keyword.rb
@@ -4654,6 +4654,12 @@ class TestKeywordArguments < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_keyword.rb#L4654
   def test_splat_empty_hash_with_block_passing
     assert_valid_syntax("bug15087(**{}, &nil)")
   end
+
+  def test_do_not_use_newarraykwsplat
+    assert_equal([42, "foo", 424242], f2(*[], 42, **{}))
+    a = [1, 2, 3]
+    assert_equal([[1,2,3,4,5,6], "foo", 424242, {:k=>:k}], f7(*a, 4,5,6, k: :k))
+  end
 end
 
 class TestKeywordArgumentsSymProcRefinements < Test::Unit::TestCase
-- 
cgit v0.10.2


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

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