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

ruby-changes:45898

From: mame <ko1@a...>
Date: Tue, 14 Mar 2017 20:40:04 +0900 (JST)
Subject: [ruby-changes:45898] mame:r57971 (trunk): Fix a consistency bug of ISEQ_COVERAGE [Bug #13305]

mame	2017-03-14 20:39:58 +0900 (Tue, 14 Mar 2017)

  New Revision: 57971

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

  Log:
    Fix a consistency bug of ISEQ_COVERAGE [Bug #13305]
    
    There is an invariant that ISEQ_COVERAGE(iseq) must be Qnil if and only
    if option->coverage_enabled is false.  This invariant was broken by
    NODE_PRELUDE which updates option->coverage_enabled but not
    ISEQ_COVERAGE(iseq).

  Modified files:
    trunk/compile.c
    trunk/test/coverage/test_coverage.rb
Index: test/coverage/test_coverage.rb
===================================================================
--- test/coverage/test_coverage.rb	(revision 57970)
+++ test/coverage/test_coverage.rb	(revision 57971)
@@ -119,4 +119,34 @@ class TestCoverage < Test::Unit::TestCas https://github.com/ruby/ruby/blob/trunk/test/coverage/test_coverage.rb#L119
     end
     assert_include Coverage.result, "<compiled>"
   end
+
+  def test_eval
+    bug13305 = '[ruby-core:80079] [Bug #13305]'
+    loaded_features = $".dup
+
+    Dir.mktmpdir {|tmp|
+      Dir.chdir(tmp) {
+        File.open("test.rb", "w") do |f|
+          f.puts 'REPEATS = 400'
+          f.puts 'def add_method(target)'
+          f.puts '  REPEATS.times do'
+          f.puts '    target.class_eval(<<~RUBY, __FILE__, __LINE__ + 1)'
+          f.puts '      def foo'
+          f.puts '        #{"\n" * rand(REPEATS)}'
+          f.puts '      end'
+          f.puts '      1'
+          f.puts '    RUBY'
+          f.puts '  end'
+          f.puts 'end'
+        end
+
+        Coverage.start
+        require tmp + '/test.rb'
+        add_method(Class.new)
+        assert_equal Coverage.result[tmp + "/test.rb"], [1, 1, 1, 400, nil, nil, nil, nil, nil, nil, nil], bug13305
+      }
+    }
+  ensure
+    $".replace loaded_features
+  end
 end unless ENV['COVERAGE']
Index: compile.c
===================================================================
--- compile.c	(revision 57970)
+++ compile.c	(revision 57971)
@@ -6310,14 +6310,17 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK https://github.com/ruby/ruby/blob/trunk/compile.c#L6310
       }
       case NODE_PRELUDE:{
 	const rb_compile_option_t *orig_opt = ISEQ_COMPILE_DATA(iseq)->option;
+	VALUE orig_cov = ISEQ_COVERAGE(iseq);
+	rb_compile_option_t new_opt = *orig_opt;
 	if (node->nd_orig) {
-	    rb_compile_option_t new_opt = *orig_opt;
 	    rb_iseq_make_compile_option(&new_opt, node->nd_orig);
 	    ISEQ_COMPILE_DATA(iseq)->option = &new_opt;
 	}
+	if (!new_opt.coverage_enabled) ISEQ_COVERAGE_SET(iseq, Qfalse);
 	CHECK(COMPILE_POPPED(ret, "prelude", node->nd_head));
 	CHECK(COMPILE_(ret, "body", node->nd_body, popped));
 	ISEQ_COMPILE_DATA(iseq)->option = orig_opt;
+	ISEQ_COVERAGE_SET(iseq, orig_cov);
 	break;
       }
       case NODE_LAMBDA:{

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

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