diff options
author | Yusuke Endoh <[email protected]> | 2019-12-22 03:31:27 +0900 |
---|---|---|
committer | Yusuke Endoh <[email protected]> | 2019-12-22 03:35:29 +0900 |
commit | 75acbd5f0076970d48bc423c2b058adbdb5da9e8 (patch) | |
tree | 63fb15a22a27aa969916849dcdfc381cd13b52bb /compile.c | |
parent | 3a29f05ba5ba7ed4b821ba5f566eeb3ff3c5c3b1 (diff) |
compile.c: avoid newarraykwsplat for argumentsv2_7_0_rc2
`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]
Diffstat (limited to 'compile.c')
-rw-r--r-- | compile.c | 9 |
1 files changed, 8 insertions, 1 deletions
@@ -5017,7 +5017,14 @@ setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn, 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. |