Bug 21356 - value.c:828: internal-error: int value_contents_bits_eq(const value*, int, const value*, int, int): Assertion `offset1 + length <= TYPE_LENGTH (val1->enclosing_type) * TARGET_CHAR_BIT' failed
Summary: value.c:828: internal-error: int value_contents_bits_eq(const value*, int, co...
Status: RESOLVED FIXED
Alias: None
Product: gdb
Classification: Unclassified
Component: gdb (show other bugs)
Version: 7.12.1
: P2 normal
Target Milestone: 10.1
Assignee: Keith Seitz
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2017-04-05 19:21 UTC by Steve Merritt
Modified: 2020-06-11 12:36 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed: 2017-12-13 00:00:00


Attachments
assertion reproducer (322 bytes, text/plain)
2017-04-05 19:22 UTC, Steve Merritt
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Steve Merritt 2017-04-05 19:21:32 UTC
gdb will assert when printing "container_object2" in the attached sample.

value.c:828: internal-error: int value_contents_bits_eq(const value*, int, const value*, int, int): Assertion `offset1 + length <= TYPE_LENGTH (val1->enclosing_type) * TARGET_CHAR_BIT' failed.


The use of a typedef in the declaration of one of the fields of the struct container_struct2 is triggering the issue.

In the attached sample, there are two nearly identical structs, container_struct1 and container_struct2.  The only difference between the two is the use of a typedef in container_struct2 when declaring one of the fields.  The field (_vla_struct_object2) is a variable length struct.

To reproduce:
   > gcc -g vls_assert.c
   > gdb a.out
   (gdb) b 49
   Breakpoint 1 at 0x40095a: file vls_assert.c, line 49.
   (gdb) r
   Breakpoint 1, vls_factory (n=5) at vls_assert.c:50
   50	  return;
   (gdb) p container_object1
   $1 = {_container_member1 = 5, _vla_struct_object1 = {_some_member = 10, 
       _vla_field = {0, 2, 4, 6, 8}}}
   (gdb) p container_object2
   $2 = {_container_member2 = 15, _vla_struct_object2 = {_some_member = 0, 
       _vla_field = {
   value.c:828: internal-error: int value_contents_bits_eq(const value*, 
   int, const value*, int, int): Assertion `offset1 + length <= TYPE_LENGTH
   (val1->enclosing_type) * TARGET_CHAR_BIT' failed.

I reproduced the issue with gcc 4.8.3 and gcc 6.3.0 on EL7.0.
Comment 1 Steve Merritt 2017-04-05 19:22:26 UTC
Created attachment 9974 [details]
assertion reproducer
Comment 2 Jan Kratochvil 2017-12-13 15:40:28 UTC
From: Keith Seitz <keiths@redhat.com>
[PATCH] Compute proper length for dynamic types of TYPE_CODE_TYPEDEF
https://sourceware.org/ml/gdb-patches/2017-06/msg00679.html
Message-Id: <1498265971-27536-1-git-send-email-keiths@redhat.com>
Comment 3 Tom de Vries 2020-06-10 11:42:56 UTC
submitted updated patch: https://sourceware.org/pipermail/gdb-patches/2020-June/169359.html
Comment 4 Sourceware Commits 2020-06-11 12:34:48 UTC
The master branch has been updated by Tom de Vries <vries@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=2f33032a93f24ccc0c0d2f23e2a3ec0442f638d4

commit 2f33032a93f24ccc0c0d2f23e2a3ec0442f638d4
Author: Keith Seitz <keiths@redhat.com>
Date:   Thu Jun 11 14:34:44 2020 +0200

    Compute proper length for dynamic types of TYPE_CODE_TYPEDEF
    
    This patch fixes gdb/21356 in which we hit an assertion in
    value_contents_bits_eq:
    
    (gdb) p container_object2
    (gdb) p container_object2
    $1 = {_container_member2 = 15, _vla_struct_object2 = {_some_member = 0,
        _vla_field = {
    ../../src/gdb/value.c:829: internal-error: \
      int value_contents_bits_eq(const value*, int, const value*, int, int): \
      Assertion `offset1 + length \
                 <= TYPE_LENGTH (val1->enclosing_type) * TARGET_CHAR_BIT' failed.
    
    This is happening because TYPE_LENGTH (val1->enclosing_type) is erroneously
    based on enclosing_type, which is a typedef, instead of the actual underlying
    type.
    
    This can be traced back to resolve_dynamic_struct, where the size of the
    type is computed:
    ...
            TYPE_FIELD_TYPE (resolved_type, i)
              = resolve_dynamic_type_internal (TYPE_FIELD_TYPE (resolved_type, i),
                                               &pinfo, 0);
            gdb_assert (TYPE_FIELD_LOC_KIND (resolved_type, i)
                        == FIELD_LOC_KIND_BITPOS);
    
            new_bit_length = TYPE_FIELD_BITPOS (resolved_type, i);
            if (TYPE_FIELD_BITSIZE (resolved_type, i) != 0)
              new_bit_length += TYPE_FIELD_BITSIZE (resolved_type, i);
            else
              new_bit_length += (TYPE_LENGTH (TYPE_FIELD_TYPE (resolved_type, i))
                                 * TARGET_CHAR_BIT);
    ...
    
    In this function, resolved_type is TYPE_CODE_TYPEDEF which is not what we
    want to use to calculate the size of the actual field.
    
    This patch fixes this and the similar problem in resolve_dynamic_union.
    
    gdb/ChangeLog:
    2020-06-11  Keith Seitz  <keiths@redhat.com>
    
            PR gdb/21356
            * gdbtypes.c (resolve_dynamic_union, resolve_dynamic_struct):
            Resolve typedefs for type length calculations.
    
    gdb/testsuite/ChangeLog:
    2020-06-11  Keith Seitz  <keiths@redhat.com>
    
            PR gdb/21356
            * gdb.base/vla-datatypes.c (vla_factory): Add typedef for struct
            vla_struct.
            Add new struct vla_typedef and union vla_typedef_union and
            corresponding instantiation objects.
            Initialize new objects.
            * gdb.base/vla-datatypes.exp: Add tests for vla_typedef_struct_object
            and vla_typedef_union_object.
            Fixup type for vla_struct_object.
Comment 5 Tom de Vries 2020-06-11 12:36:01 UTC
Patch with fix and test-case addition committed, marking resolved-fixed.