Skip to content

Commit

Permalink
[Bug #20468] Fix safe navigation in for variable
Browse files Browse the repository at this point in the history
  • Loading branch information
nobu committed May 16, 2024
1 parent 9d69619 commit 2dd46bb
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 6 deletions.
21 changes: 15 additions & 6 deletions compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -5380,12 +5380,17 @@ compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *const pre, LINK_ANCHOR *const

CHECK(COMPILE_POPPED(pre, "masgn lhs (NODE_ATTRASGN)", node));

bool safenav_call = false;
LINK_ELEMENT *insn_element = LAST_ELEMENT(pre);
iobj = (INSN *)get_prev_insn((INSN *)insn_element); /* send insn */
ASSUME(iobj);
ELEM_REMOVE(LAST_ELEMENT(pre));
ELEM_REMOVE((LINK_ELEMENT *)iobj);
pre->last = iobj->link.prev;
ELEM_REMOVE(insn_element);
if (!IS_INSN_ID(iobj, send)) {
safenav_call = true;
iobj = (INSN *)get_prev_insn(iobj);
ELEM_INSERT_NEXT(&iobj->link, insn_element);
}
(pre->last = iobj->link.prev)->next = 0;

const struct rb_callinfo *ci = (struct rb_callinfo *)OPERAND_AT(iobj, 0);
int argc = vm_ci_argc(ci) + 1;
Expand All @@ -5404,7 +5409,9 @@ compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *const pre, LINK_ANCHOR *const
return COMPILE_NG;
}

ADD_ELEM(lhs, (LINK_ELEMENT *)iobj);
iobj->link.prev = lhs->last;
lhs->last->next = &iobj->link;
for (lhs->last = &iobj->link; lhs->last->next; lhs->last = lhs->last->next);
if (vm_ci_flag(ci) & VM_CALL_ARGS_SPLAT) {
int argc = vm_ci_argc(ci);
bool dupsplat = false;
Expand Down Expand Up @@ -5437,9 +5444,11 @@ compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *const pre, LINK_ANCHOR *const
}
INSERT_BEFORE_INSN1(iobj, line_no, node_id, pushtoarray, INT2FIX(1));
}
ADD_INSN(lhs, line_node, pop);
if (argc != 1) {
if (!safenav_call) {
ADD_INSN(lhs, line_node, pop);
if (argc != 1) {
ADD_INSN(lhs, line_node, pop);
}
}
for (int i=0; i < argc; i++) {
ADD_INSN(post, line_node, pop);
Expand Down
14 changes: 14 additions & 0 deletions test/ruby/test_syntax.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1248,6 +1248,20 @@ def test_safe_call_in_massign_lhs
assert_syntax_error("a&.x,=0", /multiple assignment destination/)
end

def test_safe_call_in_for_variable
assert_valid_syntax("for x&.bar in []; end")
assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
begin;
foo = nil
for foo&.bar in [1]; end
assert_nil(foo)
foo = Struct.new(:bar).new
for foo&.bar in [1]; end
assert_equal(1, foo.bar)
end;
end

def test_no_warning_logop_literal
assert_warning("") do
eval("true||raise;nil")
Expand Down

0 comments on commit 2dd46bb

Please sign in to comment.