Branch data Line data Source code
1 : : /* Array bounds checking.
2 : : Copyright (C) 2005-2024 Free Software Foundation, Inc.
3 : :
4 : : This file is part of GCC.
5 : :
6 : : GCC is free software; you can redistribute it and/or modify
7 : : it under the terms of the GNU General Public License as published by
8 : : the Free Software Foundation; either version 3, or (at your option)
9 : : any later version.
10 : :
11 : : GCC is distributed in the hope that it will be useful,
12 : : but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : : GNU General Public License for more details.
15 : :
16 : : You should have received a copy of the GNU General Public License
17 : : along with GCC; see the file COPYING3. If not see
18 : : <http://www.gnu.org/licenses/>. */
19 : :
20 : : #include "config.h"
21 : : #include "system.h"
22 : : #include "coretypes.h"
23 : : #include "backend.h"
24 : : #include "tree.h"
25 : : #include "gimple.h"
26 : : #include "ssa.h"
27 : : #include "pointer-query.h"
28 : : #include "gimple-array-bounds.h"
29 : : #include "gimple-iterator.h"
30 : : #include "gimple-walk.h"
31 : : #include "tree-dfa.h"
32 : : #include "fold-const.h"
33 : : #include "diagnostic-core.h"
34 : : #include "intl.h"
35 : : #include "tree-vrp.h"
36 : : #include "alloc-pool.h"
37 : : #include "vr-values.h"
38 : : #include "domwalk.h"
39 : : #include "tree-cfg.h"
40 : : #include "attribs.h"
41 : :
42 : 106736 : array_bounds_checker::array_bounds_checker (struct function *func,
43 : 106736 : range_query *qry)
44 : 106736 : : fun (func), m_ptr_qry (qry)
45 : : {
46 : : /* No-op. */
47 : 106736 : }
48 : :
49 : : void
50 : 118453 : array_bounds_checker::get_value_range (irange &r, const_tree op, gimple *stmt)
51 : : {
52 : 118453 : if (m_ptr_qry.rvals->range_of_expr (r, const_cast<tree> (op), stmt))
53 : : return;
54 : 0 : r.set_varying (TREE_TYPE (op));
55 : : }
56 : :
57 : : /* Try to determine the DECL that REF refers to. Return the DECL or
58 : : the expression closest to it. Used in informational notes pointing
59 : : to referenced objects or function parameters. */
60 : :
61 : : static tree
62 : 151499 : get_base_decl (tree ref)
63 : : {
64 : 151499 : tree base = get_base_address (ref);
65 : 151499 : if (DECL_P (base))
66 : : return base;
67 : :
68 : 15108 : if (TREE_CODE (base) == MEM_REF)
69 : 14639 : base = TREE_OPERAND (base, 0);
70 : :
71 : 15108 : if (TREE_CODE (base) != SSA_NAME)
72 : : return base;
73 : :
74 : 14679 : do
75 : : {
76 : 14679 : gimple *def = SSA_NAME_DEF_STMT (base);
77 : 14679 : if (gimple_assign_single_p (def))
78 : : {
79 : 1959 : base = gimple_assign_rhs1 (def);
80 : 1959 : return base;
81 : : }
82 : :
83 : 12720 : if (!gimple_nop_p (def))
84 : : return base;
85 : :
86 : 8521 : break;
87 : : } while (true);
88 : :
89 : 8521 : tree var = SSA_NAME_VAR (base);
90 : 8521 : if (TREE_CODE (var) != PARM_DECL)
91 : 0 : return base;
92 : :
93 : : return var;
94 : : }
95 : :
96 : : /* Return the constant byte size of the object or type referenced by
97 : : the MEM_REF ARG. On success, set *PREF to the DECL or expression
98 : : ARG refers to. Otherwise return null. */
99 : :
100 : : static tree
101 : 58882 : get_ref_size (tree arg, tree *pref)
102 : : {
103 : 58882 : if (TREE_CODE (arg) != MEM_REF)
104 : : return NULL_TREE;
105 : :
106 : 58882 : arg = TREE_OPERAND (arg, 0);
107 : 58882 : tree type = TREE_TYPE (arg);
108 : 58882 : if (!POINTER_TYPE_P (type))
109 : : return NULL_TREE;
110 : :
111 : 58882 : type = TREE_TYPE (type);
112 : 58882 : if (TREE_CODE (type) != ARRAY_TYPE)
113 : : return NULL_TREE;
114 : :
115 : 572 : tree nbytes = TYPE_SIZE_UNIT (type);
116 : 572 : if (!nbytes || TREE_CODE (nbytes) != INTEGER_CST)
117 : : return NULL_TREE;
118 : :
119 : 40 : *pref = get_base_decl (arg);
120 : 40 : return nbytes;
121 : : }
122 : :
123 : : /* Return true if REF is (likely) an ARRAY_REF to a trailing array member
124 : : of a struct. It refines array_ref_flexible_size_p by detecting a pointer
125 : : to an array and an array parameter declared using the [N] syntax (as
126 : : opposed to a pointer) and returning false. Set *PREF to the decl or
127 : : expression REF refers to. */
128 : :
129 : : static bool
130 : 151459 : trailing_array (tree arg, tree *pref)
131 : : {
132 : 151459 : tree ref = arg;
133 : 151459 : tree base = get_base_decl (arg);
134 : 461717 : while (TREE_CODE (ref) == ARRAY_REF || TREE_CODE (ref) == MEM_REF)
135 : 158799 : ref = TREE_OPERAND (ref, 0);
136 : :
137 : 151459 : if (TREE_CODE (ref) == COMPONENT_REF)
138 : : {
139 : 37505 : *pref = TREE_OPERAND (ref, 1);
140 : 37505 : tree type = TREE_TYPE (*pref);
141 : 37505 : if (TREE_CODE (type) == ARRAY_TYPE)
142 : : {
143 : : /* A multidimensional trailing array is not considered special
144 : : no matter what its major bound is. */
145 : 37505 : type = TREE_TYPE (type);
146 : 37505 : if (TREE_CODE (type) == ARRAY_TYPE)
147 : : return false;
148 : : }
149 : : }
150 : : else
151 : 113954 : *pref = base;
152 : :
153 : 147503 : tree basetype = TREE_TYPE (base);
154 : 147503 : if (TREE_CODE (base) == PARM_DECL
155 : 11619 : && POINTER_TYPE_P (basetype))
156 : : {
157 : 7997 : tree ptype = TREE_TYPE (basetype);
158 : 7997 : if (TREE_CODE (ptype) == ARRAY_TYPE)
159 : : return false;
160 : : }
161 : :
162 : 147278 : return array_ref_flexible_size_p (arg);
163 : : }
164 : :
165 : : /* Acquire the upper bound and upper bound plus one for the array
166 : : reference REF and record them into UP_BOUND and UP_BOUND_P1.
167 : : Set *DECL to the decl or expresssion REF refers to. */
168 : :
169 : : static void
170 : 218854 : get_up_bounds_for_array_ref (tree ref, tree *decl,
171 : : tree *up_bound, tree *up_bound_p1)
172 : : {
173 : 218854 : if (!(*up_bound)
174 : 153126 : || TREE_CODE (*up_bound) != INTEGER_CST
175 : 370313 : || trailing_array (ref, decl))
176 : : {
177 : : /* Accesses to trailing arrays via pointers may access storage
178 : : beyond the types array bounds. For such arrays, or for flexible
179 : : array members, as well as for other arrays of an unknown size,
180 : : replace the upper bound with a more permissive one that assumes
181 : : the size of the largest object is PTRDIFF_MAX. */
182 : 74452 : tree eltsize = array_ref_element_size (ref);
183 : :
184 : 74452 : if (TREE_CODE (eltsize) != INTEGER_CST
185 : 74452 : || integer_zerop (eltsize))
186 : : {
187 : 713 : *up_bound = NULL_TREE;
188 : 713 : *up_bound_p1 = NULL_TREE;
189 : : }
190 : : else
191 : : {
192 : 73739 : tree ptrdiff_max = TYPE_MAX_VALUE (ptrdiff_type_node);
193 : 73739 : tree maxbound = ptrdiff_max;
194 : 73739 : tree arg = TREE_OPERAND (ref, 0);
195 : :
196 : 73739 : const bool compref = TREE_CODE (arg) == COMPONENT_REF;
197 : 73739 : if (compref)
198 : : {
199 : : /* Try to determine the size of the trailing array from
200 : : its initializer (if it has one). */
201 : 64820 : if (tree refsize = component_ref_size (arg))
202 : 6458 : if (TREE_CODE (refsize) == INTEGER_CST)
203 : 73739 : maxbound = refsize;
204 : : }
205 : :
206 : 73739 : if (maxbound == ptrdiff_max)
207 : : {
208 : : /* Try to determine the size of the base object. Avoid
209 : : COMPONENT_REF already tried above. Using its DECL_SIZE
210 : : size wouldn't necessarily be correct if the reference is
211 : : to its flexible array member initialized in a different
212 : : translation unit. */
213 : 67284 : poly_int64 off;
214 : 67284 : if (tree base = get_addr_base_and_unit_offset (arg, &off))
215 : : {
216 : 66908 : if (TREE_CODE (base) == MEM_REF)
217 : : {
218 : : /* Try to determine the size from a pointer to
219 : : an array if BASE is one. */
220 : 58882 : if (tree size = get_ref_size (base, decl))
221 : 66908 : maxbound = size;
222 : : }
223 : 8026 : else if (!compref && DECL_P (base))
224 : 7981 : if (tree basesize = DECL_SIZE_UNIT (base))
225 : 152 : if (TREE_CODE (basesize) == INTEGER_CST)
226 : : {
227 : 152 : maxbound = basesize;
228 : 152 : *decl = base;
229 : : }
230 : :
231 : 66908 : if (known_gt (off, 0))
232 : 58167 : maxbound = wide_int_to_tree (sizetype,
233 : 116334 : wi::sub (wi::to_wide (maxbound),
234 : : off));
235 : : }
236 : : }
237 : : else
238 : 6455 : maxbound = fold_convert (sizetype, maxbound);
239 : :
240 : 73739 : *up_bound_p1 = int_const_binop (TRUNC_DIV_EXPR, maxbound, eltsize);
241 : :
242 : 73739 : if (*up_bound_p1 != NULL_TREE)
243 : 73739 : *up_bound = int_const_binop (MINUS_EXPR, *up_bound_p1,
244 : 147478 : build_int_cst (ptrdiff_type_node, 1));
245 : : else
246 : 0 : *up_bound = NULL_TREE;
247 : : }
248 : : }
249 : : else
250 : 144402 : *up_bound_p1 = int_const_binop (PLUS_EXPR, *up_bound,
251 : 288804 : build_int_cst (TREE_TYPE (*up_bound), 1));
252 : 218854 : return;
253 : : }
254 : :
255 : : /* Given the LOW_SUB_ORG, LOW_SUB and UP_SUB, and the computed UP_BOUND
256 : : and UP_BOUND_P1, check whether the array reference REF is out of bound.
257 : : When out of bounds, set OUT_OF_BOUND to true.
258 : : Issue warnings if FOR_ARRAY_BOUND is true.
259 : : return TRUE if warnings are issued. */
260 : :
261 : : static bool
262 : 218854 : check_out_of_bounds_and_warn (location_t location, tree ref,
263 : : tree low_sub_org, tree low_sub, tree up_sub,
264 : : tree up_bound, tree up_bound_p1,
265 : : const value_range *vr,
266 : : bool ignore_off_by_one, bool for_array_bound,
267 : : bool *out_of_bound)
268 : : {
269 : 218854 : tree min, max;
270 : 218854 : tree low_bound = array_ref_low_bound (ref);
271 : 218854 : tree artype = TREE_TYPE (TREE_OPERAND (ref, 0));
272 : :
273 : 218854 : bool warned = false;
274 : 218854 : *out_of_bound = false;
275 : :
276 : : /* Empty array. */
277 : 218854 : if (up_bound && tree_int_cst_equal (low_bound, up_bound_p1))
278 : : {
279 : 284 : *out_of_bound = true;
280 : 284 : if (for_array_bound)
281 : 283 : warned = warning_at (location, OPT_Warray_bounds_,
282 : : "array subscript %E is outside array"
283 : : " bounds of %qT", low_sub_org, artype);
284 : : }
285 : :
286 : 283 : if (warned)
287 : : ; /* Do nothing. */
288 : 218571 : else if (get_legacy_range (*vr, min, max) == VR_ANTI_RANGE)
289 : : {
290 : 1214 : if (up_bound
291 : 1214 : && TREE_CODE (up_sub) == INTEGER_CST
292 : 73 : && (ignore_off_by_one
293 : 1214 : ? tree_int_cst_lt (up_bound, up_sub)
294 : 1141 : : tree_int_cst_le (up_bound, up_sub))
295 : 685 : && TREE_CODE (low_sub) == INTEGER_CST
296 : 3113 : && tree_int_cst_le (low_sub, low_bound))
297 : : {
298 : 2 : *out_of_bound = true;
299 : 2 : if (for_array_bound)
300 : 2 : warned = warning_at (location, OPT_Warray_bounds_,
301 : : "array subscript [%E, %E] is outside "
302 : : "array bounds of %qT",
303 : : low_sub, up_sub, artype);
304 : : }
305 : : }
306 : 217357 : else if (up_bound
307 : 216644 : && TREE_CODE (up_sub) == INTEGER_CST
308 : 438266 : && (ignore_off_by_one
309 : 212582 : ? !tree_int_cst_le (up_sub, up_bound_p1)
310 : 204255 : : !tree_int_cst_le (up_sub, up_bound)))
311 : : {
312 : 753 : *out_of_bound = true;
313 : 753 : if (for_array_bound)
314 : 748 : warned = warning_at (location, OPT_Warray_bounds_,
315 : : "array subscript %E is above array bounds of %qT",
316 : : up_sub, artype);
317 : : }
318 : 216604 : else if (TREE_CODE (low_sub) == INTEGER_CST
319 : 216604 : && tree_int_cst_lt (low_sub, low_bound))
320 : : {
321 : 314 : *out_of_bound = true;
322 : 314 : if (for_array_bound)
323 : 314 : warned = warning_at (location, OPT_Warray_bounds_,
324 : : "array subscript %E is below array bounds of %qT",
325 : : low_sub, artype);
326 : : }
327 : 218854 : return warned;
328 : : }
329 : :
330 : : /* Checks one ARRAY_REF in REF, located at LOCUS. Ignores flexible
331 : : arrays and "struct" hacks. If VRP can determine that the array
332 : : subscript is a constant, check if it is outside valid range. If
333 : : the array subscript is a RANGE, warn if it is non-overlapping with
334 : : valid range. IGNORE_OFF_BY_ONE is true if the ARRAY_REF is inside
335 : : a ADDR_EXPR. Return true if a warning has been issued or if
336 : : no-warning is set. */
337 : :
338 : : bool
339 : 218952 : array_bounds_checker::check_array_ref (location_t location, tree ref,
340 : : gimple *stmt, bool ignore_off_by_one)
341 : : {
342 : 218952 : if (warning_suppressed_p (ref, OPT_Warray_bounds_))
343 : : /* Return true to have the caller prevent warnings for enclosing
344 : : refs. */
345 : : return true;
346 : :
347 : : /* Upper bound and Upper bound plus one for -Warray-bounds. */
348 : 218854 : tree up_bound = array_ref_up_bound (ref);
349 : 218854 : tree up_bound_p1 = NULL_TREE;
350 : :
351 : : /* Referenced decl if one can be determined. */
352 : 218854 : tree decl = NULL_TREE;
353 : :
354 : : /* Set to the type of the special array member for a COMPONENT_REF. */
355 : 218854 : special_array_member sam{ };
356 : 218854 : tree afield_decl = NULL_TREE;
357 : 218854 : tree arg = TREE_OPERAND (ref, 0);
358 : :
359 : 218854 : if (TREE_CODE (arg) == COMPONENT_REF)
360 : : {
361 : : /* Try to determine special array member type for this COMPONENT_REF. */
362 : 93426 : sam = component_ref_sam_type (arg);
363 : 93426 : afield_decl = TREE_OPERAND (arg, 1);
364 : : }
365 : :
366 : 218854 : get_up_bounds_for_array_ref (ref, &decl, &up_bound, &up_bound_p1);
367 : :
368 : 218854 : bool warned = false;
369 : 218854 : bool out_of_bound = false;
370 : :
371 : 218854 : tree artype = TREE_TYPE (TREE_OPERAND (ref, 0));
372 : 218854 : tree low_sub_org = TREE_OPERAND (ref, 1);
373 : 218854 : tree up_sub = low_sub_org;
374 : 218854 : tree low_sub = low_sub_org;
375 : :
376 : 218854 : value_range vr;
377 : 218854 : if (TREE_CODE (low_sub_org) == SSA_NAME)
378 : : {
379 : 118453 : get_value_range (vr, low_sub_org, stmt);
380 : 118453 : if (!vr.undefined_p () && !vr.varying_p ())
381 : : {
382 : 114329 : tree min, max;
383 : 114329 : value_range_kind kind = get_legacy_range (vr, min, max);
384 : 114329 : low_sub = kind == VR_RANGE ? max : min;
385 : 114329 : up_sub = kind == VR_RANGE ? min : max;
386 : : }
387 : : }
388 : :
389 : 437708 : warned = check_out_of_bounds_and_warn (location, ref,
390 : : low_sub_org, low_sub, up_sub,
391 : : up_bound, up_bound_p1, &vr,
392 : 218854 : ignore_off_by_one, warn_array_bounds,
393 : : &out_of_bound);
394 : :
395 : :
396 : 218854 : if (!warned && sam == special_array_member::int_0)
397 : 39 : warned = warning_at (location, OPT_Wzero_length_bounds,
398 : 39 : (TREE_CODE (low_sub) == INTEGER_CST
399 : : ? G_("array subscript %E is outside the bounds "
400 : : "of an interior zero-length array %qT")
401 : : : G_("array subscript %qE is outside the bounds "
402 : : "of an interior zero-length array %qT")),
403 : : low_sub, artype);
404 : :
405 : 218854 : if (warned && dump_file && (dump_flags & TDF_DETAILS))
406 : : {
407 : 0 : fprintf (dump_file, "Array bound warning for ");
408 : 0 : dump_generic_expr (MSG_NOTE, TDF_SLIM, ref);
409 : 0 : fprintf (dump_file, "\n");
410 : : }
411 : :
412 : : /* Issue warnings for -Wstrict-flex-arrays according to the level of
413 : : flag_strict_flex_arrays. */
414 : 1353 : if (out_of_bound && warn_strict_flex_arrays
415 : 18 : && (sam == special_array_member::trail_0
416 : : || sam == special_array_member::trail_1
417 : 18 : || sam == special_array_member::trail_n)
418 : 218872 : && DECL_NOT_FLEXARRAY (afield_decl))
419 : : {
420 : 18 : bool warned1
421 : 18 : = warning_at (location, OPT_Wstrict_flex_arrays,
422 : : "trailing array %qT should not be used as "
423 : : "a flexible array member",
424 : : artype);
425 : :
426 : 18 : if (warned1 && dump_file && (dump_flags & TDF_DETAILS))
427 : : {
428 : 0 : fprintf (dump_file, "Trailing non flexible-like array bound warning for ");
429 : 0 : dump_generic_expr (MSG_NOTE, TDF_SLIM, ref);
430 : 0 : fprintf (dump_file, "\n");
431 : : }
432 : 18 : warned |= warned1;
433 : : }
434 : :
435 : 218854 : if (warned)
436 : : {
437 : : /* Avoid more warnings when checking more significant subscripts
438 : : of the same expression. */
439 : 1390 : ref = TREE_OPERAND (ref, 0);
440 : 1390 : suppress_warning (ref, OPT_Warray_bounds_);
441 : 1390 : suppress_warning (ref, OPT_Wstrict_flex_arrays);
442 : :
443 : 1390 : if (decl)
444 : 947 : ref = decl;
445 : :
446 : 1390 : tree rec = NULL_TREE;
447 : 1390 : if (TREE_CODE (ref) == COMPONENT_REF)
448 : : {
449 : : /* For a reference to a member of a struct object also mention
450 : : the object if it's known. It may be defined in a different
451 : : function than the out-of-bounds access. */
452 : 290 : rec = TREE_OPERAND (ref, 0);
453 : 290 : if (!VAR_P (rec))
454 : 205 : rec = NULL_TREE;
455 : 290 : ref = TREE_OPERAND (ref, 1);
456 : : }
457 : :
458 : 1390 : if (DECL_P (ref))
459 : 1279 : inform (DECL_SOURCE_LOCATION (ref), "while referencing %qD", ref);
460 : 1390 : if (rec && DECL_P (rec))
461 : 85 : inform (DECL_SOURCE_LOCATION (rec), "defined here %qD", rec);
462 : : }
463 : :
464 : 218854 : return warned;
465 : 218854 : }
466 : :
467 : : /* Checks one MEM_REF in REF, located at LOCATION, for out-of-bounds
468 : : references to string constants. If VRP can determine that the array
469 : : subscript is a constant, check if it is outside valid range.
470 : : If the array subscript is a RANGE, warn if it is non-overlapping
471 : : with valid range.
472 : : IGNORE_OFF_BY_ONE is true if the MEM_REF is inside an ADDR_EXPR
473 : : (used to allow one-past-the-end indices for code that takes
474 : : the address of the just-past-the-end element of an array).
475 : : Returns true if a warning has been issued. */
476 : :
477 : : bool
478 : 585244 : array_bounds_checker::check_mem_ref (location_t location, tree ref,
479 : : bool ignore_off_by_one)
480 : : {
481 : 585244 : if (warning_suppressed_p (ref, OPT_Warray_bounds_))
482 : : return false;
483 : :
484 : : /* The statement used to allocate the array or null. */
485 : 585167 : gimple *alloc_stmt = NULL;
486 : : /* For an allocation statement, the low bound of the size range. */
487 : 585167 : offset_int minbound = 0;
488 : : /* The type and size of the access. */
489 : 585167 : tree axstype = TREE_TYPE (ref);
490 : 585167 : offset_int axssize = 0;
491 : 585167 : if (tree access_size = TYPE_SIZE_UNIT (axstype))
492 : 584388 : if (TREE_CODE (access_size) == INTEGER_CST)
493 : 583438 : axssize = wi::to_offset (access_size);
494 : :
495 : 585167 : access_ref aref;
496 : 585167 : if (!m_ptr_qry.get_ref (ref, m_stmt, &aref, 0))
497 : : return false;
498 : :
499 : 585163 : if (aref.offset_in_range (axssize))
500 : : return false;
501 : :
502 : 11139 : if (TREE_CODE (aref.ref) == SSA_NAME)
503 : : {
504 : 682 : gimple *def = SSA_NAME_DEF_STMT (aref.ref);
505 : 682 : if (is_gimple_call (def))
506 : : {
507 : : /* Save the allocation call and the low bound on the size. */
508 : 645 : alloc_stmt = def;
509 : 645 : minbound = aref.sizrng[0];
510 : : }
511 : : }
512 : :
513 : : /* The range of the byte offset into the reference. Adjusted below. */
514 : 11139 : offset_int offrange[2] = { aref.offrng[0], aref.offrng[1] };
515 : :
516 : : /* The type of the referenced object. */
517 : 11139 : tree reftype = TREE_TYPE (aref.ref);
518 : : /* The size of the referenced array element. */
519 : 11139 : offset_int eltsize = 1;
520 : 11139 : if (POINTER_TYPE_P (reftype))
521 : 705 : reftype = TREE_TYPE (reftype);
522 : :
523 : 11139 : if (TREE_CODE (reftype) == FUNCTION_TYPE)
524 : : /* Restore the original (pointer) type and avoid trying to create
525 : : an array of functions (done below). */
526 : 10 : reftype = TREE_TYPE (aref.ref);
527 : : else
528 : : {
529 : : /* The byte size of the array has already been determined above
530 : : based on a pointer ARG. Set ELTSIZE to the size of the type
531 : : it points to and REFTYPE to the array with the size, rounded
532 : : down as necessary. */
533 : 11129 : if (TREE_CODE (reftype) == ARRAY_TYPE)
534 : 10153 : reftype = TREE_TYPE (reftype);
535 : 11129 : if (tree refsize = TYPE_SIZE_UNIT (reftype))
536 : 11125 : if (TREE_CODE (refsize) == INTEGER_CST)
537 : 11108 : eltsize = wi::to_offset (refsize);
538 : :
539 : 11129 : const offset_int nelts = aref.sizrng[1] / eltsize;
540 : 11129 : reftype = build_printable_array_type (reftype, nelts.to_uhwi ());
541 : : }
542 : :
543 : : /* Compute the more permissive upper bound when IGNORE_OFF_BY_ONE
544 : : is set (when taking the address of the one-past-last element
545 : : of an array) but always use the stricter bound in diagnostics. */
546 : 11139 : offset_int ubound = aref.sizrng[1];
547 : 11139 : if (ignore_off_by_one)
548 : 9800 : ubound += eltsize;
549 : :
550 : : /* Set if the lower bound of the subscript is out of bounds. */
551 : 11139 : const bool lboob = (aref.sizrng[1] == 0
552 : 10861 : || offrange[0] >= ubound
553 : 21609 : || offrange[1] < 0);
554 : : /* Set if only the upper bound of the subscript is out of bounds.
555 : : This can happen when using a bigger type to index into an array
556 : : of a smaller type, as is common with unsigned char. */
557 : 11139 : const bool uboob = !lboob && offrange[0] + axssize > ubound;
558 : 11139 : if (lboob || uboob)
559 : : {
560 : : /* Treat a reference to a non-array object as one to an array
561 : : of a single element. */
562 : 10420 : if (TREE_CODE (reftype) != ARRAY_TYPE)
563 : 10 : reftype = build_printable_array_type (reftype, 1);
564 : :
565 : : /* Extract the element type out of MEM_REF and use its size
566 : : to compute the index to print in the diagnostic; arrays
567 : : in MEM_REF don't mean anything. A type with no size like
568 : : void is as good as having a size of 1. */
569 : 10420 : tree type = strip_array_types (TREE_TYPE (ref));
570 : 10420 : if (tree size = TYPE_SIZE_UNIT (type))
571 : : {
572 : 10419 : offrange[0] = offrange[0] / wi::to_offset (size);
573 : 10419 : offrange[1] = offrange[1] / wi::to_offset (size);
574 : : }
575 : : }
576 : :
577 : 20694 : bool warned = false;
578 : 10420 : if (lboob)
579 : : {
580 : 865 : if (offrange[0] == offrange[1])
581 : 751 : warned = warning_at (location, OPT_Warray_bounds_,
582 : : "array subscript %wi is outside array bounds "
583 : : "of %qT",
584 : : offrange[0].to_shwi (), reftype);
585 : : else
586 : 114 : warned = warning_at (location, OPT_Warray_bounds_,
587 : : "array subscript [%wi, %wi] is outside "
588 : : "array bounds of %qT",
589 : : offrange[0].to_shwi (),
590 : : offrange[1].to_shwi (), reftype);
591 : : }
592 : 10274 : else if (uboob && !ignore_off_by_one)
593 : : {
594 : 553 : tree backtype = reftype;
595 : 553 : if (alloc_stmt)
596 : : /* If the memory was dynamically allocated refer to it as if
597 : : it were an untyped array of bytes. */
598 : 381 : backtype = build_array_type_nelts (unsigned_char_type_node,
599 : 381 : aref.sizrng[1].to_uhwi ());
600 : :
601 : 553 : warned = warning_at (location, OPT_Warray_bounds_,
602 : : "array subscript %<%T[%wi]%> is partly "
603 : : "outside array bounds of %qT",
604 : : axstype, offrange[0].to_shwi (), backtype);
605 : : }
606 : :
607 : 1418 : if (warned)
608 : : {
609 : : /* TODO: Determine the access from the statement and use it. */
610 : 1413 : aref.inform_access (access_none);
611 : 1413 : suppress_warning (ref, OPT_Warray_bounds_);
612 : 1413 : return true;
613 : : }
614 : :
615 : 9726 : if (warn_array_bounds < 2)
616 : : return false;
617 : :
618 : : /* At level 2 check also intermediate offsets. */
619 : 20 : int i = 0;
620 : 20 : if (aref.offmax[i] < -aref.sizrng[1] || aref.offmax[i = 1] > ubound)
621 : : {
622 : 4 : HOST_WIDE_INT tmpidx = (aref.offmax[i] / eltsize).to_shwi ();
623 : :
624 : 4 : if (warning_at (location, OPT_Warray_bounds_,
625 : : "intermediate array offset %wi is outside array bounds "
626 : : "of %qT", tmpidx, reftype))
627 : : {
628 : 3 : suppress_warning (ref, OPT_Warray_bounds_);
629 : 3 : return true;
630 : : }
631 : : }
632 : :
633 : : return false;
634 : : }
635 : :
636 : : /* Searches if the expr T, located at LOCATION computes
637 : : address of an ARRAY_REF, and call check_array_ref on it. */
638 : :
639 : : void
640 : 856346 : array_bounds_checker::check_addr_expr (location_t location, tree t,
641 : : gimple *stmt)
642 : : {
643 : : /* For the most significant subscript only, accept taking the address
644 : : of the just-past-the-end element. */
645 : 856346 : bool ignore_off_by_one = true;
646 : :
647 : : /* Check each ARRAY_REF and MEM_REF in the reference chain. */
648 : 993378 : do
649 : : {
650 : 993378 : bool warned = false;
651 : 993378 : if (TREE_CODE (t) == ARRAY_REF)
652 : : {
653 : 14354 : warned = check_array_ref (location, t, stmt, ignore_off_by_one);
654 : 14354 : ignore_off_by_one = false;
655 : : }
656 : 979024 : else if (TREE_CODE (t) == MEM_REF)
657 : 52599 : warned = check_mem_ref (location, t, ignore_off_by_one);
658 : :
659 : 66953 : if (warned)
660 : 199 : suppress_warning (t, OPT_Warray_bounds_);
661 : :
662 : 993378 : t = TREE_OPERAND (t, 0);
663 : : }
664 : 1130410 : while (handled_component_p (t) || TREE_CODE (t) == MEM_REF);
665 : :
666 : 856346 : if (TREE_CODE (t) != MEM_REF
667 : 0 : || TREE_CODE (TREE_OPERAND (t, 0)) != ADDR_EXPR
668 : 856346 : || warning_suppressed_p (t, OPT_Warray_bounds_))
669 : 856346 : return;
670 : :
671 : 0 : tree tem = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
672 : 0 : tree low_bound, up_bound, el_sz;
673 : 0 : if (TREE_CODE (TREE_TYPE (tem)) != ARRAY_TYPE
674 : 0 : || TREE_CODE (TREE_TYPE (TREE_TYPE (tem))) == ARRAY_TYPE
675 : 0 : || !TYPE_DOMAIN (TREE_TYPE (tem)))
676 : : return;
677 : :
678 : 0 : low_bound = TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (tem)));
679 : 0 : up_bound = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (tem)));
680 : 0 : el_sz = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (tem)));
681 : 0 : if (!low_bound
682 : 0 : || TREE_CODE (low_bound) != INTEGER_CST
683 : 0 : || !up_bound
684 : 0 : || TREE_CODE (up_bound) != INTEGER_CST
685 : 0 : || !el_sz
686 : 0 : || TREE_CODE (el_sz) != INTEGER_CST)
687 : : return;
688 : :
689 : 0 : offset_int idx;
690 : 0 : if (!mem_ref_offset (t).is_constant (&idx))
691 : : return;
692 : :
693 : 0 : bool warned = false;
694 : 0 : idx = wi::sdiv_trunc (idx, wi::to_offset (el_sz));
695 : 0 : if (idx < 0)
696 : : {
697 : 0 : if (dump_file && (dump_flags & TDF_DETAILS))
698 : : {
699 : 0 : fprintf (dump_file, "Array bound warning for ");
700 : 0 : dump_generic_expr (MSG_NOTE, TDF_SLIM, t);
701 : 0 : fprintf (dump_file, "\n");
702 : : }
703 : 0 : warned = warning_at (location, OPT_Warray_bounds_,
704 : : "array subscript %wi is below "
705 : : "array bounds of %qT",
706 : 0 : idx.to_shwi (), TREE_TYPE (tem));
707 : : }
708 : 0 : else if (idx > (wi::to_offset (up_bound)
709 : 0 : - wi::to_offset (low_bound) + 1))
710 : : {
711 : 0 : if (dump_file && (dump_flags & TDF_DETAILS))
712 : : {
713 : 0 : fprintf (dump_file, "Array bound warning for ");
714 : 0 : dump_generic_expr (MSG_NOTE, TDF_SLIM, t);
715 : 0 : fprintf (dump_file, "\n");
716 : : }
717 : 0 : warned = warning_at (location, OPT_Warray_bounds_,
718 : : "array subscript %wu is above "
719 : : "array bounds of %qT",
720 : 0 : idx.to_uhwi (), TREE_TYPE (tem));
721 : : }
722 : :
723 : 0 : if (warned)
724 : : {
725 : 0 : if (DECL_P (t))
726 : 0 : inform (DECL_SOURCE_LOCATION (t), "while referencing %qD", t);
727 : :
728 : 0 : suppress_warning (t, OPT_Warray_bounds_);
729 : : }
730 : : }
731 : :
732 : : /* Return true if T is a reference to a member of a base class that's within
733 : : the bounds of the enclosing complete object. The function "hacks" around
734 : : problems discussed in pr98266 and pr97595. */
735 : :
736 : : static bool
737 : 9880631 : inbounds_memaccess_p (tree t, gimple *stmt)
738 : : {
739 : 9880631 : if (TREE_CODE (t) != COMPONENT_REF)
740 : : return false;
741 : :
742 : 677555 : tree mref = TREE_OPERAND (t, 0);
743 : 677555 : if (TREE_CODE (mref) != MEM_REF)
744 : : return false;
745 : :
746 : : /* Consider the access if its type is a derived class. */
747 : 397155 : tree mreftype = TREE_TYPE (mref);
748 : 397155 : if (!RECORD_OR_UNION_TYPE_P (mreftype)
749 : 397155 : || !TYPE_BINFO (mreftype))
750 : : return false;
751 : :
752 : : /* Compute the size of the referenced object (it could be dynamically
753 : : allocated). */
754 : 203647 : access_ref aref; // unused
755 : 203647 : tree refop = TREE_OPERAND (mref, 0);
756 : 203647 : tree refsize = compute_objsize (refop, stmt, 1, &aref);
757 : 203647 : if (!refsize || TREE_CODE (refsize) != INTEGER_CST)
758 : : return false;
759 : :
760 : : /* Compute the byte offset of the member within its enclosing class. */
761 : 203647 : tree fld = TREE_OPERAND (t, 1);
762 : 203647 : tree fldpos = byte_position (fld);
763 : 203647 : if (TREE_CODE (fldpos) != INTEGER_CST)
764 : : return false;
765 : :
766 : : /* Compute the byte offset of the member with the outermost complete
767 : : object by adding its offset computed above to the MEM_REF offset. */
768 : 203647 : tree refoff = TREE_OPERAND (mref, 1);
769 : 203647 : tree fldoff = int_const_binop (PLUS_EXPR, fldpos, refoff);
770 : : /* Return false if the member offset is greater or equal to the size
771 : : of the complete object. */
772 : 203647 : if (!tree_int_cst_lt (fldoff, refsize))
773 : : return false;
774 : :
775 : 200655 : tree fldsiz = DECL_SIZE_UNIT (fld);
776 : 200655 : if (!fldsiz || TREE_CODE (fldsiz) != INTEGER_CST)
777 : : return false;
778 : :
779 : : /* Return true if the offset just past the end of the member is less
780 : : than or equal to the size of the complete object. */
781 : 200447 : tree fldend = int_const_binop (PLUS_EXPR, fldoff, fldsiz);
782 : 200447 : return tree_int_cst_le (fldend, refsize);
783 : : }
784 : :
785 : : /* Callback for walk_tree to check a tree for out of bounds array
786 : : accesses. The array_bounds_checker class is passed in DATA. */
787 : :
788 : : tree
789 : 11474220 : array_bounds_checker::check_array_bounds (tree *tp, int *walk_subtree,
790 : : void *data)
791 : : {
792 : 11474220 : tree t = *tp;
793 : 11474220 : struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
794 : :
795 : 11474220 : location_t location;
796 : :
797 : 11474220 : if (EXPR_HAS_LOCATION (t))
798 : 1592435 : location = EXPR_LOCATION (t);
799 : : else
800 : 9881785 : location = gimple_location (wi->stmt);
801 : :
802 : 11474220 : *walk_subtree = true;
803 : :
804 : 11474220 : bool warned = false;
805 : 11474220 : array_bounds_checker *checker = (array_bounds_checker *) wi->info;
806 : 11474220 : gcc_assert (checker->m_stmt == wi->stmt);
807 : :
808 : 11474220 : if (TREE_CODE (t) == ARRAY_REF)
809 : 204598 : warned = checker->check_array_ref (location, t, wi->stmt,
810 : : false/*ignore_off_by_one*/);
811 : 11269622 : else if (TREE_CODE (t) == MEM_REF)
812 : 532645 : warned = checker->check_mem_ref (location, t,
813 : : false /*ignore_off_by_one*/);
814 : 10736977 : else if (TREE_CODE (t) == ADDR_EXPR)
815 : : {
816 : 856346 : checker->check_addr_expr (location, t, wi->stmt);
817 : 856346 : *walk_subtree = false;
818 : : }
819 : 9880631 : else if (inbounds_memaccess_p (t, wi->stmt))
820 : : /* Hack: Skip MEM_REF checks in accesses to a member of a base class
821 : : at an offset that's within the bounds of the enclosing object.
822 : : See pr98266 and pr97595. */
823 : 200339 : *walk_subtree = false;
824 : :
825 : : /* Propagate the no-warning bit to the outer statement to avoid also
826 : : issuing -Wstringop-overflow/-overread for the out-of-bounds accesses. */
827 : 1793928 : if (warned)
828 : 2705 : suppress_warning (wi->stmt, OPT_Warray_bounds_);
829 : :
830 : 11474220 : return NULL_TREE;
831 : : }
832 : :
833 : : /* A dom_walker subclass for use by check_all_array_refs, to walk over
834 : : all statements of all reachable BBs and call check_array_bounds on
835 : : them. */
836 : :
837 : : class check_array_bounds_dom_walker : public dom_walker
838 : : {
839 : : public:
840 : 106736 : check_array_bounds_dom_walker (array_bounds_checker *checker)
841 : 106736 : : dom_walker (CDI_DOMINATORS,
842 : : /* Discover non-executable edges, preserving EDGE_EXECUTABLE
843 : : flags, so that we can merge in information on
844 : : non-executable edges from vrp_folder . */
845 : : REACHABLE_BLOCKS_PRESERVING_FLAGS),
846 : 213472 : checker (checker) { }
847 : 213472 : ~check_array_bounds_dom_walker () {}
848 : :
849 : : edge before_dom_children (basic_block) final override;
850 : :
851 : : private:
852 : : array_bounds_checker *checker;
853 : : };
854 : :
855 : : /* Implementation of dom_walker::before_dom_children.
856 : :
857 : : Walk over all statements of BB and call check_array_bounds on them,
858 : : and determine if there's a unique successor edge. */
859 : :
860 : : edge
861 : 1045707 : check_array_bounds_dom_walker::before_dom_children (basic_block bb)
862 : : {
863 : 1045707 : gimple_stmt_iterator si;
864 : 10549993 : for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
865 : : {
866 : 8458579 : gimple *stmt = gsi_stmt (si);
867 : 8458579 : if (!gimple_has_location (stmt)
868 : 8458579 : || is_gimple_debug (stmt))
869 : 4843130 : continue;
870 : :
871 : 3615449 : struct walk_stmt_info wi{ };
872 : 3615449 : wi.info = checker;
873 : 3615449 : checker->m_stmt = stmt;
874 : :
875 : 3615449 : walk_gimple_op (stmt, array_bounds_checker::check_array_bounds, &wi);
876 : : }
877 : :
878 : : /* Determine if there's a unique successor edge, and if so, return
879 : : that back to dom_walker, ensuring that we don't visit blocks that
880 : : became unreachable during the VRP propagation
881 : : (PR tree-optimization/83312). */
882 : 1045707 : return find_taken_edge (bb, NULL_TREE);
883 : : }
884 : :
885 : : void
886 : 106736 : array_bounds_checker::check ()
887 : : {
888 : 106736 : check_array_bounds_dom_walker w (this);
889 : 106736 : w.walk (ENTRY_BLOCK_PTR_FOR_FN (fun));
890 : 106736 : }
|