Fix coverage measurement for negative line numbers

Fixes [Bug #21220]

Co-Authored-By: Mike Bourgeous <mike@mikebourgeous.com>
Co-Authored-By: Jean Boussier <jean.boussier@gmail.com>
This commit is contained in:
Yusuke Endoh 2025-04-09 19:49:21 +09:00
parent ce0d5cc069
commit 0d6263bd41
Notes: git 2025-04-09 14:46:11 +00:00
4 changed files with 20 additions and 2 deletions

View file

@ -10746,7 +10746,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
if (nd_fl_newline(node)) { if (nd_fl_newline(node)) {
int event = RUBY_EVENT_LINE; int event = RUBY_EVENT_LINE;
ISEQ_COMPILE_DATA(iseq)->last_line = 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; event |= RUBY_EVENT_COVERAGE_LINE;
} }
ADD_TRACE(ret, event); ADD_TRACE(ret, event);

View file

@ -8597,7 +8597,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
int event = RUBY_EVENT_LINE; int event = RUBY_EVENT_LINE;
ISEQ_COMPILE_DATA(iseq)->last_line = lineno; 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; event |= RUBY_EVENT_COVERAGE_LINE;
} }
PUSH_TRACE(ret, event); PUSH_TRACE(ret, event);

View file

@ -192,6 +192,23 @@ class TestCoverage < Test::Unit::TestCase
end; end;
end end
def test_eval_negative_lineno
assert_in_out_err(ARGV, <<-"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 def test_coverage_supported
assert Coverage.supported?(:lines) assert Coverage.supported?(:lines)
assert Coverage.supported?(:oneshot_lines) assert Coverage.supported?(:oneshot_lines)

View file

@ -5662,6 +5662,7 @@ update_line_coverage(VALUE data, const rb_trace_arg_t *trace_arg)
VALUE lines = RARRAY_AREF(coverage, COVERAGE_INDEX_LINES); VALUE lines = RARRAY_AREF(coverage, COVERAGE_INDEX_LINES);
if (lines) { if (lines) {
long line = rb_sourceline() - 1; long line = rb_sourceline() - 1;
VM_ASSERT(line >= 0);
long count; long count;
VALUE num; VALUE num;
void rb_iseq_clear_event_flags(const rb_iseq_t *iseq, size_t pos, rb_event_flag_t reset); void rb_iseq_clear_event_flags(const rb_iseq_t *iseq, size_t pos, rb_event_flag_t reset);