You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
61 lines
2.4 KiB
61 lines
2.4 KiB
commit 6eeee81c8e59511962bdd83df5e7785bfdf871d2 |
|
Author: Tom Tromey <tromey@redhat.com> |
|
Date: Fri Nov 22 17:38:44 2013 +0000 |
|
|
|
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. |
|
|
|
Index: gdb-7.6.1/gdb/valops.c |
|
=================================================================== |
|
--- gdb-7.6.1.orig/gdb/valops.c |
|
+++ gdb-7.6.1/gdb/valops.c |
|
@@ -1093,7 +1093,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); |
|
@@ -1107,6 +1109,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
|
|
|