1 /* PR middle-end/91582 - missing heap overflow detection for strcpy
3 { dg-options "-O2 -Wall -Wno-array-bounds -ftrack-macro-expansion=0" } */
5 #include "../../gcc.dg/range.h"
7 #define INT_MAX __INT_MAX__
8 #define INT_MIN (-INT_MAX - 1)
10 extern "C" char* strcpy (char*, const char*);
14 #define S36 "0123456789abcdefghijklmnopqrstuvwxyz"
15 #define S(N) (S36 + sizeof S36 - N - 1)
17 #define T(src, alloc) do { \
18 const char *s = src; \
19 char *d = (char*)alloc; \
25 void test_strcpy_new_char (size_t n)
27 size_t r_0_1 = UR (0, 1);
28 size_t r_1_2 = UR (1, 2);
29 size_t r_2_3 = UR (2, 3);
31 T (S (0), new char[r_0_1]);
32 T (S (1), new char[r_0_1]); // { dg-warning "\\\[-Wstringop-overflow" }
34 T (S (0), new char[r_1_2]);
35 T (S (1), new char[r_1_2]);
36 T (S (2), new char[r_1_2]); // { dg-warning "\\\[-Wstringop-overflow" }
38 T (S (0), new char[r_2_3]);
39 T (S (2), new char[r_2_3]);
40 T (S (3), new char[r_2_3]); // { dg-warning "\\\[-Wstringop-overflow" }
41 T (S (9), new char[r_2_3]); // { dg-warning "\\\[-Wstringop-overflow" }
43 size_t r_2_smax = UR (2, SIZE_MAX);
44 T (S (0), new char[r_2_smax]);
45 T (S (1), new char[r_2_smax]);
46 T (S (2), new char[r_2_smax]);
47 T (S (3), new char[r_2_smax * 2]);
48 T (S (4), new char[r_2_smax * 2 + 1]);
50 T (S (1), new char[n]);
51 T (S (2), new char[n + 1]);
52 T (S (9), new char[n * 2 + 1]);
54 int r_imin_imax = SR (INT_MIN, INT_MAX);
55 T (S (1), new char[r_imin_imax]);
56 T (S (2), new char[r_imin_imax + 1]);
57 T (S (9), new char[r_imin_imax * 2 + 1]);
59 int r_0_imax = SR (0, INT_MAX);
60 T (S (1), new char[r_0_imax]);
61 T (S (2), new char[r_0_imax + 1]);
62 T (S (9), new char[r_0_imax * 2 + 1]);
64 int r_1_imax = SR (1, INT_MAX);
65 T (S (1), new char[r_1_imax]);
66 T (S (2), new char[r_1_imax + 1]);
67 T (S (9), new char[r_1_imax * 2 + 1]);
69 ptrdiff_t r_dmin_dmax = SR (DIFF_MIN, DIFF_MAX);
70 T (S (1), new char[r_dmin_dmax]);
71 T (S (2), new char[r_dmin_dmax + 1]);
72 T (S (9), new char[r_dmin_dmax * 2 + 1]);
76 void test_strcpy_new_char_array (size_t n)
78 size_t r_0_1 = UR (0, 1);
80 T (S (0), new char[r_0_1][1]);
81 T (S (1), new char[r_0_1][1]); // { dg-warning "\\\[-Wstringop-overflow" }
82 T (S (1), new char[r_0_1][2]);
83 T (S (2), new char[r_0_1][2]); // { dg-warning "\\\[-Wstringop-overflow" }
85 size_t r_1_2 = UR (1, 2);
86 T (S (0), new char[r_1_2][0]); // { dg-warning "\\\[-Wstringop-overflow" }
87 T (S (0), new char[r_1_2][1]);
88 T (S (1), new char[r_1_2][1]);
89 T (S (2), new char[r_1_2][1]); // { dg-warning "\\\[-Wstringop-overflow" }
91 T (S (0), new char[r_1_2][0]); // { dg-warning "\\\[-Wstringop-overflow" }
92 T (S (0), new char[r_1_2][1]);
93 T (S (1), new char[r_1_2][2]);
94 T (S (3), new char[r_1_2][2]);
95 T (S (4), new char[r_1_2][2]); // { dg-warning "\\\[-Wstringop-overflow" }
101 // Hack around PR 92829.
102 #define XUR(min, max) \
103 (++idx, (vals[idx] < min || max < vals[idx] ? min : vals[idx]))
105 typedef __INT16_TYPE__ int16_t;
107 void test_strcpy_new_int16_t (size_t n, const size_t vals[])
111 size_t r_0_1 = XUR (0, 1);
112 size_t r_1_2 = XUR (1, 2);
113 size_t r_2_3 = XUR (2, 3);
115 T (S (0), new int16_t[r_0_1]);
116 T (S (1), new int16_t[r_0_1]);
117 T (S (2), new int16_t[r_0_1]); // { dg-warning "\\\[-Wstringop-overflow" }
119 T (S (0), new int16_t[r_1_2]);
120 T (S (1), new int16_t[r_1_2]);
121 T (S (2), new int16_t[r_1_2]);
122 T (S (3), new int16_t[r_1_2]);
123 T (S (4), new int16_t[r_1_2]); // { dg-warning "\\\[-Wstringop-overflow" }
125 T (S (0), new int16_t[r_2_3]);
126 T (S (1), new int16_t[r_2_3]);
127 T (S (5), new int16_t[r_2_3]);
128 T (S (6), new int16_t[r_2_3]); // { dg-warning "\\\[-Wstringop-overflow" }
129 T (S (9), new int16_t[r_2_3]); // { dg-warning "\\\[-Wstringop-overflow" }
131 size_t r_2_smax = XUR (2, SIZE_MAX);
132 T (S (0), new int16_t[r_2_smax]);
133 T (S (1), new int16_t[r_2_smax]);
134 T (S (2), new int16_t[r_2_smax]);
135 T (S (3), new int16_t[r_2_smax * 2]);
136 T (S (4), new int16_t[r_2_smax * 2 + 1]);
138 T (S (1), new int16_t[n]);
139 T (S (2), new int16_t[n + 1]);
140 T (S (9), new int16_t[n * 2 + 1]);
142 int r_imin_imax = SR (INT_MIN, INT_MAX);
143 T (S (1), new int16_t[r_imin_imax]);
144 T (S (2), new int16_t[r_imin_imax + 1]); // { dg-bogus "into a region of size" "pr106120" { xfail { lp64 && c++98_only } } }
145 T (S (9), new int16_t[r_imin_imax * 2 + 1]);
147 int r_0_imax = SR (0, INT_MAX);
149 if (sizeof (int) < sizeof (size_t))
150 /* The code below might emit a warning when int is the same size
151 as size_t as a result of threading. See PR 101688 comment #2. */
152 T (S (1), new int16_t[r_0_imax]);
154 /* Similar to PR 101688 the following can result in a bougs warning because
156 T (S (2), new int16_t[r_0_imax + 1]); // { dg-bogus "into a region of size" "" { xfail { ilp32 } } }
157 T (S (9), new int16_t[r_0_imax * 2 + 1]);
159 int r_1_imax = SR (1, INT_MAX);
160 T (S (1), new int16_t[r_1_imax]);
161 T (S (2), new int16_t[r_1_imax + 1]);
162 T (S (9), new int16_t[r_1_imax * 2 + 1]);
164 ptrdiff_t r_dmin_dmax = SR (DIFF_MIN, DIFF_MAX);
165 T (S (1), new int16_t[r_dmin_dmax]);
166 /* ?? The above SR(DIFF_MIN, DIFF_MAX) implies r_dmin_dmax can be
167 the entire domain, including negative numbers because ptrdiff_t
170 This causes a warning in the following line after the
171 DOM/threader changes for C++98.
173 <bb 2> [local count: 1073741824]:
174 _26 ={v} signed_value_source; ;; could be -1
175 r_dmin_dmax.1_8 = (sizetype) _26;
176 if (r_dmin_dmax.1_8 <= 4611686018427387900) ;; placement new rounding
177 goto <bb 3>; [50.00%]
179 goto <bb 9>; [50.00%]
184 <bb 9> [local count: 536870912]:
185 # iftmp.0_39 = PHI <18446744073709551615(2)>
186 _41 = operator new [] (iftmp.0_39);
187 __builtin_memcpy (_41, "z", 2);
189 _44 = _26 + 1; ;; _44 = 0
190 _45 = (sizetype) _44; ;; _45 = 0
191 if (_45 <= 4611686018427387900)
194 goto <bb 7>; [100.00%]
196 <bb 8> [local count: 0]:
197 iftmp.2_33 = _45 * 2; ;; iftmp.2_33 = 0
198 _34 = operator new [] (iftmp.2_33); ;; new [] (0)
200 T (S (2), new int16_t[r_dmin_dmax + 1]); // { dg-bogus "into a region of size" "" { xfail c++98_only } }
201 T (S (9), new int16_t[r_dmin_dmax * 2 + 1]);