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