From: Andrew Burgess <andrew.burgess@embecosm.com>
To: Tom de Vries <tdevries@suse.de>
Cc: gdb-patches@sourceware.org
Subject: Re: [PATCH 3/3][gdb/testsuite] Warn about leaked global array
Date: Tue, 2 Jun 2020 16:38:30 +0100 [thread overview]
Message-ID: <20200602153830.GZ3522@embecosm.com> (raw)
In-Reply-To: <20200519163004.GA9045@delia>
* Tom de Vries <tdevries@suse.de> [2020-05-19 18:30:06 +0200]:
> Hi,
>
> A variable name cannot be used both as scalar and array without an
> intermediate unset. Trying to do so will result in tcl errors, for
> example, for:
> ...
> set var "bla"
> set var(1) "bla"
> ...
> we get:
> ...
> can't set "var(1)": variable isn't array
> ...
> and for the reverse statement order we get:
> ...
> can't set "var": variable is array
> ...
>
> So, since a global name in one test-case can leak to another
> test-case, setting a global name in one test-case can result in
> a tcl error in another test-case that reuses the name in a different
> way.
>
> Warn about leaking a global array from a test-case.
>
> Also, add a possibility to skip the warning in a given test-case using
> variable gdb_skip_check_global_vars, and use it in gdb.mi/mi2-var-child.exp
> and gdb.mi/mi-var-cp.exp.
>
> Tested on x86_64-linux.
>
> Any comments?
If we're going to add code to loop over all globals anyway, then why
not, instead of warning about bad cases, and then wrapping tests in a
namespace, just have this code "fix" the leaked globals by deleting
them?
My thinking is that any global that exists when we start a test should
continue to exist at the end of the test. Any other global should
just be unset when the test script finishes.
If there really is some global state that is lazily created by a
particular test script then (a) this seems like a bug anyway, and (b)
this is easy to fix by giving it an earlier creation / initialisation.
In this way, folk can just write test scripts, dump their junk all
over the global namespace as they like, and we'll just clean up for
them.
Thoughts?
Thanks,
Andrew
>
> Thanks,
> - Tom
>
> [gdb/testsuite] Warn about leaked global array
>
> gdb/testsuite/ChangeLog:
>
> 2020-05-18 Tom de Vries <tdevries@suse.de>
>
> PR testsuite/25996
> * lib/gdb.exp (global_array_exists, global_unset, save_global_vars)
> (check_global_vars): New proc.
> (gdb_init): Call save_global_vars.
> (gdb_finish): Call check_global_vars.
> * gdb.mi/mi-var-cp.exp: Set gdb_skip_check_global_vars.
> * gdb.mi/mi2-var-child.exp: Same.
>
> ---
> gdb/testsuite/gdb.mi/mi-var-cp.exp | 3 ++
> gdb/testsuite/gdb.mi/mi2-var-child.exp | 3 ++
> gdb/testsuite/lib/gdb.exp | 94 ++++++++++++++++++++++++++++++++++
> 3 files changed, 100 insertions(+)
>
> diff --git a/gdb/testsuite/gdb.mi/mi-var-cp.exp b/gdb/testsuite/gdb.mi/mi-var-cp.exp
> index 8c6a624f80..dc32ddc346 100644
> --- a/gdb/testsuite/gdb.mi/mi-var-cp.exp
> +++ b/gdb/testsuite/gdb.mi/mi-var-cp.exp
> @@ -23,6 +23,9 @@ if [mi_gdb_start] {
> continue
> }
>
> +# FIXME. See check_global_vars in lib/gdb.exp.
> +set gdb_skip_check_global_vars 1
> +
> standard_testfile .cc
>
> if [get_compiler_info "c++"] {
> diff --git a/gdb/testsuite/gdb.mi/mi2-var-child.exp b/gdb/testsuite/gdb.mi/mi2-var-child.exp
> index e32858fbd3..b96ac41815 100644
> --- a/gdb/testsuite/gdb.mi/mi2-var-child.exp
> +++ b/gdb/testsuite/gdb.mi/mi2-var-child.exp
> @@ -27,6 +27,9 @@ if [mi_gdb_start] {
> continue
> }
>
> +# FIXME. See check_global_vars in lib/gdb.exp.
> +set gdb_skip_check_global_vars 1
> +
> standard_testfile var-cmd.c
>
> if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
> diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
> index f7d20bd94f..a0d558c943 100644
> --- a/gdb/testsuite/lib/gdb.exp
> +++ b/gdb/testsuite/lib/gdb.exp
> @@ -5048,6 +5048,98 @@ proc standard_testfile {args} {
> }
> }
>
> +# Returns 1 if GLOBALVARNAME is a global array.
> +
> +proc global_array_exists { globalvarname } {
> + # Introduce local alias of global variable $globalvarname. Using
> + # "global $globalvarname" instead is simpler, but this may result in a
> + # clash with local name "globalvarname".
> + upvar #0 $globalvarname globalvar
> + return [array exists globalvar]
> +}
> +
> +# Unset global variable GLOBALVARNAME.
> +
> +proc global_unset { globalvarname } {
> + # Introduce local alias of global variable $globalvarname.
> + upvar #0 $globalvarname globalvar
> + unset globalvar
> +}
> +
> +# Save global vars to variable gdb_global_vars.
> +
> +proc save_global_vars { test_file_name } {
> + # Save for the warning.
> + global gdb_test_file_name
> + set gdb_test_file_name $test_file_name
> +
> + # Sample state before running test.
> + global gdb_global_vars
> + set gdb_global_vars [info globals]
> +
> + global gdb_skip_check_global_vars
> + if { [info exists gdb_skip_check_global_vars]} {
> + unset gdb_skip_check_global_vars
> + }
> +}
> +
> +# Check global variables not in gdb_global_vars.
> +
> +proc check_global_vars { } {
> + global gdb_skip_check_global_vars
> + if { [info exists gdb_skip_check_global_vars]} {
> + return
> + }
> + # Sample state after running test.
> + global gdb_global_vars
> + set vars [info globals]
> +
> + set skip [list "expect_out" "spawn_out" "auto_index"]
> +
> + foreach var $vars {
> + if { ![global_array_exists $var] } {
> + continue
> + }
> +
> + set found [lsearch -exact $gdb_global_vars $var]
> + if { $found != -1 } {
> + # Already present before running test.
> + continue
> + }
> +
> + set found [lsearch -exact $skip $var]
> + if { $found != -1 } {
> + continue
> + }
> +
> + # A variable name cannot be used both as scalar and array without an
> + # intermediate unset. Trying to do so will result in tcl errors, for
> + # example, for:
> + # set var "bla"
> + # set var(1) "bla"
> + # we get:
> + # can't set "var(1)": variable isn't array
> + # and for the reverse statement order we get:
> + # can't set "var": variable is array
> + #
> + # So, since a global name in one test-case can leak to another
> + # test-case, setting a global name in one test-case can result in
> + # a tcl error in another test-case that reuses the name in a different
> + # way.
> + #
> + # Warn about leaking a global array from the test-case.
> + #
> + # For a description on how to fix this, see "Wrapping test-cases in
> + # Tcl namespaces" in gdb/testsuite/README.
> + global gdb_test_file_name
> + warning "$gdb_test_file_name.exp defined global array $var"
> +
> + # If the variable remains set, we won't warn for the next test where
> + # it's leaked, so unset.
> + global_unset $var
> + }
> +}
> +
> # The default timeout used when testing GDB commands. We want to use
> # the same timeout as the default dejagnu timeout, unless the user has
> # already provided a specific value (probably through a site.exp file).
> @@ -5177,10 +5269,12 @@ proc gdb_init { test_file_name } {
> global gdb_instances
> set gdb_instances 0
>
> + save_global_vars $test_file_name
> return [default_gdb_init $test_file_name]
> }
>
> proc gdb_finish { } {
> + check_global_vars
> global gdbserver_reconnect_p
> global gdb_prompt
> global cleanfiles
next prev parent reply other threads:[~2020-06-02 15:38 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-05-19 16:30 Tom de Vries
2020-05-22 20:15 ` Tom Tromey
2020-06-02 13:08 ` Tom de Vries
2020-06-02 15:38 ` Andrew Burgess [this message]
2020-06-02 15:52 ` Andrew Burgess
2020-06-02 16:31 ` Tom de Vries
2020-06-02 17:01 ` Andrew Burgess
2020-06-02 20:18 ` Andrew Burgess
2020-06-03 8:47 ` Tom de Vries
2020-06-03 9:38 ` Tom de Vries
2020-06-03 10:09 ` Tom de Vries
2020-06-03 10:24 ` Tom de Vries
2020-06-03 12:54 ` Andrew Burgess
2020-06-03 15:35 ` Tom de Vries
2020-06-04 11:16 ` Pedro Alves
2020-06-04 12:29 ` Tom de Vries
2020-06-12 13:11 ` [committed] gdb/testsuite: Prevent globals leaking between test scripts Tom de Vries
2020-06-03 9:49 ` [PATCH 3/3][gdb/testsuite] Warn about leaked global array Pedro Alves
2020-06-04 11:40 ` Tom de Vries
2020-06-05 10:06 ` [PATCH][gdb/testsuite] Don't leak tuiterm.exp spawn override Tom de Vries
2020-06-11 13:55 ` Tom Tromey
2020-06-12 11:36 ` [committed][gdb/testsuite] " Tom de Vries
2020-06-15 19:46 ` Tom Tromey
2020-06-17 14:55 ` Tom de Vries
2020-06-17 15:28 ` Andreas Schwab
2020-06-11 12:11 ` [committed][gdb/testsuite] Make gdb.base/dbx.exp more robust Tom de Vries
2020-06-11 12:16 ` Pedro Alves
2020-06-11 14:39 ` Simon Marchi
2020-06-11 14:52 ` Tom de Vries
2020-06-11 14:59 ` Simon Marchi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200602153830.GZ3522@embecosm.com \
--to=andrew.burgess@embecosm.com \
--cc=gdb-patches@sourceware.org \
--cc=tdevries@suse.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox