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

source code of gcc/gimple-ssa-warn-restrict.cc