From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id 2FJKN32dgWD+XwAAWB0awg (envelope-from ) for ; Thu, 22 Apr 2021 11:59:57 -0400 Received: by simark.ca (Postfix, from userid 112) id D5FBD1F104; Thu, 22 Apr 2021 11:59:57 -0400 (EDT) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-0.7 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,MAILING_LIST_MULTI,RDNS_DYNAMIC,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from sourceware.org (ip-8-43-85-97.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id B7AE31E54D for ; Thu, 22 Apr 2021 11:59:56 -0400 (EDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 32A383894C3B; Thu, 22 Apr 2021 15:59:56 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 32A383894C3B DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1619107196; bh=DX/65ucpoRVWUEUAxyYCftGn6aV8Hp75kMRh96YCQOE=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=Gxb+PTwIK4bG6YwMvYa6UD8S98hcB9jIIz7Fy9Nutgv0XTu4U0Qu8QmD/GCONEiWN G5uNKkzOi6VPCa6bP+yQQt6bv5HkRB469RH4I4vXJu3N+c49OJfUMT0YMUiMRNKbLX D8VpH1St6nRFR2ot/Xa7s8PBj1UiUgnKiNWP6Slo= Received: from barracuda.ebox.ca (barracuda.ebox.ca [96.127.255.19]) by sourceware.org (Postfix) with ESMTPS id 0A8093894404 for ; Thu, 22 Apr 2021 15:59:53 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 0A8093894404 X-ASG-Debug-ID: 1619107191-0c856e67e2dd7310001-fS2M51 Received: from smtp.ebox.ca (smtp.ebox.ca [96.127.255.82]) by barracuda.ebox.ca with ESMTP id XTJSm2QRqqLNBQ4n (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Thu, 22 Apr 2021 11:59:52 -0400 (EDT) X-Barracuda-Envelope-From: simon.marchi@polymtl.ca X-Barracuda-RBL-Trusted-Forwarder: 96.127.255.82 Received: from simark.localdomain (192-222-157-6.qc.cable.ebox.net [192.222.157.6]) by smtp.ebox.ca (Postfix) with ESMTP id DCBFE441B21; Thu, 22 Apr 2021 11:59:51 -0400 (EDT) X-Barracuda-RBL-IP: 192.222.157.6 X-Barracuda-Effective-Source-IP: 192-222-157-6.qc.cable.ebox.net[192.222.157.6] X-Barracuda-Apparent-Source-IP: 192.222.157.6 To: gdb-patches@sourceware.org Subject: [PATCH master + gdb-10-branch] gdb: fix getting range of flexible array member in Python Date: Thu, 22 Apr 2021 11:59:50 -0400 X-ASG-Orig-Subj: [PATCH master + gdb-10-branch] gdb: fix getting range of flexible array member in Python Message-Id: <20210422155950.3520038-1-simon.marchi@polymtl.ca> X-Mailer: git-send-email 2.30.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Barracuda-Connect: smtp.ebox.ca[96.127.255.82] X-Barracuda-Start-Time: 1619107192 X-Barracuda-Encrypted: DHE-RSA-AES256-SHA X-Barracuda-URL: https://96.127.255.19:443/cgi-mod/mark.cgi X-Barracuda-BRTS-Status: 1 X-Virus-Scanned: by bsmtpd at ebox.ca X-Barracuda-Scan-Msg-Size: 8728 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using global scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=8.0 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.89432 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , From: Simon Marchi via Gdb-patches Reply-To: Simon Marchi Errors-To: gdb-patches-bounces@sourceware.org Sender: "Gdb-patches" As reported in bug 27757, we get an internal error when doing: $ cat test.c struct foo { int len; int items[]; }; struct foo *p; int main() { return 0; } $ gcc test.c -g -O0 -o test $ ./gdb -q -nx --data-directory=data-directory ./test -ex 'python gdb.parse_and_eval("p").type.target()["items"].type.range()' Reading symbols from ./test... /home/simark/src/binutils-gdb/gdb/gdbtypes.h:435: internal-error: LONGEST dynamic_prop::const_val() const: Assertion `m_kind == PROP_CONST' failed. A problem internal to GDB has been detected, further debugging may prove unreliable. Quit this debugging session? (y or n) This is because the Python code (typy_range) blindly reads the high bound of the type of `items` as a constant value. Since it is a flexible array member, it has no high bound, the property is undefined. Since commit 8c2e4e0689 ("gdb: add accessors to struct dynamic_prop"), the getters check that you are not getting a property value of the wrong kind, so this causes a failed assertion. Fix it by checking if the property is indeed a constant value before accessing it as such. Otherwise, use 0. This restores the previous GDB behavior: because the structure was zero-initialized, this is what was returned before. But now this behavior is explicit and not accidental. Add a test, gdb.python/flexible-array-member.exp, that is derived from gdb.base/flexible-array-member.exp. It tests the same things, but through the Python API. It also specifically tests getting the range from the various kinds of flexible array member types (AFAIK it wasn't possible to do the equivalent through the CLI). gdb/ChangeLog: PR gdb/27757 * python/py-type.c (typy_range): Check that bounds are constant before accessing them as such. gdb/testsuite/ChangeLog: PR gdb/27757 * gdb.python/flexible-array-member.c: New test. * gdb.python/flexible-array-member.exp: New test. Change-Id: Ibef92ee5fd871ecb7c791db2a788f203dff2b841 --- gdb/python/py-type.c | 11 ++- .../gdb.python/flexible-array-member.c | 70 ++++++++++++++++ .../gdb.python/flexible-array-member.exp | 81 +++++++++++++++++++ 3 files changed, 160 insertions(+), 2 deletions(-) create mode 100644 gdb/testsuite/gdb.python/flexible-array-member.c create mode 100644 gdb/testsuite/gdb.python/flexible-array-member.exp diff --git a/gdb/python/py-type.c b/gdb/python/py-type.c index bf707078841f..148e4a6aa3a0 100644 --- a/gdb/python/py-type.c +++ b/gdb/python/py-type.c @@ -592,8 +592,15 @@ typy_range (PyObject *self, PyObject *args) case TYPE_CODE_ARRAY: case TYPE_CODE_STRING: case TYPE_CODE_RANGE: - low = type->bounds ()->low.const_val (); - high = type->bounds ()->high.const_val ();; + if (type->bounds ()->low.kind () == PROP_CONST) + low = type->bounds ()->low.const_val (); + else + low = 0; + + if (type->bounds ()->high.kind () == PROP_CONST) + high = type->bounds ()->high.const_val (); + else + high = 0; break; } diff --git a/gdb/testsuite/gdb.python/flexible-array-member.c b/gdb/testsuite/gdb.python/flexible-array-member.c new file mode 100644 index 000000000000..79815e2d38e0 --- /dev/null +++ b/gdb/testsuite/gdb.python/flexible-array-member.c @@ -0,0 +1,70 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2020-2021 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +struct no_size +{ + int n; + int items[]; +}; + +struct zero_size +{ + int n; + int items[0]; +}; + +struct zero_size_only +{ + int items[0]; +}; + +struct no_size *ns; +struct zero_size *zs; +struct zero_size_only *zso; + +static void +break_here (void) +{ +} + +int +main (void) +{ + ns = (struct no_size *) malloc (sizeof (*ns) + 3 * sizeof (int)); + zs = (struct zero_size *) malloc (sizeof (*zs) + 3 * sizeof (int)); + zso = (struct zero_size_only *) malloc (sizeof (*zso) + 3 * sizeof (int)); + + ns->n = 3; + ns->items[0] = 101; + ns->items[1] = 102; + ns->items[2] = 103; + + zs->n = 3; + zs->items[0] = 201; + zs->items[1] = 202; + zs->items[2] = 203; + + zso->items[0] = 301; + zso->items[1] = 302; + zso->items[2] = 303; + + break_here (); + + return 0; +} diff --git a/gdb/testsuite/gdb.python/flexible-array-member.exp b/gdb/testsuite/gdb.python/flexible-array-member.exp new file mode 100644 index 000000000000..3739c9a9e5c0 --- /dev/null +++ b/gdb/testsuite/gdb.python/flexible-array-member.exp @@ -0,0 +1,81 @@ +# Copyright 2020-2021 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Test getting the range of flexible array members in Python. + +standard_testfile + +if { [prepare_for_testing "failed to prepare" \ + ${testfile} ${srcfile}] } { + return +} + +if { ![runto break_here] } { + untested "could not run to break_here" + return +} + +# The various cases are: +# +# - ns: flexible array member with no size +# - zs: flexible array member with size 0 (GNU C extension that predates the +# standardization of the feature, but widely supported) +# - zso: zero-size only, a corner case where the array is the sole member of +# the structure + +gdb_test "python ns = gdb.parse_and_eval('ns').dereference()" +gdb_test "python zs = gdb.parse_and_eval('zs').dereference()" +gdb_test "python zso = gdb.parse_and_eval('zso').dereference()" + +# Print the whole structure. + +gdb_test "python print(ns)" "{n = 3, items = $hex}" +gdb_test "python print(zs)" "{n = 3, items = $hex}" +gdb_test "python print(zso)" "{items = $hex}" + +# Print all items. + +gdb_test "python print(ns\['items'\])" "$hex" +gdb_test "python print(ns\['items'\]\[0\])" "101" +gdb_test "python print(ns\['items'\]\[1\])" "102" +gdb_test "python print(ns\['items'\]\[2\])" "103" + +gdb_test "python print(zs\['items'\])" "$hex" +gdb_test "python print(zs\['items'\]\[0\])" "201" +gdb_test "python print(zs\['items'\]\[1\])" "202" +gdb_test "python print(zs\['items'\]\[2\])" "203" + +gdb_test "python print(zso\['items'\])" "$hex" +gdb_test "python print(zso\['items'\]\[0\])" "301" +gdb_test "python print(zso\['items'\]\[1\])" "302" +gdb_test "python print(zso\['items'\]\[2\])" "303" + +# Check taking the address of array elements (how PR 28675 was originally +# reported). + +gdb_test "python print(ns\['items'\] == ns\['items'\]\[0\].address)" "True" +gdb_test "python print(ns\['items'\]\[0\].address + 1 == ns\['items'\]\[1\].address)" "True" +gdb_test "python print(zs\['items'\] == zs\['items'\]\[0\].address)" "True" +gdb_test "python print(zs\['items'\]\[0\].address + 1 == zs\['items'\]\[1\].address)" "True" +gdb_test "python print(zso\['items'\] == zso\['items'\]\[0\].address)" "True" +gdb_test "python print(zso\['items'\]\[0\].address + 1 == zso\['items'\]\[1\].address)" "True" + +# Verify the range attribute. It looks a bit inconsistent that the high bound +# is sometimes 0, sometimes -1, but that's what GDB produces today, so that's +# what we test. + +gdb_test "python print(ns\['items'\].type.range())" "\\(0, 0\\)" +gdb_test "python print(zs\['items'\].type.range())" "\\(0, -1\\)" +gdb_test "python print(zso\['items'\].type.range())" "\\(0, -1\\)" -- 2.30.1