From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 7690 invoked by alias); 22 Nov 2013 14:31:39 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 7681 invoked by uid 89); 22 Nov 2013 14:31:38 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.2 required=5.0 tests=AWL,BAYES_00,RDNS_NONE,SPF_HELO_PASS,SPF_PASS autolearn=no version=3.3.2 X-HELO: mx1.redhat.com Received: from Unknown (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 22 Nov 2013 14:31:37 +0000 Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id rAMEVUtO023905 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Fri, 22 Nov 2013 09:31:30 -0500 Received: from [127.0.0.1] (ovpn01.gateway.prod.ext.ams2.redhat.com [10.39.146.11]) by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id rAMEVSok010879; Fri, 22 Nov 2013 09:31:29 -0500 Message-ID: <528F6AC0.6020509@redhat.com> Date: Fri, 22 Nov 2013 14:52:00 -0000 From: Pedro Alves User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130625 Thunderbird/17.0.7 MIME-Version: 1.0 To: Tom Tromey CC: gdb-patches@sourceware.org Subject: Re: [PATCH 1/2] avoid infinite loop with bad debuginfo References: <1384375873-32160-1-git-send-email-tromey@redhat.com> <1384375873-32160-2-git-send-email-tromey@redhat.com> <52850730.1060109@redhat.com> <87d2lxpo1l.fsf@fleche.redhat.com> In-Reply-To: <87d2lxpo1l.fsf@fleche.redhat.com> Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit X-SW-Source: 2013-11/txt/msg00686.txt.bz2 On 11/18/2013 06:23 PM, Tom Tromey wrote: >>> + if (VALUE_LVAL (new_val) == lval_register >>> + && value_lazy (new_val) >>> + && frame_id_eq (VALUE_FRAME_ID (new_val), last_frame_id)) > > Pedro> I think this should also check the regnum: > > Barf. I have a memory of actually writing that. False memory I guess. > Sigh. Don't sigh. :-) I now believe the regnum check would be wrong. This shouldn't return any register of the same frame. WDYT of adjusting the patch like this? ------ From: Tom Tromey Subject: [PATCH] Detect lval_register handling infinite loop in value_fetch_lazy. 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 Pedro Alves PR backtrace/16155 * value.c (value_fetch_lazy): Internal error if get_frame_register_value returns the same register. --- gdb/value.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/gdb/value.c b/gdb/value.c index 8c263ea..da7778f 100644 --- a/gdb/value.c +++ b/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 -- 1.7.11.7