1 /* Test exercising -Wrawmem-overflow and -Wstringop-overflow warnings. */
2 /* { dg-do compile } */
3 /* { dg-options "-O2 -Wstringop-overflow=2" } */
5 #define offsetof(type, mem) __builtin_offsetof (type, mem)
7 /* Return the number of bytes from member MEM of TYPE to the end
9 #define offsetfrom(type, obj, mem) (sizeof (obj) - offsetof (type, mem))
12 typedef __SIZE_TYPE__
size_t;
13 extern void* memcpy (void*, const void*, size_t);
14 extern void* memset (void*, int, __SIZE_TYPE__
);
17 struct A
{ char a
, b
; };
18 struct B
{ struct A a
; char c
, d
; };
20 /* Function to call to "escape" pointers from tests below to prevent
21 GCC from assuming the values of the objects they point to stay
23 void escape (void*, ...);
25 /* Function to "generate" a random number each time it's called. Declared
26 (but not defined) and used to prevent GCC from making assumptions about
27 their values based on the variables uses in the tested expressions. */
28 size_t random_unsigned_value (void);
30 /* Return a random unsigned value between MIN and MAX. */
33 range (size_t min
, size_t max
)
35 const size_t val
= random_unsigned_value ();
36 return val
< min
|| max
< val
? min
: val
;
40 void test_memop_warn_object (const void *src
)
42 unsigned n
= range (17, 29);
46 /* At both -Wstringop-overflow=2, like at 1, the destination of functions
47 that operate on raw memory is considered to be the whole array and its
48 size is therefore sizeof a. */
49 memcpy (&a
[0], src
, n
); /* { dg-warning "writing between 17 and 29 bytes into a region of size 4 overflows the destination" } */
53 void test_memop_warn_subobject (const void *src
)
55 unsigned n
= range (17, 31);
59 /* At -Wrawmem-overflow=2 the destination is considered to be
60 the member sobobject of the first array element and its size
61 is therefore sizeof b[0].a. */
62 memcpy (&b
[0].a
, src
, n
); /* { dg-warning "writing between 17 and 31 bytes into a region of size 8 overflows the destination" } */
67 void test_memop_nowarn_subobject (void)
71 /* The following idiom of clearing multiple members of a struct
72 has been seen in a few places in the Linux kernel. Verify
73 that a warning is not issued for it. */
74 memset (&b
[0].c
, 0, sizeof b
[0] - offsetof (struct B
, c
));
79 struct C
{ char a
[3], b
; };
80 struct D
{ struct C c
; char d
, e
; };
82 extern char* strncpy (char*, const char*, __SIZE_TYPE__
);
84 void test_stringop_warn_object (const char *str
)
86 unsigned n
= range (2 * sizeof (struct D
), 32);
90 /* Similarly, at -Wstringop-overflow=2 the destination is considered
91 to be the array member of the first element of the array c and its
92 size is therefore sizeof c[0].a. */
93 strncpy (c
[0].a
, "123", n
); /* { dg-warning "writing between 12 and 32 bytes into a region of size 3 overflows the destination" } */
96 strncpy (c
[0].a
, str
, n
); /* { dg-warning "writing between 12 and 32 bytes into a region of size 3 overflows the destination" } */
100 void test_stringop_warn_subobject (const char *src
)
102 unsigned n
= range (2 * sizeof (struct D
), 32);
107 strncpy (d
[0].c
.a
, "123", n
); /* { dg-warning "writing between 12 and 32 bytes into a region of size 3 overflows the destination" } */
110 strncpy (d
[0].c
.a
, src
, n
); /* { dg-warning "writing between 12 and 32 bytes into a region of size 3 overflows the destination" } */