aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite/c-c++-common/analyzer/overlapping-buffers.c
blob: f02238dfa42cda6baa72754d8e0838887fe90d58 (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
/* Test of -Wanalyzer-overlapping-buffers.  */

#include <string.h>

/* Use noinline functions to hide these calls from the optimizer, to avoid
   undefined behavior being optimized away to GIMPLE_NOP before the analyzer
   sees it.  */

char *  __attribute__((noinline))
call_strcat_symbolic_1 (char *dest, const char *src)
{
  return strcat (dest, src); /* { dg-warning "overlapping buffers" } */
}

void test_strcat_symbolic_1 (char *p)
{
  call_strcat_symbolic_1 (p, p);
}

char *  __attribute__((noinline))
call_strcpy_symbolic_1 (char *dest, const char *src)
{
  return strcpy (dest, src); /* { dg-warning "overlapping buffers" } */
}

void test_strcpy_symbolic_1 (char *p)
{
  call_strcpy_symbolic_1 (p, p);
}

void *  __attribute__((noinline))
call_memcpy_concrete_1 (void *dest, const void *src, size_t n)
{
  return memcpy (dest, src, n); /* { dg-warning "overlapping buffers" } */
}

void test_memcpy_concrete_1 (void *p)
{
  call_memcpy_concrete_1 (p, p, 10);
}

void *  __attribute__((noinline))
call_memcpy_symbolic_1 (void *dest, const void *src, size_t n)
{
  return memcpy (dest, src, n); /* { dg-warning "overlapping buffers" } */
}

void test_memcpy_symbolic_1 (void *p, size_t n)
{
  call_memcpy_symbolic_1 (p, p, n);
}

/* Intersecting vs non-intersecting parts of the same buffer.  */

void *  __attribute__((noinline))
call_memcpy_nonintersecting_concrete_1 (void *dest, const void *src, size_t n)
{
  return memcpy (dest, src, n); /* { dg-bogus "overlapping buffers passed as" } */
}

void test_memcpy_nonintersecting_concrete_1 (char *p)
{
  call_memcpy_nonintersecting_concrete_1 (p, p + 10, 10);
}

void *  __attribute__((noinline))
call_memcpy_nonintersecting_concrete_2 (void *dest, const void *src, size_t n)
{
  return memcpy (dest, src, n); /* { dg-bogus "overlapping buffers passed as" } */
}

void test_memcpy_nonintersecting_concrete_2 (char *p)
{
  call_memcpy_nonintersecting_concrete_2 (p + 10, p, 10);
}

void *  __attribute__((noinline))
call_memcpy_intersecting_concrete_1 (void *dest, const void *src, size_t n)
{
  return memcpy (dest, src, n); /* { dg-warning "overlapping buffers" } */
}

void test_memcpy_intersecting_concrete_1 (char *p)
{
  call_memcpy_intersecting_concrete_1 (p, p + 9, 10);
}

void *  __attribute__((noinline))
call_memcpy_intersecting_concrete_2 (void *dest, const void *src, size_t n)
{
  return memcpy (dest, src, n); /* { dg-warning "overlapping buffers" } */
}

void test_memcpy_intersecting_concrete_2 (char *p)
{
  call_memcpy_intersecting_concrete_2 (p + 9, p, 10);
}

void *  __attribute__((noinline))
call_memcpy_intersecting_symbolic_1 (void *dest, const void *src, size_t n)
{
  return memcpy (dest, src, n); /* { dg-warning "overlapping buffers" "" { xfail *-*-* } } */
  // TODO(xfail)
}

void test_memcpy_intersecting_symbolic_1 (char *p, size_t n)
{
  call_memcpy_intersecting_symbolic_1 (p, p + 1, n);
}

void *  __attribute__((noinline))
call_memcpy_nonintersecting_symbolic_1 (void *dest, const void *src, size_t n)
{
  return memcpy (dest, src, n); /* { dg-bogus "overlapping buffers passed as" } */
}

void test_memcpy_nonintersecting_symbolic_1 (char *p, size_t n)
{
  call_memcpy_nonintersecting_symbolic_1 (p, p + n, n);
}

void *  __attribute__((noinline))
call_memcpy_nonintersecting_symbolic_2 (void *dest, const void *src, size_t n)
{
  return memcpy (dest, src, n); /* { dg-bogus "overlapping buffers passed as" } */
}

void test_memcpy_nonintersecting_symbolic_2 (char *p, size_t n)
{
  call_memcpy_nonintersecting_symbolic_2 (p + n, p, n);
}
/* It's OK for memmove's arguments to overlap.  */

void *  __attribute__((noinline))
call_memmove_symbolic_1 (void *dest, const void *src, size_t n)
{
  return memmove (dest, src, n); /* { dg-bogus "overlapping buffers passed as" } */
}

void test_memmove_symbolic_1 (void *p, size_t n)
{
  call_memmove_symbolic_1 (p, p, n);
}

static char *  __attribute__((noinline))
call_strncpy_1 (char *dest, const char *src, size_t n)
{
  return strncpy (dest, src, n); /* { dg-warning "overlapping buffers" } */
}

void
test_strncpy_1 (char *p, size_t n)
{
  call_strncpy_1 (p, p, n);
}