131
|
1 /* PR middle-end/77608 - missing protection on trivially detectable runtime
|
|
2 buffer overflow
|
|
3 { dg-do compile }
|
|
4 { dg-options "-O2 -Wstringop-overflow -ftrack-macro-expansion=0" } */
|
|
5
|
|
6 #define SIZE_MAX __SIZE_MAX__
|
|
7 #define DIFF_MAX __PTRDIFF_MAX__
|
|
8 #define DIFF_MIN (-DIFF_MAX - 1)
|
|
9
|
|
10 typedef __SIZE_TYPE__ size_t;
|
|
11
|
|
12 extern void* memcpy (void*, const void*, size_t);
|
|
13 extern char* strcpy (char*, const char*);
|
|
14 extern char* strncpy (char*, const char*, size_t);
|
|
15
|
|
16 void sink (void*);
|
|
17
|
|
18 static size_t unsigned_value (void)
|
|
19 {
|
|
20 extern volatile size_t unsigned_value_source;
|
|
21 return unsigned_value_source;
|
|
22 }
|
|
23
|
|
24 static size_t unsigned_range (size_t min, size_t max)
|
|
25 {
|
|
26 size_t val = unsigned_value ();
|
|
27 return val < min || max < val ? min : val;
|
|
28 }
|
|
29
|
|
30 #define UR(min, max) unsigned_range (min, max)
|
|
31
|
|
32
|
|
33 char a7[7];
|
|
34
|
|
35 struct MemArray { char a9[9]; char a1[1]; };
|
|
36
|
|
37 void test_memcpy_array (const void *s)
|
|
38 {
|
|
39 #define T(d, s, n) (memcpy ((d), (s), (n)), sink (d))
|
|
40
|
|
41 T (a7 + UR (0, 1), s, 7);
|
|
42 T (a7 + UR (0, 7), s, 7);
|
|
43 T (a7 + UR (0, 8), s, 7);
|
|
44 T (a7 + UR (0, DIFF_MAX), s, 7);
|
|
45 T (a7 + UR (0, SIZE_MAX), s, 7);
|
|
46
|
|
47 T (a7 + UR (1, 2), s, 7); /* { dg-warning "writing 7 bytes into a region of size 6" } */
|
|
48 T (a7 + UR (2, 3), s, 7); /* { dg-warning "writing 7 bytes into a region of size 5" } */
|
|
49 T (a7 + UR (6, 9), s, 7); /* { dg-warning "writing 7 bytes into a region of size 1" } */
|
|
50 T (a7 + UR (7, 9), s, 7); /* { dg-warning "writing 7 bytes into a region of size 0" } */
|
|
51 T (a7 + UR (8, 9), s, 7); /* { dg-warning "writing 7 bytes into a region of size 0" } */
|
|
52
|
|
53 T (a7 + UR (9, 10), s, 7); /* { dg-warning "writing 7 bytes into a region of size 0" } */
|
|
54 T (a7 + UR (DIFF_MAX, DIFF_MAX + (size_t)1), s, 7); /* { dg-warning "writing 7 bytes into a region of size 0" } */
|
|
55 T (a7 + UR (DIFF_MAX, SIZE_MAX), s, 7); /* { dg-warning "writing 7 bytes into a region of size 0" } */
|
|
56
|
|
57 /* This is valid. */
|
|
58 char *d = a7 + 7;
|
|
59 T (d + UR (-8, -7), s, 7);
|
|
60 }
|
|
61
|
|
62 /* Verify the absence of warnings for memcpy writing beyond object
|
|
63 boundaries. */
|
|
64
|
|
65 void test_memcpy_memarray (struct MemArray *p, const void *s)
|
|
66 {
|
|
67 #undef T
|
|
68 #define T(d, s, n) (memcpy ((d), (s), (n)), sink (d))
|
|
69
|
|
70 /* The following are valid. */
|
|
71 T (p->a9 + UR (0, 1), s, 9);
|
|
72 T (p->a9 + UR (0, 7), s, 9);
|
|
73 T (p->a9 + UR (0, 8), s, 9);
|
|
74 T (p->a9 + UR (0, DIFF_MAX), s, 9);
|
|
75 T (p->a9 + UR (0, SIZE_MAX), s, 9);
|
|
76
|
|
77 /* The following are invalid. Unfortunately, there is apparently enough
|
|
78 code out there that abuses memcpy to write past the end of one member
|
|
79 and into the members that follow so the following are not diagnosed
|
|
80 by design. It sure would be nice not to have to cater to hacks like
|
|
81 these... */
|
|
82 T (p->a9 + UR (1, 2), s, 9);
|
|
83 T (p->a9 + UR (1, 2), s, 123);
|
|
84 }
|
|
85
|
|
86
|
|
87 void test_strcpy_array (void)
|
|
88 {
|
|
89 #undef T
|
|
90 #define T(d, s) (strcpy ((d), (s)), sink (d))
|
|
91
|
|
92 T (a7 + UR (0, 1), "012345");
|
|
93 T (a7 + UR (0, 7), "012345");
|
|
94 T (a7 + UR (0, 8), "012345");
|
|
95 T (a7 + UR (0, DIFF_MAX), "012345");
|
|
96 T (a7 + UR (0, SIZE_MAX), "012345");
|
|
97
|
|
98 T (a7 + UR (1, 2), "012345"); /* { dg-warning "writing 7 bytes into a region of size 6" } */
|
|
99 T (a7 + UR (2, 3), "012345"); /* { dg-warning "writing 7 bytes into a region of size 5" } */
|
|
100 T (a7 + UR (6, 9), "012345"); /* { dg-warning "writing 7 bytes into a region of size 1" } */
|
|
101 T (a7 + UR (7, 9), "012345"); /* { dg-warning "writing 7 bytes into a region of size 0" } */
|
|
102 T (a7 + UR (8, 9), "012345"); /* { dg-warning "writing 7 bytes into a region of size 0" } */
|
|
103
|
|
104 T (a7 + UR (9, 10), "012345"); /* { dg-warning "writing 7 bytes into a region of size 0" } */
|
|
105 T (a7 + UR (DIFF_MAX, DIFF_MAX + (size_t)1), "012345"); /* { dg-warning "writing 7 bytes into a region of size 0" } */
|
|
106 T (a7 + UR (DIFF_MAX, SIZE_MAX), "012345"); /* { dg-warning "writing 7 bytes into a region of size 0" } */
|
|
107
|
|
108 char *d = a7 + 7;
|
|
109
|
|
110 T (d + UR (-8, -7), "012345");
|
|
111 }
|
|
112
|
|
113 void test_strncpy_memarray (struct MemArray *p, const void *s)
|
|
114 {
|
|
115 #undef T
|
|
116 #define T(d, s, n) (strncpy ((d), (s), (n)), sink (d))
|
|
117
|
|
118 T (p->a9 + UR (0, 1), s, 9);
|
|
119 T (p->a9 + UR (0, 7), s, 9);
|
|
120 T (p->a9 + UR (0, 8), s, 9);
|
|
121 T (p->a9 + UR (0, DIFF_MAX), s, 9);
|
|
122 T (p->a9 + UR (0, SIZE_MAX), s, 9);
|
|
123
|
|
124 T (p->a9 + UR (1, 2), s, 9); /* { dg-warning "writing 9 bytes into a region of size 8" } */
|
|
125 T (p->a9 + UR (2, 3), s, 9); /* { dg-warning "writing 9 bytes into a region of size 7" } */
|
|
126 T (p->a9 + UR (6, 9), s, 9); /* { dg-warning "writing 9 bytes into a region of size 3" } */
|
|
127 T (p->a9 + UR (9, 10), s, 9); /* { dg-warning "writing 9 bytes into a region of size 0" } */
|
|
128 T (p->a9 + UR (10, 11), s, 9); /* { dg-warning "writing 9 bytes into a region of size 0" } */
|
|
129
|
|
130 T (p->a9 + UR (DIFF_MAX, DIFF_MAX + (size_t)1), s, 1); /* { dg-warning "writing 1 byte into a region of size 0" } */
|
|
131 T (p->a9 + UR (DIFF_MAX, SIZE_MAX), s, 3); /* { dg-warning "writing 3 bytes into a region of size 0" } */
|
|
132 }
|