[前][次][番号順一覧][スレッド一覧]

ruby-changes:49503

From: nobu <ko1@a...>
Date: Fri, 5 Jan 2018 23:23:30 +0900 (JST)
Subject: [ruby-changes:49503] nobu:r61618 (trunk): compile.c: fix stack consistency error

nobu	2018-01-05 23:23:23 +0900 (Fri, 05 Jan 2018)

  New Revision: 61618

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=61618

  Log:
    compile.c: fix stack consistency error
    
    * compile.c (iseq_peephole_optimize): fix stack consistency error
      from return in loop, by adding extra `pop` when replacing `jump`
      with `leave`, which is never reached but needed to adjust sp
      calculation.  [ruby-core:84589] [Bug #14273]

  Modified files:
    trunk/compile.c
    trunk/test/ruby/test_syntax.rb
Index: compile.c
===================================================================
--- compile.c	(revision 61617)
+++ compile.c	(revision 61618)
@@ -2476,6 +2476,7 @@ iseq_peephole_optimize(rb_iseq_t *iseq, https://github.com/ruby/ruby/blob/trunk/compile.c#L2476
 	    goto again;
 	}
 	else if (IS_INSN_ID(diobj, leave)) {
+	    INSN *pop;
 	    /*
 	     *  jump LABEL
 	     *  ...
@@ -2483,6 +2484,7 @@ iseq_peephole_optimize(rb_iseq_t *iseq, https://github.com/ruby/ruby/blob/trunk/compile.c#L2484
 	     *  leave
 	     * =>
 	     *  leave
+	     *  pop
 	     *  ...
 	     * LABEL:
 	     *  leave
@@ -2492,6 +2494,9 @@ iseq_peephole_optimize(rb_iseq_t *iseq, https://github.com/ruby/ruby/blob/trunk/compile.c#L2494
 	    iobj->insn_id = BIN(leave);
 	    iobj->operand_size = 0;
 	    iobj->insn_info = diobj->insn_info;
+	    /* adjust stack depth */
+	    pop = new_insn_body(iseq, diobj->insn_info.line_no, BIN(pop), 0);
+	    ELEM_INSERT_NEXT(&iobj->link, &pop->link);
 	    goto again;
 	}
 	else if ((piobj = (INSN *)get_prev_insn(iobj)) != 0 &&
Index: test/ruby/test_syntax.rb
===================================================================
--- test/ruby/test_syntax.rb	(revision 61617)
+++ test/ruby/test_syntax.rb	(revision 61618)
@@ -1128,6 +1128,15 @@ eom https://github.com/ruby/ruby/blob/trunk/test/ruby/test_syntax.rb#L1128
     assert_equal(:begin, result)
   end
 
+  def test_return_in_loop
+    obj = Object.new
+    def obj.test
+      x = nil
+      return until x unless x
+    end
+    assert_nil obj.test
+  end
+
   private
 
   def not_label(x) @result = x; @not_label ||= nil end

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]