mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-27 20:14:06 +08:00
Detect infinite loop in value_fetch_lazy's lval_register handling.
If value_fetch_lazy loops infinitely while unwrapping lval_register values, it means we either somehow ended up with two frames with the same ID in the frame chain, or some code is trying to unwind behind get_prev_frame's back (e.g., a frame unwind sniffer trying to unwind). In any case, it should always be an internal error to end up in this situation. This patch adds a check and throws an internal error if the same frame is returned. 2013-11-22 Tom Tromey <tromey@redhat.com> Pedro Alves <palves@redhat.com> PR backtrace/16155 * value.c (value_fetch_lazy): Internal error if get_frame_register_value returns the same register.
This commit is contained in:
parent
0cb112f740
commit
6eeee81c8e
@ -1,3 +1,10 @@
|
||||
2013-11-22 Tom Tromey <tromey@redhat.com>
|
||||
Pedro Alves <palves@redhat.com>
|
||||
|
||||
PR backtrace/16155
|
||||
* value.c (value_fetch_lazy): Internal error if
|
||||
get_frame_register_value returns the same register.
|
||||
|
||||
2013-11-22 Pedro Alves <palves@redhat.com>
|
||||
Tom Tromey <tromey@redhat.com>
|
||||
|
||||
|
20
gdb/value.c
20
gdb/value.c
@ -3507,7 +3507,9 @@ value_fetch_lazy (struct value *val)
|
||||
|
||||
while (VALUE_LVAL (new_val) == lval_register && value_lazy (new_val))
|
||||
{
|
||||
frame = frame_find_by_id (VALUE_FRAME_ID (new_val));
|
||||
struct frame_id frame_id = VALUE_FRAME_ID (new_val);
|
||||
|
||||
frame = frame_find_by_id (frame_id);
|
||||
regnum = VALUE_REGNUM (new_val);
|
||||
|
||||
gdb_assert (frame != NULL);
|
||||
@ -3521,6 +3523,22 @@ value_fetch_lazy (struct value *val)
|
||||
regnum, type));
|
||||
|
||||
new_val = get_frame_register_value (frame, regnum);
|
||||
|
||||
/* If we get another lazy lval_register value, it means the
|
||||
register is found by reading it from the next frame.
|
||||
get_frame_register_value should never return a value with
|
||||
the frame id pointing to FRAME. If it does, it means we
|
||||
either have two consecutive frames with the same frame id
|
||||
in the frame chain, or some code is trying to unwind
|
||||
behind get_prev_frame's back (e.g., a frame unwind
|
||||
sniffer trying to unwind), bypassing its validations. In
|
||||
any case, it should always be an internal error to end up
|
||||
in this situation. */
|
||||
if (VALUE_LVAL (new_val) == lval_register
|
||||
&& value_lazy (new_val)
|
||||
&& frame_id_eq (VALUE_FRAME_ID (new_val), frame_id))
|
||||
internal_error (__FILE__, __LINE__,
|
||||
_("infinite loop while fetching a register"));
|
||||
}
|
||||
|
||||
/* If it's still lazy (for instance, a saved register on the
|
||||
|
Loading…
Reference in New Issue
Block a user