[Bug middle-end/99630] New: missing -Warray-bounds accessing a trailing array of a virtual base class

msebor at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Wed Mar 17 16:57:37 GMT 2021


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99630

            Bug ID: 99630
           Summary: missing -Warray-bounds accessing a trailing array of a
                    virtual base class
           Product: gcc
           Version: 11.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: middle-end
          Assignee: unassigned at gcc dot gnu.org
          Reporter: msebor at gcc dot gnu.org
  Target Milestone: ---

GCC issues -Warray-bounds for the out of bounds access to an object with an
ordinary base class in f() but not for the same out of bounds access to an
object with a virtual base class in g().  Both access should be diagnosed.

The problem is that trailing_array() calls array_at_struct_end_p() which
returns true for trailing array members without considering the type of the
enclosing object.

$ cat u.C && gcc -O2 -S -Wall -fdump-tree-vrp1=/dev/stdout u.C
struct A1
{
  virtual ~A1 ();
  int a1a[1];
};

struct A2
{
  virtual ~A2 ();
  int a2a[1];
};

struct B1: A1 { };
struct B2: A2 { };
struct D1: B1, B2 { };

void f (D1 *p)
{
  extern D1 d1;
  p->a1a[0] = (char*)d1.a1a - (char*)&d1;
  p->a1a[1] = (char*)d1.a2a - (char*)&d1;   // -Warray-bounds (good)
}

struct V1: virtual A1 { };
struct V2: virtual A2 { };

struct D2: V1, V2 { };

void f (D2 *p)
{
  extern D2 d2;
  p->a1a[0] = (char*)d2.a1a - (char*)&d2;
  p->a1a[1] = (char*)d2.a2a - (char*)&d2;   // missing -Warray-bounds
}

;; Function f (_Z1fP2D1, funcdef_no=0, decl_uid=2468, cgraph_uid=1,
symbol_order=0)

;; 1 loops found
;;
;; Loop 0
;;  header 0, latch 1
;;  depth 0, outer -1
;;  nodes: 0 1 2
;; 2 succs { 1 }

SSA replacement table
N_i -> { O_1 ... O_j } means that N_i replaces O_1, ..., O_j

p_5 -> { p_2(D) }
Incremental SSA update started at block: 2
Number of blocks in CFG: 3
Number of blocks to update: 1 ( 33%)



Value ranges after VRP:

p_2(D): struct D1 * VARYING
p_5: struct D1 * [1B, +INF]  EQUIVALENCES: { p_2(D) } (1 elements)


u.C: In function ‘void f(D1*)’:
u.C:21:11: warning: array subscript 1 is above array bounds of ‘int [1]’
[-Warray-bounds]
   21 |   p->a1a[1] = (char*)d1.a2a - (char*)&d1;   // -Warray-bounds (good)
      |   ~~~~~~~~^
u.C:4:7: note: while referencing ‘A1::a1a’
    4 |   int a1a[1];
      |       ^~~
void f (struct D1 * p)
{
  <bb 2> [local count: 1073741824]:
  p_2(D)->D.2450.D.2409.a1a[0] = 8;
  p_2(D)->D.2450.D.2409.a1a[1] = 24;
  return;

}



;; Function f (_Z1fP2D2, funcdef_no=1, decl_uid=2566, cgraph_uid=2,
symbol_order=1)

;; 1 loops found
;;
;; Loop 0
;;  header 0, latch 1
;;  depth 0, outer -1
;;  nodes: 0 1 2
;; 2 succs { 1 }

SSA replacement table
N_i -> { O_1 ... O_j } means that N_i replaces O_1, ..., O_j

_9 -> { _4 }
p_10 -> { p_6(D) }
Incremental SSA update started at block: 2
Number of blocks in CFG: 3
Number of blocks to update: 1 ( 33%)



Value ranges after VRP:

_1: int (*) () * VARYING
_2: long int VARYING
_3: sizetype VARYING
_4: struct D2 * [1B, +INF]
p_6(D): struct D2 * VARYING
_9: struct D2 * [1B, +INF]  EQUIVALENCES: { _4 } (1 elements)
p_10: struct D2 * [1B, +INF]  EQUIVALENCES: { p_6(D) } (1 elements)


void f (struct D2 * p)
{
  int (*) () * _1;
  long int _2;
  sizetype _3;
  struct D2 * _4;

  <bb 2> [local count: 1073741824]:
  _1 = p_6(D)->D.2549._vptr.V1;
  _2 = MEM[(long int *)_1 + -24B];
  _3 = (sizetype) _2;
  _4 = p_6(D) + _3;
  MEM[(struct A1 *)_4].a1a[0] = 24;
  MEM[(struct A1 *)_4].a1a[1] = 40;   <<< _4's type is D2 and a1a[1] overlaps
its _vptr
  return;

}


More information about the Gcc-bugs mailing list