зеркало из https://github.com/github/ruby.git
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]
This commit is contained in:
Родитель
3a29f05ba5
Коммит
75acbd5f00
|
@ -5017,7 +5017,14 @@ setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn,
|
||||||
case NODE_ARGSPUSH: {
|
case NODE_ARGSPUSH: {
|
||||||
int next_is_list = (nd_type(argn->nd_head) == NODE_LIST);
|
int next_is_list = (nd_type(argn->nd_head) == NODE_LIST);
|
||||||
VALUE argc = setup_args_core(iseq, args, argn->nd_head, 1, NULL, NULL);
|
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) {
|
if (flag) {
|
||||||
*flag |= VM_CALL_ARGS_SPLAT;
|
*flag |= VM_CALL_ARGS_SPLAT;
|
||||||
/* This is a dirty hack. It traverses the AST twice.
|
/* This is a dirty hack. It traverses the AST twice.
|
||||||
|
|
|
@ -4654,6 +4654,12 @@ class TestKeywordArguments < Test::Unit::TestCase
|
||||||
def test_splat_empty_hash_with_block_passing
|
def test_splat_empty_hash_with_block_passing
|
||||||
assert_valid_syntax("bug15087(**{}, &nil)")
|
assert_valid_syntax("bug15087(**{}, &nil)")
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
class TestKeywordArgumentsSymProcRefinements < Test::Unit::TestCase
|
class TestKeywordArgumentsSymProcRefinements < Test::Unit::TestCase
|
||||||
|
|
Загрузка…
Ссылка в новой задаче