aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite/c-c++-common/ubsan/bounds-5.c
blob: c82287a561cfb3d9e0cd66b3ff78cf6e310b02ed (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/* { dg-do run } */
/* { dg-options "-fsanitize=bounds -Wall -Wextra -Wno-unused -Wno-array-bounds" } */

/* Test flexible array member-like arrays.  Normal flexible array members
   are tested in bounds-1.c.  Test non-strict mode.  */

__attribute__ ((noinline, noclone))
void
fn1 (void)
{
  volatile struct S { char a[1]; char b; } s;
  volatile int i;
  asm ("" : : "r" (&s.a) : "memory");
  i = s.a[0]; // OK
  asm ("" : : "r" (&s.a) : "memory");
  i = s.a[1]; // error
  volatile struct S *p = &s;
  asm ("" : : "r" (&p->a) : "memory");
  i = p->a[0]; // OK
  asm ("" : : "r" (&p->a) : "memory");
  i = p->a[1]; // error
}

__attribute__ ((noinline, noclone))
void
fn2 (void)
{
  struct S { int c; char d[4]; };
  volatile struct T { int e; struct S f; int g; } t;
  volatile int i;
  asm ("" : : "r" (&t.f.d) : "memory");
  i = t.f.d[3]; // OK
  asm ("" : : "r" (&t.f.d) : "memory");
  i = t.f.d[4]; // error
  volatile struct T *p = &t;
  asm ("" : : "r" (&p->f.d) : "memory");
  i = p->f.d[3]; // OK
  asm ("" : : "r" (&p->f.d) : "memory");
  i = p->f.d[4]; // error
}

__attribute__ ((noinline, noclone))
void
fn3 (void)
{
  volatile struct S { char b; char a[1]; } s;
  volatile int i;
  asm ("" : : "r" (&s.a) : "memory");
  i = s.a[0]; // OK
  asm ("" : : "r" (&s.a) : "memory");
  i = s.a[1]; // error
  volatile struct S *p = &s;
  asm ("" : : "r" (&p->a) : "memory");
  i = p->a[0]; // OK
  asm ("" : : "r" (&p->a) : "memory");
  i = p->a[1]; // error in strict mode
}

__attribute__ ((noinline, noclone))
void
fn4 (void)
{
  volatile struct S { char b; char a[1]; } s;
  volatile struct T { struct S s; int i; } t;
  volatile int i;
  asm ("" : : "r" (&t.s.a) : "memory");
  i = t.s.a[0]; // OK
  asm ("" : : "r" (&t.s.a) : "memory");
  i = t.s.a[1]; // error
  volatile struct T *pt = &t;
  asm ("" : : "r" (&pt->s.a) : "memory");
  i = pt->s.a[0]; // OK
  asm ("" : : "r" (&pt->s.a) : "memory");
  i = pt->s.a[1]; // error
}

__attribute__ ((noinline, noclone))
void
fn5 (void)
{
  volatile struct S { char b; char a[1]; } s;
  volatile struct U { int a; struct S s; } u;
  volatile int i;
  asm ("" : : "r" (&u.s.a) : "memory");
  i = u.s.a[0]; // OK
  asm ("" : : "r" (&u.s.a) : "memory");
  i = u.s.a[1]; // error
  volatile struct U *pu = &u;
  asm ("" : : "r" (&pu->s.a) : "memory");
  i = pu->s.a[0]; // OK
  asm ("" : : "r" (&pu->s.a) : "memory");
  i = pu->s.a[1]; // error in strict mode
}

int
main (void)
{
  fn1 ();
  fn2 ();
  fn3 ();
  fn4 ();
  fn5 ();
  return 0;
}

/* { dg-output "index 1 out of bounds for type 'char \\\[1\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output "\[^\n\r]*index 1 out of bounds for type 'char \\\[1\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output "\[^\n\r]*index 4 out of bounds for type 'char \\\[4\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output "\[^\n\r]*index 4 out of bounds for type 'char \\\[4\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output "\[^\n\r]*index 1 out of bounds for type 'char \\\[1\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output "\[^\n\r]*index 1 out of bounds for type 'char \\\[1\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output "\[^\n\r]*index 1 out of bounds for type 'char \\\[1\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output "\[^\n\r]*index 1 out of bounds for type 'char \\\[1\\\]'" } */