Internal error trying to print uninitialized string.

Trying to print the value of a string whose size is not known at
compile-time before it gets assigned a value can lead to the following
internal error:

    (gdb) p my_str
    $1 =
    /[...]/utils.c:1089: internal-error: virtual memory exhausted.

What happens is that my_str is described as a reference to an array
type whose bounds are dynamic. During the read of that variable's
value (in default_read_var_value), we end up resolving dynamic types
which, for reference types, makes us also resolve the target of that
reference type. This means we resolve our variable to a reference
to an array whose bounds are undefined, and unfortunately very far
appart.

So, when we pass that value to ada-valprint, and in particular to
da_val_print_ref, we eventually try to allocate too large of a buffer
corresponding to the (bogus) size of our array, hence the internal
error.

This patch fixes the problem by adding a size_check before trying
to print the dereferenced value. To perform this check, a function
that was previously specific to ada-lang.c (check_size) gets
exported, and renamed to something less prone to name collisions
(ada_ensure_varsize_limit).

gdb/ChangeLog:

        * ada-lang.h (ada_ensure_varsize_limit): Declare.
        * ada-lang.c (check_size): Remove advance declaration.
        (ada_ensure_varsize_limit): Renames check_size.
        Replace calls to check_size by calls to ada_ensure_varsize_limit
        throughout.
        * ada-valprint.c (ada_val_print_ref): Add call to
        ada_ensure_varsize_limit.  Add comment explaining why.

gdb/testsuite/ChangeLog:

        * gdb.ada/str_uninit: New testcase.
This commit is contained in:
Joel Brobecker 2014-12-08 10:37:00 -05:00
parent 3c46a02f50
commit c1b5a1a6e7
9 changed files with 143 additions and 9 deletions

View File

@ -1,3 +1,13 @@
2014-12-13 Joel Brobecker <brobecker@adacore.com>
* ada-lang.h (ada_ensure_varsize_limit): Declare.
* ada-lang.c (check_size): Remove advance declaration.
(ada_ensure_varsize_limit): Renames check_size.
Replace calls to check_size by calls to ada_ensure_varsize_limit
throughout.
* ada-valprint.c (ada_val_print_ref): Add call to
ada_ensure_varsize_limit. Add comment explaining why.
2014-12-13 Joel Brobecker <brobecker@adacore.com>
* utils.c (make_hex_string): Replace use of sprintf by use of

View File

@ -232,8 +232,6 @@ static int ada_is_direct_array_type (struct type *);
static void ada_language_arch_info (struct gdbarch *,
struct language_arch_info *);
static void check_size (const struct type *);
static struct value *ada_index_struct_field (int, struct value *, int,
struct type *);
@ -678,7 +676,7 @@ coerce_unspec_val_to_type (struct value *val, struct type *type)
/* Make sure that the object size is not unreasonable before
trying to allocate some memory for it. */
check_size (type);
ada_ensure_varsize_limit (type);
if (value_lazy (val)
|| TYPE_LENGTH (type) > TYPE_LENGTH (value_type (val)))
@ -740,8 +738,8 @@ lim_warning (const char *format, ...)
i.e. if it would be a bad idea to allocate a value of this type in
GDB. */
static void
check_size (const struct type *type)
void
ada_ensure_varsize_limit (const struct type *type)
{
if (TYPE_LENGTH (type) > varsize_limit)
error (_("object size is larger than varsize-limit"));
@ -2052,7 +2050,7 @@ ada_coerce_to_simple_array (struct value *arr)
if (arrVal == NULL)
error (_("Bounds unavailable for null array pointer."));
check_size (TYPE_TARGET_TYPE (value_type (arrVal)));
ada_ensure_varsize_limit (TYPE_TARGET_TYPE (value_type (arrVal)));
return value_ind (arrVal);
}
else if (ada_is_constrained_packed_array_type (value_type (arr)))
@ -7917,7 +7915,7 @@ ada_template_to_fixed_record_type_1 (struct type *type,
initialized, the type size may be completely bogus and
GDB may fail to allocate a value for it. So check the
size first before creating the value. */
check_size (rtype);
ada_ensure_varsize_limit (rtype);
/* Using plain value_from_contents_and_address here
causes problems because we will end up trying to
resolve a type that is currently being
@ -7965,7 +7963,7 @@ ada_template_to_fixed_record_type_1 (struct type *type,
large (due to an uninitialized variable in the inferior)
that it would cause an overflow when adding it to the
record size. */
check_size (field_type);
ada_ensure_varsize_limit (field_type);
TYPE_FIELD_TYPE (rtype, f) = field_type;
TYPE_FIELD_NAME (rtype, f) = TYPE_FIELD_NAME (type, f);
@ -10907,7 +10905,7 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp,
(ada_aligned_type
(ada_check_typedef (TYPE_TARGET_TYPE (type))));
}
check_size (type);
ada_ensure_varsize_limit (type);
return value_zero (type, lval_memory);
}
else if (TYPE_CODE (type) == TYPE_CODE_INT)

View File

@ -162,6 +162,8 @@ struct ada_task_info
extern void *grow_vect (void *, size_t *, size_t, int);
extern void ada_ensure_varsize_limit (const struct type *type);
extern int ada_get_field_index (const struct type *type,
const char *field_name,
int maybe_missing);

View File

@ -1055,6 +1055,12 @@ ada_val_print_ref (struct type *type, const gdb_byte *valaddr,
if (ada_is_tagged_type (value_type (deref_val), 1))
deref_val = ada_tag_value_at_base_address (deref_val);
/* Make sure that the object does not have an unreasonable size
before trying to print it. This can happen for instance with
references to dynamic objects whose contents is uninitialized
(Eg: an array whose bounds are not set yet). */
ada_ensure_varsize_limit (value_type (deref_val));
val_print (value_type (deref_val),
value_contents_for_printing (deref_val),
value_embedded_offset (deref_val),

View File

@ -1,3 +1,7 @@
2014-12-13 Joel Brobecker <brobecker@adacore.com>
* gdb.ada/str_uninit: New testcase.
2014-12-13 Jan Kratochvil <jan.kratochvil@redhat.com>
PR symtab/17642

View File

@ -0,0 +1,40 @@
# Copyright 2014 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 <http://www.gnu.org/licenses/>.
load_lib "ada.exp"
standard_ada_testfile parse
if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug ]] != "" } {
return -1
}
clean_restart ${testfile}
set bp_location [gdb_get_line_number "START" ${testdir}/parse.adb]
if ![runto "parse.adb:$bp_location" ] then {
perror "Couldn't run ${testfile}"
return
}
# Print MY_STR. Since the string has not been initialized, including
# its bounds, anything can happen, including an error. The purpose
# of this test is just to verify that we do not get an _internal_
# error.
gdb_test "print my_str" " = .*"
# Just to be certain that the debugger is really still alive,
# try printing something really simple.
gdb_test "print 1235813" " = 1235813"

View File

@ -0,0 +1,22 @@
-- Copyright 2014 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 <http://www.gnu.org/licenses/>.
with Pck; use Pck;
procedure Parse is
My_Str : String := Foos; -- START
begin
Do_Nothing (My_Str'Address);
end Parse;

View File

@ -0,0 +1,28 @@
-- Copyright 2011-2014 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 <http://www.gnu.org/licenses/>.
package body Pck is
procedure Do_Nothing (A : System.Address) is
begin
null;
end Do_Nothing;
function Foos return String is
begin
return "string";
end Foos;
end Pck;

View File

@ -0,0 +1,24 @@
-- Copyright 2011-2014 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 <http://www.gnu.org/licenses/>.
with System;
package Pck is
procedure Do_Nothing (A : System.Address);
function Foos return String;
end Pck;