summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Evans <[email protected]>2025-01-08 08:49:51 -0800
committer<[email protected]>2025-01-08 08:49:51 -0800
commite0d600ec190c64aff76cfcbd6009cffb927da166 ()
tree3ef2eba19dc6ab2269b8f0c9f3ccb303f24e2037
parente728170043ab9afb0f064af2bcfcf6ca06f9573d (diff)
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 <[email protected]>
Notes: Merged: https://.com/ruby/ruby/pull/12528 Merged-By: jeremyevans <[email protected]>
-rw-r--r--compile.c6
-rw-r--r--iseq.h1
-rw-r--r--test/ruby/test_assignment.rb10
3 files changed, 16 insertions, 1 deletions
@@ -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 &&
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:{
compile_massign(iseq, ret, node, popped);
break;
}
@@ -119,6 +119,7 @@ struct iseq_compile_data {
struct iseq_compile_data_storage *storage_current;
} insn;
bool in_rescue;
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_assign_rescue
a = raise rescue 2; assert_equal(2, a)
a, b = raise rescue [3,4]; assert_equal([3, 4], [a, b])