diff options
author | Joel Brobecker <brobecker@gnat.com> | 2010-11-23 01:07:22 +0000 |
---|---|---|
committer | Joel Brobecker <brobecker@gnat.com> | 2010-11-23 01:07:22 +0000 |
commit | 27f2a97baff4c840ed98027b7eab67d905fe93c8 (patch) | |
tree | 937b7d68c6d702776eae25e4514a0133920ef607 | |
parent | 1324a0d9b562a38f4ce23c8835e1dacbbe3b51b9 (diff) | |
download | gdb-27f2a97baff4c840ed98027b7eab67d905fe93c8.zip gdb-27f2a97baff4c840ed98027b7eab67d905fe93c8.tar.gz gdb-27f2a97baff4c840ed98027b7eab67d905fe93c8.tar.bz2 |
GDB SEGV while trying to print uninitialize variant record
We have a variant record whose value is defined as follow:
type Discriminant_Record (Num1, Num2,
Num3, Num4 : Natural) is record
Field1 : My_Record_Array (1 .. Num2);
Field2 : My_Record_Array (Num1 .. 10);
Field3 : My_Record_Array (Num1 .. Num2);
Field4 : My_Record_Array (Num3 .. Num2);
Field5 : My_Record_Array (Num4 .. Num2);
end record;
Dire : Discriminant_Record (1, 7, 3, 0);
However, we're trying to print "Dire" before it is elaborated.
This is common if one breaks on a function and then starts doing
"info locals" for instance.
What happens is that GDB reads bogus values for fields Num1 to
Num4, and deduces a bogus (ginormouos) size for component
"Field1". The length is so large that it then later causes
an overflow in the overall record length computation. Things
go downhill from there, because length(field1) > length(record).
So, when after we've fetched the value of the record based on
the computed size, we crash trying to access unallocated memory
when accessing field1...
The first fix we can do is to check the size of the field
against the maximum object size. If it exceeds that size,
then we know the record will also exceed that size...
gdb/ChangeLog:
* ada-lang.c (ada_template_to_fixed_record_type_1):
For dynamic fields, check the field size against the maximum
object size.
-rw-r--r-- | gdb/ChangeLog | 6 | ||||
-rw-r--r-- | gdb/ada-lang.c | 14 |
2 files changed, 20 insertions, 0 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 559d07c..8872ab4 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,11 @@ 2010-11-22 Joel Brobecker <brobecker@adacore.com> + * ada-lang.c (ada_template_to_fixed_record_type_1): + For dynamic fields, check the field size against the maximum + object size. + +2010-11-22 Joel Brobecker <brobecker@adacore.com> + * mips-irix-tdep.c (mips_irix_n32_stack_tramp_frame_init): New function. (mips_irix_n32_stack_tramp_frame): New static global. diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c index 15c96b7..341db4a 100644 --- a/gdb/ada-lang.c +++ b/gdb/ada-lang.c @@ -7122,9 +7122,23 @@ ada_template_to_fixed_record_type_1 (struct type *type, field_type = ada_get_base_type (field_type); field_type = ada_to_fixed_type (field_type, field_valaddr, field_address, dval, 0); + /* If the field size is already larger than the maximum + object size, then the record itself will necessarily + be larger than the maximum object size. We need to make + this check now, because the size might be so ridiculously + 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); TYPE_FIELD_TYPE (rtype, f) = field_type; TYPE_FIELD_NAME (rtype, f) = TYPE_FIELD_NAME (type, f); + /* The multiplication can potentially overflow. But because + the field length has been size-checked just above, and + assuming that the maximum size is a reasonable value, + an overflow should not happen in practice. So rather than + adding overflow recovery code to this already complex code, + we just assume that it's not going to happen. */ bit_incr = fld_bit_len = TYPE_LENGTH (TYPE_FIELD_TYPE (rtype, f)) * TARGET_CHAR_BIT; } |