Change how to correct the first lineno in the backtrace on ArgumentError

Follow up to fix 3b7373fd00.
In that commit, the line number in the first frame was overwritten after
the whole backtrace was created. There was a problem that the line
number was overwritten even if the location was backpatched.

Instead, this commit uses first_lineno if the frame is
VM_FRAME_MAGIC_DUMMY when generating the backtrace.

Before the patch:
```
$ ./miniruby -e '[1, 2].inject(:tap)'
-e:in '<main>': wrong number of arguments (given 1, expected 0) (ArgumentError)
        from -e:1:in 'Enumerable#inject'
        from -e:1:in '<main>'
```

After the patch:
```
$ ./miniruby -e '[1, 2].inject(:tap)'
-e:1:in '<main>': wrong number of arguments (given 1, expected 0) (ArgumentError)
        from -e:1:in 'Enumerable#inject'
        from -e:1:in '<main>'
```
This commit is contained in:
Yusuke Endoh 2025-06-23 22:00:28 +09:00
parent 74e6bddf15
commit a18fa86351
3 changed files with 6 additions and 19 deletions

View file

@ -121,7 +121,6 @@ int rb_get_node_id_from_frame_info(VALUE obj);
const struct rb_iseq_struct *rb_get_iseq_from_frame_info(VALUE obj);
VALUE rb_ec_backtrace_object(const struct rb_execution_context_struct *ec);
void rb_backtrace_use_iseq_first_lineno_for_last_location(VALUE self);
#define RUBY_DTRACE_CREATE_HOOK(name, arg) \
RUBY_DTRACE_HOOK(name##_CREATE, arg)

View file

@ -985,7 +985,6 @@ raise_argument_error(rb_execution_context_t *ec, const rb_iseq_t *iseq, const VA
ISEQ_BODY(iseq)->iseq_encoded,
ec->cfp->sp, 0, 0 /* stack_max */);
at = rb_ec_backtrace_object(ec);
rb_backtrace_use_iseq_first_lineno_for_last_location(at);
rb_vm_pop_frame(ec);
}
else {

View file

@ -715,7 +715,12 @@ rb_ec_partial_backtrace_object(const rb_execution_context_t *ec, long start_fram
}
else {
RB_OBJ_WRITE(btobj, &loc->iseq, iseq);
if ((VM_FRAME_TYPE(cfp) & VM_FRAME_MAGIC_MASK) == VM_FRAME_MAGIC_DUMMY) {
loc->pc = NULL; // means location.first_lineno
}
else {
loc->pc = pc;
}
bt_backpatch_loc(backpatch_counter, loc-1, iseq, pc);
if (do_yield) {
bt_yield_loc(loc - backpatch_counter, backpatch_counter+1, btobj);
@ -813,22 +818,6 @@ rb_backtrace_to_str_ary(VALUE self)
return bt->strary;
}
void
rb_backtrace_use_iseq_first_lineno_for_last_location(VALUE self)
{
rb_backtrace_t *bt;
rb_backtrace_location_t *loc;
TypedData_Get_Struct(self, rb_backtrace_t, &backtrace_data_type, bt);
VM_ASSERT(bt->backtrace_size > 0);
loc = &bt->backtrace[0];
VM_ASSERT(!loc->cme || loc->cme->def->type == VM_METHOD_TYPE_ISEQ);
loc->pc = NULL; // means location.first_lineno
}
static VALUE
location_create(rb_backtrace_location_t *srcloc, void *btobj)
{