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