1 /* Test exercising -Wstringop-overread warnings for reading past the end. */
2 /* { dg-do compile } */
3 /* { dg-options "-O2 -Wstringop-overread -ftrack-macro-expansion=0" } */
5 #define PTRDIFF_MAX __PTRDIFF_MAX__
6 #define SIZE_MAX __SIZE_MAX__
8 #define offsetof(type, mem) __builtin_offsetof (type, mem)
10 /* Return the number of bytes from member MEM of TYPE to the end
12 #define offsetfrom(type, obj, mem) (sizeof (obj) - offsetof (type, mem))
15 typedef __SIZE_TYPE__
size_t;
16 extern void* memchr (const void*, int, size_t);
17 extern int memcmp (const void*, const void*, size_t);
18 extern void* memcpy (void*, const void*, size_t);
19 extern void* memmove (void*, const void*, size_t);
20 extern void* mempcpy (void*, const void*, size_t);
22 #define memchr(d, s, n) sink (memchr (d, s, n))
23 #define memcmp(d, s, n) sink (d, memcmp (d, s, n))
24 #define memcpy(d, s, n) sink (memcpy (d, s, n))
25 #define memmove(d, s, n) sink (memmove (d, s, n))
26 #define mempcpy(d, s, n) sink (mempcpy (d, s, n))
28 struct A
{ char a
, b
; };
29 struct B
{ struct A a
; char c
, d
; };
31 /* Function to call to "escape" pointers from tests below to prevent
32 GCC from assuming the values of the objects they point to stay
34 void sink (void*, ...);
36 /* Function to "generate" a random number each time it's called. Declared
37 (but not defined) and used to prevent GCC from making assumptions about
38 their values based on the variables uses in the tested expressions. */
39 size_t random_unsigned_value (void);
41 /* Return a random unsigned value between MIN and MAX. */
44 range (size_t min
, size_t max
)
46 const size_t val
= random_unsigned_value ();
47 return val
< min
|| max
< val
? min
: val
;
50 #define R(min, max) range (min, max)
52 /* Verify that reading beyond the end of a local array is diagnosed. */
54 void test_memop_warn_local (void *p
, const void *q
)
56 memcpy (p
, "1234", R (6, 7)); /* { dg-warning "reading between 6 and 7 bytes from a region of size 5" } */
60 memcpy (p
, a
, R (7, 8)); /* { dg-warning "reading between 7 and 8 bytes from a region of size 4" } */
62 /* At -Wstringop-overflow=1 the destination is considered to be
63 the whole array and its size is therefore sizeof a. */
64 memcpy (p
, &a
[0], R (8, 9)); /* { dg-warning "reading between 8 and 9 bytes from a region of size 4" } */
66 /* Verify the same as above but by reading from the first mmeber
67 of the first element of the array. */
68 memcpy (p
, &a
[0].a
, R (8, 9)); /* { dg-warning "reading between 8 and 9 bytes from a region of size 4" } */
72 memcpy (p
, &b
[0], R (12, 32)); /* { dg-warning "reading between 12 and 32 bytes from a region of size 8" } */
74 /* Verify memchr/memcmp. */
76 memchr ("", i
, 2); /* { dg-warning "specified bound 2 exceeds source size 1" "memchr" } */
77 memchr ("", i
, 2); /* { dg-warning "specified bound 2 exceeds source size 1" "memchr" } */
78 memchr ("123", i
, 5); /* { dg-warning "specified bound 5 exceeds source size 4" "memchr" } */
79 memchr (a
, i
, sizeof a
+ 1); /* { dg-warning "specified bound 5 exceeds source size 4" "memchr" } */
81 memcmp (p
, "", 2); /* { dg-warning "specified bound 2 exceeds source size 1" "memcmp" } */
82 memcmp (p
, "123", 5); /* { dg-warning "specified bound 5 exceeds source size 4" "memcmp" } */
83 memcmp (p
, a
, sizeof a
+ 1); /* { dg-warning "specified bound 5 exceeds source size 4" "memcmp" } */
85 size_t n
= PTRDIFF_MAX
+ (size_t)1;
86 memchr (p
, 1, n
); /* { dg-warning "exceeds maximum object size" "memchr" } */
87 memcmp (p
, q
, n
); /* { dg-warning "exceeds maximum object size" "memcmp" } */
90 memchr (p
, 1, n
); /* { dg-warning "exceeds maximum object size" "memchr" } */
91 memcmp (p
, q
, n
); /* { dg-warning "exceeds maximum object size" "memcmp" } */
94 /* Verify that reading beyond the end of a dynamically allocated array
95 of known size is diagnosed. */
97 void test_memop_warn_alloc (void *p
)
103 struct A
*a
= __builtin_malloc (sizeof *a
* 2);
105 memcpy (p
, a
, n
); /* { dg-warning "reading between 8 and 32 bytes from a region of size 4" "memcpy from allocated" } */
107 memcpy (p
, &a
[0], n
); /* { dg-warning "reading between 8 and 32 bytes from a region of size 4" "memcpy from allocated" } */
109 memcpy (p
, &a
[0].a
, n
); /* { dg-warning "reading between 8 and 32 bytes from a region of size " "memcpy from allocated" } */
113 struct B
*b
= __builtin_malloc (sizeof *b
* 2);
115 memcpy (p
, &b
[0], n
); /* { dg-warning "reading between 12 and 32 bytes from a region of size 8" "memcpy from allocated" } */
117 /* Verify memchr/memcmp. */
118 n
= sizeof *b
* 2 + 1;
120 memchr (b
, 1, n
); /* { dg-warning "specified bound 9 exceeds source size 8" "memchr from allocated" } */
121 memcmp (p
, b
, n
); /* { dg-warning "specified bound 9 exceeds source size 8" "memcmp from allocated" } */
125 void test_memop_nowarn (void *p
)
129 size_t n
= range (sizeof b
, 32);
131 /* Verify that copying the whole array is not diagnosed regardless
132 of whether the expression pointing to its beginning is obtained
133 from the array itself or its first member(s). */
136 memcpy (p
, &b
[0], n
);
138 memcpy (p
, &b
[0].a
, n
);
140 memcpy (p
, &b
[0].a
.a
, n
);
142 /* Verify that memchr/memcmp doesn't cause a warning. */
145 memchr (&b
[0], 3, n
);
146 memchr (&b
[0].a
, 4, n
);
147 memchr (&b
[0].a
.a
, 5, n
);
148 memchr ("01234567", R (0, 255), n
);
152 memcmp (p
, &b
[0], n
);
153 memcmp (p
, &b
[0].a
, n
);
154 memcmp (p
, &b
[0].a
.a
, n
);
155 memcmp (p
, "01234567", n
);
159 /* The following function could specify in its API that it takes
160 an array of exactly two elements, as shown below (or simply be
161 called with such an array). Verify that reading from both
162 elements is not diagnosed. */
163 void test_memop_nowarn_arg (void*, const struct A
[2]);
165 void test_memop_nowarn_arg (void *p
, const struct A
*a
)
167 memcpy (p
, a
, 2 * sizeof *a
);
169 memcpy (p
, a
, range (2 * sizeof *a
, 123));