1 /* PR c/78284 - warn on malloc with very large arguments
2    Test exercising the ability to detect and diagnose calls to allocation
3    functions decorated with attribute alloc_size that attempt to allocate
4    zero bytes.  For standard allocation functions the return value is
5    implementation-defined and so relying on it may be a source of bugs.  */
6 /* { dg-do compile } */
7 /* { dg-options "-O2 -Wall -Walloc-zero" } */
8 
9 #define SCHAR_MAX  __SCHAR_MAX__
10 #define SCHAR_MIN  (-SCHAR_MAX - 1)
11 #define UCHAR_MAX  (SCHAR_MAX * 2 + 1)
12 
13 #define SHRT_MAX   __SHRT_MAX__
14 #define SHRT_MIN   (-SHRT_MAX - 1)
15 #define USHRT_MAX  (SHRT_MAX * 2 + 1)
16 
17 #define INT_MAX    __INT_MAX__
18 #define INT_MIN    (-INT_MAX - 1)
19 #define UINT_MAX   (INT_MAX * 2U + 1)
20 
21 #define LONG_MAX   __LONG_MAX__
22 #define LONG_MIN   (-LONG_MAX - 1L)
23 #define ULONG_MAX  (LONG_MAX * 2LU + 1)
24 
25 #define LLONG_MAX  __LLONG_MAX__
26 #define LLONG_MIN  (-LLONG_MAX - 1LL)
27 #define ULLONG_MAX (ULLONG_MAX * 2LLU + 1)
28 
29 #define SIZE_MAX   __SIZE_MAX__
30 
31 typedef __SIZE_TYPE__ size_t;
32 
33 
34 #define ALLOC_SIZE(...) __attribute__ ((alloc_size (__VA_ARGS__)))
35 
36 void* f_uchar_1 (unsigned char) ALLOC_SIZE (1);
37 void* f_uchar_2 (unsigned char, unsigned char) ALLOC_SIZE (1, 2);
38 void* f_schar_1 (signed char) ALLOC_SIZE (1);
39 void* f_schar_2 (signed char, signed char) ALLOC_SIZE (1, 2);
40 
41 void* f_ushrt_1 (unsigned short) ALLOC_SIZE (1);
42 void* f_ushrt_2 (unsigned short, unsigned short) ALLOC_SIZE (1, 2);
43 void* f_shrt_1 (signed short) ALLOC_SIZE (1);
44 void* f_shrt_2 (signed short, signed short) ALLOC_SIZE (1, 2);
45 
46 void* f_uint_1 (unsigned) ALLOC_SIZE (1);
47 void* f_uint_2 (unsigned, unsigned) ALLOC_SIZE (1, 2);
48 void* f_int_1 (int) ALLOC_SIZE (1);
49 void* f_int_2 (int, int) ALLOC_SIZE (1, 2);
50 
51 void* f_ulong_1 (unsigned long) ALLOC_SIZE (1);
52 void* f_ulong_2 (unsigned long, unsigned long) ALLOC_SIZE (1, 2);
53 void* f_long_1 (long) ALLOC_SIZE (1);
54 void* f_long_2 (long, long) ALLOC_SIZE (1, 2);
55 
56 void* f_ullong_1 (unsigned long long) ALLOC_SIZE (1);
57 void* f_ullong_2 (unsigned long long, unsigned long long) ALLOC_SIZE (1, 2);
58 void* f_llong_1 (long long) ALLOC_SIZE (1);
59 void* f_llong_2 (long long, long long) ALLOC_SIZE (1, 2);
60 
61 void* f_size_1 (size_t) ALLOC_SIZE (1);
62 void* f_size_2 (size_t, size_t) ALLOC_SIZE (1, 2);
63 
64 void* f_size_1_nonnull (size_t)
65      ALLOC_SIZE (1)  __attribute__ ((returns_nonnull));
66 void* f_size_2_nonnull (size_t, size_t)
67      ALLOC_SIZE (1, 2) __attribute__ ((returns_nonnull));
68 
69 void sink (void*);
70 
71 void
test_uchar(unsigned char n)72 test_uchar (unsigned char n)
73 {
74   sink (f_uchar_1 (0));     /* { dg-warning "argument 1 value is zero" } */
75   sink (f_uchar_2 (0, 1));  /* { dg-warning "argument 1 value is zero" } */
76   sink (f_uchar_2 (1, 0));  /* { dg-warning "argument 2 value is zero" } */
77   sink (f_uchar_2 (n, 0));  /* { dg-warning "argument 2 value is zero" } */
78   sink (f_uchar_2 (0, n));  /* { dg-warning "argument 1 value is zero" } */
79 
80   sink (f_uchar_1 (n));
81   n = 0;
82   sink (f_uchar_1 (n));     /* { dg-warning "argument 1 value is zero" } */
83   sink (f_uchar_2 (1, n));  /* { dg-warning "argument 2 value is zero" } */
84 }
85 
86 void
test_schar(signed char n)87 test_schar (signed char n)
88 {
89   sink (f_schar_1 (0));     /* { dg-warning "argument 1 value is zero" } */
90   sink (f_schar_2 (0, 1));  /* { dg-warning "argument 1 value is zero" } */
91   sink (f_schar_2 (1, 0));  /* { dg-warning "argument 2 value is zero" } */
92   sink (f_schar_2 (n, 0));  /* { dg-warning "argument 2 value is zero" } */
93   sink (f_schar_2 (0, n));  /* { dg-warning "argument 1 value is zero" } */
94 
95   sink (f_schar_1 (n));
96   n = 0;
97   sink (f_schar_1 (n));     /* { dg-warning "argument 1 value is zero" } */
98   sink (f_schar_2 (1, n));  /* { dg-warning "argument 2 value is zero" } */
99 }
100 
101 void
test_ushrt(unsigned short n)102 test_ushrt (unsigned short n)
103 {
104   sink (f_ushrt_1 (0));     /* { dg-warning "argument 1 value is zero" } */
105   sink (f_ushrt_2 (0, 1));  /* { dg-warning "argument 1 value is zero" } */
106   sink (f_ushrt_2 (1, 0));  /* { dg-warning "argument 2 value is zero" } */
107   sink (f_ushrt_2 (n, 0));  /* { dg-warning "argument 2 value is zero" } */
108   sink (f_ushrt_2 (0, n));  /* { dg-warning "argument 1 value is zero" } */
109 
110   sink (f_ushrt_1 (n));
111   n = 0;
112   sink (f_ushrt_1 (n));     /* { dg-warning "argument 1 value is zero" } */
113   sink (f_ushrt_2 (1, n));  /* { dg-warning "argument 2 value is zero" } */
114 }
115 
116 void
test_shrt(short n)117 test_shrt (short n)
118 {
119   sink (f_shrt_1 (0));      /* { dg-warning "argument 1 value is zero" } */
120   sink (f_shrt_2 (0, 1));   /* { dg-warning "argument 1 value is zero" } */
121   sink (f_shrt_2 (1, 0));   /* { dg-warning "argument 2 value is zero" } */
122   sink (f_shrt_2 (n, 0));   /* { dg-warning "argument 2 value is zero" } */
123   sink (f_shrt_2 (0, n));   /* { dg-warning "argument 1 value is zero" } */
124 
125   sink (f_shrt_1 (n));
126   n = 0;
127   sink (f_shrt_1 (n));      /* { dg-warning "argument 1 value is zero" } */
128   sink (f_shrt_2 (1, n));   /* { dg-warning "argument 2 value is zero" } */
129 }
130 
131 void
test_uint(unsigned n)132 test_uint (unsigned n)
133 {
134   sink (f_uint_1 (0));      /* { dg-warning "argument 1 value is zero" } */
135   sink (f_uint_2 (0, 1));   /* { dg-warning "argument 1 value is zero" } */
136   sink (f_uint_2 (1, 0));   /* { dg-warning "argument 2 value is zero" } */
137   sink (f_uint_2 (n, 0));   /* { dg-warning "argument 2 value is zero" } */
138   sink (f_uint_2 (0, n));   /* { dg-warning "argument 1 value is zero" } */
139 
140   sink (f_uint_1 (n));
141   n = 0;
142   sink (f_uint_1 (n));      /* { dg-warning "argument 1 value is zero" } */
143   sink (f_uint_2 (1, n));   /* { dg-warning "argument 2 value is zero" } */
144 }
145 
146 void
test_int(int n)147 test_int (int n)
148 {
149   sink (f_int_1 (0));       /* { dg-warning "argument 1 value is zero" } */
150   sink (f_int_2 (0, 1));    /* { dg-warning "argument 1 value is zero" } */
151   sink (f_int_2 (1, 0));    /* { dg-warning "argument 2 value is zero" } */
152   sink (f_int_2 (n, 0));    /* { dg-warning "argument 2 value is zero" } */
153   sink (f_int_2 (0, n));    /* { dg-warning "argument 1 value is zero" } */
154 
155   sink (f_int_1 (n));
156   n = 0;
157   sink (f_int_1 (n));       /* { dg-warning "argument 1 value is zero" } */
158   sink (f_int_2 (1, n));    /* { dg-warning "argument 2 value is zero" } */
159 }
160 
161 void
test_ulong(unsigned long n)162 test_ulong (unsigned long n)
163 {
164   sink (f_ulong_1 (0));     /* { dg-warning "argument 1 value is zero" } */
165   sink (f_ulong_2 (0, 1));  /* { dg-warning "argument 1 value is zero" } */
166   sink (f_ulong_2 (1, 0));  /* { dg-warning "argument 2 value is zero" } */
167   sink (f_ulong_2 (n, 0));  /* { dg-warning "argument 2 value is zero" } */
168   sink (f_ulong_2 (0, n));  /* { dg-warning "argument 1 value is zero" } */
169 
170   sink (f_ulong_1 (n));
171   n = 0;
172   sink (f_ulong_1 (n));     /* { dg-warning "argument 1 value is zero" } */
173   sink (f_ulong_2 (1, n));  /* { dg-warning "argument 2 value is zero" } */
174 }
175 
176 void
test_long(long n)177 test_long (long n)
178 {
179   sink (f_long_1 (0));      /* { dg-warning "argument 1 value is zero" } */
180   sink (f_long_2 (0, 1));   /* { dg-warning "argument 1 value is zero" } */
181   sink (f_long_2 (1, 0));   /* { dg-warning "argument 2 value is zero" } */
182   sink (f_long_2 (n, 0));   /* { dg-warning "argument 2 value is zero" } */
183   sink (f_long_2 (0, n));   /* { dg-warning "argument 1 value is zero" } */
184 
185   sink (f_long_1 (n));
186   n = 0;
187   sink (f_long_1 (n));      /* { dg-warning "argument 1 value is zero" } */
188   sink (f_long_2 (1, n));   /* { dg-warning "argument 2 value is zero" } */
189 }
190 
191 void
test_size(size_t n)192 test_size (size_t n)
193 {
194   sink (f_size_1 (0));      /* { dg-warning "argument 1 value is zero" } */
195   sink (f_size_2 (0, 1));   /* { dg-warning "argument 1 value is zero" } */
196   sink (f_size_2 (1, 0));   /* { dg-warning "argument 2 value is zero" } */
197   sink (f_size_2 (n, 0));   /* { dg-warning "argument 2 value is zero" } */
198   sink (f_size_2 (0, n));   /* { dg-warning "argument 1 value is zero" } */
199 
200   sink (f_size_1 (n));
201   n = 0;
202   sink (f_size_1 (n));      /* { dg-warning "argument 1 value is zero" } */
203   sink (f_size_2 (1, n));   /* { dg-warning "argument 2 value is zero" } */
204 }
205 
206 /* Verify that calls to allocation function decorated with attribute
207    returns_nonnull don't cause warnings (unlike functions like malloc
208    that can return null in this case there's nothing to warn about
209    because a returns_nonnull function guarantees success).  */
210 
211 void
test_size_nonnull(size_t n)212 test_size_nonnull (size_t n)
213 {
214   sink (f_size_1_nonnull (0));
215   sink (f_size_2_nonnull (0, 1));
216   sink (f_size_2_nonnull (1, 0));
217   sink (f_size_2_nonnull (n, 0));
218   sink (f_size_2_nonnull (0, n));
219 
220   sink (f_size_1_nonnull (n));
221   n = 0;
222   sink (f_size_1_nonnull (n));
223   sink (f_size_2_nonnull (1, n));
224 }
225 
226 /* Verify that call to plain alloca(0) is not diagnosed.  */
227 
228 void
test_alloca(size_t n)229 test_alloca (size_t n)
230 {
231   extern void* alloca (size_t);
232 
233   alloca (0);
234 }
235