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:
Tom Tromey 2013-11-22 17:38:44 +00:00 committed by Pedro Alves
parent 0cb112f740
commit 6eeee81c8e
2 changed files with 26 additions and 1 deletions

View File

@ -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>

View File

@ -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