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