Thanks to visit codestin.com
Credit goes to github.com

Skip to content

fix raise in exception with jump #4399

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 27 additions & 7 deletions compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -5203,9 +5203,22 @@ add_ensure_range(rb_iseq_t *iseq, struct ensure_range *erange,
erange->next = ne;
}

static bool
can_add_ensure_iseq(const rb_iseq_t *iseq)
{
if (ISEQ_COMPILE_DATA(iseq)->in_rescue && ISEQ_COMPILE_DATA(iseq)->ensure_node_stack) {
return false;
}
else {
return true;
}
}

static void
add_ensure_iseq(LINK_ANCHOR *const ret, rb_iseq_t *iseq, int is_return)
{
assert(can_add_ensure_iseq(iseq));

struct iseq_compile_data_ensure_node_stack *enlp =
ISEQ_COMPILE_DATA(iseq)->ensure_node_stack;
struct iseq_compile_data_ensure_node_stack *prev_enlp = enlp;
Expand Down Expand Up @@ -6697,7 +6710,7 @@ compile_break(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i
const int line = nd_line(node);
unsigned long throw_flag = 0;

if (ISEQ_COMPILE_DATA(iseq)->redo_label != 0) {
if (ISEQ_COMPILE_DATA(iseq)->redo_label != 0 && can_add_ensure_iseq(iseq)) {
/* while/until */
LABEL *splabel = NEW_LABEL(0);
ADD_LABEL(ret, splabel);
Expand Down Expand Up @@ -6756,7 +6769,7 @@ compile_next(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in
const int line = nd_line(node);
unsigned long throw_flag = 0;

if (ISEQ_COMPILE_DATA(iseq)->redo_label != 0) {
if (ISEQ_COMPILE_DATA(iseq)->redo_label != 0 && can_add_ensure_iseq(iseq)) {
LABEL *splabel = NEW_LABEL(0);
debugs("next in while loop\n");
ADD_LABEL(ret, splabel);
Expand All @@ -6769,7 +6782,7 @@ compile_next(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in
ADD_INSN(ret, line, putnil);
}
}
else if (ISEQ_COMPILE_DATA(iseq)->end_label) {
else if (ISEQ_COMPILE_DATA(iseq)->end_label && can_add_ensure_iseq(iseq)) {
LABEL *splabel = NEW_LABEL(0);
debugs("next in block\n");
ADD_LABEL(ret, splabel);
Expand Down Expand Up @@ -6829,7 +6842,7 @@ compile_redo(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in
{
const int line = nd_line(node);

if (ISEQ_COMPILE_DATA(iseq)->redo_label) {
if (ISEQ_COMPILE_DATA(iseq)->redo_label && can_add_ensure_iseq(iseq)) {
LABEL *splabel = NEW_LABEL(0);
debugs("redo in while");
ADD_LABEL(ret, splabel);
Expand All @@ -6841,7 +6854,7 @@ compile_redo(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in
ADD_INSN(ret, line, putnil);
}
}
else if (iseq->body->type != ISEQ_TYPE_EVAL && ISEQ_COMPILE_DATA(iseq)->start_label) {
else if (iseq->body->type != ISEQ_TYPE_EVAL && ISEQ_COMPILE_DATA(iseq)->start_label && can_add_ensure_iseq(iseq)) {
LABEL *splabel = NEW_LABEL(0);

debugs("redo in block");
Expand Down Expand Up @@ -6927,7 +6940,14 @@ compile_rescue(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node,
lstart->rescued = LABEL_RESCUE_BEG;
lend->rescued = LABEL_RESCUE_END;
ADD_LABEL(ret, lstart);
CHECK(COMPILE(ret, "rescue head", node->nd_head));

bool prev_in_rescue = ISEQ_COMPILE_DATA(iseq)->in_rescue;
ISEQ_COMPILE_DATA(iseq)->in_rescue = true;
{
CHECK(COMPILE(ret, "rescue head", node->nd_head));
}
ISEQ_COMPILE_DATA(iseq)->in_rescue = prev_in_rescue;

ADD_LABEL(ret, lend);
if (node->nd_else) {
ADD_INSN(ret, line, pop);
Expand Down Expand Up @@ -7088,7 +7108,7 @@ compile_return(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node,

CHECK(COMPILE(ret, "return nd_stts (return val)", retval));

if (type == ISEQ_TYPE_METHOD) {
if (type == ISEQ_TYPE_METHOD && can_add_ensure_iseq(iseq)) {
add_ensure_iseq(ret, iseq, 1);
ADD_TRACE(ret, RUBY_EVENT_RETURN);
ADD_INSN(ret, line, leave);
Expand Down
1 change: 1 addition & 0 deletions iseq.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ struct iseq_compile_data {
struct iseq_compile_data_storage *storage_head;
struct iseq_compile_data_storage *storage_current;
} insn;
bool in_rescue;
int loopval_popped; /* used by NODE_BREAK */
int last_line;
int label_no;
Expand Down
60 changes: 60 additions & 0 deletions test/ruby/test_exception.rb
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,66 @@ def test_exception_ensure_2 # just duplication?
assert(!bad)
end

def test_exception_in_ensure_with_next
string = "[ruby-core:82936] [Bug #13930]"
assert_raise_with_message(RuntimeError, string) do
lambda do
next
rescue
assert(false)
ensure
raise string
end.call
assert(false)
end

assert_raise_with_message(RuntimeError, string) do
flag = true
while flag
flag = false
begin
next
rescue
assert(false)
ensure
raise string
end
end
end
end

def test_exception_in_ensure_with_redo
string = "[ruby-core:82936] [Bug #13930]"

assert_raise_with_message(RuntimeError, string) do
i = 0
lambda do
i += 1
redo if i < 2
rescue
assert(false)
ensure
raise string
end.call
assert(false)
end
end

def test_exception_in_ensure_with_return
@string = "[ruby-core:97104] [Bug #16618]"
def self.meow
return
assert(false)
rescue
assert(false)
ensure
raise @string
end
assert_raise_with_message(RuntimeError, @string) do
meow
end
end

def test_errinfo_in_debug
bug9568 = EnvUtil.labeled_class("[ruby-core:61091] [Bug #9568]", RuntimeError) do
def to_s
Expand Down