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