aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite/gcc.dg/Wstringop-overflow-34.c
blob: d9ca3447eb963c24ea460f89b6d7177cbf67cc89 (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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
/* PR middle-end/95353 - spurious -Wstringop-overflow writing to a trailing
   array plus offset
   { dg-do compile }
   { dg-options "-O2 -Wall" } */

typedef __SIZE_TYPE__ size_t;

struct S0 { char n, a[0]; };


void s0_nowarn_cstidx (struct S0 *p)
{
  char *q = p->a;
  q[1] = __LINE__;
  q[9] = __LINE__;
}

void s0_nowarn_cstoff_cstidx (struct S0 *p)
{
  char *q = p->a + 1;
  q[1] = __LINE__;
  q[9] = __LINE__;
}

void s0_nowarn_varoff_cstdix (struct S0 *p, int i)
{
  char *q = p->a + i;
  q[1] = __LINE__;            // { dg-bogus "\\\[-Wstringop-overflow" }
  q[9] = __LINE__;            // { dg-bogus "\\\[-Wstringop-overflow" }
}

void s0_nowarn_cstoff_varidx (struct S0 *p, int i)
{
  char *q = p->a + 1;
  q[i] = __LINE__;
}

void s0_nowarn_varoff_varidx (struct S0 *p, int i, int j)
{
  char *q = p->a + i;
  q[j] = __LINE__;            // { dg-bogus "\\\[-Wstringop-overflow" }
}


/* Accesses past the end of a trailing array with one element is
   discouraged but still reluctantly not diagnosed.  This should
   change.  */

struct S1 { char n, a[1]; };


void s1_nowarn_cstidx (struct S1 *p)
{
  char *q = p->a;
  q[1] = __LINE__;
  q[9] = __LINE__;
}

void s1_nowarn_cstoff_cstidx (struct S1 *p)
{
  char *q = p->a + 1;
  q[1] = __LINE__;
  q[9] = __LINE__;
}

void s1_nowarn_varoff_cstdix (struct S1 *p, int i)
{
  char *q = p->a + i;
  q[1] = __LINE__;            // { dg-bogus "\\\[-Wstringop-overflow" }
  q[9] = __LINE__;            // { dg-bogus "\\\[-Wstringop-overflow" }
}

void s1_nowarn_cstoff_varidx (struct S1 *p, int i)
{
  char *q = p->a + 1;
  q[i] = __LINE__;
}

void s1_nowarn_varoff_varidx (struct S1 *p, int i, int j)
{
  char *q = p->a + i;
  q[j] = __LINE__;
}


/* Accesses past the end of a trailing array with more than one
   element should be diagnosed but aren't yet because the MEM_REF
   makes the out-of-bounds accesses indistinguishable from valid
   ones to subsequent elements of the array pointed by P.  */

struct S2 { char n, a[2]; };


void s2_warn_cstidx (struct S2 *p)
{
  char *q = p->a;

  /* The following invalid store is represented as
       MEM[(char *)p_1(D) + 3B] = __LINE__;
     which is indistinguishable from the valid
       q = &p[1].n; q[0] = __LINE__;
  */
  q[2] = __LINE__;            // { dg-warning "\\\[-Wstringop-overflow" "pr?????" { xfail *-*-* } }
}

void s2_warn_cstoff_cstidx (struct S2 *p)
{
  char *q = p->a + 1;
  q[1] = __LINE__;            // { dg-warning "\\\[-Wstringop-overflow" "pr?????" { xfail *-*-* }  }
}

void s2_warn_varoff_cstdix (struct S2 *p, int i)
{
  char *q = p->a + i;
  q[2] = __LINE__;            // { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" }
}

void s2_warn_cstoff_varidx (struct S2 *p, int i)
{
  char *q = p->a + 1;
  q[i] = __LINE__;            // { dg-warning "\\\[-Wstringop-overflow" "pr?????" { xfail *-*-* }  }
}

void s2_warn_varoff_varidx (struct S2 *p, int i, int j)
{
  char *q = p->a + i;
  q[j] = __LINE__;            // { dg-warning "\\\[-Wstringop-overflow" "pr?????" { xfail *-*-* }  }
}


/* Verify that none of these triggers a bogus warning (not tested
   elsewhere but triggered during bootstrap).  */

void s2_nowarn_varidx_int (struct S2 *p, int i)
{
  extern struct S2 s2;
  extern struct S2 s2a[];

  s2.a[i - 1] = __LINE__;
  s2.a[i] = __LINE__;
  s2.a[i + 1] = __LINE__;

  s2a[i].a[i - 1] = __LINE__;
  s2a[i].a[i] = __LINE__;
  s2a[i].a[i + 1] = __LINE__;

  p[i].a[i - 1] = __LINE__;
  p[i].a[i] = __LINE__;
  p[i].a[i + 1] = __LINE__;

  char *q = p->a;
  q[i - 1] = __LINE__;
  q[i] = __LINE__;
  q[i + 1] = __LINE__;
}

/* Same as above but with a size_t index in range [1, SIZE_MAX].  */

void* s2_nowarn_varidx_size (struct S2 *p, size_t i, size_t j)
{
  extern struct S2 s2;
  extern struct S2 s2a[];
  struct S2 *ps2 = __builtin_malloc (3 * sizeof *ps2);

  s2.a[i - 1] = __LINE__;
  s2.a[i] = __LINE__;
  s2.a[i + 1] = __LINE__;

  s2a[i].a[i - 1] = __LINE__;
  s2a[i].a[i] = __LINE__;
  s2a[i].a[i + 1] = __LINE__;

  p[i].a[i - 1] = __LINE__;
  p[i].a[i] = __LINE__;
  p[i].a[i + 1] = __LINE__;

  ps2->a[i - 1] = __LINE__;
  ps2->a[i] = __LINE__;
  ps2->a[i + 1] = __LINE__;

  char *q = p->a;
  q[i - 1] = __LINE__;
  q[i] = __LINE__;
  q[i + 1] = __LINE__;

  if (j == 0)
    return ps2;

  s2.a[j - 1] = __LINE__;
  s2.a[j] = __LINE__;
  s2.a[j + 1] = __LINE__;

  s2a[j].a[j - 1] = __LINE__;
  s2a[j].a[j] = __LINE__;
  s2a[j].a[j + 1] = __LINE__;

  p[j].a[j - 1] = __LINE__;
  p[j].a[j] = __LINE__;
  p[j].a[j + 1] = __LINE__;

  ps2->a[j - 1] = __LINE__;
  ps2->a[j] = __LINE__;
  ps2->a[j + 1] = __LINE__;

  q = p->a;
  q[j - 1] = __LINE__;
  q[j] = __LINE__;
  q[j + 1] = __LINE__;

  return ps2;
}

/* Verify that accesses to an interior zero-length array are diagnosed.  */

struct Si0 { char c, a[0], d; };

void si0_warn_cstidx (struct Si0 *p)
{
  // These are indistinguishable from valid accesses to p->d:
  //   MEM[(char *)p_1(D) + 1B] = 0;
  char *q = p->a;
  q[1] = __LINE__;            // { dg-warning "writing 1 byte into a region of size 0"  "pr?????" { xfail *-*-* } }
  q[9] = __LINE__;            // { dg-warning "\\\[-Wstringop-overflow" "pr?????" { xfail *-*-* } }
}

void si0_warn_cstoff_cstidx (struct Si0 *p)
{
  // Like those above, these too are indistinguishable from valid accesses
  // to p->d.
  char *q = p->a + 1;
  q[1] = __LINE__;            // { dg-warning "\\\[-Wstringop-overflow" "pr?????" { xfail *-*-* } }
  q[9] = __LINE__;            // { dg-warning "\\\[-Wstringop-overflow" "pr?????" { xfail *-*-* } }
}

void si0_warn_varoff_cstdix (struct Si0 *p, int i)
{
  char *q = p->a + i;
  q[1] = __LINE__;            // { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" }
  q[9] = __LINE__;            // { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" }
}

void si0_warn_cstoff_varidx (struct Si0 *p, int i)
{
  char *q = p->a + 1;
  q[i] = __LINE__;            // { dg-warning "\\\[-Wstringop-overflow" "pr?????" { xfail *-*-* } }
}

void si0_warn_varoff_varidx (struct Si0 *p, int i, int j)
{
  char *q = p->a + i;
  q[j] = __LINE__;            // { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" }
}