From patchwork Mon Jun 25 20:59:01 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Vrany X-Patchwork-Id: 28035 Received: (qmail 79284 invoked by alias); 25 Jun 2018 20:59:23 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 79218 invoked by uid 89); 25 Jun 2018 20:59:22 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT, SPF_PASS autolearn=ham version=3.3.2 spammy=sk:stephen, H*Ad:D*cz, sk:andrew., rooted X-HELO: relay.fit.cvut.cz Received: from relay.fit.cvut.cz (HELO relay.fit.cvut.cz) (147.32.232.237) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 25 Jun 2018 20:59:18 +0000 Received: from imap.fit.cvut.cz (imap.fit.cvut.cz [IPv6:2001:718:2:2901:0:0:0:238] (may be forged)) by relay.fit.cvut.cz (8.15.2/8.15.2) with ESMTPS id w5PKxD9q011678 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=OK); Mon, 25 Jun 2018 22:59:14 +0200 (CEST) (envelope-from jan.vrany@fit.cvut.cz) Received: from localhost (0279192e.bb.sky.com [2.121.25.46] (may be forged)) (authenticated bits=0 as user vranyj1) by imap.fit.cvut.cz (8.15.2/8.15.2) with ESMTPSA id w5PKxBvw017597 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT); Mon, 25 Jun 2018 22:59:12 +0200 (CEST) (envelope-from jan.vrany@fit.cvut.cz) From: Jan Vrany To: gdb-patches@sourceware.org Cc: Jan Vrany Subject: [PATCH v2] Fix segfault when invoking -var-info-path-expression on a dynamic varobj Date: Mon, 25 Jun 2018 21:59:01 +0100 Message-Id: <20180625205901.29762-1-jan.vrany@fit.cvut.cz> Invoking -var-info-path-expression on a dynamic varobj lead either in wrong (nonsense) result or to a segmentation fault in cplus_describe_child(). This was caused by the fact that varobj_get_path_expr() called cplus_path_expr_of_child() ignoring the fact the parent of the variable is dynamic. Then, cplus_describe_child() accessed the underlaying C type members by index, causing (i) either wrong (nonsense) expression being returned (since dynamic child may be completely arbibtrary value) or (ii) segmentation fault (in case the index higher than number of underlaying C type members. This fixes the problem by checking whether a varobj is a child of a dynamic varobj and, if so, reporting an error to MI consumer as described in the documentation. gdb/ChangeLog: * mi/mi-cmd-var.c: Report an error if varobj is a child of dynamic varobj as stated in documentation. * varobj.c: New assert. gdb/testsuite/Changelog: * gdb.python/py-mi-var-info-path-expression.c: New file. * gdb.python/py-mi-var-info-path-expression.py: New file. * gdb.python/py-mi-var-info-path-expression.exp: New file. --- gdb/ChangeLog | 6 ++ gdb/mi/mi-cmd-var.c | 10 +- gdb/testsuite/ChangeLog | 6 ++ .../py-mi-var-info-path-expression.c | 62 +++++++++++++ .../py-mi-var-info-path-expression.exp | 91 +++++++++++++++++++ .../py-mi-var-info-path-expression.py | 51 +++++++++++ gdb/varobj.c | 6 +- 7 files changed, 230 insertions(+), 2 deletions(-) create mode 100644 gdb/testsuite/gdb.python/py-mi-var-info-path-expression.c create mode 100644 gdb/testsuite/gdb.python/py-mi-var-info-path-expression.exp create mode 100644 gdb/testsuite/gdb.python/py-mi-var-info-path-expression.py diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 42995dfc93..5b0dde9d01 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,9 @@ +2018-06-04 Jan Vrany + + * mi/mi-cmd-var.c: Report an error if varobj is a child of dynamic + varobj as stated in documentation. + * varobj.c: New assert. + 2018-06-13 Rainer Orth * procfs.c (_initialize_procfs): Use add_inf_child_target. diff --git a/gdb/mi/mi-cmd-var.c b/gdb/mi/mi-cmd-var.c index 38c59c7e66..fa47387357 100644 --- a/gdb/mi/mi-cmd-var.c +++ b/gdb/mi/mi-cmd-var.c @@ -438,7 +438,15 @@ mi_cmd_var_info_path_expression (const char *command, char **argv, int argc) /* Get varobj handle, if a valid var obj name was specified. */ var = varobj_get_handle (argv[0]); - + + /* -var-info-path-expression is currently not valid for children of + a dynamic varobj. */ + for (struct varobj *cur = var->parent; cur != nullptr; cur = cur->parent) + { + if (varobj_is_dynamic_p (cur)) + error (_("Invalid variable object (child of a dynamic varobj)")); + } + const char *path_expr = varobj_get_path_expr (var); uiout->field_string ("path_expr", path_expr); diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 0059828b7b..5b8cd6ff0e 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2018-06-04 Jan Vrany + + * gdb.python/py-mi-var-info-path-expression.c: New file. + * gdb.python/py-mi-var-info-path-expression.py: New file. + * gdb.python/py-mi-var-info-path-expression.exp: New file. + 2018-06-12 Andrew Burgess Stephen Roberts diff --git a/gdb/testsuite/gdb.python/py-mi-var-info-path-expression.c b/gdb/testsuite/gdb.python/py-mi-var-info-path-expression.c new file mode 100644 index 0000000000..9d6ff126dd --- /dev/null +++ b/gdb/testsuite/gdb.python/py-mi-var-info-path-expression.c @@ -0,0 +1,62 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright (C) 1999-2018 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 . */ + +enum cons_type +{ + type_atom = 0, + type_cons = 1 +}; + +struct atom +{ + int ival; +}; + +struct cons +{ + enum cons_type type; + union + { + struct atom atom; + struct cons *slots[2]; + }; +}; + +#define nil ((struct cons*)0); + +int +main () +{ + struct cons c1, c2, c3, c4; + + c1.type = type_cons; + c1.slots[0] = &c4; + c1.slots[1] = &c2; + + c2.type = type_cons; + c2.slots[0] = nil; + c2.slots[1] = &c3; + + c3.type = type_cons; + c3.slots[0] = nil; + c3.slots[1] = nil; + + c4.type = type_atom; + c4.atom.ival = 13; + + return 0; /* next line */ +} diff --git a/gdb/testsuite/gdb.python/py-mi-var-info-path-expression.exp b/gdb/testsuite/gdb.python/py-mi-var-info-path-expression.exp new file mode 100644 index 0000000000..ecebc2e761 --- /dev/null +++ b/gdb/testsuite/gdb.python/py-mi-var-info-path-expression.exp @@ -0,0 +1,91 @@ +# Copyright (C) 2008-2018 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 . + +# Tests whether -var-info-path-expression fails as documented when +# invoked on a dynamic varobj. + +load_lib mi-support.exp +set MIFLAGS "-i=mi" + +gdb_exit +if {[mi_gdb_start]} { + continue +} + +# +# Start here +# +standard_testfile + +if {[gdb_compile "$srcdir/$subdir/$srcfile" $binfile executable {debug}] != "" } { + return -1 +} + +mi_gdb_test "source ${srcdir}/${subdir}/${testfile}.py" \ + ".*\\^done" \ + "load python file" + +mi_gdb_test "-enable-pretty-printing" \ + "\\^done" \ + "-enable-pretty-printing" + +mi_gdb_test "set python print-stack full" \ + ".*\\^done" \ + "set python print-stack full" + + +mi_run_to_main + + +mi_continue_to_line [gdb_get_line_number "next line" ${srcfile}] \ + "step to breakpoint" + +mi_gdb_test "-var-create c1 * &c1" \ + "\\^done.*" \ + "-var-create c1 * &c1" + +mi_gdb_test "-var-info-path-expression c1" \ + "\\^done,path_expr=\"&c1\"" \ + "-var-info-path-expression c1" + +mi_gdb_test "-var-list-children c1" \ + "\\^done,numchild=\"2\",children=.child=\{name=\"c1.car\".*child=\{name=\"c1.cdr\".*" \ + "-var-list-children c1" + +mi_gdb_test "-var-info-path-expression c1.cdr" \ + "\\^error,msg=\".*\"" \ + "-var-info-path-expression c1.cdr" + +mi_gdb_test "-var-list-children c1.cdr" \ + "\\^done,numchild=\"2\",children=.child=\{name=\"c1.cdr.car\".*child=\{name=\"c1.cdr.cdr\".*" \ + "-var-list-children c1.cdr" + +mi_gdb_test "-var-info-path-expression c1.cdr.cdr" \ + "\\^error,msg=\".*\"" \ + "-var-info-path-expression c1.cdr.cdr" + +mi_gdb_test "-var-list-children c1.car" \ + "\\^done,numchild=\"1\",children=.child=\{name=\"c1.car.atom\".*" \ + "-var-list-children c1.car" + +mi_gdb_test "-var-list-children c1.car.atom" \ + "\\^done,numchild=\"1\",children=.child=\{name=\"c1.car.atom.ival\".*" \ + "-var-list-children c1.car.atom" + +mi_gdb_test "-var-info-path-expression c1.car.atom.ival" \ + "\\^error,msg=\".*\"" \ + "-var-info-path-expression c1.car.atom.ival" + + diff --git a/gdb/testsuite/gdb.python/py-mi-var-info-path-expression.py b/gdb/testsuite/gdb.python/py-mi-var-info-path-expression.py new file mode 100644 index 0000000000..13f9742016 --- /dev/null +++ b/gdb/testsuite/gdb.python/py-mi-var-info-path-expression.py @@ -0,0 +1,51 @@ +# Copyright (C) 2008-2018 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 . + +import gdb +import gdb.types + +class cons_pp(object): + def __init__(self, val): + self._val = val + + def to_string(self): + if int(self._val) == 0: + return "nil" + elif int(self._val['type']) == 0: + return "( . )" + else: + return "%d" % self._val['atom']['ival'] + + def children(self): + if int(self._val) == 0: + return [] + elif int(self._val['type']) == 0: + return [ + ('atom', self._val['atom']) + ] + else: + return [ + ('car' , self._val["slots"][0]), + ('cdr' , self._val["slots"][1]), + ] + +def cons_pp_lookup(val): + if str(val.type) == 'struct cons *': + return cons_pp(val) + else: + return None + +del gdb.pretty_printers[1:] +gdb.pretty_printers.append(cons_pp_lookup) \ No newline at end of file diff --git a/gdb/varobj.c b/gdb/varobj.c index a0df485ae9..6b044abdbf 100644 --- a/gdb/varobj.c +++ b/gdb/varobj.c @@ -962,9 +962,13 @@ varobj_get_path_expr (const struct varobj *var) /* For root varobjs, we initialize path_expr when creating varobj, so here it should be child varobj. */ - struct varobj *mutable_var = (struct varobj *) var; gdb_assert (!is_root_p (var)); + /* Computation of full rooted expression for children of dynamic + varobjs is not supported. */ + gdb_assert (!varobj_is_dynamic_p (cur)); + + struct varobj *mutable_var = (struct varobj *) var; mutable_var->path_expr = (*var->root->lang_ops->path_expr_of_child) (var); }