Avoid opt_aset_with optimization inside multiple assignment
Previously, since the opt_aset_with optimization was introduced, use of the opt_aset_with optimization inside multiple assignment would result in a segfault or incorrect instructions. Fixes [Bug #21012] Co-authored-by: Nobuyoshi Nakada <nobu.nakada@gmail.com>
This commit is contained in:
parent
e728170043
commit
e0d600ec19
Notes:
git
2025-01-08 16:50:14 +00:00
Merged: https://github.com/ruby/ruby/pull/12528 Merged-By: jeremyevans <code@jeremyevans.net>
@ -10240,7 +10240,8 @@ compile_attrasgn(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node
|
||||
/* optimization shortcut
|
||||
* obj["literal"] = value -> opt_aset_with(obj, "literal", value)
|
||||
*/
|
||||
if (mid == idASET && !private_recv_p(node) && RNODE_ATTRASGN(node)->nd_args &&
|
||||
if (!ISEQ_COMPILE_DATA(iseq)->in_masgn &&
|
||||
mid == idASET && !private_recv_p(node) && RNODE_ATTRASGN(node)->nd_args &&
|
||||
nd_type_p(RNODE_ATTRASGN(node)->nd_args, NODE_LIST) && RNODE_LIST(RNODE_ATTRASGN(node)->nd_args)->as.nd_alen == 2 &&
|
||||
(nd_type_p(RNODE_LIST(RNODE_ATTRASGN(node)->nd_args)->nd_head, NODE_STR) || nd_type_p(RNODE_LIST(RNODE_ATTRASGN(node)->nd_args)->nd_head, NODE_FILE)) &&
|
||||
ISEQ_COMPILE_DATA(iseq)->current_block == NULL &&
|
||||
@ -10793,7 +10794,10 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
|
||||
}
|
||||
|
||||
case NODE_MASGN:{
|
||||
bool prev_in_masgn = ISEQ_COMPILE_DATA(iseq)->in_masgn;
|
||||
ISEQ_COMPILE_DATA(iseq)->in_masgn = true;
|
||||
compile_massign(iseq, ret, node, popped);
|
||||
ISEQ_COMPILE_DATA(iseq)->in_masgn = prev_in_masgn;
|
||||
break;
|
||||
}
|
||||
|
||||
|
1
iseq.h
1
iseq.h
@ -119,6 +119,7 @@ struct iseq_compile_data {
|
||||
struct iseq_compile_data_storage *storage_current;
|
||||
} insn;
|
||||
bool in_rescue;
|
||||
bool in_masgn;
|
||||
int loopval_popped; /* used by NODE_BREAK */
|
||||
int last_line;
|
||||
int label_no;
|
||||
|
@ -248,6 +248,16 @@ class TestAssignment < Test::Unit::TestCase
|
||||
a,b,*c = *[*[1,2]]; assert_equal([1,2,[]], [a,b,c])
|
||||
end
|
||||
|
||||
def test_massign_optimized_literal_bug_21012
|
||||
a = []
|
||||
def a.[]=(*args)
|
||||
push args
|
||||
end
|
||||
a["a", "b"], = 1
|
||||
a["a", 10], = 2
|
||||
assert_equal [["a", "b", 1], ["a", 10, 2]], a
|
||||
end
|
||||
|
||||
def test_assign_rescue
|
||||
a = raise rescue 2; assert_equal(2, a)
|
||||
a, b = raise rescue [3,4]; assert_equal([3, 4], [a, b])
|
||||
|
Loading…
x
Reference in New Issue
Block a user