diff --git a/compile.c b/compile.c index 110530f89f..22eadc8d25 100644 --- a/compile.c +++ b/compile.c @@ -9783,7 +9783,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no if (nd_fl_newline(node)) { int event = RUBY_EVENT_LINE; ISEQ_COMPILE_DATA(iseq)->last_line = line; - if (ISEQ_COVERAGE(iseq) && ISEQ_LINE_COVERAGE(iseq)) { + if (line > 0 && ISEQ_COVERAGE(iseq) && ISEQ_LINE_COVERAGE(iseq)) { event |= RUBY_EVENT_COVERAGE_LINE; } ADD_TRACE(ret, event); diff --git a/prism_compile.c b/prism_compile.c index b60ca0ac68..15b5f1cb41 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2786,7 +2786,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, int event = RUBY_EVENT_LINE; ISEQ_COMPILE_DATA(iseq)->last_line = lineno; - if (ISEQ_COVERAGE(iseq) && ISEQ_LINE_COVERAGE(iseq)) { + if (lineno > 0 && ISEQ_COVERAGE(iseq) && ISEQ_LINE_COVERAGE(iseq)) { event |= RUBY_EVENT_COVERAGE_LINE; } ADD_TRACE(ret, event); diff --git a/test/coverage/test_coverage.rb b/test/coverage/test_coverage.rb index 16be47b458..4751bec6d5 100644 --- a/test/coverage/test_coverage.rb +++ b/test/coverage/test_coverage.rb @@ -181,6 +181,23 @@ class TestCoverage < Test::Unit::TestCase end; end + def test_eval_negative_lineno + assert_in_out_err(["-rcoverage"], <<-"end;", ["[1, 1, 1]"], []) + Coverage.start(eval: true, lines: true) + + eval(<<-RUBY, TOPLEVEL_BINDING, "test.rb", -2) + p # -2 # Not subject to measurement + p # -1 # Not subject to measurement + p # 0 # Not subject to measurement + p # 1 # Subject to measurement + p # 2 # Subject to measurement + p # 3 # Subject to measurement + RUBY + + p Coverage.result["test.rb"][:lines] + end; + end + def test_coverage_supported assert Coverage.supported?(:lines) assert Coverage.supported?(:oneshot_lines) diff --git a/thread.c b/thread.c index bcafbaacfa..51316c100e 100644 --- a/thread.c +++ b/thread.c @@ -5589,6 +5589,7 @@ update_line_coverage(VALUE data, const rb_trace_arg_t *trace_arg) VALUE lines = RARRAY_AREF(coverage, COVERAGE_INDEX_LINES); if (lines) { long line = rb_sourceline() - 1; + VM_ASSERT(line >= 0); long count; VALUE num; void rb_iseq_clear_event_flags(const rb_iseq_t *iseq, size_t pos, rb_event_flag_t reset); diff --git a/version.h b/version.h index 149c58e500..d6924e761f 100644 --- a/version.h +++ b/version.h @@ -11,7 +11,7 @@ # define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR #define RUBY_VERSION_TEENY 8 #define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR -#define RUBY_PATCHLEVEL 145 +#define RUBY_PATCHLEVEL 146 #include "ruby/version.h" #include "ruby/internal/abi.h"