1 /* Verify the handling of anti-ranges/multi-ranges by allocation functions
2 and subsequent accesses.
3 { dg-do compile }
4 { dg-options "-O2" } */
5
6 typedef __SIZE_TYPE__ size_t;
7
8 void* malloc (size_t);
9 void bzero (void*, size_t);
10 void* memset (void*, int, size_t);
11
12
13 /* Exercise size_t (via malloc and memset) and unsigned/signed int. */
14
15 __attribute__ ((alloc_size (1))) void*
16 alloc_int (int);
17
18 __attribute__ ((access (write_only, 1, 2))) void
19 access_int (void*, int);
20
21 __attribute__ ((alloc_size (1))) void*
22 alloc_uint (unsigned);
23
24 __attribute__ ((access (write_only, 1, 2))) void
25 access_uint (void*, unsigned);
26
27
28 void* nowarn_malloc_memset_same_anti_range (size_t n)
29 {
30 /* Set N to the anti-range ~[3, 3]. */
31 if (n == 3)
32 n = 4;
33 void *p = malloc (n);
34
35 /* Verify there is no warning for an access to N bytes at P.
36 This means the warning has to assume the value of N in the call
37 to alloc() is in the larger subrange [4, UINT_MAX], while in
38 the call to access() in [0, 3]. */
39 return memset (p, 0, n);
40 }
41
42 /* Same as above but with two valid ranges. */
43
44 void* nowarn_malloc_memset_anti_range (size_t n1, size_t n2)
45 {
46 /* Set N1 to the anti-range ~[3, 3]. */
47 if (n1 == 3)
48 n1 = 4;
49 void *p = malloc (n1);
50
51 /* Set N2 to the anti-range ~[7, 7]. */
52 if (n2 == 7)
53 n2 = 8;
54
55 return memset (p, 0, n2);
56 }
57
58
59 void nowarn_alloc_access_same_anti_range_int (int n)
60 {
61 /* Set N to the anti-range ~[3, 3]. */
62 if (n == 3)
63 n = 4;
64 void *p = alloc_int (n);
65
66 /* Verify there is no warning for an access to N bytes at P.
67 This means the warning has to assume the value of N in the call
68 to alloc() is in the larger subrange [4, UINT_MAX], while in
69 the call to access() in [0, 3]. */
70 access_int (p, n);
71 }
72
73 /* Same as above but with two valid ranges. */
74
75 void nowarn_alloc_access_anti_range_int (int n1, int n2)
76 {
77 /* Set N1 to the anti-range ~[3, 3]. */
78 if (n1 == 3)
79 n1 = 4;
80 void *p = alloc_int (n1);
81
82 /* Set N2 to the anti-range ~[7, 7]. */
83 if (n2 == 7)
84 n2 = 8;
85
86 access_int (p, n2);
87 }
88
89
90 void nowarn_alloc_access_same_anti_range_uint (unsigned n)
91 {
92 /* Set N to the anti-range ~[3, 3]. */
93 if (n == 3)
94 n = 4;
95 void *p = alloc_uint (n);
96
97 /* Verify there is no warning for an access to N bytes at P.
98 This means the warning has to assume the value of N in the call
99 to alloc() is in the larger subrange [4, UINT_MAX], while in
100 the call to access() in [0, 3]. */
101 access_uint (p, n);
102 }
103
104 /* Same as above but with two valid ranges. */
105
106 void nowarn_alloc_access_anti_range_uint (unsigned n1, unsigned n2)
107 {
108 /* Set N1 to the anti-range ~[3, 3]. */
109 if (n1 == 3)
110 n1 = 4;
111 void *p = alloc_uint (n1);
112
113 /* Set N2 to the anti-range ~[7, 7]. */
114 if (n2 == 7)
115 n2 = 8;
116
117 access_uint (p, n2);
118 }
119
120
121 void* nowarn_malloc_anti_range_memset_range (size_t n1, size_t n2)
122 {
123 /* Set N1 to the anti-range ~[3, 3]. */
124 if (n1 == 3)
125 n1 = 4;
126 void *p = malloc (n1);
127
128 /* Set N2 to the range [5, MAX]. */
129 if (n2 < 5)
130 n2 = 5;
131 return memset (p, 0, n2);
132 }
133
134 void* nowarn_malloc_range_bzero_anti_range (size_t n1, size_t n2)
135 {
136 /* Set N1 to the anti-range ~[3, 3]. */
137 if (n1 > 4)
138 n1 = 4;
139 void *p = malloc (n1);
140
141 /* Set N2 to the range [5, MAX]. */
142 if (n2 <= 3 || 5 <= n2)
143 n2 = 4;
144 bzero (p, n2);
145 return p;
146 }