diff options
author | usa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2019-04-30 12:40:20 +0000 |
---|---|---|
committer | usa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2019-04-30 12:40:20 +0000 |
commit | bcdcee47381aa7314a6b249074078f8298d12c7a (patch) | |
tree | 7aa4d14162ae92ac7b32e739659b9b35994b41fb | |
parent | b33a168e65c64f2d852b3911e34bd4faab451ab8 (diff) |
merge revision(s) 66326,66649: [Backport #15385]
Fix infinite loop by ensure
* compile.c (iseq_insert_nop_between_end_and_cont): insert nop so that the end of rescue and continuing points are not same, to get rid of infinite loop. [Bug #15385]
test_optimization.rb: increase timeout for RubyCI
https://rubyci.org/logs/rubyci.s3.amazonaws.com/opensuseleap/ruby-trunk/log/20181230T040002Z.fail.html.gz
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_5@67702 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | compile.c | 35 | ||||
-rw-r--r-- | test/ruby/test_optimization.rb | 9 | ||||
-rw-r--r-- | version.h | 8 |
3 files changed, 39 insertions, 13 deletions
@@ -1226,6 +1226,27 @@ new_child_iseq(rb_iseq_t *iseq, const NODE *const node, return ret_iseq; } +static void +iseq_insert_nop_between_end_and_cont(rb_iseq_t *iseq) +{ + VALUE catch_table_ary = ISEQ_COMPILE_DATA(iseq)->catch_table_ary; + unsigned int i, tlen = (unsigned int)RARRAY_LEN(catch_table_ary); + const VALUE *tptr = RARRAY_CONST_PTR(catch_table_ary); + for (i = 0; i < tlen; i++) { + const VALUE *ptr = RARRAY_CONST_PTR(tptr[i]); + LINK_ELEMENT *end = (LINK_ELEMENT *)(ptr[2] & ~1); + LINK_ELEMENT *cont = (LINK_ELEMENT *)(ptr[4] & ~1); + LINK_ELEMENT *e; + for (e = end; e && (IS_LABEL(e) || IS_TRACE(e)); e = e->next) { + if (e == cont) { + INSN *nop = new_insn_core(iseq, 0, BIN(nop), 0, 0); + ELEM_INSERT_NEXT(end, &nop->link); + break; + } + } + } +} + static int iseq_setup(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) { @@ -1257,6 +1278,9 @@ iseq_setup(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) dump_disasm_list(FIRST_ELEMENT(anchor)); } + debugs("[compile step 3.4 (iseq_insert_nop_between_end_and_cont)]\n"); + iseq_insert_nop_between_end_and_cont(iseq); + debugs("[compile step 4.1 (iseq_set_sequence)]\n"); if (!iseq_set_sequence(iseq, anchor)) return COMPILE_NG; if (compile_debug > 5) @@ -5382,15 +5406,8 @@ compile_ensure(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, ADD_LABEL(ret, lstart); CHECK(COMPILE_(ret, "ensure head", node->nd_head, (popped | last_leave))); ADD_LABEL(ret, lend); - if (LIST_INSN_SIZE_ZERO(ensr)) { - ADD_INSN(ret, line, nop); - } - else { - ADD_SEQ(ret, ensr); - if (!popped && last_leave) { - ADD_INSN(ret, line, putnil); - } - } + ADD_SEQ(ret, ensr); + if (!popped && last_leave) ADD_INSN(ret, line, putnil); ADD_LABEL(ret, lcont); if (last_leave) ADD_INSN(ret, line, pop); diff --git a/test/ruby/test_optimization.rb b/test/ruby/test_optimization.rb index 6b08d07fe2..983054eafc 100644 --- a/test/ruby/test_optimization.rb +++ b/test/ruby/test_optimization.rb @@ -760,4 +760,13 @@ class TestRubyOptimization < Test::Unit::TestCase %w(1) || 2 while (i += 1) < 100 assert_equal(100, i) end + + def test_optimized_empty_ensure + assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}", timeout: 10) + begin; + assert_raise(RuntimeError) { + begin raise ensure nil if nil end + } + end; + end end @@ -1,10 +1,10 @@ #define RUBY_VERSION "2.5.6" -#define RUBY_RELEASE_DATE "2019-03-15" -#define RUBY_PATCHLEVEL 159 +#define RUBY_RELEASE_DATE "2019-04-30" +#define RUBY_PATCHLEVEL 160 #define RUBY_RELEASE_YEAR 2019 -#define RUBY_RELEASE_MONTH 3 -#define RUBY_RELEASE_DAY 15 +#define RUBY_RELEASE_MONTH 4 +#define RUBY_RELEASE_DAY 30 #include "ruby/version.h" |