Line data Source code
1 : /* Pass to detect and issue warnings for violations of the restrict
2 : qualifier.
3 : Copyright (C) 2017-2026 Free Software Foundation, Inc.
4 : Contributed by Martin Sebor <msebor@redhat.com>.
5 :
6 : This file is part of GCC.
7 :
8 : GCC is free software; you can redistribute it and/or modify it under
9 : the terms of the GNU General Public License as published by the Free
10 : Software Foundation; either version 3, or (at your option) any later
11 : version.
12 :
13 : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 : WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 : for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with GCC; see the file COPYING3. If not see
20 : <http://www.gnu.org/licenses/>. */
21 :
22 : #include "config.h"
23 : #include "system.h"
24 : #include "coretypes.h"
25 : #include "backend.h"
26 : #include "tree.h"
27 : #include "gimple.h"
28 : #include "tree-pass.h"
29 : #include "pointer-query.h"
30 : #include "ssa.h"
31 : #include "gimple-pretty-print.h"
32 : #include "gimple-ssa-warn-access.h"
33 : #include "gimple-ssa-warn-restrict.h"
34 : #include "diagnostic-core.h"
35 : #include "fold-const.h"
36 : #include "gimple-iterator.h"
37 : #include "tree-dfa.h"
38 : #include "tree-ssa.h"
39 : #include "tree-cfg.h"
40 : #include "tree-object-size.h"
41 : #include "calls.h"
42 : #include "cfgloop.h"
43 : #include "diagnostic-context-rich-location.h"
44 : #include "intl.h"
45 : #include "gimple-range.h"
46 :
47 : namespace {
48 :
49 : const pass_data pass_data_wrestrict = {
50 : GIMPLE_PASS,
51 : "wrestrict",
52 : OPTGROUP_NONE,
53 : TV_NONE,
54 : PROP_cfg, /* Properties_required. */
55 : 0, /* properties_provided. */
56 : 0, /* properties_destroyed. */
57 : 0, /* properties_start */
58 : 0, /* properties_finish */
59 : };
60 :
61 : /* Pass to detect violations of strict aliasing requirements in calls
62 : to built-in string and raw memory functions. */
63 : class pass_wrestrict : public gimple_opt_pass
64 : {
65 : public:
66 : pass_wrestrict (gcc::context *);
67 :
68 : bool gate (function *) final override;
69 : unsigned int execute (function *) final override;
70 :
71 : void check_call (gimple *);
72 :
73 : void check_block (basic_block);
74 :
75 : /* A pointer_query object to store information about pointers and
76 : their targets in. */
77 : pointer_query m_ptr_qry;
78 : };
79 :
80 285722 : pass_wrestrict::pass_wrestrict (gcc::context *ctxt)
81 : : gimple_opt_pass (pass_data_wrestrict, ctxt),
82 285722 : m_ptr_qry ()
83 285722 : { }
84 :
85 : bool
86 1041484 : pass_wrestrict::gate (function *fun ATTRIBUTE_UNUSED)
87 : {
88 1041484 : return warn_array_bounds || warn_restrict || warn_stringop_overflow;
89 : }
90 :
91 : void
92 9811418 : pass_wrestrict::check_block (basic_block bb)
93 : {
94 : /* Iterate over statements, looking for function calls. */
95 107618687 : for (auto si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
96 : {
97 87995851 : gimple *stmt = gsi_stmt (si);
98 87995851 : if (!is_gimple_call (stmt))
99 82905016 : continue;
100 :
101 5090835 : check_call (stmt);
102 : }
103 9811418 : }
104 :
105 : unsigned
106 1041298 : pass_wrestrict::execute (function *fun)
107 : {
108 : /* Create a new ranger instance and associate it with FUN. */
109 1041298 : m_ptr_qry.rvals = enable_ranger (fun);
110 1041298 : bool new_dominance_for_diagnostics = false;
111 :
112 1041298 : if (flag_diagnostics_show_context
113 1041298 : && !dom_info_available_p (fun, CDI_DOMINATORS))
114 : {
115 23 : calculate_dominance_info (CDI_DOMINATORS);
116 23 : new_dominance_for_diagnostics = true;
117 : }
118 :
119 1041298 : basic_block bb;
120 10852716 : FOR_EACH_BB_FN (bb, fun)
121 9811418 : check_block (bb);
122 :
123 1041298 : if (new_dominance_for_diagnostics
124 1041298 : && dom_info_available_p (fun, CDI_DOMINATORS))
125 23 : free_dominance_info (fun, CDI_DOMINATORS);
126 :
127 1041298 : m_ptr_qry.flush_cache ();
128 :
129 : /* Release the ranger instance and replace it with a global ranger.
130 : Also reset the pointer since calling disable_ranger() deletes it. */
131 1041298 : disable_ranger (fun);
132 1041298 : m_ptr_qry.rvals = NULL;
133 :
134 1041298 : return 0;
135 : }
136 :
137 : /* Description of a memory reference by a built-in function. This
138 : is similar to ao_ref but made especially suitable for -Wrestrict
139 : and not for optimization. */
140 : class builtin_memref
141 : {
142 : public:
143 : /* The original pointer argument to the built-in function. */
144 : tree ptr;
145 : /* The referenced subobject or NULL if not available, and the base
146 : object of the memory reference or NULL. */
147 : tree ref;
148 : tree base;
149 :
150 : /* The size of the BASE object, PTRDIFF_MAX if indeterminate,
151 : and negative until (possibly lazily) initialized. */
152 : offset_int basesize;
153 : /* Same for the subobject. */
154 : offset_int refsize;
155 :
156 : /* The non-negative offset of the referenced subobject. Used to avoid
157 : warnings for (apparently) possibly but not definitively overlapping
158 : accesses to member arrays. Negative when unknown/invalid. */
159 : offset_int refoff;
160 :
161 : /* The offset range relative to the base. */
162 : offset_int offrange[2];
163 : /* The size range of the access to this reference. */
164 : offset_int sizrange[2];
165 :
166 : /* Cached result of get_max_objsize(). */
167 : const offset_int maxobjsize;
168 :
169 : /* True for "bounded" string functions like strncat, and strncpy
170 : and their variants that specify either an exact or upper bound
171 : on the size of the accesses they perform. For strncat both
172 : the source and destination references are bounded. For strncpy
173 : only the destination reference is. */
174 : bool strbounded_p;
175 :
176 : builtin_memref (pointer_query &, gimple *, tree, tree);
177 :
178 : tree offset_out_of_bounds (int, offset_int[3]) const;
179 :
180 : private:
181 : /* Call statement to the built-in. */
182 : gimple *stmt;
183 :
184 : pointer_query &m_ptr_qry;
185 :
186 : /* Ctor helper to set or extend OFFRANGE based on argument. */
187 : void extend_offset_range (tree);
188 :
189 : /* Ctor helper to determine BASE and OFFRANGE from argument. */
190 : void set_base_and_offset (tree);
191 : };
192 :
193 : /* Description of a memory access by a raw memory or string built-in
194 : function involving a pair of builtin_memref's. */
195 : class builtin_access
196 : {
197 : public:
198 : /* Destination and source memory reference. */
199 : builtin_memref* const dstref;
200 : builtin_memref* const srcref;
201 : /* The size range of the access. It's the greater of the accesses
202 : to the two references. */
203 : HOST_WIDE_INT sizrange[2];
204 :
205 : /* The minimum and maximum offset of an overlap of the access
206 : (if it does, in fact, overlap), and the size of the overlap. */
207 : HOST_WIDE_INT ovloff[2];
208 : HOST_WIDE_INT ovlsiz[2];
209 :
210 : /* True to consider valid only accesses to the smallest subobject
211 : and false for raw memory functions. */
212 199276 : bool strict () const
213 : {
214 199276 : return (detect_overlap != &builtin_access::generic_overlap
215 63476 : && detect_overlap != &builtin_access::no_overlap);
216 : }
217 :
218 : builtin_access (pointer_query &, gimple *,
219 : builtin_memref &, builtin_memref &);
220 :
221 : /* Entry point to determine overlap. */
222 : bool overlap ();
223 :
224 : offset_int write_off (tree) const;
225 :
226 : void dump (FILE *) const;
227 :
228 : private:
229 : /* Implementation functions used to determine overlap. */
230 : bool generic_overlap ();
231 : bool strcat_overlap ();
232 : bool strcpy_overlap ();
233 :
234 0 : bool no_overlap ()
235 : {
236 0 : return false;
237 : }
238 :
239 : offset_int overlap_size (const offset_int [2], const offset_int[2],
240 : offset_int [2]);
241 :
242 : private:
243 : /* Temporaries used to compute the final result. */
244 : offset_int dstoff[2];
245 : offset_int srcoff[2];
246 : offset_int dstsiz[2];
247 : offset_int srcsiz[2];
248 :
249 : /* Pointer to a member function to call to determine overlap. */
250 : bool (builtin_access::*detect_overlap) ();
251 : };
252 :
253 : /* Initialize a memory reference representation from a pointer EXPR and
254 : a size SIZE in bytes. If SIZE is NULL_TREE then the size is assumed
255 : to be unknown. STMT is the statement in which expr appears in. */
256 :
257 398552 : builtin_memref::builtin_memref (pointer_query &ptrqry, gimple *stmt, tree expr,
258 398552 : tree size)
259 398552 : : ptr (expr),
260 398552 : ref (),
261 398552 : base (),
262 398552 : basesize (-1),
263 398552 : refsize (-1),
264 398552 : refoff (HOST_WIDE_INT_MIN),
265 398552 : offrange (),
266 398552 : sizrange (),
267 398552 : maxobjsize (tree_to_shwi (max_object_size ())),
268 398552 : strbounded_p (),
269 398552 : stmt (stmt),
270 398552 : m_ptr_qry (ptrqry)
271 : {
272 : /* Unfortunately, wide_int default ctor is a no-op so array members
273 : of the type must be set individually. */
274 398552 : offrange[0] = offrange[1] = 0;
275 398552 : sizrange[0] = sizrange[1] = 0;
276 :
277 398552 : if (!expr)
278 271873 : return;
279 :
280 : /* Find the BASE object or pointer referenced by EXPR and set
281 : the offset range OFFRANGE in the process. */
282 366954 : set_base_and_offset (expr);
283 :
284 366954 : if (size)
285 : {
286 240555 : tree range[2];
287 : /* Determine the size range, allowing for the result to be [0, 0]
288 : for SIZE in the anti-range ~[0, N] where N >= PTRDIFF_MAX. */
289 240555 : get_size_range (m_ptr_qry.rvals, size, stmt, range, SR_ALLOW_ZERO);
290 240555 : sizrange[0] = wi::to_offset (range[0]);
291 240555 : sizrange[1] = wi::to_offset (range[1]);
292 : /* get_size_range returns SIZE_MAX for the maximum size.
293 : Constrain it to the real maximum of PTRDIFF_MAX. */
294 240555 : if (sizrange[0] <= maxobjsize && sizrange[1] > maxobjsize)
295 25645 : sizrange[1] = maxobjsize;
296 : }
297 : else
298 126399 : sizrange[1] = maxobjsize;
299 :
300 366954 : if (!DECL_P (base))
301 : return;
302 :
303 : /* If the offset could be in the range of the referenced object
304 : constrain its bounds so neither exceeds those of the object. */
305 126679 : if (offrange[0] < 0 && offrange[1] > 0)
306 1507 : offrange[0] = 0;
307 :
308 126679 : offset_int maxoff = maxobjsize;
309 126679 : tree basetype = TREE_TYPE (base);
310 126679 : if (TREE_CODE (basetype) == ARRAY_TYPE)
311 : {
312 73410 : if (ref && array_ref_flexible_size_p (ref))
313 : ; /* Use the maximum possible offset for an array that might
314 : have flexible size. */
315 70638 : else if (tree basesize = TYPE_SIZE_UNIT (basetype))
316 68989 : if (TREE_CODE (basesize) == INTEGER_CST)
317 : /* Size could be non-constant for a variable-length type such
318 : as a struct with a VLA member (a GCC extension). */
319 68989 : maxoff = wi::to_offset (basesize);
320 : }
321 :
322 126679 : if (offrange[0] >= 0)
323 : {
324 126544 : if (offrange[1] < 0)
325 544 : offrange[1] = offrange[0] <= maxoff ? maxoff : maxobjsize;
326 126000 : else if (offrange[0] <= maxoff && offrange[1] > maxoff)
327 1618 : offrange[1] = maxoff;
328 : }
329 : }
330 :
331 : /* Based on the initial length of the destination STARTLEN, returns
332 : the offset of the first write access from the beginning of
333 : the destination. Nonzero only for strcat-type of calls. */
334 :
335 199276 : offset_int builtin_access::write_off (tree startlen) const
336 : {
337 199276 : if (detect_overlap != &builtin_access::strcat_overlap
338 2856 : || !startlen || TREE_CODE (startlen) != INTEGER_CST)
339 198145 : return 0;
340 :
341 1131 : return wi::to_offset (startlen);
342 : }
343 :
344 : /* Ctor helper to set or extend OFFRANGE based on the OFFSET argument.
345 : Pointer offsets are represented as unsigned sizetype but must be
346 : treated as signed. */
347 :
348 : void
349 47539 : builtin_memref::extend_offset_range (tree offset)
350 : {
351 47539 : if (TREE_CODE (offset) == INTEGER_CST)
352 : {
353 17363 : offset_int off = int_cst_value (offset);
354 17363 : if (off != 0)
355 : {
356 9221 : offrange[0] += off;
357 9221 : offrange[1] += off;
358 : }
359 17363 : return;
360 : }
361 :
362 30176 : if (TREE_CODE (offset) == SSA_NAME)
363 : {
364 : /* A pointer offset is represented as sizetype but treated
365 : as signed. */
366 30102 : wide_int min, max;
367 30102 : value_range_kind rng = VR_VARYING;
368 30102 : int_range_max vr;
369 30102 : if (m_ptr_qry.rvals->range_of_expr (vr, offset, stmt))
370 : {
371 30102 : tree vr_min, vr_max;
372 30102 : rng = get_legacy_range (vr, vr_min, vr_max);
373 30102 : if (!vr.undefined_p ())
374 : {
375 30102 : min = wi::to_wide (vr_min);
376 30102 : max = wi::to_wide (vr_max);
377 : }
378 : }
379 :
380 30102 : if (rng == VR_ANTI_RANGE && wi::lts_p (max, min))
381 : {
382 : /* Convert an anti-range whose upper bound is less than
383 : its lower bound to a signed range. */
384 1008 : offrange[0] += offset_int::from (max + 1, SIGNED);
385 1008 : offrange[1] += offset_int::from (min - 1, SIGNED);
386 1008 : return;
387 : }
388 :
389 29094 : if (rng == VR_RANGE
390 29094 : && (DECL_P (base) || wi::lts_p (min, max)))
391 : {
392 : /* Preserve the bounds of the range for an offset into
393 : a known object (it may be adjusted later relative to
394 : a constant offset from its beginning). Otherwise use
395 : the bounds only when they are ascending when treated
396 : as signed. */
397 12065 : offrange[0] += offset_int::from (min, SIGNED);
398 12065 : offrange[1] += offset_int::from (max, SIGNED);
399 12065 : return;
400 : }
401 :
402 : /* Handle an anti-range the same as no range at all. */
403 17029 : gimple *stmt = SSA_NAME_DEF_STMT (offset);
404 17029 : tree type;
405 17029 : if (is_gimple_assign (stmt)
406 11318 : && (type = TREE_TYPE (gimple_assign_rhs1 (stmt)))
407 11318 : && INTEGRAL_TYPE_P (type)
408 28347 : && TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (offset)))
409 : {
410 11317 : tree_code code = gimple_assign_rhs_code (stmt);
411 11317 : if (code == NOP_EXPR)
412 : {
413 : /* Use the bounds of the type of the NOP_EXPR operand
414 : even if it's signed. The result doesn't trigger
415 : warnings but makes their output more readable. */
416 4570 : offrange[0] += wi::to_offset (TYPE_MIN_VALUE (type));
417 4570 : offrange[1] += wi::to_offset (TYPE_MAX_VALUE (type));
418 4570 : return;
419 : }
420 : }
421 30102 : }
422 :
423 12533 : const offset_int maxoff = tree_to_shwi (max_object_size ()) >> 1;
424 12533 : const offset_int minoff = -maxoff - 1;
425 :
426 12533 : offrange[0] += minoff;
427 12533 : offrange[1] += maxoff;
428 : }
429 :
430 : /* Determines the base object or pointer of the reference EXPR
431 : and the offset range from the beginning of the base. */
432 :
433 : void
434 408534 : builtin_memref::set_base_and_offset (tree expr)
435 : {
436 408534 : tree offset = NULL_TREE;
437 :
438 408534 : if (TREE_CODE (expr) == SSA_NAME)
439 : {
440 : /* Try to tease the offset out of the pointer. */
441 250362 : gimple *stmt = SSA_NAME_DEF_STMT (expr);
442 250362 : if (!base
443 208782 : && gimple_assign_single_p (stmt)
444 309203 : && gimple_assign_rhs_code (stmt) == ADDR_EXPR)
445 10419 : expr = gimple_assign_rhs1 (stmt);
446 239943 : else if (is_gimple_assign (stmt))
447 : {
448 118549 : tree_code code = gimple_assign_rhs_code (stmt);
449 118549 : if (CONVERT_EXPR_CODE_P (code))
450 : {
451 17616 : tree rhs = gimple_assign_rhs1 (stmt);
452 17616 : if (POINTER_TYPE_P (TREE_TYPE (rhs)))
453 : expr = gimple_assign_rhs1 (stmt);
454 : else
455 : {
456 17616 : base = expr;
457 202059 : return;
458 : }
459 : }
460 100933 : else if (code == POINTER_PLUS_EXPR)
461 : {
462 37884 : expr = gimple_assign_rhs1 (stmt);
463 37884 : offset = gimple_assign_rhs2 (stmt);
464 : }
465 : else
466 : {
467 63049 : base = expr;
468 63049 : return;
469 : }
470 : }
471 : else
472 : {
473 : /* FIXME: Handle PHI nodes in case like:
474 : _12 = &MEM[(void *)&a + 2B] + _10;
475 :
476 : <bb> [local count: 1073741824]:
477 : # prephitmp_13 = PHI <_12, &MEM[(void *)&a + 2B]>
478 : memcpy (prephitmp_13, p_7(D), 6); */
479 121394 : base = expr;
480 121394 : return;
481 : }
482 : }
483 :
484 206475 : if (TREE_CODE (expr) == ADDR_EXPR)
485 161298 : expr = TREE_OPERAND (expr, 0);
486 :
487 : /* Stash the reference for offset validation. */
488 206475 : ref = expr;
489 :
490 206475 : poly_int64 bitsize, bitpos;
491 206475 : tree var_off;
492 206475 : machine_mode mode;
493 206475 : int sign, reverse, vol;
494 :
495 : /* Determine the base object or pointer of the reference and
496 : the constant bit offset from the beginning of the base.
497 : If the offset has a non-constant component, it will be in
498 : VAR_OFF. MODE, SIGN, REVERSE, and VOL are write only and
499 : unused here. */
500 206475 : base = get_inner_reference (expr, &bitsize, &bitpos, &var_off,
501 : &mode, &sign, &reverse, &vol);
502 :
503 : /* get_inner_reference is not expected to return null. */
504 206475 : gcc_assert (base != NULL);
505 :
506 206475 : if (offset)
507 37884 : extend_offset_range (offset);
508 :
509 206475 : poly_int64 bytepos = exact_div (bitpos, BITS_PER_UNIT);
510 :
511 : /* Convert the poly_int64 offset to offset_int. The offset
512 : should be constant but be prepared for it not to be just in
513 : case. */
514 206475 : offset_int cstoff;
515 206475 : if (bytepos.is_constant (&cstoff))
516 : {
517 206475 : offrange[0] += cstoff;
518 206475 : offrange[1] += cstoff;
519 :
520 : /* Besides the reference saved above, also stash the offset
521 : for validation. */
522 206475 : if (TREE_CODE (expr) == COMPONENT_REF)
523 26986 : refoff = cstoff;
524 : }
525 : else
526 : offrange[1] += maxobjsize;
527 :
528 206475 : if (var_off)
529 : {
530 1938 : if (TREE_CODE (var_off) == INTEGER_CST)
531 : {
532 20 : cstoff = wi::to_offset (var_off);
533 20 : offrange[0] += cstoff;
534 20 : offrange[1] += cstoff;
535 : }
536 : else
537 1918 : offrange[1] += maxobjsize;
538 : }
539 :
540 206475 : if (TREE_CODE (base) == MEM_REF)
541 : {
542 9655 : tree memrefoff = fold_convert (ptrdiff_type_node, TREE_OPERAND (base, 1));
543 9655 : extend_offset_range (memrefoff);
544 :
545 13354 : if (refoff != HOST_WIDE_INT_MIN
546 9655 : && TREE_CODE (expr) == COMPONENT_REF)
547 : {
548 : /* Bump up the offset of the referenced subobject to reflect
549 : the offset to the enclosing object. For example, so that
550 : in
551 : struct S { char a, b[3]; } s[2];
552 : strcpy (s[1].b, "1234");
553 : REFOFF is set to s[1].b - (char*)s. */
554 5956 : offset_int off = tree_to_shwi (memrefoff);
555 5956 : refoff += off;
556 :
557 5956 : if (!integer_zerop (memrefoff)
558 1398 : && !COMPLETE_TYPE_P (TREE_TYPE (expr))
559 5963 : && multiple_of_p (sizetype, memrefoff,
560 7 : TYPE_SIZE_UNIT (TREE_TYPE (base)), true))
561 : /* A non-zero offset into an array of struct with flexible array
562 : members implies that the array is empty because there is no
563 : way to initialize such a member when it belongs to an array.
564 : This must be some sort of a bug. */
565 7 : refsize = 0;
566 : }
567 :
568 9655 : base = TREE_OPERAND (base, 0);
569 : }
570 :
571 206475 : if (TREE_CODE (ref) == COMPONENT_REF)
572 26986 : if (tree size = component_ref_size (ref))
573 26789 : if (TREE_CODE (size) == INTEGER_CST)
574 26771 : refsize = wi::to_offset (size);
575 :
576 206475 : if (TREE_CODE (base) == SSA_NAME)
577 41580 : set_base_and_offset (base);
578 : }
579 :
580 : /* Return error_mark_node if the signed offset exceeds the bounds
581 : of the address space (PTRDIFF_MAX). Otherwise, return either BASE
582 : or REF when the offset exceeds the bounds of the BASE or REF object,
583 : and set OOBOFF to the past-the-end offset formed by the reference,
584 : including its size. OOBOFF is initially setto the range of offsets,
585 : and OOBOFF[2] to the offset of the first write access (nonzero for
586 : the strcat family). When STRICT is nonzero use REF size, when
587 : available, otherwise use BASE size. When STRICT is greater than 1,
588 : use the size of the last array member as the bound, otherwise treat
589 : such a member as a flexible array member. Return NULL when the offset
590 : is in bounds. */
591 :
592 : tree
593 397569 : builtin_memref::offset_out_of_bounds (int strict, offset_int ooboff[3]) const
594 : {
595 397569 : if (!ptr)
596 : return NULL_TREE;
597 :
598 : /* The offset of the first write access or zero. */
599 366018 : offset_int wroff = ooboff[2];
600 :
601 : /* A temporary, possibly adjusted, copy of the offset range. */
602 366018 : offset_int offrng[2] = { ooboff[0], ooboff[1] };
603 :
604 366018 : if (DECL_P (base) && TREE_CODE (TREE_TYPE (base)) == ARRAY_TYPE)
605 : {
606 : /* Check for offset in an anti-range with a negative lower bound.
607 : For such a range, consider only the non-negative subrange. */
608 73152 : if (offrng[1] < offrng[0] && offrng[1] < 0)
609 0 : offrng[1] = maxobjsize;
610 : }
611 :
612 : /* Conservative offset of the last byte of the referenced object. */
613 366018 : offset_int endoff;
614 :
615 : /* The bounds need not be ordered. Set HIB to use as the index
616 : of the larger of the bounds and LOB as the opposite. */
617 366018 : bool hib = wi::les_p (offrng[0], offrng[1]);
618 366018 : bool lob = !hib;
619 :
620 : /* Set to the size remaining in the object after subtracting
621 : REFOFF. It may become negative as a result of negative indices
622 : into the enclosing object, such as in:
623 : extern struct S { char a[4], b[3], c[1]; } *p;
624 : strcpy (p[-3].b, "123"); */
625 366018 : offset_int size = basesize;
626 366018 : tree obj = base;
627 :
628 366018 : const bool decl_p = DECL_P (obj);
629 :
630 366018 : if (basesize < 0)
631 : {
632 183731 : endoff = offrng[lob] + (sizrange[0] - wroff);
633 :
634 : /* For a reference through a pointer to an object of unknown size
635 : all initial offsets are considered valid, positive as well as
636 : negative, since the pointer itself can point past the beginning
637 : of the object. However, the sum of the lower bound of the offset
638 : and that of the size must be less than or equal than PTRDIFF_MAX. */
639 183731 : if (endoff > maxobjsize)
640 73 : return error_mark_node;
641 :
642 : /* When the referenced subobject is known, the end offset must be
643 : within its bounds. Otherwise there is nothing to do. */
644 183658 : if (strict
645 183658 : && !decl_p
646 1692 : && ref
647 818 : && refsize >= 0
648 184346 : && TREE_CODE (ref) == COMPONENT_REF)
649 : {
650 : /* If REFOFF is negative, SIZE will become negative here. */
651 634 : size = refoff + refsize;
652 634 : obj = ref;
653 : }
654 : else
655 183024 : return NULL_TREE;
656 : }
657 :
658 : /* A reference to an object of known size must be within the bounds
659 : of either the base object or the subobject (see above for when
660 : a subobject can be used). */
661 182921 : if ((decl_p && offrng[hib] < 0) || offrng[lob] > size)
662 238 : return obj;
663 :
664 : /* The extent of the reference must also be within the bounds of
665 : the base object (if known) or the subobject or the maximum object
666 : size otherwise. */
667 182683 : endoff = offrng[lob] + sizrange[0];
668 182683 : if (endoff > maxobjsize)
669 21 : return error_mark_node;
670 :
671 182662 : if (strict
672 182662 : && decl_p
673 3446 : && ref
674 182688 : && refsize >= 0
675 183262 : && TREE_CODE (ref) == COMPONENT_REF)
676 : {
677 : /* If the reference is to a member subobject of a declared object,
678 : the offset must be within the bounds of the subobject. */
679 574 : size = refoff + refsize;
680 574 : obj = ref;
681 : }
682 :
683 182662 : if (endoff <= size)
684 : return NULL_TREE;
685 :
686 : /* Set the out-of-bounds offset range to be one greater than
687 : that delimited by the reference including its size. */
688 2145 : ooboff[lob] = size;
689 :
690 2145 : if (endoff > ooboff[lob])
691 2145 : ooboff[hib] = endoff - 1;
692 : else
693 0 : ooboff[hib] = offrng[lob] + sizrange[1];
694 :
695 : return obj;
696 : }
697 :
698 : /* Create an association between the memory references DST and SRC
699 : for access by a call EXPR to a memory or string built-in funtion. */
700 :
701 199276 : builtin_access::builtin_access (pointer_query &ptrqry, gimple *call,
702 : builtin_memref &dst,
703 199276 : builtin_memref &src)
704 199276 : : dstref (&dst), srcref (&src), sizrange (), ovloff (), ovlsiz (),
705 199276 : dstoff (), srcoff (), dstsiz (), srcsiz ()
706 : {
707 199276 : dstoff[0] = dst.offrange[0];
708 199276 : dstoff[1] = dst.offrange[1];
709 :
710 : /* Zero out since the offset_int ctors invoked above are no-op. */
711 199276 : srcoff[0] = srcoff[1] = 0;
712 199276 : dstsiz[0] = dstsiz[1] = 0;
713 199276 : srcsiz[0] = srcsiz[1] = 0;
714 :
715 : /* Object Size Type to use to determine the size of the destination
716 : and source objects. Overridden below for raw memory functions. */
717 199276 : int ostype = 1;
718 :
719 : /* True when the size of one reference depends on the offset of
720 : itself or the other. */
721 199276 : bool depends_p = true;
722 :
723 : /* True when the size of the destination reference DSTREF has been
724 : determined from SRCREF and so needs to be adjusted by the latter's
725 : offset. Only meaningful for bounded string functions like strncpy. */
726 199276 : bool dstadjust_p = false;
727 :
728 : /* The size argument number (depends on the built-in). */
729 199276 : unsigned sizeargno = 2;
730 :
731 199276 : tree func = gimple_call_fndecl (call);
732 199276 : switch (DECL_FUNCTION_CODE (func))
733 : {
734 135800 : case BUILT_IN_MEMCPY:
735 135800 : case BUILT_IN_MEMCPY_CHK:
736 135800 : case BUILT_IN_MEMPCPY:
737 135800 : case BUILT_IN_MEMPCPY_CHK:
738 135800 : ostype = 0;
739 135800 : depends_p = false;
740 135800 : detect_overlap = &builtin_access::generic_overlap;
741 135800 : break;
742 :
743 20394 : case BUILT_IN_MEMMOVE:
744 20394 : case BUILT_IN_MEMMOVE_CHK:
745 : /* For memmove there is never any overlap to check for. */
746 20394 : ostype = 0;
747 20394 : depends_p = false;
748 20394 : detect_overlap = &builtin_access::no_overlap;
749 20394 : break;
750 :
751 31591 : case BUILT_IN_MEMSET:
752 31591 : case BUILT_IN_MEMSET_CHK:
753 : /* For memset there is never any overlap to check for. */
754 31591 : ostype = 0;
755 31591 : depends_p = false;
756 31591 : detect_overlap = &builtin_access::no_overlap;
757 31591 : break;
758 :
759 4698 : case BUILT_IN_STPNCPY:
760 4698 : case BUILT_IN_STPNCPY_CHK:
761 4698 : case BUILT_IN_STRNCPY:
762 4698 : case BUILT_IN_STRNCPY_CHK:
763 4698 : dstref->strbounded_p = true;
764 4698 : detect_overlap = &builtin_access::strcpy_overlap;
765 4698 : break;
766 :
767 3937 : case BUILT_IN_STPCPY:
768 3937 : case BUILT_IN_STPCPY_CHK:
769 3937 : case BUILT_IN_STRCPY:
770 3937 : case BUILT_IN_STRCPY_CHK:
771 3937 : detect_overlap = &builtin_access::strcpy_overlap;
772 3937 : break;
773 :
774 1348 : case BUILT_IN_STRCAT:
775 1348 : case BUILT_IN_STRCAT_CHK:
776 1348 : detect_overlap = &builtin_access::strcat_overlap;
777 1348 : break;
778 :
779 1508 : case BUILT_IN_STRNCAT:
780 1508 : case BUILT_IN_STRNCAT_CHK:
781 1508 : dstref->strbounded_p = true;
782 1508 : srcref->strbounded_p = true;
783 1508 : detect_overlap = &builtin_access::strcat_overlap;
784 1508 : break;
785 :
786 : default:
787 : /* Handle other string functions here whose access may need
788 : to be validated for in-bounds offsets and non-overlapping
789 : copies. */
790 4 : return;
791 : }
792 :
793 : /* Try to determine the size of the base object. compute_objsize
794 : expects a pointer so create one if BASE is a non-pointer object. */
795 199276 : if (dst.basesize < 0)
796 : {
797 199276 : access_ref aref;
798 199276 : if (ptrqry.get_ref (dst.base, call, &aref, ostype) && aref.base0)
799 102827 : dst.basesize = aref.sizrng[1];
800 : else
801 96449 : dst.basesize = HOST_WIDE_INT_MIN;
802 : }
803 :
804 199276 : if (src.base && src.basesize < 0)
805 : {
806 167678 : access_ref aref;
807 167678 : if (ptrqry.get_ref (src.base, call, &aref, ostype) && aref.base0)
808 79827 : src.basesize = aref.sizrng[1];
809 : else
810 87851 : src.basesize = HOST_WIDE_INT_MIN;
811 : }
812 :
813 199276 : const offset_int maxobjsize = dst.maxobjsize;
814 :
815 : /* Make adjustments for references to the same object by string
816 : built-in functions to reflect the constraints imposed by
817 : the function. */
818 :
819 : /* For bounded string functions determine the range of the bound
820 : on the access. For others, the range stays unbounded. */
821 199276 : offset_int bounds[2] = { maxobjsize, maxobjsize };
822 199276 : if (dstref->strbounded_p)
823 : {
824 6206 : unsigned nargs = gimple_call_num_args (call);
825 6206 : if (nargs <= sizeargno)
826 4 : return;
827 :
828 6202 : tree size = gimple_call_arg (call, sizeargno);
829 6202 : tree range[2];
830 6202 : if (get_size_range (ptrqry.rvals, size, call, range, true))
831 : {
832 6202 : bounds[0] = wi::to_offset (range[0]);
833 6202 : bounds[1] = wi::to_offset (range[1]);
834 : }
835 :
836 : /* If both references' size ranges are indeterminate use the last
837 : (size) argument from the function call as a substitute. This
838 : may only be necessary for strncpy (but not for memcpy where
839 : the size range would have been already determined this way). */
840 10485 : if (dstref->sizrange[0] == 0 && dstref->sizrange[1] == maxobjsize
841 10485 : && srcref->sizrange[0] == 0 && srcref->sizrange[1] == maxobjsize)
842 : {
843 3346 : dstref->sizrange[0] = bounds[0];
844 3346 : dstref->sizrange[1] = bounds[1];
845 : }
846 : }
847 :
848 199272 : bool dstsize_set = false;
849 : /* The size range of one reference involving the same base object
850 : can be determined from the size range of the other reference.
851 : This makes it possible to compute accurate offsets for warnings
852 : involving functions like strcpy where the length of just one of
853 : the two arguments is known (determined by tree-ssa-strlen). */
854 199272 : if (dstref->sizrange[0] == 0 && dstref->sizrange[1] == maxobjsize)
855 : {
856 : /* When the destination size is unknown set it to the size of
857 : the source. */
858 17253 : dstref->sizrange[0] = srcref->sizrange[0];
859 17253 : dstref->sizrange[1] = srcref->sizrange[1];
860 17253 : dstsize_set = true;
861 : }
862 182019 : else if (srcref->sizrange[0] == 0 && srcref->sizrange[1] == maxobjsize)
863 : {
864 : /* When the size of the source access is unknown set it to the size
865 : of the destination first and adjust it later if necessary. */
866 108585 : srcref->sizrange[0] = dstref->sizrange[0];
867 108585 : srcref->sizrange[1] = dstref->sizrange[1];
868 :
869 108585 : if (depends_p)
870 : {
871 8869 : if (dstref->strbounded_p)
872 : {
873 : /* Read access by strncpy is constrained by the third
874 : argument but except for a zero bound is at least one. */
875 5924 : srcref->sizrange[0] = bounds[1] > 0 ? 1 : 0;
876 5860 : offset_int bound = wi::umin (srcref->basesize, bounds[1]);
877 5860 : if (bound < srcref->sizrange[1])
878 1214 : srcref->sizrange[1] = bound;
879 : }
880 : /* For string functions, adjust the size range of the source
881 : reference by the inverse boundaries of the offset (because
882 : the higher the offset into the string the shorter its
883 : length). */
884 8869 : if (srcref->offrange[1] >= 0
885 8869 : && srcref->offrange[1] < srcref->sizrange[0])
886 6008 : srcref->sizrange[0] -= srcref->offrange[1];
887 : else
888 2861 : srcref->sizrange[0] = 1;
889 :
890 8869 : if (srcref->offrange[0] > 0)
891 : {
892 2544 : if (srcref->offrange[0] < srcref->sizrange[1])
893 746 : srcref->sizrange[1] -= srcref->offrange[0];
894 : else
895 1798 : srcref->sizrange[1] = 0;
896 : }
897 :
898 : dstadjust_p = true;
899 : }
900 : }
901 :
902 199272 : if (detect_overlap == &builtin_access::generic_overlap)
903 : {
904 135800 : if (dstref->strbounded_p)
905 : {
906 0 : dstref->sizrange[0] = bounds[0];
907 0 : dstref->sizrange[1] = bounds[1];
908 :
909 0 : if (dstref->sizrange[0] < srcref->sizrange[0])
910 0 : srcref->sizrange[0] = dstref->sizrange[0];
911 :
912 0 : if (dstref->sizrange[1] < srcref->sizrange[1])
913 0 : srcref->sizrange[1] = dstref->sizrange[1];
914 : }
915 : }
916 63472 : else if (detect_overlap == &builtin_access::strcpy_overlap)
917 : {
918 8633 : if (!dstref->strbounded_p)
919 : {
920 : /* For strcpy, adjust the destination size range to match that
921 : of the source computed above. */
922 3937 : if (depends_p && dstadjust_p)
923 : {
924 2314 : dstref->sizrange[0] = srcref->sizrange[0];
925 2314 : dstref->sizrange[1] = srcref->sizrange[1];
926 : }
927 : }
928 : }
929 54839 : else if (!dstsize_set && detect_overlap == &builtin_access::strcat_overlap)
930 : {
931 2286 : dstref->sizrange[0] += srcref->sizrange[0] - 1;
932 2286 : dstref->sizrange[1] += srcref->sizrange[1] - 1;
933 : }
934 :
935 199272 : if (dstref->strbounded_p)
936 : {
937 : /* For strncpy, adjust the destination size range to match that
938 : of the source computed above. */
939 6202 : dstref->sizrange[0] = bounds[0];
940 6202 : dstref->sizrange[1] = bounds[1];
941 :
942 6202 : if (bounds[0] < srcref->sizrange[0])
943 2586 : srcref->sizrange[0] = bounds[0];
944 :
945 6202 : if (bounds[1] < srcref->sizrange[1])
946 192 : srcref->sizrange[1] = bounds[1];
947 : }
948 : }
949 :
950 : offset_int
951 6424 : builtin_access::overlap_size (const offset_int a[2], const offset_int b[2],
952 : offset_int *off)
953 : {
954 6424 : const offset_int *p = a;
955 6424 : const offset_int *q = b;
956 :
957 : /* Point P at the bigger of the two ranges and Q at the smaller. */
958 6424 : if (wi::lts_p (a[1] - a[0], b[1] - b[0]))
959 : {
960 328 : p = b;
961 328 : q = a;
962 : }
963 :
964 6424 : if (p[0] < q[0])
965 : {
966 3802 : if (p[1] < q[0])
967 248 : return 0;
968 :
969 3554 : *off = q[0];
970 3554 : return wi::smin (p[1], q[1]) - q[0];
971 : }
972 :
973 2622 : if (q[1] < p[0])
974 14 : return 0;
975 :
976 2608 : off[0] = p[0];
977 2608 : return q[1] - p[0];
978 : }
979 :
980 : /* Return true if the bounded mempry (memcpy amd similar) or string function
981 : access (strncpy and similar) ACS overlaps. */
982 :
983 : bool
984 2091 : builtin_access::generic_overlap ()
985 : {
986 2091 : builtin_access &acs = *this;
987 2091 : const builtin_memref *dstref = acs.dstref;
988 2091 : const builtin_memref *srcref = acs.srcref;
989 :
990 2091 : gcc_assert (dstref->base == srcref->base);
991 :
992 2091 : const offset_int maxobjsize = acs.dstref->maxobjsize;
993 :
994 2091 : offset_int maxsize = dstref->basesize < 0 ? maxobjsize : dstref->basesize;
995 :
996 : /* Adjust the larger bounds of the offsets (which may be the first
997 : element if the lower bound is larger than the upper bound) to
998 : make them valid for the smallest access (if possible) but no smaller
999 : than the smaller bounds. */
1000 2091 : gcc_assert (wi::les_p (acs.dstoff[0], acs.dstoff[1]));
1001 :
1002 2091 : if (maxsize < acs.dstoff[1] + acs.dstsiz[0])
1003 338 : acs.dstoff[1] = maxsize - acs.dstsiz[0];
1004 2091 : if (acs.dstoff[1] < acs.dstoff[0])
1005 11 : acs.dstoff[1] = acs.dstoff[0];
1006 :
1007 2091 : gcc_assert (wi::les_p (acs.srcoff[0], acs.srcoff[1]));
1008 :
1009 2091 : if (maxsize < acs.srcoff[1] + acs.srcsiz[0])
1010 182 : acs.srcoff[1] = maxsize - acs.srcsiz[0];
1011 2091 : if (acs.srcoff[1] < acs.srcoff[0])
1012 11 : acs.srcoff[1] = acs.srcoff[0];
1013 :
1014 : /* Determine the minimum and maximum space for the access given
1015 : the offsets. */
1016 2091 : offset_int space[2];
1017 2091 : space[0] = wi::abs (acs.dstoff[0] - acs.srcoff[0]);
1018 2091 : space[1] = space[0];
1019 :
1020 2091 : offset_int d = wi::abs (acs.dstoff[0] - acs.srcoff[1]);
1021 2091 : if (acs.srcsiz[0] > 0)
1022 : {
1023 2009 : if (d < space[0])
1024 102 : space[0] = d;
1025 :
1026 2009 : if (space[1] < d)
1027 382 : space[1] = d;
1028 : }
1029 : else
1030 82 : space[1] = acs.dstsiz[1];
1031 :
1032 2091 : d = wi::abs (acs.dstoff[1] - acs.srcoff[0]);
1033 2091 : if (d < space[0])
1034 61 : space[0] = d;
1035 :
1036 2091 : if (space[1] < d)
1037 333 : space[1] = d;
1038 :
1039 : /* Treat raw memory functions both of whose references are bounded
1040 : as special and permit uncertain overlaps to go undetected. For
1041 : all kinds of constant offset and constant size accesses, if
1042 : overlap isn't certain it is not possible. */
1043 2091 : bool overlap_possible = space[0] < acs.dstsiz[1];
1044 2091 : if (!overlap_possible)
1045 : return false;
1046 :
1047 811 : bool overlap_certain = space[1] < acs.dstsiz[0];
1048 :
1049 : /* True when the size of one reference depends on the offset of
1050 : the other. */
1051 811 : bool depends_p = detect_overlap != &builtin_access::generic_overlap;
1052 :
1053 811 : if (!overlap_certain)
1054 : {
1055 420 : if (!dstref->strbounded_p && !depends_p)
1056 : /* Memcpy only considers certain overlap. */
1057 : return false;
1058 :
1059 : /* There's no way to distinguish an access to the same member
1060 : of a structure from one to two distinct members of the same
1061 : structure. Give up to avoid excessive false positives. */
1062 149 : tree basetype = TREE_TYPE (dstref->base);
1063 :
1064 149 : if (POINTER_TYPE_P (basetype))
1065 16 : basetype = TREE_TYPE (basetype);
1066 : else
1067 274 : while (TREE_CODE (basetype) == ARRAY_TYPE)
1068 141 : basetype = TREE_TYPE (basetype);
1069 :
1070 149 : if (RECORD_OR_UNION_TYPE_P (basetype))
1071 : return false;
1072 : }
1073 :
1074 : /* True for stpcpy and strcpy. */
1075 996 : bool stxcpy_p = (!dstref->strbounded_p
1076 498 : && detect_overlap == &builtin_access::strcpy_overlap);
1077 :
1078 498 : if (dstref->refoff >= 0
1079 13 : && srcref->refoff >= 0
1080 5 : && dstref->refoff != srcref->refoff
1081 500 : && (stxcpy_p || dstref->strbounded_p || srcref->strbounded_p))
1082 2 : return false;
1083 :
1084 496 : offset_int siz[2] = { maxobjsize + 1, 0 };
1085 :
1086 496 : ovloff[0] = HOST_WIDE_INT_MAX;
1087 496 : ovloff[1] = HOST_WIDE_INT_MIN;
1088 :
1089 496 : if (stxcpy_p)
1090 : {
1091 : /* Iterate over the extreme locations (on the horizontal axis formed
1092 : by their offsets) and sizes of two regions and find their smallest
1093 : and largest overlap and the corresponding offsets. */
1094 324 : for (unsigned i = 0; i != 2; ++i)
1095 : {
1096 216 : const offset_int a[2] = {
1097 432 : acs.dstoff[i], acs.dstoff[i] + acs.dstsiz[!i]
1098 216 : };
1099 :
1100 216 : const offset_int b[2] = {
1101 432 : acs.srcoff[i], acs.srcoff[i] + acs.srcsiz[!i]
1102 216 : };
1103 :
1104 216 : offset_int off;
1105 216 : offset_int sz = overlap_size (a, b, &off);
1106 216 : if (sz < siz[0])
1107 182 : siz[0] = sz;
1108 :
1109 216 : if (siz[1] <= sz)
1110 142 : siz[1] = sz;
1111 :
1112 216 : if (sz != 0)
1113 : {
1114 162 : if (wi::lts_p (off, ovloff[0]))
1115 108 : ovloff[0] = off.to_shwi ();
1116 162 : if (wi::lts_p (ovloff[1], off))
1117 128 : ovloff[1] = off.to_shwi ();
1118 : }
1119 : }
1120 : }
1121 : else
1122 : {
1123 : /* Iterate over the extreme locations (on the horizontal axis
1124 : formed by their offsets) and sizes of the two regions and
1125 : find their smallest and largest overlap and the corresponding
1126 : offsets. */
1127 :
1128 1164 : for (unsigned io = 0; io != 2; ++io)
1129 2328 : for (unsigned is = 0; is != 2; ++is)
1130 : {
1131 1552 : const offset_int a[2] = {
1132 1552 : acs.dstoff[io], acs.dstoff[io] + acs.dstsiz[is]
1133 1552 : };
1134 :
1135 4656 : for (unsigned jo = 0; jo != 2; ++jo)
1136 9312 : for (unsigned js = 0; js != 2; ++js)
1137 : {
1138 6208 : const offset_int b[2] = {
1139 12416 : acs.srcoff[jo], acs.srcoff[jo] + acs.srcsiz[js]
1140 6208 : };
1141 :
1142 6208 : offset_int off;
1143 6208 : offset_int sz = overlap_size (a, b, &off);
1144 6208 : if (sz < siz[0])
1145 515 : siz[0] = sz;
1146 :
1147 6208 : if (siz[1] <= sz)
1148 4467 : siz[1] = sz;
1149 :
1150 6208 : if (sz != 0)
1151 : {
1152 5752 : if (wi::lts_p (off, ovloff[0]))
1153 388 : ovloff[0] = off.to_shwi ();
1154 5752 : if (wi::lts_p (ovloff[1], off))
1155 500 : ovloff[1] = off.to_shwi ();
1156 : }
1157 : }
1158 : }
1159 : }
1160 :
1161 496 : ovlsiz[0] = siz[0].to_shwi ();
1162 496 : ovlsiz[1] = siz[1].to_shwi ();
1163 :
1164 : /* Adjust the overlap offset range to reflect the overlap size range. */
1165 496 : if (ovlsiz[0] == 0 && ovlsiz[1] > 1)
1166 62 : ovloff[1] = ovloff[0] + ovlsiz[1] - 1;
1167 :
1168 : return true;
1169 : }
1170 :
1171 : /* Return true if the strcat-like access overlaps. */
1172 :
1173 : bool
1174 133 : builtin_access::strcat_overlap ()
1175 : {
1176 133 : builtin_access &acs = *this;
1177 133 : const builtin_memref *dstref = acs.dstref;
1178 133 : const builtin_memref *srcref = acs.srcref;
1179 :
1180 133 : gcc_assert (dstref->base == srcref->base);
1181 :
1182 133 : const offset_int maxobjsize = acs.dstref->maxobjsize;
1183 :
1184 133 : gcc_assert (dstref->base && dstref->base == srcref->base);
1185 :
1186 : /* Adjust for strcat-like accesses. */
1187 :
1188 : /* As a special case for strcat, set the DSTREF offsets to the length
1189 : of the destination string since the function starts writing over
1190 : its terminating nul, and set the destination size to 1 for the length
1191 : of the nul. */
1192 133 : acs.dstoff[0] += dstsiz[0] - srcref->sizrange[0];
1193 133 : acs.dstoff[1] += dstsiz[1] - srcref->sizrange[1];
1194 :
1195 133 : bool strfunc_unknown_args = acs.dstsiz[0] == 0 && acs.dstsiz[1] != 0;
1196 :
1197 : /* The lower bound is zero when the size is unknown because then
1198 : overlap is not certain. */
1199 133 : acs.dstsiz[0] = strfunc_unknown_args ? 0 : 1;
1200 133 : acs.dstsiz[1] = 1;
1201 :
1202 133 : offset_int maxsize = dstref->basesize < 0 ? maxobjsize : dstref->basesize;
1203 :
1204 : /* For references to the same base object, determine if there's a pair
1205 : of valid offsets into the two references such that access between
1206 : them doesn't overlap. Adjust both upper bounds to be valid for
1207 : the smaller size (i.e., at most MAXSIZE - SIZE). */
1208 :
1209 133 : if (maxsize < acs.dstoff[1] + acs.dstsiz[0])
1210 5 : acs.dstoff[1] = maxsize - acs.dstsiz[0];
1211 :
1212 133 : if (maxsize < acs.srcoff[1] + acs.srcsiz[0])
1213 2 : acs.srcoff[1] = maxsize - acs.srcsiz[0];
1214 :
1215 : /* Check to see if there's enough space for both accesses without
1216 : overlap. Determine the optimistic (maximum) amount of available
1217 : space. */
1218 133 : offset_int space;
1219 133 : if (acs.dstoff[0] <= acs.srcoff[0])
1220 : {
1221 54 : if (acs.dstoff[1] < acs.srcoff[1])
1222 40 : space = acs.srcoff[1] + acs.srcsiz[0] - acs.dstoff[0];
1223 : else
1224 14 : space = acs.dstoff[1] + acs.dstsiz[0] - acs.srcoff[0];
1225 : }
1226 : else
1227 79 : space = acs.dstoff[1] + acs.dstsiz[0] - acs.srcoff[0];
1228 :
1229 : /* Overlap is certain if the distance between the farthest offsets
1230 : of the opposite accesses is less than the sum of the lower bounds
1231 : of the sizes of the two accesses. */
1232 133 : bool overlap_certain = space < acs.dstsiz[0] + acs.srcsiz[0];
1233 :
1234 : /* For a constant-offset, constant size access, consider the largest
1235 : distance between the offset bounds and the lower bound of the access
1236 : size. If the overlap isn't certain return success. */
1237 133 : if (!overlap_certain
1238 97 : && acs.dstoff[0] == acs.dstoff[1]
1239 86 : && acs.srcoff[0] == acs.srcoff[1]
1240 77 : && acs.dstsiz[0] == acs.dstsiz[1]
1241 185 : && acs.srcsiz[0] == acs.srcsiz[1])
1242 : return false;
1243 :
1244 : /* Overlap is not certain but may be possible. */
1245 :
1246 81 : offset_int access_min = acs.dstsiz[0] + acs.srcsiz[0];
1247 :
1248 : /* Determine the conservative (minimum) amount of space. */
1249 81 : space = wi::abs (acs.dstoff[0] - acs.srcoff[0]);
1250 81 : offset_int d = wi::abs (acs.dstoff[0] - acs.srcoff[1]);
1251 81 : if (d < space)
1252 6 : space = d;
1253 81 : d = wi::abs (acs.dstoff[1] - acs.srcoff[0]);
1254 81 : if (d < space)
1255 2 : space = d;
1256 :
1257 : /* For a strict test (used for strcpy and similar with unknown or
1258 : variable bounds or sizes), consider the smallest distance between
1259 : the offset bounds and either the upper bound of the access size
1260 : if known, or the lower bound otherwise. */
1261 81 : if (access_min <= space && (access_min != 0 || !strfunc_unknown_args))
1262 0 : return false;
1263 :
1264 : /* When strcat overlap is certain it is always a single byte:
1265 : the terminating NUL, regardless of offsets and sizes. When
1266 : overlap is only possible its range is [0, 1]. */
1267 81 : acs.ovlsiz[0] = dstref->sizrange[0] == dstref->sizrange[1] ? 1 : 0;
1268 81 : acs.ovlsiz[1] = 1;
1269 :
1270 81 : offset_int endoff
1271 81 : = dstref->offrange[0] + (dstref->sizrange[0] - srcref->sizrange[0]);
1272 81 : if (endoff <= srcref->offrange[0])
1273 34 : acs.ovloff[0] = wi::smin (maxobjsize, srcref->offrange[0]).to_shwi ();
1274 : else
1275 47 : acs.ovloff[0] = wi::smin (maxobjsize, endoff).to_shwi ();
1276 :
1277 81 : acs.sizrange[0] = wi::smax (wi::abs (endoff - srcref->offrange[0]) + 1,
1278 81 : srcref->sizrange[0]).to_shwi ();
1279 81 : if (dstref->offrange[0] == dstref->offrange[1])
1280 : {
1281 73 : if (srcref->offrange[0] == srcref->offrange[1])
1282 63 : acs.ovloff[1] = acs.ovloff[0];
1283 : else
1284 10 : acs.ovloff[1]
1285 10 : = wi::smin (maxobjsize,
1286 10 : srcref->offrange[1] + srcref->sizrange[1]).to_shwi ();
1287 : }
1288 : else
1289 8 : acs.ovloff[1]
1290 8 : = wi::smin (maxobjsize,
1291 8 : dstref->offrange[1] + dstref->sizrange[1]).to_shwi ();
1292 :
1293 81 : if (acs.sizrange[0] == 0)
1294 0 : acs.sizrange[0] = 1;
1295 81 : acs.sizrange[1] = wi::smax (acs.dstsiz[1], srcref->sizrange[1]).to_shwi ();
1296 81 : return true;
1297 : }
1298 :
1299 : /* Return true if the strcpy-like access overlaps. */
1300 :
1301 : bool
1302 1311 : builtin_access::strcpy_overlap ()
1303 : {
1304 1311 : return generic_overlap ();
1305 : }
1306 :
1307 : /* For a BASE of array type, clamp REFOFF to at most [0, BASE_SIZE]
1308 : if known, or [0, MAXOBJSIZE] otherwise. */
1309 :
1310 : static void
1311 24246 : clamp_offset (tree base, offset_int refoff[2], offset_int maxobjsize)
1312 : {
1313 24246 : if (!base || TREE_CODE (TREE_TYPE (base)) != ARRAY_TYPE)
1314 : return;
1315 :
1316 10054 : if (refoff[0] < 0 && refoff[1] >= 0)
1317 0 : refoff[0] = 0;
1318 :
1319 10054 : if (refoff[1] < refoff[0])
1320 : {
1321 5 : offset_int maxsize = maxobjsize;
1322 5 : if (tree size = TYPE_SIZE_UNIT (TREE_TYPE (base)))
1323 5 : maxsize = wi::to_offset (size);
1324 :
1325 5 : refoff[1] = wi::umin (refoff[1], maxsize);
1326 : }
1327 : }
1328 :
1329 : /* Return true if DSTREF and SRCREF describe accesses that either overlap
1330 : one another or that, in order not to overlap, would imply that the size
1331 : of the referenced object(s) exceeds the maximum size of an object. Set
1332 : Otherwise, if DSTREF and SRCREF do not definitely overlap (even though
1333 : they may overlap in a way that's not apparent from the available data),
1334 : return false. */
1335 :
1336 : bool
1337 12151 : builtin_access::overlap ()
1338 : {
1339 12151 : builtin_access &acs = *this;
1340 :
1341 12151 : const offset_int maxobjsize = dstref->maxobjsize;
1342 :
1343 12151 : acs.sizrange[0] = wi::smax (dstref->sizrange[0],
1344 12151 : srcref->sizrange[0]).to_shwi ();
1345 12151 : acs.sizrange[1] = wi::smax (dstref->sizrange[1],
1346 12151 : srcref->sizrange[1]).to_shwi ();
1347 :
1348 : /* Check to see if the two references refer to regions that are
1349 : too large not to overlap in the address space (whose maximum
1350 : size is PTRDIFF_MAX). */
1351 12151 : offset_int size = dstref->sizrange[0] + srcref->sizrange[0];
1352 12151 : if (maxobjsize < size)
1353 : {
1354 28 : acs.ovloff[0] = (maxobjsize - dstref->sizrange[0]).to_shwi ();
1355 28 : acs.ovlsiz[0] = (size - maxobjsize).to_shwi ();
1356 28 : return true;
1357 : }
1358 :
1359 : /* If both base objects aren't known return the maximum possible
1360 : offset that would make them not overlap. */
1361 12123 : if (!dstref->base || !srcref->base)
1362 : return false;
1363 :
1364 : /* If the base object is an array adjust the bounds of the offset
1365 : to be non-negative and within the bounds of the array if possible. */
1366 12123 : clamp_offset (dstref->base, acs.dstoff, maxobjsize);
1367 :
1368 12123 : acs.srcoff[0] = srcref->offrange[0];
1369 12123 : acs.srcoff[1] = srcref->offrange[1];
1370 :
1371 12123 : clamp_offset (srcref->base, acs.srcoff, maxobjsize);
1372 :
1373 : /* When the upper bound of the offset is less than the lower bound
1374 : the former is the result of a negative offset being represented
1375 : as a large positive value or vice versa. The resulting range is
1376 : a union of two subranges: [MIN, UB] and [LB, MAX]. Since such
1377 : a union is not representable using the current data structure
1378 : replace it with the full range of offsets. */
1379 12123 : if (acs.dstoff[1] < acs.dstoff[0])
1380 : {
1381 5 : acs.dstoff[0] = -maxobjsize - 1;
1382 5 : acs.dstoff[1] = maxobjsize;
1383 : }
1384 :
1385 : /* Validate the offset and size of each reference on its own first.
1386 : This is independent of whether or not the base objects are the
1387 : same. Normally, this would have already been detected and
1388 : diagnosed by -Warray-bounds, unless it has been disabled. */
1389 12123 : offset_int maxoff = acs.dstoff[0] + dstref->sizrange[0];
1390 12123 : if (maxobjsize < maxoff)
1391 : {
1392 29 : acs.ovlsiz[0] = (maxoff - maxobjsize).to_shwi ();
1393 29 : acs.ovloff[0] = acs.dstoff[0].to_shwi () - acs.ovlsiz[0];
1394 29 : return true;
1395 : }
1396 :
1397 : /* Repeat the same as above but for the source offsets. */
1398 12094 : if (acs.srcoff[1] < acs.srcoff[0])
1399 : {
1400 0 : acs.srcoff[0] = -maxobjsize - 1;
1401 0 : acs.srcoff[1] = maxobjsize;
1402 : }
1403 :
1404 12094 : maxoff = acs.srcoff[0] + srcref->sizrange[0];
1405 12094 : if (maxobjsize < maxoff)
1406 : {
1407 28 : acs.ovlsiz[0] = (maxoff - maxobjsize).to_shwi ();
1408 28 : acs.ovlsiz[1] = (acs.srcoff[0] + srcref->sizrange[1]
1409 28 : - maxobjsize).to_shwi ();
1410 28 : acs.ovloff[0] = acs.srcoff[0].to_shwi () - acs.ovlsiz[0];
1411 28 : return true;
1412 : }
1413 :
1414 12066 : if (dstref->base != srcref->base)
1415 : return false;
1416 :
1417 2224 : acs.dstsiz[0] = dstref->sizrange[0];
1418 2224 : acs.dstsiz[1] = dstref->sizrange[1];
1419 :
1420 2224 : acs.srcsiz[0] = srcref->sizrange[0];
1421 2224 : acs.srcsiz[1] = srcref->sizrange[1];
1422 :
1423 : /* Call the appropriate function to determine the overlap. */
1424 2224 : if ((this->*detect_overlap) ())
1425 : {
1426 577 : if (!sizrange[1])
1427 : {
1428 : /* Unless the access size range has already been set, do so here. */
1429 0 : sizrange[0] = wi::smax (acs.dstsiz[0], srcref->sizrange[0]).to_shwi ();
1430 0 : sizrange[1] = wi::smax (acs.dstsiz[1], srcref->sizrange[1]).to_shwi ();
1431 : }
1432 577 : return true;
1433 : }
1434 :
1435 : return false;
1436 : }
1437 :
1438 : /* Attempt to detect and diagnose an overlapping copy in a call expression
1439 : EXPR involving an access ACS to a built-in memory or string function.
1440 : Return true when one has been detected, false otherwise. */
1441 :
1442 : static bool
1443 12151 : maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs)
1444 : {
1445 12151 : if (!acs.overlap ())
1446 : return false;
1447 :
1448 662 : if (warning_suppressed_p (call, OPT_Wrestrict))
1449 : return true;
1450 :
1451 : /* For convenience. */
1452 618 : const builtin_memref &dstref = *acs.dstref;
1453 618 : const builtin_memref &srcref = *acs.srcref;
1454 :
1455 : /* Determine the range of offsets and sizes of the overlap if it
1456 : exists and issue diagnostics. */
1457 618 : HOST_WIDE_INT *ovloff = acs.ovloff;
1458 618 : HOST_WIDE_INT *ovlsiz = acs.ovlsiz;
1459 618 : HOST_WIDE_INT *sizrange = acs.sizrange;
1460 :
1461 618 : tree func = gimple_call_fndecl (call);
1462 :
1463 618 : rich_location_with_details richloc (loc, call);
1464 :
1465 : /* To avoid a combinatorial explosion of diagnostics format the offsets
1466 : or their ranges as strings and use them in the warning calls below. */
1467 618 : char offstr[3][64];
1468 :
1469 618 : if (dstref.offrange[0] == dstref.offrange[1]
1470 618 : || dstref.offrange[1] > HOST_WIDE_INT_MAX)
1471 451 : sprintf (offstr[0], HOST_WIDE_INT_PRINT_DEC,
1472 : dstref.offrange[0].to_shwi ());
1473 : else
1474 167 : sprintf (offstr[0],
1475 : "[" HOST_WIDE_INT_PRINT_DEC ", " HOST_WIDE_INT_PRINT_DEC "]",
1476 : dstref.offrange[0].to_shwi (),
1477 : dstref.offrange[1].to_shwi ());
1478 :
1479 618 : if (srcref.offrange[0] == srcref.offrange[1]
1480 618 : || srcref.offrange[1] > HOST_WIDE_INT_MAX)
1481 397 : sprintf (offstr[1],
1482 : HOST_WIDE_INT_PRINT_DEC,
1483 : srcref.offrange[0].to_shwi ());
1484 : else
1485 221 : sprintf (offstr[1],
1486 : "[" HOST_WIDE_INT_PRINT_DEC ", " HOST_WIDE_INT_PRINT_DEC "]",
1487 : srcref.offrange[0].to_shwi (),
1488 : srcref.offrange[1].to_shwi ());
1489 :
1490 618 : if (ovloff[0] == ovloff[1] || !ovloff[1])
1491 418 : sprintf (offstr[2], HOST_WIDE_INT_PRINT_DEC, ovloff[0]);
1492 : else
1493 200 : sprintf (offstr[2],
1494 : "[" HOST_WIDE_INT_PRINT_DEC ", " HOST_WIDE_INT_PRINT_DEC "]",
1495 : ovloff[0], ovloff[1]);
1496 :
1497 618 : const offset_int maxobjsize = dstref.maxobjsize;
1498 618 : bool must_overlap = ovlsiz[0] > 0;
1499 :
1500 618 : if (ovlsiz[1] == 0)
1501 53 : ovlsiz[1] = ovlsiz[0];
1502 :
1503 618 : if (must_overlap)
1504 : {
1505 : /* Issue definitive "overlaps" diagnostic in this block. */
1506 :
1507 462 : if (sizrange[0] == sizrange[1])
1508 : {
1509 368 : if (ovlsiz[0] == ovlsiz[1])
1510 576 : warning_at (&richloc, OPT_Wrestrict,
1511 : sizrange[0] == 1
1512 : ? (ovlsiz[0] == 1
1513 6 : ? G_("%qD accessing %wu byte at offsets %s "
1514 : "and %s overlaps %wu byte at offset %s")
1515 : : G_("%qD accessing %wu byte at offsets %s "
1516 : "and %s overlaps %wu bytes at offset "
1517 : "%s"))
1518 : : (ovlsiz[0] == 1
1519 282 : ? G_("%qD accessing %wu bytes at offsets %s "
1520 : "and %s overlaps %wu byte at offset %s")
1521 : : G_("%qD accessing %wu bytes at offsets %s "
1522 : "and %s overlaps %wu bytes at offset "
1523 : "%s")),
1524 : func, sizrange[0],
1525 : offstr[0], offstr[1], ovlsiz[0], offstr[2]);
1526 80 : else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ())
1527 80 : warning_n (&richloc, OPT_Wrestrict, sizrange[0],
1528 : "%qD accessing %wu byte at offsets %s "
1529 : "and %s overlaps between %wu and %wu bytes "
1530 : "at offset %s",
1531 : "%qD accessing %wu bytes at offsets %s "
1532 : "and %s overlaps between %wu and %wu bytes "
1533 : "at offset %s",
1534 : func, sizrange[0], offstr[0], offstr[1],
1535 : ovlsiz[0], ovlsiz[1], offstr[2]);
1536 : else
1537 0 : warning_n (&richloc, OPT_Wrestrict, sizrange[0],
1538 : "%qD accessing %wu byte at offsets %s and "
1539 : "%s overlaps %wu or more bytes at offset %s",
1540 : "%qD accessing %wu bytes at offsets %s and "
1541 : "%s overlaps %wu or more bytes at offset %s",
1542 : func, sizrange[0],
1543 : offstr[0], offstr[1], ovlsiz[0], offstr[2]);
1544 368 : return true;
1545 : }
1546 :
1547 94 : if (sizrange[1] >= 0 && sizrange[1] < maxobjsize.to_shwi ())
1548 : {
1549 54 : if (ovlsiz[0] == ovlsiz[1])
1550 1 : warning_n (&richloc, OPT_Wrestrict, ovlsiz[0],
1551 : "%qD accessing between %wu and %wu bytes "
1552 : "at offsets %s and %s overlaps %wu byte at "
1553 : "offset %s",
1554 : "%qD accessing between %wu and %wu bytes "
1555 : "at offsets %s and %s overlaps %wu bytes "
1556 : "at offset %s",
1557 : func, sizrange[0], sizrange[1],
1558 : offstr[0], offstr[1], ovlsiz[0], offstr[2]);
1559 53 : else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ())
1560 53 : warning_at (&richloc, OPT_Wrestrict,
1561 : "%qD accessing between %wu and %wu bytes at "
1562 : "offsets %s and %s overlaps between %wu and %wu "
1563 : "bytes at offset %s",
1564 : func, sizrange[0], sizrange[1],
1565 : offstr[0], offstr[1], ovlsiz[0], ovlsiz[1],
1566 : offstr[2]);
1567 : else
1568 0 : warning_at (&richloc, OPT_Wrestrict,
1569 : "%qD accessing between %wu and %wu bytes at "
1570 : "offsets %s and %s overlaps %wu or more bytes "
1571 : "at offset %s",
1572 : func, sizrange[0], sizrange[1],
1573 : offstr[0], offstr[1], ovlsiz[0], offstr[2]);
1574 54 : return true;
1575 : }
1576 :
1577 40 : if (ovlsiz[0] != ovlsiz[1])
1578 36 : ovlsiz[1] = maxobjsize.to_shwi ();
1579 :
1580 40 : if (ovlsiz[0] == ovlsiz[1])
1581 4 : warning_n (&richloc, OPT_Wrestrict, ovlsiz[0],
1582 : "%qD accessing %wu or more bytes at offsets "
1583 : "%s and %s overlaps %wu byte at offset %s",
1584 : "%qD accessing %wu or more bytes at offsets "
1585 : "%s and %s overlaps %wu bytes at offset %s",
1586 : func, sizrange[0], offstr[0], offstr[1],
1587 : ovlsiz[0], offstr[2]);
1588 36 : else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ())
1589 0 : warning_at (&richloc, OPT_Wrestrict,
1590 : "%qD accessing %wu or more bytes at offsets %s "
1591 : "and %s overlaps between %wu and %wu bytes "
1592 : "at offset %s",
1593 : func, sizrange[0], offstr[0], offstr[1],
1594 : ovlsiz[0], ovlsiz[1], offstr[2]);
1595 : else
1596 36 : warning_at (&richloc, OPT_Wrestrict,
1597 : "%qD accessing %wu or more bytes at offsets %s "
1598 : "and %s overlaps %wu or more bytes at offset %s",
1599 : func, sizrange[0], offstr[0], offstr[1],
1600 : ovlsiz[0], offstr[2]);
1601 40 : return true;
1602 : }
1603 :
1604 : /* Use more concise wording when one of the offsets is unbounded
1605 : to avoid confusing the user with large and mostly meaningless
1606 : numbers. */
1607 156 : bool open_range;
1608 156 : if (DECL_P (dstref.base) && TREE_CODE (TREE_TYPE (dstref.base)) == ARRAY_TYPE)
1609 113 : open_range = ((dstref.offrange[0] == 0
1610 89 : && dstref.offrange[1] == maxobjsize)
1611 255 : || (srcref.offrange[0] == 0
1612 53 : && srcref.offrange[1] == maxobjsize));
1613 : else
1614 43 : open_range = ((dstref.offrange[0] == -maxobjsize - 1
1615 0 : && dstref.offrange[1] == maxobjsize)
1616 43 : || (srcref.offrange[0] == -maxobjsize - 1
1617 0 : && srcref.offrange[1] == maxobjsize));
1618 :
1619 156 : if (sizrange[0] == sizrange[1] || sizrange[1] == 1)
1620 : {
1621 86 : if (ovlsiz[1] == 1)
1622 : {
1623 46 : if (open_range)
1624 0 : warning_n (&richloc, OPT_Wrestrict, sizrange[1],
1625 : "%qD accessing %wu byte may overlap "
1626 : "%wu byte",
1627 : "%qD accessing %wu bytes may overlap "
1628 : "%wu byte",
1629 : func, sizrange[1], ovlsiz[1]);
1630 : else
1631 46 : warning_n (&richloc, OPT_Wrestrict, sizrange[1],
1632 : "%qD accessing %wu byte at offsets %s "
1633 : "and %s may overlap %wu byte at offset %s",
1634 : "%qD accessing %wu bytes at offsets %s "
1635 : "and %s may overlap %wu byte at offset %s",
1636 : func, sizrange[1], offstr[0], offstr[1],
1637 : ovlsiz[1], offstr[2]);
1638 46 : return true;
1639 : }
1640 :
1641 40 : if (open_range)
1642 0 : warning_n (&richloc, OPT_Wrestrict, sizrange[1],
1643 : "%qD accessing %wu byte may overlap "
1644 : "up to %wu bytes",
1645 : "%qD accessing %wu bytes may overlap "
1646 : "up to %wu bytes",
1647 : func, sizrange[1], ovlsiz[1]);
1648 : else
1649 40 : warning_n (&richloc, OPT_Wrestrict, sizrange[1],
1650 : "%qD accessing %wu byte at offsets %s and "
1651 : "%s may overlap up to %wu bytes at offset %s",
1652 : "%qD accessing %wu bytes at offsets %s and "
1653 : "%s may overlap up to %wu bytes at offset %s",
1654 : func, sizrange[1], offstr[0], offstr[1],
1655 : ovlsiz[1], offstr[2]);
1656 40 : return true;
1657 : }
1658 :
1659 70 : if (sizrange[1] >= 0 && sizrange[1] < maxobjsize.to_shwi ())
1660 : {
1661 28 : if (open_range)
1662 0 : warning_n (&richloc, OPT_Wrestrict, ovlsiz[1],
1663 : "%qD accessing between %wu and %wu bytes "
1664 : "may overlap %wu byte",
1665 : "%qD accessing between %wu and %wu bytes "
1666 : "may overlap up to %wu bytes",
1667 : func, sizrange[0], sizrange[1], ovlsiz[1]);
1668 : else
1669 28 : warning_n (&richloc, OPT_Wrestrict, ovlsiz[1],
1670 : "%qD accessing between %wu and %wu bytes "
1671 : "at offsets %s and %s may overlap %wu byte "
1672 : "at offset %s",
1673 : "%qD accessing between %wu and %wu bytes "
1674 : "at offsets %s and %s may overlap up to %wu "
1675 : "bytes at offset %s",
1676 : func, sizrange[0], sizrange[1],
1677 : offstr[0], offstr[1], ovlsiz[1], offstr[2]);
1678 28 : return true;
1679 : }
1680 :
1681 42 : warning_n (&richloc, OPT_Wrestrict, ovlsiz[1],
1682 : "%qD accessing %wu or more bytes at offsets %s "
1683 : "and %s may overlap %wu byte at offset %s",
1684 : "%qD accessing %wu or more bytes at offsets %s "
1685 : "and %s may overlap up to %wu bytes at offset %s",
1686 : func, sizrange[0], offstr[0], offstr[1],
1687 : ovlsiz[1], offstr[2]);
1688 :
1689 42 : return true;
1690 618 : }
1691 :
1692 : /* Validate REF size and offsets in an expression passed as an argument
1693 : to a CALL to a built-in function FUNC to make sure they are within
1694 : the bounds of the referenced object if its size is known, or
1695 : PTRDIFF_MAX otherwise. DO_WARN is true when a diagnostic should
1696 : be issued, false otherwise.
1697 : Both initial values of the offsets and their final value computed
1698 : by the function by incrementing the initial value by the size are
1699 : validated. Return the warning number if the offsets are not valid
1700 : and a diagnostic has been issued, or would have been issued if
1701 : DO_WARN had been true, otherwise an invalid warning number. */
1702 :
1703 : static opt_code
1704 397688 : maybe_diag_access_bounds (gimple *call, tree func, int strict,
1705 : const builtin_memref &ref, offset_int wroff,
1706 : bool do_warn)
1707 : {
1708 397688 : location_t loc = gimple_location (call);
1709 397688 : const offset_int maxobjsize = ref.maxobjsize;
1710 :
1711 397688 : rich_location_with_details richloc (loc, call);
1712 :
1713 : /* Check for excessive size first and regardless of warning options
1714 : since the result is used to make codegen decisions. */
1715 397688 : if (ref.sizrange[0] > maxobjsize)
1716 : {
1717 125 : const opt_code opt = OPT_Wstringop_overflow_;
1718 : /* Return true without issuing a warning. */
1719 125 : if (!do_warn)
1720 : return opt;
1721 :
1722 125 : if (ref.ref && warning_suppressed_p (ref.ref, OPT_Wstringop_overflow_))
1723 : return no_warning;
1724 :
1725 125 : bool warned = false;
1726 125 : if (warn_stringop_overflow)
1727 : {
1728 119 : if (ref.sizrange[0] == ref.sizrange[1])
1729 85 : warned = warning_at (&richloc, opt,
1730 : "%qD specified bound %wu "
1731 : "exceeds maximum object size %wu",
1732 : func, ref.sizrange[0].to_uhwi (),
1733 : maxobjsize.to_uhwi ());
1734 : else
1735 34 : warned = warning_at (&richloc, opt,
1736 : "%qD specified bound between %wu and %wu "
1737 : "exceeds maximum object size %wu",
1738 : func, ref.sizrange[0].to_uhwi (),
1739 : ref.sizrange[1].to_uhwi (),
1740 : maxobjsize.to_uhwi ());
1741 201 : return warned ? opt : no_warning;
1742 : }
1743 : }
1744 :
1745 : /* Check for out-bounds pointers regardless of warning options since
1746 : the result is used to make codegen decisions. An excessive WROFF
1747 : can only come up as a result of an invalid strncat bound and is
1748 : diagnosed separately using a more meaningful warning. */
1749 397569 : if (maxobjsize < wroff)
1750 0 : wroff = 0;
1751 397569 : offset_int ooboff[] = { ref.offrange[0], ref.offrange[1], wroff };
1752 397569 : tree oobref = ref.offset_out_of_bounds (strict, ooboff);
1753 397569 : if (!oobref)
1754 : return no_warning;
1755 :
1756 2477 : const opt_code opt = OPT_Warray_bounds_;
1757 : /* Return true without issuing a warning. */
1758 2477 : if (!do_warn)
1759 : return opt;
1760 :
1761 1475 : if (!warn_array_bounds)
1762 : return no_warning;
1763 :
1764 533 : if (warning_suppressed_p (ref.ptr, opt)
1765 533 : || (ref.ref && warning_suppressed_p (ref.ref, opt)))
1766 18 : return no_warning;
1767 :
1768 515 : char rangestr[2][64];
1769 515 : if (ooboff[0] == ooboff[1]
1770 515 : || (ooboff[0] != ref.offrange[0]
1771 172 : && ooboff[0].to_shwi () >= ooboff[1].to_shwi ()))
1772 224 : sprintf (rangestr[0], "%lli", (long long) ooboff[0].to_shwi ());
1773 : else
1774 291 : sprintf (rangestr[0], "[%lli, %lli]",
1775 291 : (long long) ooboff[0].to_shwi (),
1776 291 : (long long) ooboff[1].to_shwi ());
1777 :
1778 515 : bool warned = false;
1779 :
1780 515 : if (oobref == error_mark_node)
1781 : {
1782 22 : if (ref.sizrange[0] == ref.sizrange[1])
1783 18 : sprintf (rangestr[1], "%llu",
1784 18 : (unsigned long long) ref.sizrange[0].to_shwi ());
1785 : else
1786 4 : sprintf (rangestr[1], "[%lli, %lli]",
1787 4 : (unsigned long long) ref.sizrange[0].to_uhwi (),
1788 4 : (unsigned long long) ref.sizrange[1].to_uhwi ());
1789 :
1790 22 : tree type;
1791 :
1792 22 : if (DECL_P (ref.base)
1793 22 : && TREE_CODE (type = TREE_TYPE (ref.base)) == ARRAY_TYPE)
1794 : {
1795 8 : auto_diagnostic_group d;
1796 8 : if (warning_at (&richloc, opt,
1797 : "%qD pointer overflow between offset %s "
1798 : "and size %s accessing array %qD with type %qT",
1799 8 : func, rangestr[0], rangestr[1], ref.base, type))
1800 : {
1801 16 : inform (DECL_SOURCE_LOCATION (ref.base),
1802 8 : "array %qD declared here", ref.base);
1803 8 : warned = true;
1804 : }
1805 : else
1806 0 : warned = warning_at (&richloc, opt,
1807 : "%qD pointer overflow between offset %s "
1808 : "and size %s",
1809 : func, rangestr[0], rangestr[1]);
1810 8 : }
1811 : else
1812 14 : warned = warning_at (&richloc, opt,
1813 : "%qD pointer overflow between offset %s "
1814 : "and size %s",
1815 : func, rangestr[0], rangestr[1]);
1816 : }
1817 493 : else if (oobref == ref.base)
1818 : {
1819 : /* True when the offset formed by an access to the reference
1820 : is out of bounds, rather than the initial offset wich is
1821 : in bounds. This implies access past the end. */
1822 302 : bool form = ooboff[0] != ref.offrange[0];
1823 :
1824 302 : if (DECL_P (ref.base))
1825 : {
1826 279 : auto_diagnostic_group d;
1827 279 : if ((ref.basesize < maxobjsize
1828 422 : && warning_at (&richloc, opt,
1829 : form
1830 : ? G_("%qD forming offset %s is out of "
1831 : "the bounds [0, %wu] of object %qD with "
1832 : "type %qT")
1833 : : G_("%qD offset %s is out of the bounds "
1834 : "[0, %wu] of object %qD with type %qT"),
1835 : func, rangestr[0], ref.basesize.to_uhwi (),
1836 263 : ref.base, TREE_TYPE (ref.base)))
1837 313 : || warning_at (&richloc, opt,
1838 : form
1839 : ? G_("%qD forming offset %s is out of "
1840 : "the bounds of object %qD with type %qT")
1841 : : G_("%qD offset %s is out of the bounds "
1842 : "of object %qD with type %qT"),
1843 : func, rangestr[0],
1844 18 : ref.base, TREE_TYPE (ref.base)))
1845 : {
1846 554 : inform (DECL_SOURCE_LOCATION (ref.base),
1847 277 : "%qD declared here", ref.base);
1848 277 : warned = true;
1849 : }
1850 279 : }
1851 23 : else if (ref.basesize < maxobjsize)
1852 29 : warned = warning_at (&richloc, opt,
1853 : form
1854 : ? G_("%qD forming offset %s is out "
1855 : "of the bounds [0, %wu]")
1856 : : G_("%qD offset %s is out "
1857 : "of the bounds [0, %wu]"),
1858 : func, rangestr[0], ref.basesize.to_uhwi ());
1859 : else
1860 0 : warned = warning_at (&richloc, opt,
1861 : form
1862 : ? G_("%qD forming offset %s is out of bounds")
1863 : : G_("%qD offset %s is out of bounds"),
1864 : func, rangestr[0]);
1865 : }
1866 191 : else if (TREE_CODE (ref.ref) == MEM_REF)
1867 : {
1868 0 : tree refop = TREE_OPERAND (ref.ref, 0);
1869 0 : tree type = TREE_TYPE (refop);
1870 0 : if (POINTER_TYPE_P (type))
1871 0 : type = TREE_TYPE (type);
1872 0 : type = TYPE_MAIN_VARIANT (type);
1873 :
1874 0 : if (warning_at (&richloc, opt,
1875 : "%qD offset %s from the object at %qE is out "
1876 : "of the bounds of %qT",
1877 0 : func, rangestr[0], ref.base, type))
1878 : {
1879 0 : if (TREE_CODE (ref.ref) == COMPONENT_REF)
1880 0 : refop = TREE_OPERAND (ref.ref, 1);
1881 0 : if (DECL_P (refop))
1882 0 : inform (DECL_SOURCE_LOCATION (refop),
1883 : "subobject %qD declared here", refop);
1884 : warned = true;
1885 : }
1886 : }
1887 : else
1888 : {
1889 191 : tree refop = TREE_OPERAND (ref.ref, 0);
1890 191 : tree type = TYPE_MAIN_VARIANT (TREE_TYPE (ref.ref));
1891 :
1892 382 : if (warning_at (&richloc, opt,
1893 : "%qD offset %s from the object at %qE is out "
1894 : "of the bounds of referenced subobject %qD with "
1895 : "type %qT at offset %wi",
1896 191 : func, rangestr[0], ref.base,
1897 191 : TREE_OPERAND (ref.ref, 1), type,
1898 : ref.refoff.to_shwi ()))
1899 : {
1900 191 : if (TREE_CODE (ref.ref) == COMPONENT_REF)
1901 191 : refop = TREE_OPERAND (ref.ref, 1);
1902 191 : if (DECL_P (refop))
1903 191 : inform (DECL_SOURCE_LOCATION (refop),
1904 : "subobject %qD declared here", refop);
1905 : warned = true;
1906 : }
1907 : }
1908 :
1909 324 : return warned ? opt : no_warning;
1910 397688 : }
1911 :
1912 : /* Check a CALL statement for restrict-violations and issue warnings
1913 : if/when appropriate. */
1914 :
1915 : void
1916 5090835 : pass_wrestrict::check_call (gimple *call)
1917 : {
1918 : /* Avoid checking the call if it has already been diagnosed for
1919 : some reason. */
1920 5090835 : if (warning_suppressed_p (call, OPT_Wrestrict))
1921 : return;
1922 :
1923 5081760 : tree func = gimple_call_fndecl (call);
1924 5081760 : if (!func || !fndecl_built_in_p (func, BUILT_IN_NORMAL))
1925 : return;
1926 :
1927 : /* Argument number to extract from the call (depends on the built-in
1928 : and its kind). */
1929 1173869 : unsigned dst_idx = -1;
1930 1173869 : unsigned src_idx = -1;
1931 1173869 : unsigned bnd_idx = -1;
1932 :
1933 : /* Is this CALL to a string function (as opposed to one to a raw
1934 : memory function). */
1935 1173869 : bool strfun = true;
1936 :
1937 1173869 : switch (DECL_FUNCTION_CODE (func))
1938 : {
1939 112220 : case BUILT_IN_MEMCPY:
1940 112220 : case BUILT_IN_MEMCPY_CHK:
1941 112220 : case BUILT_IN_MEMPCPY:
1942 112220 : case BUILT_IN_MEMPCPY_CHK:
1943 112220 : case BUILT_IN_MEMMOVE:
1944 112220 : case BUILT_IN_MEMMOVE_CHK:
1945 112220 : strfun = false;
1946 : /* Fall through. */
1947 :
1948 : case BUILT_IN_STPNCPY:
1949 : case BUILT_IN_STPNCPY_CHK:
1950 : case BUILT_IN_STRNCAT:
1951 : case BUILT_IN_STRNCAT_CHK:
1952 : case BUILT_IN_STRNCPY:
1953 : case BUILT_IN_STRNCPY_CHK:
1954 : dst_idx = 0;
1955 : src_idx = 1;
1956 : bnd_idx = 2;
1957 : break;
1958 :
1959 : case BUILT_IN_MEMSET:
1960 : case BUILT_IN_MEMSET_CHK:
1961 : dst_idx = 0;
1962 : bnd_idx = 2;
1963 : break;
1964 :
1965 2919 : case BUILT_IN_STPCPY:
1966 2919 : case BUILT_IN_STPCPY_CHK:
1967 2919 : case BUILT_IN_STRCPY:
1968 2919 : case BUILT_IN_STRCPY_CHK:
1969 2919 : case BUILT_IN_STRCAT:
1970 2919 : case BUILT_IN_STRCAT_CHK:
1971 2919 : dst_idx = 0;
1972 2919 : src_idx = 1;
1973 2919 : break;
1974 :
1975 : default:
1976 : /* Handle other string functions here whose access may need
1977 : to be validated for in-bounds offsets and non-overlapping
1978 : copies. */
1979 : return;
1980 : }
1981 :
1982 149710 : unsigned nargs = gimple_call_num_args (call);
1983 :
1984 149710 : tree dst = dst_idx < nargs ? gimple_call_arg (call, dst_idx) : NULL_TREE;
1985 149698 : tree src = src_idx < nargs ? gimple_call_arg (call, src_idx) : NULL_TREE;
1986 149710 : tree dstwr = bnd_idx < nargs ? gimple_call_arg (call, bnd_idx) : NULL_TREE;
1987 :
1988 : /* For string functions with an unspecified or unknown bound,
1989 : assume the size of the access is one. */
1990 149710 : if (!dstwr && strfun)
1991 2925 : dstwr = size_one_node;
1992 :
1993 : /* DST and SRC can be null for a call with an insufficient number
1994 : of arguments to a built-in function declared without a protype. */
1995 149710 : if (!dst || (src_idx < nargs && !src))
1996 : return;
1997 :
1998 : /* DST, SRC, or DSTWR can also have the wrong type in a call to
1999 : a function declared without a prototype. Avoid checking such
2000 : invalid calls. */
2001 151930 : if (!POINTER_TYPE_P (TREE_TYPE (dst))
2002 149646 : || (src && !POINTER_TYPE_P (TREE_TYPE (src)))
2003 299344 : || (dstwr && !INTEGRAL_TYPE_P (TREE_TYPE (dstwr))))
2004 : return;
2005 :
2006 149644 : opt_code opt = check_bounds_or_overlap (m_ptr_qry, call, dst, src, dstwr,
2007 : NULL_TREE);
2008 : /* Avoid diagnosing the call again. */
2009 149644 : suppress_warning (call, opt);
2010 : }
2011 :
2012 : } /* anonymous namespace */
2013 :
2014 : /* Attempt to detect and diagnose invalid offset bounds and (except for
2015 : memmove) overlapping copy in a call expression EXPR from SRC to DST
2016 : and DSTSIZE and SRCSIZE bytes, respectively. Both DSTSIZE and
2017 : SRCSIZE may be NULL. DO_WARN is false to detect either problem
2018 : without issue a warning. Return the OPT_Wxxx constant corresponding
2019 : to the warning if one has been detected and zero otherwise. */
2020 :
2021 : opt_code
2022 49632 : check_bounds_or_overlap (gimple *call, tree dst, tree src, tree dstsize,
2023 : tree srcsize, bool bounds_only /* = false */,
2024 : bool do_warn /* = true */)
2025 : {
2026 99264 : pointer_query ptrqry (get_range_query (cfun));
2027 49632 : return check_bounds_or_overlap (ptrqry,
2028 : call, dst, src, dstsize, srcsize,
2029 49632 : bounds_only, do_warn);
2030 49632 : }
2031 :
2032 : opt_code
2033 199276 : check_bounds_or_overlap (pointer_query &ptrqry,
2034 : gimple *call, tree dst, tree src, tree dstsize,
2035 : tree srcsize, bool bounds_only /* = false */,
2036 : bool do_warn /* = true */)
2037 : {
2038 199276 : tree func = gimple_call_fndecl (call);
2039 :
2040 199276 : builtin_memref dstref (ptrqry, call, dst, dstsize);
2041 199276 : builtin_memref srcref (ptrqry, call, src, srcsize);
2042 :
2043 : /* Create a descriptor of the access. This may adjust both DSTREF
2044 : and SRCREF based on one another and the kind of the access. */
2045 199276 : builtin_access acs (ptrqry, call, dstref, srcref);
2046 :
2047 : /* Set STRICT to the value of the -Warray-bounds=N argument for
2048 : string functions or when N > 1. */
2049 199276 : int strict = (acs.strict () || warn_array_bounds > 1 ? warn_array_bounds : 0);
2050 :
2051 : /* The starting offset of the destination write access. Nonzero only
2052 : for the strcat family of functions. */
2053 199276 : offset_int wroff = acs.write_off (dstsize);
2054 :
2055 : /* Validate offsets to each reference before the access first to make
2056 : sure they are within the bounds of the destination object if its
2057 : size is known, or PTRDIFF_MAX otherwise. */
2058 199276 : opt_code opt
2059 199276 : = maybe_diag_access_bounds (call, func, strict, dstref, wroff, do_warn);
2060 199276 : if (opt == no_warning)
2061 198412 : opt = maybe_diag_access_bounds (call, func, strict, srcref, 0, do_warn);
2062 :
2063 198412 : if (opt != no_warning)
2064 : {
2065 1550 : if (do_warn)
2066 548 : suppress_warning (call, opt);
2067 1550 : return opt;
2068 : }
2069 :
2070 197726 : if (!warn_restrict || bounds_only || !src)
2071 : return no_warning;
2072 :
2073 13164 : if (!bounds_only)
2074 : {
2075 13164 : switch (DECL_FUNCTION_CODE (func))
2076 : {
2077 : case BUILT_IN_MEMMOVE:
2078 : case BUILT_IN_MEMMOVE_CHK:
2079 : case BUILT_IN_MEMSET:
2080 : case BUILT_IN_MEMSET_CHK:
2081 : return no_warning;
2082 : default:
2083 : break;
2084 : }
2085 : }
2086 :
2087 12219 : location_t loc = gimple_location (call);
2088 12219 : if (operand_equal_p (dst, src, 0))
2089 : {
2090 : /* Issue -Wrestrict unless the pointers are null (those do
2091 : not point to objects and so do not indicate an overlap;
2092 : such calls could be the result of sanitization and jump
2093 : threading). */
2094 68 : if (!integer_zerop (dst) && !warning_suppressed_p (call, OPT_Wrestrict))
2095 : {
2096 50 : warning_at (loc, OPT_Wrestrict,
2097 : "%qD source argument is the same as destination",
2098 : func);
2099 50 : suppress_warning (call, OPT_Wrestrict);
2100 50 : return OPT_Wrestrict;
2101 : }
2102 :
2103 18 : return no_warning;
2104 : }
2105 :
2106 : /* Return false when overlap has been detected. */
2107 12151 : if (maybe_diag_overlap (loc, call, acs))
2108 : {
2109 662 : suppress_warning (call, OPT_Wrestrict);
2110 662 : return OPT_Wrestrict;
2111 : }
2112 :
2113 : return no_warning;
2114 : }
2115 :
2116 : gimple_opt_pass *
2117 285722 : make_pass_warn_restrict (gcc::context *ctxt)
2118 : {
2119 285722 : return new pass_wrestrict (ctxt);
2120 : }
2121 :
2122 : DEBUG_FUNCTION void
2123 0 : dump_builtin_memref (FILE *fp, const builtin_memref &ref)
2124 : {
2125 0 : fprintf (fp, "\n ptr = ");
2126 0 : print_generic_expr (fp, ref.ptr, TDF_LINENO);
2127 0 : fprintf (fp, "\n ref = ");
2128 0 : if (ref.ref)
2129 0 : print_generic_expr (fp, ref.ref, TDF_LINENO);
2130 : else
2131 0 : fputs ("null", fp);
2132 0 : fprintf (fp, "\n base = ");
2133 0 : print_generic_expr (fp, ref.base, TDF_LINENO);
2134 0 : fprintf (fp,
2135 : "\n basesize = %lli"
2136 : "\n refsize = %lli"
2137 : "\n refoff = %lli"
2138 : "\n offrange = [%lli, %lli]"
2139 : "\n sizrange = [%lli, %lli]"
2140 : "\n strbounded_p = %s\n",
2141 0 : (long long)ref.basesize.to_shwi (),
2142 0 : (long long)ref.refsize.to_shwi (),
2143 0 : (long long)ref.refoff.to_shwi (),
2144 0 : (long long)ref.offrange[0].to_shwi (),
2145 0 : (long long)ref.offrange[1].to_shwi (),
2146 0 : (long long)ref.sizrange[0].to_shwi (),
2147 0 : (long long)ref.sizrange[1].to_shwi (),
2148 0 : ref.strbounded_p ? "true" : "false");
2149 0 : }
2150 :
2151 : void
2152 0 : builtin_access::dump (FILE *fp) const
2153 : {
2154 0 : fprintf (fp, " dstref:");
2155 0 : dump_builtin_memref (fp, *dstref);
2156 0 : fprintf (fp, "\n srcref:");
2157 0 : dump_builtin_memref (fp, *srcref);
2158 :
2159 0 : fprintf (fp,
2160 : " sizrange = [%lli, %lli]\n"
2161 : " ovloff = [%lli, %lli]\n"
2162 : " ovlsiz = [%lli, %lli]\n"
2163 : " dstoff = [%lli, %lli]\n"
2164 : " dstsiz = [%lli, %lli]\n"
2165 : " srcoff = [%lli, %lli]\n"
2166 : " srcsiz = [%lli, %lli]\n",
2167 0 : (long long)sizrange[0], (long long)sizrange[1],
2168 0 : (long long)ovloff[0], (long long)ovloff[1],
2169 0 : (long long)ovlsiz[0], (long long)ovlsiz[1],
2170 0 : (long long)dstoff[0].to_shwi (), (long long)dstoff[1].to_shwi (),
2171 0 : (long long)dstsiz[0].to_shwi (), (long long)dstsiz[1].to_shwi (),
2172 0 : (long long)srcoff[0].to_shwi (), (long long)srcoff[1].to_shwi (),
2173 0 : (long long)srcsiz[0].to_shwi (), (long long)srcsiz[1].to_shwi ());
2174 0 : }
2175 :
2176 : DEBUG_FUNCTION void
2177 0 : dump_builtin_access (FILE *fp, gimple *stmt, const builtin_access &acs)
2178 : {
2179 0 : if (stmt)
2180 : {
2181 0 : fprintf (fp, "\nDumping builtin_access for ");
2182 0 : print_gimple_expr (fp, stmt, TDF_LINENO);
2183 0 : fputs (":\n", fp);
2184 : }
2185 :
2186 0 : acs.dump (fp);
2187 0 : }
2188 :
2189 : DEBUG_FUNCTION void
2190 0 : debug (gimple *stmt, const builtin_access &acs)
2191 : {
2192 0 : dump_builtin_access (stdout, stmt, acs);
2193 0 : }
|