1 /* Verify that writes at excessive offsets into objects of unknown size
2 pointed to by function arguments are diagnosed.
3 { dg-do compile }
4 { dg-options "-O2" } */
5
6 #define DIFF_MAX __PTRDIFF_MAX__
7
8 typedef __PTRDIFF_TYPE__ ptrdiff_t;
9 typedef __SIZE_TYPE__ size_t;
10
11 void* memset (void*, int, size_t);
12
13 void sink (void*);
14
15 char* fcall (void);
16
17 void char_ptr_cst_off_cst_size (char *p)
18 // { dg-message "at offset \[1-9\]\[0-9\]+ into destination object 'p'" "note" { target *-*-* } .-1 }
19 {
20 size_t idx = DIFF_MAX - 3;
21
22 memset (p + idx, 0, 3);
23 sink (p);
24
25 ++idx;
26 memset (p + idx, 0, 3); // { dg-warning "writing 3 bytes into a region of size 2" }
27 sink (p);
28
29 ++idx;
30 memset (p + idx, 0, 3); // { dg-warning "writing 3 bytes into a region of size 1" }
31
32 ++idx;
33 memset (p + idx, 0, 3); // { dg-warning "writing 3 bytes into a region of size 0" }
34 }
35
36
37 void char_ptr_var_difoff_cst_size (ptrdiff_t idx)
38 {
39 char *p = fcall ();
40 /* The offset is a range with a very large lower bound and an upper
41 bound of DIFF_MAX. There's not point in also mentioning the latter
42 (it wouldn't make the note any more meaningful) so verify it only
43 mentions the lower bound.
44 { dg-message "at offset \\d+ into destination object of size \\\[0, \\d+] (allocated|returned) by 'fcall'" "note" { target *-*-* } .-5 } */
45
46 if (idx < DIFF_MAX - 3)
47 idx = DIFF_MAX - 3;
48
49 memset (p + idx, 0, 3);
50 sink (p);
51
52 memset (p + idx, 0, 5); // { dg-warning "writing 5 bytes into a region of size 3" }
53 }
54
55
56 void char_ptr_var_szoff_cst_size (size_t idx)
57 {
58 extern char* gptr;
59 // { dg-message "at offset \\d+ into destination object 'gptr'" "note" { target *-*-* } .-1 }
60
61 char *p = gptr;
62
63 if (idx < DIFF_MAX - 3)
64 idx = DIFF_MAX - 3;
65
66 memset (p + idx, 0, 3);
67 sink (p);
68
69 memset (p + idx, 0, 5); // { dg-warning "writing 5 bytes into a region of size 3" "" { xfail *-*-* } }
70
71 if (idx > DIFF_MAX)
72 idx = DIFF_MAX;
73
74 memset (p + idx, 0, 7); // { dg-warning "writing 7 bytes into a region of size 3" }
75 }
76
77
78 void char_ptr_var_difoff_var_size (char *p, ptrdiff_t idx, size_t n)
79 // { dg-message "at offset \\d+ into destination object 'p'" "note" { target *-*-* } .-1 }
80 {
81 if (idx < DIFF_MAX - 3)
82 idx = DIFF_MAX - 3;
83
84 if (n < 3 || 7 < n)
85 n = 3;
86
87 memset (p + idx, 0, n);
88 sink (p);
89
90 ++n;
91 memset (p + idx, 0, n); // { dg-warning "writing between 4 and 8 bytes into a region of size 3" }
92 }
93
94
95 void char_ptr_var_szoff_var_size (char *p, size_t idx, size_t n)
96 // { dg-message "at offset \\\[\[1-9\]\[0-9\]+, \[1-9\]\[0-9\]+] into destination object 'p'" "note" { xfail *-*-* } .-1 }
97 {
98 if (idx < DIFF_MAX - 3)
99 idx = DIFF_MAX - 3;
100
101 if (n < 3 || 7 < n)
102 n = 3;
103
104 memset (p + idx, 0, n);
105 sink (p);
106
107 ++n;
108 /* With an unsigned offset large values are interpreted as negative
109 so the addition (p + idx) is effectively treated as subtraction,
110 making an overflow indistinguishable from a valid (if unlikely)
111 store. */
112 memset (p + idx, 0, n); // { dg-warning "writing between 4 and 8 bytes into a region of size 3" "pr?????" { xfail *-*-* } }
113 }
114
115
116 void int_ptr_cst_off_cst_size (int *p)
117 // { dg-message "at offset \[1-9\]\[0-9\]+ into destination object 'p'" "note" { target *-*-* } .-1 }
118 {
119 size_t idx = DIFF_MAX / sizeof *p;
120
121 memset (p + idx, 0, 3);
122 sink (p);
123
124 memset (p + idx, 0, 5); // { dg-warning "writing 5 bytes into a region of size 3" }
125 }