ada: Fix wrong finalization for call to BIP function in conditional expression
[official-gcc.git] / gcc / ubsan.cc
blobcfae13d7cde86e14a0d05134fc1e70ca5a2066c3
1 /* UndefinedBehaviorSanitizer, undefined behavior detector.
2 Copyright (C) 2013-2023 Free Software Foundation, Inc.
3 Contributed by Marek Polacek <polacek@redhat.com>
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "backend.h"
25 #include "rtl.h"
26 #include "c-family/c-common.h"
27 #include "gimple.h"
28 #include "cfghooks.h"
29 #include "tree-pass.h"
30 #include "memmodel.h"
31 #include "tm_p.h"
32 #include "ssa.h"
33 #include "cgraph.h"
34 #include "tree-pretty-print.h"
35 #include "stor-layout.h"
36 #include "cfganal.h"
37 #include "gimple-iterator.h"
38 #include "output.h"
39 #include "cfgloop.h"
40 #include "ubsan.h"
41 #include "expr.h"
42 #include "stringpool.h"
43 #include "attribs.h"
44 #include "asan.h"
45 #include "gimplify-me.h"
46 #include "dfp.h"
47 #include "builtins.h"
48 #include "tree-object-size.h"
49 #include "tree-cfg.h"
50 #include "gimple-fold.h"
51 #include "varasm.h"
52 #include "realmpfr.h"
54 /* Map from a tree to a VAR_DECL tree. */
56 struct GTY((for_user)) tree_type_map {
57 struct tree_map_base type;
58 tree decl;
61 struct tree_type_map_cache_hasher : ggc_cache_ptr_hash<tree_type_map>
63 static inline hashval_t
64 hash (tree_type_map *t)
66 return TYPE_UID (t->type.from);
69 static inline bool
70 equal (tree_type_map *a, tree_type_map *b)
72 return a->type.from == b->type.from;
75 static int
76 keep_cache_entry (tree_type_map *&m)
78 return ggc_marked_p (m->type.from);
82 static GTY ((cache))
83 hash_table<tree_type_map_cache_hasher> *decl_tree_for_type;
85 /* Lookup a VAR_DECL for TYPE, and return it if we find one. */
87 static tree
88 decl_for_type_lookup (tree type)
90 /* If the hash table is not initialized yet, create it now. */
91 if (decl_tree_for_type == NULL)
93 decl_tree_for_type
94 = hash_table<tree_type_map_cache_hasher>::create_ggc (10);
95 /* That also means we don't have to bother with the lookup. */
96 return NULL_TREE;
99 struct tree_type_map *h, in;
100 in.type.from = type;
102 h = decl_tree_for_type->find_with_hash (&in, TYPE_UID (type));
103 return h ? h->decl : NULL_TREE;
106 /* Insert a mapping TYPE->DECL in the VAR_DECL for type hashtable. */
108 static void
109 decl_for_type_insert (tree type, tree decl)
111 struct tree_type_map *h;
113 h = ggc_alloc<tree_type_map> ();
114 h->type.from = type;
115 h->decl = decl;
116 *decl_tree_for_type->find_slot_with_hash (h, TYPE_UID (type), INSERT) = h;
119 /* Helper routine, which encodes a value in the pointer_sized_int_node.
120 Arguments with precision <= POINTER_SIZE are passed directly,
121 the rest is passed by reference. T is a value we are to encode.
122 PHASE determines when this function is called. */
124 tree
125 ubsan_encode_value (tree t, enum ubsan_encode_value_phase phase)
127 tree type = TREE_TYPE (t);
128 scalar_mode mode = SCALAR_TYPE_MODE (type);
129 const unsigned int bitsize = GET_MODE_BITSIZE (mode);
130 if (bitsize <= POINTER_SIZE)
131 switch (TREE_CODE (type))
133 case BOOLEAN_TYPE:
134 case ENUMERAL_TYPE:
135 case INTEGER_TYPE:
136 return fold_build1 (NOP_EXPR, pointer_sized_int_node, t);
137 case REAL_TYPE:
139 tree itype = build_nonstandard_integer_type (bitsize, true);
140 t = fold_build1 (VIEW_CONVERT_EXPR, itype, t);
141 return fold_convert (pointer_sized_int_node, t);
143 default:
144 gcc_unreachable ();
146 else
148 if (!DECL_P (t) || !TREE_ADDRESSABLE (t))
150 /* The reason for this is that we don't want to pessimize
151 code by making vars unnecessarily addressable. */
152 tree var;
153 if (phase != UBSAN_ENCODE_VALUE_GENERIC)
155 var = create_tmp_var (type);
156 mark_addressable (var);
158 else
160 var = create_tmp_var_raw (type);
161 TREE_ADDRESSABLE (var) = 1;
162 DECL_CONTEXT (var) = current_function_decl;
164 if (phase == UBSAN_ENCODE_VALUE_RTL)
166 rtx mem = assign_stack_temp_for_type (mode, GET_MODE_SIZE (mode),
167 type);
168 SET_DECL_RTL (var, mem);
169 expand_assignment (var, t, false);
170 return build_fold_addr_expr (var);
172 if (phase != UBSAN_ENCODE_VALUE_GENERIC)
174 tree tem = build2 (MODIFY_EXPR, void_type_node, var, t);
175 t = build_fold_addr_expr (var);
176 return build2 (COMPOUND_EXPR, TREE_TYPE (t), tem, t);
178 else
180 var = build4 (TARGET_EXPR, type, var, t, NULL_TREE, NULL_TREE);
181 return build_fold_addr_expr (var);
184 else
185 return build_fold_addr_expr (t);
189 /* Cached ubsan_get_type_descriptor_type () return value. */
190 static GTY(()) tree ubsan_type_descriptor_type;
192 /* Build
193 struct __ubsan_type_descriptor
195 unsigned short __typekind;
196 unsigned short __typeinfo;
197 char __typename[];
199 type. */
201 static tree
202 ubsan_get_type_descriptor_type (void)
204 static const char *field_names[3]
205 = { "__typekind", "__typeinfo", "__typename" };
206 tree fields[3], ret;
208 if (ubsan_type_descriptor_type)
209 return ubsan_type_descriptor_type;
211 tree itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
212 tree flex_arr_type = build_array_type (char_type_node, itype);
214 ret = make_node (RECORD_TYPE);
215 for (int i = 0; i < 3; i++)
217 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
218 get_identifier (field_names[i]),
219 (i == 2) ? flex_arr_type
220 : short_unsigned_type_node);
221 DECL_CONTEXT (fields[i]) = ret;
222 if (i)
223 DECL_CHAIN (fields[i - 1]) = fields[i];
225 tree type_decl = build_decl (input_location, TYPE_DECL,
226 get_identifier ("__ubsan_type_descriptor"),
227 ret);
228 DECL_IGNORED_P (type_decl) = 1;
229 DECL_ARTIFICIAL (type_decl) = 1;
230 TYPE_FIELDS (ret) = fields[0];
231 TYPE_NAME (ret) = type_decl;
232 TYPE_STUB_DECL (ret) = type_decl;
233 TYPE_ARTIFICIAL (ret) = 1;
234 layout_type (ret);
235 ubsan_type_descriptor_type = ret;
236 return ret;
239 /* Cached ubsan_get_source_location_type () return value. */
240 static GTY(()) tree ubsan_source_location_type;
242 /* Build
243 struct __ubsan_source_location
245 const char *__filename;
246 unsigned int __line;
247 unsigned int __column;
249 type. */
251 tree
252 ubsan_get_source_location_type (void)
254 static const char *field_names[3]
255 = { "__filename", "__line", "__column" };
256 tree fields[3], ret;
257 if (ubsan_source_location_type)
258 return ubsan_source_location_type;
260 tree const_char_type = build_qualified_type (char_type_node,
261 TYPE_QUAL_CONST);
263 ret = make_node (RECORD_TYPE);
264 for (int i = 0; i < 3; i++)
266 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
267 get_identifier (field_names[i]),
268 (i == 0) ? build_pointer_type (const_char_type)
269 : unsigned_type_node);
270 DECL_CONTEXT (fields[i]) = ret;
271 if (i)
272 DECL_CHAIN (fields[i - 1]) = fields[i];
274 tree type_decl = build_decl (input_location, TYPE_DECL,
275 get_identifier ("__ubsan_source_location"),
276 ret);
277 DECL_IGNORED_P (type_decl) = 1;
278 DECL_ARTIFICIAL (type_decl) = 1;
279 TYPE_FIELDS (ret) = fields[0];
280 TYPE_NAME (ret) = type_decl;
281 TYPE_STUB_DECL (ret) = type_decl;
282 TYPE_ARTIFICIAL (ret) = 1;
283 layout_type (ret);
284 ubsan_source_location_type = ret;
285 return ret;
288 /* Helper routine that returns a CONSTRUCTOR of __ubsan_source_location
289 type with its fields filled from a location_t LOC. */
291 static tree
292 ubsan_source_location (location_t loc)
294 expanded_location xloc;
295 tree type = ubsan_get_source_location_type ();
297 xloc = expand_location (loc);
298 tree str;
299 if (xloc.file == NULL)
301 str = build_int_cst (ptr_type_node, 0);
302 xloc.line = 0;
303 xloc.column = 0;
305 else
307 /* Fill in the values from LOC. */
308 size_t len = strlen (xloc.file) + 1;
309 str = build_string (len, xloc.file);
310 TREE_TYPE (str) = build_array_type_nelts (char_type_node, len);
311 TREE_READONLY (str) = 1;
312 TREE_STATIC (str) = 1;
313 str = build_fold_addr_expr (str);
315 tree ctor = build_constructor_va (type, 3, NULL_TREE, str, NULL_TREE,
316 build_int_cst (unsigned_type_node,
317 xloc.line), NULL_TREE,
318 build_int_cst (unsigned_type_node,
319 xloc.column));
320 TREE_CONSTANT (ctor) = 1;
321 TREE_STATIC (ctor) = 1;
323 return ctor;
326 /* This routine returns a magic number for TYPE. */
328 static unsigned short
329 get_ubsan_type_info_for_type (tree type)
331 if (SCALAR_FLOAT_TYPE_P (type))
332 return tree_to_uhwi (TYPE_SIZE (type));
333 else if (INTEGRAL_TYPE_P (type))
335 int prec = exact_log2 (tree_to_uhwi (TYPE_SIZE (type)));
336 gcc_assert (prec != -1);
337 return (prec << 1) | !TYPE_UNSIGNED (type);
339 else
340 return 0;
343 /* Counters for internal labels. ubsan_ids[0] for Lubsan_type,
344 ubsan_ids[1] for Lubsan_data labels. */
345 static GTY(()) unsigned int ubsan_ids[2];
347 /* Helper routine that returns ADDR_EXPR of a VAR_DECL of a type
348 descriptor. It first looks into the hash table; if not found,
349 create the VAR_DECL, put it into the hash table and return the
350 ADDR_EXPR of it. TYPE describes a particular type. PSTYLE is
351 an enum controlling how we want to print the type. */
353 tree
354 ubsan_type_descriptor (tree type, enum ubsan_print_style pstyle)
356 /* See through any typedefs. */
357 type = TYPE_MAIN_VARIANT (type);
359 tree decl = decl_for_type_lookup (type);
360 /* It is possible that some of the earlier created DECLs were found
361 unused, in that case they weren't emitted and varpool_node::get
362 returns NULL node on them. But now we really need them. Thus,
363 renew them here. */
364 if (decl != NULL_TREE && varpool_node::get (decl))
365 return build_fold_addr_expr (decl);
367 tree dtype = ubsan_get_type_descriptor_type ();
368 tree type2 = type;
369 const char *tname = NULL;
370 pretty_printer pretty_name;
371 unsigned char deref_depth = 0;
372 unsigned short tkind, tinfo;
374 /* Get the name of the type, or the name of the pointer type. */
375 if (pstyle == UBSAN_PRINT_POINTER)
377 gcc_assert (POINTER_TYPE_P (type));
378 type2 = TREE_TYPE (type);
380 /* Remove any '*' operators from TYPE. */
381 while (POINTER_TYPE_P (type2))
382 deref_depth++, type2 = TREE_TYPE (type2);
384 if (TREE_CODE (type2) == METHOD_TYPE)
385 type2 = TYPE_METHOD_BASETYPE (type2);
388 /* If an array, get its type. */
389 type2 = strip_array_types (type2);
391 if (pstyle == UBSAN_PRINT_ARRAY)
393 while (POINTER_TYPE_P (type2))
394 deref_depth++, type2 = TREE_TYPE (type2);
397 if (TYPE_NAME (type2) != NULL)
399 if (TREE_CODE (TYPE_NAME (type2)) == IDENTIFIER_NODE)
400 tname = IDENTIFIER_POINTER (TYPE_NAME (type2));
401 else if (DECL_NAME (TYPE_NAME (type2)) != NULL)
402 tname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type2)));
405 if (tname == NULL)
406 /* We weren't able to determine the type name. */
407 tname = "<unknown>";
409 pp_quote (&pretty_name);
411 tree eltype = type;
412 if (pstyle == UBSAN_PRINT_POINTER)
414 pp_printf (&pretty_name, "%s%s%s%s%s%s%s",
415 TYPE_VOLATILE (type2) ? "volatile " : "",
416 TYPE_READONLY (type2) ? "const " : "",
417 TYPE_RESTRICT (type2) ? "restrict " : "",
418 TYPE_ATOMIC (type2) ? "_Atomic " : "",
419 TREE_CODE (type2) == RECORD_TYPE
420 ? "struct "
421 : TREE_CODE (type2) == UNION_TYPE
422 ? "union " : "", tname,
423 deref_depth == 0 ? "" : " ");
424 while (deref_depth-- > 0)
425 pp_star (&pretty_name);
427 else if (pstyle == UBSAN_PRINT_ARRAY)
429 /* Pretty print the array dimensions. */
430 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
431 tree t = type;
432 pp_string (&pretty_name, tname);
433 pp_space (&pretty_name);
434 while (deref_depth-- > 0)
435 pp_star (&pretty_name);
436 while (TREE_CODE (t) == ARRAY_TYPE)
438 pp_left_bracket (&pretty_name);
439 tree dom = TYPE_DOMAIN (t);
440 if (dom != NULL_TREE
441 && TYPE_MAX_VALUE (dom) != NULL_TREE
442 && TREE_CODE (TYPE_MAX_VALUE (dom)) == INTEGER_CST)
444 unsigned HOST_WIDE_INT m;
445 if (tree_fits_uhwi_p (TYPE_MAX_VALUE (dom))
446 && (m = tree_to_uhwi (TYPE_MAX_VALUE (dom))) + 1 != 0)
447 pp_unsigned_wide_integer (&pretty_name, m + 1);
448 else
449 pp_wide_int (&pretty_name,
450 wi::add (wi::to_widest (TYPE_MAX_VALUE (dom)), 1),
451 TYPE_SIGN (TREE_TYPE (dom)));
453 else
454 /* ??? We can't determine the variable name; print VLA unspec. */
455 pp_star (&pretty_name);
456 pp_right_bracket (&pretty_name);
457 t = TREE_TYPE (t);
460 /* Save the tree with stripped types. */
461 eltype = t;
463 else
464 pp_string (&pretty_name, tname);
466 pp_quote (&pretty_name);
468 switch (TREE_CODE (eltype))
470 case BOOLEAN_TYPE:
471 case ENUMERAL_TYPE:
472 case INTEGER_TYPE:
473 tkind = 0x0000;
474 break;
475 case REAL_TYPE:
476 /* FIXME: libubsan right now only supports float, double and
477 long double type formats. */
478 if (TYPE_MODE (eltype) == TYPE_MODE (float_type_node)
479 || TYPE_MODE (eltype) == TYPE_MODE (double_type_node)
480 || TYPE_MODE (eltype) == TYPE_MODE (long_double_type_node))
481 tkind = 0x0001;
482 else
483 tkind = 0xffff;
484 break;
485 default:
486 tkind = 0xffff;
487 break;
489 tinfo = get_ubsan_type_info_for_type (eltype);
491 /* Create a new VAR_DECL of type descriptor. */
492 const char *tmp = pp_formatted_text (&pretty_name);
493 size_t len = strlen (tmp) + 1;
494 tree str = build_string (len, tmp);
495 TREE_TYPE (str) = build_array_type_nelts (char_type_node, len);
496 TREE_READONLY (str) = 1;
497 TREE_STATIC (str) = 1;
499 char tmp_name[32];
500 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_type", ubsan_ids[0]++);
501 decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name),
502 dtype);
503 TREE_STATIC (decl) = 1;
504 TREE_PUBLIC (decl) = 0;
505 DECL_ARTIFICIAL (decl) = 1;
506 DECL_IGNORED_P (decl) = 1;
507 DECL_EXTERNAL (decl) = 0;
508 DECL_SIZE (decl)
509 = size_binop (PLUS_EXPR, DECL_SIZE (decl), TYPE_SIZE (TREE_TYPE (str)));
510 DECL_SIZE_UNIT (decl)
511 = size_binop (PLUS_EXPR, DECL_SIZE_UNIT (decl),
512 TYPE_SIZE_UNIT (TREE_TYPE (str)));
514 tree ctor = build_constructor_va (dtype, 3, NULL_TREE,
515 build_int_cst (short_unsigned_type_node,
516 tkind), NULL_TREE,
517 build_int_cst (short_unsigned_type_node,
518 tinfo), NULL_TREE, str);
519 TREE_CONSTANT (ctor) = 1;
520 TREE_STATIC (ctor) = 1;
521 DECL_INITIAL (decl) = ctor;
522 varpool_node::finalize_decl (decl);
524 /* Save the VAR_DECL into the hash table. */
525 decl_for_type_insert (type, decl);
527 return build_fold_addr_expr (decl);
530 /* Create a structure for the ubsan library. NAME is a name of the new
531 structure. LOCCNT is number of locations, PLOC points to array of
532 locations. The arguments in ... are of __ubsan_type_descriptor type
533 and there are at most two of them, followed by NULL_TREE, followed
534 by optional extra arguments and another NULL_TREE. */
536 tree
537 ubsan_create_data (const char *name, int loccnt, const location_t *ploc, ...)
539 va_list args;
540 tree ret, t;
541 tree fields[6];
542 vec<tree, va_gc> *saved_args = NULL;
543 size_t i = 0;
544 int j;
546 /* It is possible that PCH zapped table with definitions of sanitizer
547 builtins. Reinitialize them if needed. */
548 initialize_sanitizer_builtins ();
550 /* Firstly, create a pointer to type descriptor type. */
551 tree td_type = ubsan_get_type_descriptor_type ();
552 td_type = build_pointer_type (td_type);
554 /* Create the structure type. */
555 ret = make_node (RECORD_TYPE);
556 for (j = 0; j < loccnt; j++)
558 gcc_checking_assert (i < 2);
559 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
560 ubsan_get_source_location_type ());
561 DECL_CONTEXT (fields[i]) = ret;
562 if (i)
563 DECL_CHAIN (fields[i - 1]) = fields[i];
564 i++;
567 va_start (args, ploc);
568 for (t = va_arg (args, tree); t != NULL_TREE;
569 i++, t = va_arg (args, tree))
571 gcc_checking_assert (i < 4);
572 /* Save the tree arguments for later use. */
573 vec_safe_push (saved_args, t);
574 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
575 td_type);
576 DECL_CONTEXT (fields[i]) = ret;
577 if (i)
578 DECL_CHAIN (fields[i - 1]) = fields[i];
581 for (t = va_arg (args, tree); t != NULL_TREE;
582 i++, t = va_arg (args, tree))
584 gcc_checking_assert (i < 6);
585 /* Save the tree arguments for later use. */
586 vec_safe_push (saved_args, t);
587 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
588 TREE_TYPE (t));
589 DECL_CONTEXT (fields[i]) = ret;
590 if (i)
591 DECL_CHAIN (fields[i - 1]) = fields[i];
593 va_end (args);
595 tree type_decl = build_decl (input_location, TYPE_DECL,
596 get_identifier (name), ret);
597 DECL_IGNORED_P (type_decl) = 1;
598 DECL_ARTIFICIAL (type_decl) = 1;
599 TYPE_FIELDS (ret) = fields[0];
600 TYPE_NAME (ret) = type_decl;
601 TYPE_STUB_DECL (ret) = type_decl;
602 TYPE_ARTIFICIAL (ret) = 1;
603 layout_type (ret);
605 /* Now, fill in the type. */
606 char tmp_name[32];
607 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_data", ubsan_ids[1]++);
608 tree var = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name),
609 ret);
610 TREE_STATIC (var) = 1;
611 TREE_PUBLIC (var) = 0;
612 DECL_ARTIFICIAL (var) = 1;
613 DECL_IGNORED_P (var) = 1;
614 DECL_EXTERNAL (var) = 0;
616 vec<constructor_elt, va_gc> *v;
617 vec_alloc (v, i);
618 tree ctor = build_constructor (ret, v);
620 /* If desirable, set the __ubsan_source_location element. */
621 for (j = 0; j < loccnt; j++)
623 location_t loc = LOCATION_LOCUS (ploc[j]);
624 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, ubsan_source_location (loc));
627 size_t nelts = vec_safe_length (saved_args);
628 for (i = 0; i < nelts; i++)
630 t = (*saved_args)[i];
631 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, t);
634 TREE_CONSTANT (ctor) = 1;
635 TREE_STATIC (ctor) = 1;
636 DECL_INITIAL (var) = ctor;
637 varpool_node::finalize_decl (var);
639 return var;
642 /* Shared between *build_builtin_unreachable. */
644 tree
645 sanitize_unreachable_fn (tree *data, location_t loc)
647 tree fn = NULL_TREE;
648 bool san = sanitize_flags_p (SANITIZE_UNREACHABLE);
649 if (san
650 ? (flag_sanitize_trap & SANITIZE_UNREACHABLE)
651 : flag_unreachable_traps)
653 fn = builtin_decl_explicit (BUILT_IN_UNREACHABLE_TRAP);
654 *data = NULL_TREE;
656 else if (san)
658 /* Call ubsan_create_data first as it initializes SANITIZER built-ins. */
659 *data = ubsan_create_data ("__ubsan_unreachable_data", 1, &loc,
660 NULL_TREE, NULL_TREE);
661 fn = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE);
662 *data = build_fold_addr_expr_loc (loc, *data);
664 else
666 fn = builtin_decl_explicit (BUILT_IN_UNREACHABLE);
667 *data = NULL_TREE;
669 return fn;
672 /* Rewrite a gcall to __builtin_unreachable for -fsanitize=unreachable. Called
673 by the sanopt pass. */
675 bool
676 ubsan_instrument_unreachable (gimple_stmt_iterator *gsi)
678 location_t loc = gimple_location (gsi_stmt (*gsi));
679 gimple *g = gimple_build_builtin_unreachable (loc);
680 gsi_replace (gsi, g, false);
681 return false;
684 /* Return true if T is a call to a libubsan routine. */
686 bool
687 is_ubsan_builtin_p (tree t)
689 return TREE_CODE (t) == FUNCTION_DECL
690 && fndecl_built_in_p (t, BUILT_IN_NORMAL)
691 && strncmp (IDENTIFIER_POINTER (DECL_NAME (t)),
692 "__builtin___ubsan_", 18) == 0;
695 /* Create a callgraph edge for statement STMT. */
697 static void
698 ubsan_create_edge (gimple *stmt)
700 gcall *call_stmt = dyn_cast <gcall *> (stmt);
701 basic_block bb = gimple_bb (stmt);
702 cgraph_node *node = cgraph_node::get (current_function_decl);
703 tree decl = gimple_call_fndecl (call_stmt);
704 if (decl)
705 node->create_edge (cgraph_node::get_create (decl), call_stmt, bb->count);
708 /* Expand the UBSAN_BOUNDS special builtin function. */
710 bool
711 ubsan_expand_bounds_ifn (gimple_stmt_iterator *gsi)
713 gimple *stmt = gsi_stmt (*gsi);
714 location_t loc = gimple_location (stmt);
715 gcc_assert (gimple_call_num_args (stmt) == 3);
717 /* Pick up the arguments of the UBSAN_BOUNDS call. */
718 tree type = TREE_TYPE (TREE_TYPE (gimple_call_arg (stmt, 0)));
719 tree index = gimple_call_arg (stmt, 1);
720 tree orig_index = index;
721 tree bound = gimple_call_arg (stmt, 2);
723 gimple_stmt_iterator gsi_orig = *gsi;
725 /* Create condition "if (index >= bound)". */
726 basic_block then_bb, fallthru_bb;
727 gimple_stmt_iterator cond_insert_point
728 = create_cond_insert_point (gsi, false, false, true,
729 &then_bb, &fallthru_bb);
730 index = fold_convert (TREE_TYPE (bound), index);
731 index = force_gimple_operand_gsi (&cond_insert_point, index,
732 true, NULL_TREE,
733 false, GSI_NEW_STMT);
734 gimple *g = gimple_build_cond (GE_EXPR, index, bound, NULL_TREE, NULL_TREE);
735 gimple_set_location (g, loc);
736 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
738 /* Generate __ubsan_handle_out_of_bounds call. */
739 *gsi = gsi_after_labels (then_bb);
740 if (flag_sanitize_trap & SANITIZE_BOUNDS)
741 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
742 else
744 tree data
745 = ubsan_create_data ("__ubsan_out_of_bounds_data", 1, &loc,
746 ubsan_type_descriptor (type, UBSAN_PRINT_ARRAY),
747 ubsan_type_descriptor (TREE_TYPE (orig_index)),
748 NULL_TREE, NULL_TREE);
749 data = build_fold_addr_expr_loc (loc, data);
750 enum built_in_function bcode
751 = (flag_sanitize_recover & SANITIZE_BOUNDS)
752 ? BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS
753 : BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS_ABORT;
754 tree fn = builtin_decl_explicit (bcode);
755 tree val = ubsan_encode_value (orig_index, UBSAN_ENCODE_VALUE_GIMPLE);
756 val = force_gimple_operand_gsi (gsi, val, true, NULL_TREE, true,
757 GSI_SAME_STMT);
758 g = gimple_build_call (fn, 2, data, val);
760 gimple_set_location (g, loc);
761 gsi_insert_before (gsi, g, GSI_SAME_STMT);
763 /* Get rid of the UBSAN_BOUNDS call from the IR. */
764 unlink_stmt_vdef (stmt);
765 gsi_remove (&gsi_orig, true);
767 /* Point GSI to next logical statement. */
768 *gsi = gsi_start_bb (fallthru_bb);
769 return true;
772 /* Expand UBSAN_NULL internal call. The type is kept on the ckind
773 argument which is a constant, because the middle-end treats pointer
774 conversions as useless and therefore the type of the first argument
775 could be changed to any other pointer type. */
777 bool
778 ubsan_expand_null_ifn (gimple_stmt_iterator *gsip)
780 gimple_stmt_iterator gsi = *gsip;
781 gimple *stmt = gsi_stmt (gsi);
782 location_t loc = gimple_location (stmt);
783 gcc_assert (gimple_call_num_args (stmt) == 3);
784 tree ptr = gimple_call_arg (stmt, 0);
785 tree ckind = gimple_call_arg (stmt, 1);
786 tree align = gimple_call_arg (stmt, 2);
787 tree check_align = NULL_TREE;
788 bool check_null;
790 basic_block cur_bb = gsi_bb (gsi);
792 gimple *g;
793 if (!integer_zerop (align))
795 unsigned int ptralign = get_pointer_alignment (ptr) / BITS_PER_UNIT;
796 if (compare_tree_int (align, ptralign) == 1)
798 check_align = make_ssa_name (pointer_sized_int_node);
799 g = gimple_build_assign (check_align, NOP_EXPR, ptr);
800 gimple_set_location (g, loc);
801 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
804 check_null = sanitize_flags_p (SANITIZE_NULL);
806 if (check_align == NULL_TREE && !check_null)
808 gsi_remove (gsip, true);
809 /* Unlink the UBSAN_NULLs vops before replacing it. */
810 unlink_stmt_vdef (stmt);
811 return true;
814 /* Split the original block holding the pointer dereference. */
815 edge e = split_block (cur_bb, stmt);
817 /* Get a hold on the 'condition block', the 'then block' and the
818 'else block'. */
819 basic_block cond_bb = e->src;
820 basic_block fallthru_bb = e->dest;
821 basic_block then_bb = create_empty_bb (cond_bb);
822 add_bb_to_loop (then_bb, cond_bb->loop_father);
823 loops_state_set (LOOPS_NEED_FIXUP);
825 /* Make an edge coming from the 'cond block' into the 'then block';
826 this edge is unlikely taken, so set up the probability accordingly. */
827 e = make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
828 e->probability = profile_probability::very_unlikely ();
829 then_bb->count = e->count ();
831 /* Connect 'then block' with the 'else block'. This is needed
832 as the ubsan routines we call in the 'then block' are not noreturn.
833 The 'then block' only has one outcoming edge. */
834 make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);
836 /* Set up the fallthrough basic block. */
837 e = find_edge (cond_bb, fallthru_bb);
838 e->flags = EDGE_FALSE_VALUE;
839 e->probability = profile_probability::very_likely ();
841 /* Update dominance info for the newly created then_bb; note that
842 fallthru_bb's dominance info has already been updated by
843 split_block. */
844 if (dom_info_available_p (CDI_DOMINATORS))
845 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
847 /* Put the ubsan builtin call into the newly created BB. */
848 if (flag_sanitize_trap & ((check_align ? SANITIZE_ALIGNMENT + 0 : 0)
849 | (check_null ? SANITIZE_NULL + 0 : 0)))
850 g = gimple_build_call (builtin_decl_implicit (BUILT_IN_TRAP), 0);
851 else
853 enum built_in_function bcode
854 = (flag_sanitize_recover & ((check_align ? SANITIZE_ALIGNMENT + 0 : 0)
855 | (check_null ? SANITIZE_NULL + 0 : 0)))
856 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_V1
857 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_V1_ABORT;
858 tree fn = builtin_decl_implicit (bcode);
859 int align_log = tree_log2 (align);
860 tree data
861 = ubsan_create_data ("__ubsan_null_data", 1, &loc,
862 ubsan_type_descriptor (TREE_TYPE (ckind),
863 UBSAN_PRINT_POINTER),
864 NULL_TREE,
865 build_int_cst (unsigned_char_type_node,
866 MAX (align_log, 0)),
867 fold_convert (unsigned_char_type_node, ckind),
868 NULL_TREE);
869 data = build_fold_addr_expr_loc (loc, data);
870 g = gimple_build_call (fn, 2, data,
871 check_align ? check_align
872 : build_zero_cst (pointer_sized_int_node));
874 gimple_stmt_iterator gsi2 = gsi_start_bb (then_bb);
875 gimple_set_location (g, loc);
876 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
878 /* Unlink the UBSAN_NULLs vops before replacing it. */
879 unlink_stmt_vdef (stmt);
881 if (check_null)
883 g = gimple_build_cond (EQ_EXPR, ptr, build_int_cst (TREE_TYPE (ptr), 0),
884 NULL_TREE, NULL_TREE);
885 gimple_set_location (g, loc);
887 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
888 gsi_replace (&gsi, g, false);
889 stmt = g;
892 if (check_align)
894 if (check_null)
896 /* Split the block with the condition again. */
897 e = split_block (cond_bb, stmt);
898 basic_block cond1_bb = e->src;
899 basic_block cond2_bb = e->dest;
901 /* Make an edge coming from the 'cond1 block' into the 'then block';
902 this edge is unlikely taken, so set up the probability
903 accordingly. */
904 e = make_edge (cond1_bb, then_bb, EDGE_TRUE_VALUE);
905 e->probability = profile_probability::very_unlikely ();
907 /* Set up the fallthrough basic block. */
908 e = find_edge (cond1_bb, cond2_bb);
909 e->flags = EDGE_FALSE_VALUE;
910 e->probability = profile_probability::very_likely ();
912 /* Update dominance info. */
913 if (dom_info_available_p (CDI_DOMINATORS))
915 set_immediate_dominator (CDI_DOMINATORS, fallthru_bb, cond1_bb);
916 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond1_bb);
919 gsi2 = gsi_start_bb (cond2_bb);
922 tree mask = build_int_cst (pointer_sized_int_node,
923 tree_to_uhwi (align) - 1);
924 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
925 BIT_AND_EXPR, check_align, mask);
926 gimple_set_location (g, loc);
927 if (check_null)
928 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
929 else
930 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
932 g = gimple_build_cond (NE_EXPR, gimple_assign_lhs (g),
933 build_int_cst (pointer_sized_int_node, 0),
934 NULL_TREE, NULL_TREE);
935 gimple_set_location (g, loc);
936 if (check_null)
937 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
938 else
939 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
940 gsi_replace (&gsi, g, false);
942 return false;
945 #define OBJSZ_MAX_OFFSET (1024 * 16)
947 /* Expand UBSAN_OBJECT_SIZE internal call. */
949 bool
950 ubsan_expand_objsize_ifn (gimple_stmt_iterator *gsi)
952 gimple *stmt = gsi_stmt (*gsi);
953 location_t loc = gimple_location (stmt);
954 gcc_assert (gimple_call_num_args (stmt) == 4);
956 tree ptr = gimple_call_arg (stmt, 0);
957 tree offset = gimple_call_arg (stmt, 1);
958 tree size = gimple_call_arg (stmt, 2);
959 tree ckind = gimple_call_arg (stmt, 3);
960 gimple_stmt_iterator gsi_orig = *gsi;
961 gimple *g;
963 /* See if we can discard the check. */
964 if (TREE_CODE (size) == INTEGER_CST
965 && integer_all_onesp (size))
966 /* Yes, __builtin_object_size couldn't determine the
967 object size. */;
968 else if (TREE_CODE (offset) == INTEGER_CST
969 && wi::to_widest (offset) >= -OBJSZ_MAX_OFFSET
970 && wi::to_widest (offset) <= -1)
971 /* The offset is in range [-16K, -1]. */;
972 else
974 /* if (offset > objsize) */
975 basic_block then_bb, fallthru_bb;
976 gimple_stmt_iterator cond_insert_point
977 = create_cond_insert_point (gsi, false, false, true,
978 &then_bb, &fallthru_bb);
979 g = gimple_build_cond (GT_EXPR, offset, size, NULL_TREE, NULL_TREE);
980 gimple_set_location (g, loc);
981 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
983 /* If the offset is small enough, we don't need the second
984 run-time check. */
985 if (TREE_CODE (offset) == INTEGER_CST
986 && wi::to_widest (offset) >= 0
987 && wi::to_widest (offset) <= OBJSZ_MAX_OFFSET)
988 *gsi = gsi_after_labels (then_bb);
989 else
991 /* Don't issue run-time error if (ptr > ptr + offset). That
992 may happen when computing a POINTER_PLUS_EXPR. */
993 basic_block then2_bb, fallthru2_bb;
995 gimple_stmt_iterator gsi2 = gsi_after_labels (then_bb);
996 cond_insert_point = create_cond_insert_point (&gsi2, false, false,
997 true, &then2_bb,
998 &fallthru2_bb);
999 /* Convert the pointer to an integer type. */
1000 tree p = make_ssa_name (pointer_sized_int_node);
1001 g = gimple_build_assign (p, NOP_EXPR, ptr);
1002 gimple_set_location (g, loc);
1003 gsi_insert_before (&cond_insert_point, g, GSI_NEW_STMT);
1004 p = gimple_assign_lhs (g);
1005 /* Compute ptr + offset. */
1006 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
1007 PLUS_EXPR, p, offset);
1008 gimple_set_location (g, loc);
1009 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
1010 /* Now build the conditional and put it into the IR. */
1011 g = gimple_build_cond (LE_EXPR, p, gimple_assign_lhs (g),
1012 NULL_TREE, NULL_TREE);
1013 gimple_set_location (g, loc);
1014 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
1015 *gsi = gsi_after_labels (then2_bb);
1018 /* Generate __ubsan_handle_type_mismatch call. */
1019 if (flag_sanitize_trap & SANITIZE_OBJECT_SIZE)
1020 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1021 else
1023 tree data
1024 = ubsan_create_data ("__ubsan_objsz_data", 1, &loc,
1025 ubsan_type_descriptor (TREE_TYPE (ptr),
1026 UBSAN_PRINT_POINTER),
1027 NULL_TREE,
1028 build_zero_cst (unsigned_char_type_node),
1029 ckind,
1030 NULL_TREE);
1031 data = build_fold_addr_expr_loc (loc, data);
1032 enum built_in_function bcode
1033 = (flag_sanitize_recover & SANITIZE_OBJECT_SIZE)
1034 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_V1
1035 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_V1_ABORT;
1036 tree p = make_ssa_name (pointer_sized_int_node);
1037 g = gimple_build_assign (p, NOP_EXPR, ptr);
1038 gimple_set_location (g, loc);
1039 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1040 g = gimple_build_call (builtin_decl_explicit (bcode), 2, data, p);
1042 gimple_set_location (g, loc);
1043 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1045 /* Point GSI to next logical statement. */
1046 *gsi = gsi_start_bb (fallthru_bb);
1048 /* Get rid of the UBSAN_OBJECT_SIZE call from the IR. */
1049 unlink_stmt_vdef (stmt);
1050 gsi_remove (&gsi_orig, true);
1051 return true;
1054 /* Get rid of the UBSAN_OBJECT_SIZE call from the IR. */
1055 unlink_stmt_vdef (stmt);
1056 gsi_remove (gsi, true);
1057 return true;
1060 /* Expand UBSAN_PTR internal call. */
1062 bool
1063 ubsan_expand_ptr_ifn (gimple_stmt_iterator *gsip)
1065 gimple_stmt_iterator gsi = *gsip;
1066 gimple *stmt = gsi_stmt (gsi);
1067 location_t loc = gimple_location (stmt);
1068 gcc_assert (gimple_call_num_args (stmt) == 2);
1069 tree ptr = gimple_call_arg (stmt, 0);
1070 tree off = gimple_call_arg (stmt, 1);
1072 if (integer_zerop (off))
1074 gsi_remove (gsip, true);
1075 unlink_stmt_vdef (stmt);
1076 return true;
1079 basic_block cur_bb = gsi_bb (gsi);
1080 tree ptrplusoff = make_ssa_name (pointer_sized_int_node);
1081 tree ptri = make_ssa_name (pointer_sized_int_node);
1082 int pos_neg = get_range_pos_neg (off);
1084 /* Split the original block holding the pointer dereference. */
1085 edge e = split_block (cur_bb, stmt);
1087 /* Get a hold on the 'condition block', the 'then block' and the
1088 'else block'. */
1089 basic_block cond_bb = e->src;
1090 basic_block fallthru_bb = e->dest;
1091 basic_block then_bb = create_empty_bb (cond_bb);
1092 basic_block cond_pos_bb = NULL, cond_neg_bb = NULL;
1093 add_bb_to_loop (then_bb, cond_bb->loop_father);
1094 loops_state_set (LOOPS_NEED_FIXUP);
1096 /* Set up the fallthrough basic block. */
1097 e->flags = EDGE_FALSE_VALUE;
1098 if (pos_neg != 3)
1100 e->probability = profile_probability::very_likely ();
1102 /* Connect 'then block' with the 'else block'. This is needed
1103 as the ubsan routines we call in the 'then block' are not noreturn.
1104 The 'then block' only has one outcoming edge. */
1105 make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);
1107 /* Make an edge coming from the 'cond block' into the 'then block';
1108 this edge is unlikely taken, so set up the probability
1109 accordingly. */
1110 e = make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
1111 e->probability = profile_probability::very_unlikely ();
1112 then_bb->count = e->count ();
1114 else
1116 e->probability = profile_probability::even ();
1118 e = split_block (fallthru_bb, (gimple *) NULL);
1119 cond_neg_bb = e->src;
1120 fallthru_bb = e->dest;
1121 e->probability = profile_probability::very_likely ();
1122 e->flags = EDGE_FALSE_VALUE;
1124 e = make_edge (cond_neg_bb, then_bb, EDGE_TRUE_VALUE);
1125 e->probability = profile_probability::very_unlikely ();
1126 then_bb->count = e->count ();
1128 cond_pos_bb = create_empty_bb (cond_bb);
1129 add_bb_to_loop (cond_pos_bb, cond_bb->loop_father);
1131 e = make_edge (cond_bb, cond_pos_bb, EDGE_TRUE_VALUE);
1132 e->probability = profile_probability::even ();
1133 cond_pos_bb->count = e->count ();
1135 e = make_edge (cond_pos_bb, then_bb, EDGE_TRUE_VALUE);
1136 e->probability = profile_probability::very_unlikely ();
1138 e = make_edge (cond_pos_bb, fallthru_bb, EDGE_FALSE_VALUE);
1139 e->probability = profile_probability::very_likely ();
1141 make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);
1144 gimple *g = gimple_build_assign (ptri, NOP_EXPR, ptr);
1145 gimple_set_location (g, loc);
1146 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
1147 g = gimple_build_assign (ptrplusoff, PLUS_EXPR, ptri, off);
1148 gimple_set_location (g, loc);
1149 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
1151 /* Update dominance info for the newly created then_bb; note that
1152 fallthru_bb's dominance info has already been updated by
1153 split_block. */
1154 if (dom_info_available_p (CDI_DOMINATORS))
1156 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
1157 if (pos_neg == 3)
1159 set_immediate_dominator (CDI_DOMINATORS, cond_pos_bb, cond_bb);
1160 set_immediate_dominator (CDI_DOMINATORS, fallthru_bb, cond_bb);
1164 /* Put the ubsan builtin call into the newly created BB. */
1165 if (flag_sanitize_trap & SANITIZE_POINTER_OVERFLOW)
1166 g = gimple_build_call (builtin_decl_implicit (BUILT_IN_TRAP), 0);
1167 else
1169 enum built_in_function bcode
1170 = (flag_sanitize_recover & SANITIZE_POINTER_OVERFLOW)
1171 ? BUILT_IN_UBSAN_HANDLE_POINTER_OVERFLOW
1172 : BUILT_IN_UBSAN_HANDLE_POINTER_OVERFLOW_ABORT;
1173 tree fn = builtin_decl_implicit (bcode);
1174 tree data
1175 = ubsan_create_data ("__ubsan_ptrovf_data", 1, &loc,
1176 NULL_TREE, NULL_TREE);
1177 data = build_fold_addr_expr_loc (loc, data);
1178 g = gimple_build_call (fn, 3, data, ptr, ptrplusoff);
1180 gimple_stmt_iterator gsi2 = gsi_start_bb (then_bb);
1181 gimple_set_location (g, loc);
1182 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
1184 /* Unlink the UBSAN_PTRs vops before replacing it. */
1185 unlink_stmt_vdef (stmt);
1187 if (TREE_CODE (off) == INTEGER_CST)
1188 g = gimple_build_cond (wi::neg_p (wi::to_wide (off)) ? LT_EXPR : GE_EXPR,
1189 ptri, fold_build1 (NEGATE_EXPR, sizetype, off),
1190 NULL_TREE, NULL_TREE);
1191 else if (pos_neg != 3)
1192 g = gimple_build_cond (pos_neg == 1 ? LT_EXPR : GT_EXPR,
1193 ptrplusoff, ptri, NULL_TREE, NULL_TREE);
1194 else
1196 gsi2 = gsi_start_bb (cond_pos_bb);
1197 g = gimple_build_cond (LT_EXPR, ptrplusoff, ptri, NULL_TREE, NULL_TREE);
1198 gimple_set_location (g, loc);
1199 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
1201 gsi2 = gsi_start_bb (cond_neg_bb);
1202 g = gimple_build_cond (GT_EXPR, ptrplusoff, ptri, NULL_TREE, NULL_TREE);
1203 gimple_set_location (g, loc);
1204 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
1206 tree t = gimple_build (&gsi, true, GSI_SAME_STMT,
1207 loc, NOP_EXPR, ssizetype, off);
1208 g = gimple_build_cond (GE_EXPR, t, ssize_int (0),
1209 NULL_TREE, NULL_TREE);
1211 gimple_set_location (g, loc);
1212 /* Replace the UBSAN_PTR with a GIMPLE_COND stmt. */
1213 gsi_replace (&gsi, g, false);
1214 return false;
1218 /* Cached __ubsan_vptr_type_cache decl. */
1219 static GTY(()) tree ubsan_vptr_type_cache_decl;
1221 /* Expand UBSAN_VPTR internal call. The type is kept on the ckind
1222 argument which is a constant, because the middle-end treats pointer
1223 conversions as useless and therefore the type of the first argument
1224 could be changed to any other pointer type. */
1226 bool
1227 ubsan_expand_vptr_ifn (gimple_stmt_iterator *gsip)
1229 gimple_stmt_iterator gsi = *gsip;
1230 gimple *stmt = gsi_stmt (gsi);
1231 location_t loc = gimple_location (stmt);
1232 gcc_assert (gimple_call_num_args (stmt) == 5);
1233 tree op = gimple_call_arg (stmt, 0);
1234 tree vptr = gimple_call_arg (stmt, 1);
1235 tree str_hash = gimple_call_arg (stmt, 2);
1236 tree ti_decl_addr = gimple_call_arg (stmt, 3);
1237 tree ckind_tree = gimple_call_arg (stmt, 4);
1238 ubsan_null_ckind ckind = (ubsan_null_ckind) tree_to_uhwi (ckind_tree);
1239 tree type = TREE_TYPE (TREE_TYPE (ckind_tree));
1240 gimple *g;
1241 basic_block fallthru_bb = NULL;
1243 if (ckind == UBSAN_DOWNCAST_POINTER)
1245 /* Guard everything with if (op != NULL) { ... }. */
1246 basic_block then_bb;
1247 gimple_stmt_iterator cond_insert_point
1248 = create_cond_insert_point (gsip, false, false, true,
1249 &then_bb, &fallthru_bb);
1250 g = gimple_build_cond (NE_EXPR, op, build_zero_cst (TREE_TYPE (op)),
1251 NULL_TREE, NULL_TREE);
1252 gimple_set_location (g, loc);
1253 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
1254 *gsip = gsi_after_labels (then_bb);
1255 gsi_remove (&gsi, false);
1256 gsi_insert_before (gsip, stmt, GSI_NEW_STMT);
1257 gsi = *gsip;
1260 tree htype = TREE_TYPE (str_hash);
1261 tree cst = wide_int_to_tree (htype,
1262 wi::uhwi (((uint64_t) 0x9ddfea08 << 32)
1263 | 0xeb382d69, 64));
1264 g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1265 vptr, str_hash);
1266 gimple_set_location (g, loc);
1267 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1268 g = gimple_build_assign (make_ssa_name (htype), MULT_EXPR,
1269 gimple_assign_lhs (g), cst);
1270 gimple_set_location (g, loc);
1271 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1272 tree t1 = gimple_assign_lhs (g);
1273 g = gimple_build_assign (make_ssa_name (htype), LSHIFT_EXPR,
1274 t1, build_int_cst (integer_type_node, 47));
1275 gimple_set_location (g, loc);
1276 tree t2 = gimple_assign_lhs (g);
1277 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1278 g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1279 vptr, t1);
1280 gimple_set_location (g, loc);
1281 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1282 g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1283 t2, gimple_assign_lhs (g));
1284 gimple_set_location (g, loc);
1285 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1286 g = gimple_build_assign (make_ssa_name (htype), MULT_EXPR,
1287 gimple_assign_lhs (g), cst);
1288 gimple_set_location (g, loc);
1289 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1290 tree t3 = gimple_assign_lhs (g);
1291 g = gimple_build_assign (make_ssa_name (htype), LSHIFT_EXPR,
1292 t3, build_int_cst (integer_type_node, 47));
1293 gimple_set_location (g, loc);
1294 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1295 g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1296 t3, gimple_assign_lhs (g));
1297 gimple_set_location (g, loc);
1298 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1299 g = gimple_build_assign (make_ssa_name (htype), MULT_EXPR,
1300 gimple_assign_lhs (g), cst);
1301 gimple_set_location (g, loc);
1302 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1303 if (!useless_type_conversion_p (pointer_sized_int_node, htype))
1305 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
1306 NOP_EXPR, gimple_assign_lhs (g));
1307 gimple_set_location (g, loc);
1308 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1310 tree hash = gimple_assign_lhs (g);
1312 if (ubsan_vptr_type_cache_decl == NULL_TREE)
1314 tree atype = build_array_type_nelts (pointer_sized_int_node, 128);
1315 tree array = build_decl (UNKNOWN_LOCATION, VAR_DECL,
1316 get_identifier ("__ubsan_vptr_type_cache"),
1317 atype);
1318 DECL_ARTIFICIAL (array) = 1;
1319 DECL_IGNORED_P (array) = 1;
1320 TREE_PUBLIC (array) = 1;
1321 TREE_STATIC (array) = 1;
1322 DECL_EXTERNAL (array) = 1;
1323 DECL_VISIBILITY (array) = VISIBILITY_DEFAULT;
1324 DECL_VISIBILITY_SPECIFIED (array) = 1;
1325 varpool_node::finalize_decl (array);
1326 ubsan_vptr_type_cache_decl = array;
1329 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
1330 BIT_AND_EXPR, hash,
1331 build_int_cst (pointer_sized_int_node, 127));
1332 gimple_set_location (g, loc);
1333 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1335 tree c = build4_loc (loc, ARRAY_REF, pointer_sized_int_node,
1336 ubsan_vptr_type_cache_decl, gimple_assign_lhs (g),
1337 NULL_TREE, NULL_TREE);
1338 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
1339 ARRAY_REF, c);
1340 gimple_set_location (g, loc);
1341 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1343 basic_block then_bb, fallthru2_bb;
1344 gimple_stmt_iterator cond_insert_point
1345 = create_cond_insert_point (gsip, false, false, true,
1346 &then_bb, &fallthru2_bb);
1347 g = gimple_build_cond (NE_EXPR, gimple_assign_lhs (g), hash,
1348 NULL_TREE, NULL_TREE);
1349 gimple_set_location (g, loc);
1350 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
1351 *gsip = gsi_after_labels (then_bb);
1352 if (fallthru_bb == NULL)
1353 fallthru_bb = fallthru2_bb;
1355 tree data
1356 = ubsan_create_data ("__ubsan_vptr_data", 1, &loc,
1357 ubsan_type_descriptor (type), NULL_TREE, ti_decl_addr,
1358 build_int_cst (unsigned_char_type_node, ckind),
1359 NULL_TREE);
1360 data = build_fold_addr_expr_loc (loc, data);
1361 enum built_in_function bcode
1362 = (flag_sanitize_recover & SANITIZE_VPTR)
1363 ? BUILT_IN_UBSAN_HANDLE_DYNAMIC_TYPE_CACHE_MISS
1364 : BUILT_IN_UBSAN_HANDLE_DYNAMIC_TYPE_CACHE_MISS_ABORT;
1366 g = gimple_build_call (builtin_decl_explicit (bcode), 3, data, op, hash);
1367 gimple_set_location (g, loc);
1368 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1370 /* Point GSI to next logical statement. */
1371 *gsip = gsi_start_bb (fallthru_bb);
1373 /* Get rid of the UBSAN_VPTR call from the IR. */
1374 unlink_stmt_vdef (stmt);
1375 gsi_remove (&gsi, true);
1376 return true;
1379 /* Instrument a memory reference. BASE is the base of MEM, IS_LHS says
1380 whether the pointer is on the left hand side of the assignment. */
1382 static void
1383 instrument_mem_ref (tree mem, tree base, gimple_stmt_iterator *iter,
1384 bool is_lhs)
1386 enum ubsan_null_ckind ikind = is_lhs ? UBSAN_STORE_OF : UBSAN_LOAD_OF;
1387 unsigned int align = 0;
1388 if (sanitize_flags_p (SANITIZE_ALIGNMENT))
1390 align = min_align_of_type (TREE_TYPE (base));
1391 if (align <= 1)
1392 align = 0;
1394 if (align == 0 && !sanitize_flags_p (SANITIZE_NULL))
1395 return;
1396 tree t = TREE_OPERAND (base, 0);
1397 if (!POINTER_TYPE_P (TREE_TYPE (t)))
1398 return;
1399 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (base)) && mem != base)
1400 ikind = UBSAN_MEMBER_ACCESS;
1401 tree kind = build_int_cst (build_pointer_type (TREE_TYPE (base)), ikind);
1402 tree alignt = build_int_cst (pointer_sized_int_node, align);
1403 gcall *g = gimple_build_call_internal (IFN_UBSAN_NULL, 3, t, kind, alignt);
1404 gimple_set_location (g, gimple_location (gsi_stmt (*iter)));
1405 gsi_insert_before (iter, g, GSI_SAME_STMT);
1408 /* Perform the pointer instrumentation. */
1410 static void
1411 instrument_null (gimple_stmt_iterator gsi, tree t, bool is_lhs)
1413 /* Handle also e.g. &s->i. */
1414 if (TREE_CODE (t) == ADDR_EXPR)
1415 t = TREE_OPERAND (t, 0);
1416 tree base = get_base_address (t);
1417 if (base != NULL_TREE
1418 && TREE_CODE (base) == MEM_REF
1419 && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
1420 instrument_mem_ref (t, base, &gsi, is_lhs);
1423 /* Instrument pointer arithmetics PTR p+ OFF. */
1425 static void
1426 instrument_pointer_overflow (gimple_stmt_iterator *gsi, tree ptr, tree off)
1428 if (TYPE_PRECISION (sizetype) != POINTER_SIZE)
1429 return;
1430 gcall *g = gimple_build_call_internal (IFN_UBSAN_PTR, 2, ptr, off);
1431 gimple_set_location (g, gimple_location (gsi_stmt (*gsi)));
1432 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1435 /* Instrument pointer arithmetics if any. */
1437 static void
1438 maybe_instrument_pointer_overflow (gimple_stmt_iterator *gsi, tree t)
1440 if (TYPE_PRECISION (sizetype) != POINTER_SIZE)
1441 return;
1443 /* Handle also e.g. &s->i. */
1444 if (TREE_CODE (t) == ADDR_EXPR)
1445 t = TREE_OPERAND (t, 0);
1447 if (!handled_component_p (t) && TREE_CODE (t) != MEM_REF)
1448 return;
1450 poly_int64 bitsize, bitpos, bytepos;
1451 tree offset;
1452 machine_mode mode;
1453 int volatilep = 0, reversep, unsignedp = 0;
1454 tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset, &mode,
1455 &unsignedp, &reversep, &volatilep);
1456 tree moff = NULL_TREE;
1458 bool decl_p = DECL_P (inner);
1459 tree base;
1460 if (decl_p)
1462 if ((VAR_P (inner)
1463 || TREE_CODE (inner) == PARM_DECL
1464 || TREE_CODE (inner) == RESULT_DECL)
1465 && DECL_REGISTER (inner))
1466 return;
1467 base = inner;
1468 /* If BASE is a fixed size automatic variable or
1469 global variable defined in the current TU and bitpos
1470 fits, don't instrument anything. */
1471 poly_int64 base_size;
1472 if (offset == NULL_TREE
1473 && maybe_ne (bitpos, 0)
1474 && (VAR_P (base)
1475 || TREE_CODE (base) == PARM_DECL
1476 || TREE_CODE (base) == RESULT_DECL)
1477 && poly_int_tree_p (DECL_SIZE (base), &base_size)
1478 && known_ge (base_size, bitpos)
1479 && (!is_global_var (base) || decl_binds_to_current_def_p (base)))
1480 return;
1482 else if (TREE_CODE (inner) == MEM_REF)
1484 base = TREE_OPERAND (inner, 0);
1485 if (TREE_CODE (base) == ADDR_EXPR
1486 && DECL_P (TREE_OPERAND (base, 0))
1487 && !TREE_ADDRESSABLE (TREE_OPERAND (base, 0))
1488 && !is_global_var (TREE_OPERAND (base, 0)))
1489 return;
1490 moff = TREE_OPERAND (inner, 1);
1491 if (integer_zerop (moff))
1492 moff = NULL_TREE;
1494 else
1495 return;
1497 if (!POINTER_TYPE_P (TREE_TYPE (base)) && !DECL_P (base))
1498 return;
1499 bytepos = bits_to_bytes_round_down (bitpos);
1500 if (offset == NULL_TREE && known_eq (bytepos, 0) && moff == NULL_TREE)
1501 return;
1503 tree base_addr = base;
1504 if (decl_p)
1505 base_addr = build1 (ADDR_EXPR,
1506 build_pointer_type (TREE_TYPE (base)), base);
1507 t = offset;
1508 if (maybe_ne (bytepos, 0))
1510 if (t)
1511 t = fold_build2 (PLUS_EXPR, TREE_TYPE (t), t,
1512 build_int_cst (TREE_TYPE (t), bytepos));
1513 else
1514 t = size_int (bytepos);
1516 if (moff)
1518 if (t)
1519 t = fold_build2 (PLUS_EXPR, TREE_TYPE (t), t,
1520 fold_convert (TREE_TYPE (t), moff));
1521 else
1522 t = fold_convert (sizetype, moff);
1524 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE, true,
1525 GSI_SAME_STMT);
1526 base_addr = force_gimple_operand_gsi (gsi, base_addr, true, NULL_TREE, true,
1527 GSI_SAME_STMT);
1528 instrument_pointer_overflow (gsi, base_addr, t);
1531 /* Build an ubsan builtin call for the signed-integer-overflow
1532 sanitization. CODE says what kind of builtin are we building,
1533 LOC is a location, LHSTYPE is the type of LHS, OP0 and OP1
1534 are operands of the binary operation. */
1536 tree
1537 ubsan_build_overflow_builtin (tree_code code, location_t loc, tree lhstype,
1538 tree op0, tree op1, tree *datap)
1540 if (flag_sanitize_trap & SANITIZE_SI_OVERFLOW)
1541 return build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
1543 tree data;
1544 if (datap && *datap)
1545 data = *datap;
1546 else
1547 data = ubsan_create_data ("__ubsan_overflow_data", 1, &loc,
1548 ubsan_type_descriptor (lhstype), NULL_TREE,
1549 NULL_TREE);
1550 if (datap)
1551 *datap = data;
1552 enum built_in_function fn_code;
1554 switch (code)
1556 case PLUS_EXPR:
1557 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1558 ? BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW
1559 : BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW_ABORT;
1560 break;
1561 case MINUS_EXPR:
1562 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1563 ? BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW
1564 : BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW_ABORT;
1565 break;
1566 case MULT_EXPR:
1567 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1568 ? BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW
1569 : BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW_ABORT;
1570 break;
1571 case NEGATE_EXPR:
1572 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1573 ? BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW
1574 : BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW_ABORT;
1575 break;
1576 default:
1577 gcc_unreachable ();
1579 tree fn = builtin_decl_explicit (fn_code);
1580 return build_call_expr_loc (loc, fn, 2 + (code != NEGATE_EXPR),
1581 build_fold_addr_expr_loc (loc, data),
1582 ubsan_encode_value (op0, UBSAN_ENCODE_VALUE_RTL),
1584 ? ubsan_encode_value (op1,
1585 UBSAN_ENCODE_VALUE_RTL)
1586 : NULL_TREE);
1589 /* Perform the signed integer instrumentation. GSI is the iterator
1590 pointing at statement we are trying to instrument. */
1592 static void
1593 instrument_si_overflow (gimple_stmt_iterator gsi)
1595 gimple *stmt = gsi_stmt (gsi);
1596 tree_code code = gimple_assign_rhs_code (stmt);
1597 tree lhs = gimple_assign_lhs (stmt);
1598 tree lhstype = TREE_TYPE (lhs);
1599 tree lhsinner = VECTOR_TYPE_P (lhstype) ? TREE_TYPE (lhstype) : lhstype;
1600 tree a, b;
1601 gimple *g;
1603 /* If this is not a signed operation, don't instrument anything here.
1604 Also punt on bit-fields. */
1605 if (!INTEGRAL_TYPE_P (lhsinner)
1606 || TYPE_OVERFLOW_WRAPS (lhsinner)
1607 || maybe_ne (GET_MODE_BITSIZE (TYPE_MODE (lhsinner)),
1608 TYPE_PRECISION (lhsinner)))
1609 return;
1611 switch (code)
1613 case MINUS_EXPR:
1614 case PLUS_EXPR:
1615 case MULT_EXPR:
1616 /* Transform
1617 i = u {+,-,*} 5;
1618 into
1619 i = UBSAN_CHECK_{ADD,SUB,MUL} (u, 5); */
1620 a = gimple_assign_rhs1 (stmt);
1621 b = gimple_assign_rhs2 (stmt);
1622 g = gimple_build_call_internal (code == PLUS_EXPR
1623 ? IFN_UBSAN_CHECK_ADD
1624 : code == MINUS_EXPR
1625 ? IFN_UBSAN_CHECK_SUB
1626 : IFN_UBSAN_CHECK_MUL, 2, a, b);
1627 gimple_call_set_lhs (g, lhs);
1628 gsi_replace (&gsi, g, true);
1629 break;
1630 case NEGATE_EXPR:
1631 /* Represent i = -u;
1633 i = UBSAN_CHECK_SUB (0, u); */
1634 a = build_zero_cst (lhstype);
1635 b = gimple_assign_rhs1 (stmt);
1636 g = gimple_build_call_internal (IFN_UBSAN_CHECK_SUB, 2, a, b);
1637 gimple_call_set_lhs (g, lhs);
1638 gsi_replace (&gsi, g, true);
1639 break;
1640 case ABS_EXPR:
1641 /* Transform i = ABS_EXPR<u>;
1642 into
1643 _N = UBSAN_CHECK_SUB (0, u);
1644 i = ABS_EXPR<_N>; */
1645 a = build_zero_cst (lhstype);
1646 b = gimple_assign_rhs1 (stmt);
1647 g = gimple_build_call_internal (IFN_UBSAN_CHECK_SUB, 2, a, b);
1648 a = make_ssa_name (lhstype);
1649 gimple_call_set_lhs (g, a);
1650 gimple_set_location (g, gimple_location (stmt));
1651 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
1652 gimple_assign_set_rhs1 (stmt, a);
1653 update_stmt (stmt);
1654 break;
1655 default:
1656 break;
1660 /* Instrument loads from (non-bitfield) bool and C++ enum values
1661 to check if the memory value is outside of the range of the valid
1662 type values. */
1664 static void
1665 instrument_bool_enum_load (gimple_stmt_iterator *gsi)
1667 gimple *stmt = gsi_stmt (*gsi);
1668 tree rhs = gimple_assign_rhs1 (stmt);
1669 tree type = TREE_TYPE (rhs);
1670 tree minv = NULL_TREE, maxv = NULL_TREE;
1672 if (TREE_CODE (type) == BOOLEAN_TYPE
1673 && sanitize_flags_p (SANITIZE_BOOL))
1675 minv = boolean_false_node;
1676 maxv = boolean_true_node;
1678 else if (TREE_CODE (type) == ENUMERAL_TYPE
1679 && sanitize_flags_p (SANITIZE_ENUM)
1680 && TREE_TYPE (type) != NULL_TREE
1681 && TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE
1682 && (TYPE_PRECISION (TREE_TYPE (type))
1683 < GET_MODE_PRECISION (SCALAR_INT_TYPE_MODE (type))))
1685 minv = TYPE_MIN_VALUE (TREE_TYPE (type));
1686 maxv = TYPE_MAX_VALUE (TREE_TYPE (type));
1688 else
1689 return;
1691 int modebitsize = GET_MODE_BITSIZE (SCALAR_INT_TYPE_MODE (type));
1692 poly_int64 bitsize, bitpos;
1693 tree offset;
1694 machine_mode mode;
1695 int volatilep = 0, reversep, unsignedp = 0;
1696 tree base = get_inner_reference (rhs, &bitsize, &bitpos, &offset, &mode,
1697 &unsignedp, &reversep, &volatilep);
1698 tree utype = build_nonstandard_integer_type (modebitsize, 1);
1700 if ((VAR_P (base) && DECL_HARD_REGISTER (base))
1701 || !multiple_p (bitpos, modebitsize)
1702 || maybe_ne (bitsize, modebitsize)
1703 || GET_MODE_BITSIZE (SCALAR_INT_TYPE_MODE (utype)) != modebitsize
1704 || TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME)
1705 return;
1707 bool ends_bb = stmt_ends_bb_p (stmt);
1708 location_t loc = gimple_location (stmt);
1709 tree lhs = gimple_assign_lhs (stmt);
1710 tree ptype = build_pointer_type (TREE_TYPE (rhs));
1711 tree atype = reference_alias_ptr_type (rhs);
1712 gimple *g = gimple_build_assign (make_ssa_name (ptype),
1713 build_fold_addr_expr (rhs));
1714 gimple_set_location (g, loc);
1715 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1716 tree mem = build2 (MEM_REF, utype, gimple_assign_lhs (g),
1717 build_int_cst (atype, 0));
1718 tree urhs = make_ssa_name (utype);
1719 if (ends_bb)
1721 gimple_assign_set_lhs (stmt, urhs);
1722 g = gimple_build_assign (lhs, NOP_EXPR, urhs);
1723 gimple_set_location (g, loc);
1724 edge e = find_fallthru_edge (gimple_bb (stmt)->succs);
1725 gsi_insert_on_edge_immediate (e, g);
1726 gimple_assign_set_rhs_from_tree (gsi, mem);
1727 update_stmt (stmt);
1728 *gsi = gsi_for_stmt (g);
1729 g = stmt;
1731 else
1733 g = gimple_build_assign (urhs, mem);
1734 gimple_set_location (g, loc);
1735 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1737 minv = fold_convert (utype, minv);
1738 maxv = fold_convert (utype, maxv);
1739 if (!integer_zerop (minv))
1741 g = gimple_build_assign (make_ssa_name (utype), MINUS_EXPR, urhs, minv);
1742 gimple_set_location (g, loc);
1743 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1746 gimple_stmt_iterator gsi2 = *gsi;
1747 basic_block then_bb, fallthru_bb;
1748 *gsi = create_cond_insert_point (gsi, true, false, true,
1749 &then_bb, &fallthru_bb);
1750 g = gimple_build_cond (GT_EXPR, gimple_assign_lhs (g),
1751 int_const_binop (MINUS_EXPR, maxv, minv),
1752 NULL_TREE, NULL_TREE);
1753 gimple_set_location (g, loc);
1754 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1756 if (!ends_bb)
1758 gimple_assign_set_rhs_with_ops (&gsi2, NOP_EXPR, urhs);
1759 update_stmt (stmt);
1762 gsi2 = gsi_after_labels (then_bb);
1763 if (flag_sanitize_trap & (TREE_CODE (type) == BOOLEAN_TYPE
1764 ? SANITIZE_BOOL : SANITIZE_ENUM))
1765 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1766 else
1768 tree data = ubsan_create_data ("__ubsan_invalid_value_data", 1, &loc,
1769 ubsan_type_descriptor (type), NULL_TREE,
1770 NULL_TREE);
1771 data = build_fold_addr_expr_loc (loc, data);
1772 enum built_in_function bcode
1773 = (flag_sanitize_recover & (TREE_CODE (type) == BOOLEAN_TYPE
1774 ? SANITIZE_BOOL : SANITIZE_ENUM))
1775 ? BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE
1776 : BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE_ABORT;
1777 tree fn = builtin_decl_explicit (bcode);
1779 tree val = ubsan_encode_value (urhs, UBSAN_ENCODE_VALUE_GIMPLE);
1780 val = force_gimple_operand_gsi (&gsi2, val, true, NULL_TREE, true,
1781 GSI_SAME_STMT);
1782 g = gimple_build_call (fn, 2, data, val);
1784 gimple_set_location (g, loc);
1785 gsi_insert_before (&gsi2, g, GSI_SAME_STMT);
1786 ubsan_create_edge (g);
1787 *gsi = gsi_for_stmt (stmt);
1790 /* Determine if we can propagate given LOCATION to ubsan_data descriptor to use
1791 new style handlers. Libubsan uses heuristics to destinguish between old and
1792 new styles and relies on these properties for filename:
1794 a) Location's filename must not be NULL.
1795 b) Location's filename must not be equal to "".
1796 c) Location's filename must not be equal to "\1".
1797 d) First two bytes of filename must not contain '\xff' symbol. */
1799 static bool
1800 ubsan_use_new_style_p (location_t loc)
1802 if (loc == UNKNOWN_LOCATION)
1803 return false;
1805 expanded_location xloc = expand_location (loc);
1806 if (xloc.file == NULL || startswith (xloc.file, "\1")
1807 || xloc.file[0] == '\0' || xloc.file[0] == '\xff'
1808 || xloc.file[1] == '\xff')
1809 return false;
1811 return true;
1814 /* Instrument float point-to-integer conversion. TYPE is an integer type of
1815 destination, EXPR is floating-point expression. */
1817 tree
1818 ubsan_instrument_float_cast (location_t loc, tree type, tree expr)
1820 tree expr_type = TREE_TYPE (expr);
1821 tree t, tt, fn, min, max;
1822 machine_mode mode = TYPE_MODE (expr_type);
1823 int prec = TYPE_PRECISION (type);
1824 bool uns_p = TYPE_UNSIGNED (type);
1825 if (loc == UNKNOWN_LOCATION)
1826 loc = input_location;
1828 /* Float to integer conversion first truncates toward zero, so
1829 even signed char c = 127.875f; is not problematic.
1830 Therefore, we should complain only if EXPR is unordered or smaller
1831 or equal than TYPE_MIN_VALUE - 1.0 or greater or equal than
1832 TYPE_MAX_VALUE + 1.0. */
1833 if (REAL_MODE_FORMAT (mode)->b == 2)
1835 /* For maximum, TYPE_MAX_VALUE might not be representable
1836 in EXPR_TYPE, e.g. if TYPE is 64-bit long long and
1837 EXPR_TYPE is IEEE single float, but TYPE_MAX_VALUE + 1.0 is
1838 either representable or infinity. */
1839 REAL_VALUE_TYPE maxval = dconst1;
1840 SET_REAL_EXP (&maxval, REAL_EXP (&maxval) + prec - !uns_p);
1841 real_convert (&maxval, mode, &maxval);
1842 max = build_real (expr_type, maxval);
1844 /* For unsigned, assume -1.0 is always representable. */
1845 if (uns_p)
1846 min = build_minus_one_cst (expr_type);
1847 else
1849 /* TYPE_MIN_VALUE is generally representable (or -inf),
1850 but TYPE_MIN_VALUE - 1.0 might not be. */
1851 REAL_VALUE_TYPE minval = dconstm1, minval2;
1852 SET_REAL_EXP (&minval, REAL_EXP (&minval) + prec - 1);
1853 real_convert (&minval, mode, &minval);
1854 real_arithmetic (&minval2, MINUS_EXPR, &minval, &dconst1);
1855 real_convert (&minval2, mode, &minval2);
1856 if (real_compare (EQ_EXPR, &minval, &minval2)
1857 && !real_isinf (&minval))
1859 /* If TYPE_MIN_VALUE - 1.0 is not representable and
1860 rounds to TYPE_MIN_VALUE, we need to subtract
1861 more. As REAL_MODE_FORMAT (mode)->p is the number
1862 of base digits, we want to subtract a number that
1863 will be 1 << (REAL_MODE_FORMAT (mode)->p - 1)
1864 times smaller than minval. */
1865 minval2 = dconst1;
1866 gcc_assert (prec > REAL_MODE_FORMAT (mode)->p);
1867 SET_REAL_EXP (&minval2,
1868 REAL_EXP (&minval2) + prec - 1
1869 - REAL_MODE_FORMAT (mode)->p + 1);
1870 real_arithmetic (&minval2, MINUS_EXPR, &minval, &minval2);
1871 real_convert (&minval2, mode, &minval2);
1873 min = build_real (expr_type, minval2);
1876 else if (REAL_MODE_FORMAT (mode)->b == 10)
1878 /* For _Decimal128 up to 34 decimal digits, - sign,
1879 dot, e, exponent. */
1880 char buf[64];
1881 int p = REAL_MODE_FORMAT (mode)->p;
1882 REAL_VALUE_TYPE maxval, minval;
1884 /* Use mpfr_snprintf rounding to compute the smallest
1885 representable decimal number greater or equal than
1886 1 << (prec - !uns_p). */
1887 auto_mpfr m (prec + 2);
1888 mpfr_set_ui_2exp (m, 1, prec - !uns_p, MPFR_RNDN);
1889 mpfr_snprintf (buf, sizeof buf, "%.*RUe", p - 1, (mpfr_srcptr) m);
1890 decimal_real_from_string (&maxval, buf);
1891 max = build_real (expr_type, maxval);
1893 /* For unsigned, assume -1.0 is always representable. */
1894 if (uns_p)
1895 min = build_minus_one_cst (expr_type);
1896 else
1898 /* Use mpfr_snprintf rounding to compute the largest
1899 representable decimal number less or equal than
1900 (-1 << (prec - 1)) - 1. */
1901 mpfr_set_si_2exp (m, -1, prec - 1, MPFR_RNDN);
1902 mpfr_sub_ui (m, m, 1, MPFR_RNDN);
1903 mpfr_snprintf (buf, sizeof buf, "%.*RDe", p - 1, (mpfr_srcptr) m);
1904 decimal_real_from_string (&minval, buf);
1905 min = build_real (expr_type, minval);
1908 else
1909 return NULL_TREE;
1911 if (HONOR_NANS (mode))
1913 t = fold_build2 (UNLE_EXPR, boolean_type_node, expr, min);
1914 tt = fold_build2 (UNGE_EXPR, boolean_type_node, expr, max);
1916 else
1918 t = fold_build2 (LE_EXPR, boolean_type_node, expr, min);
1919 tt = fold_build2 (GE_EXPR, boolean_type_node, expr, max);
1921 t = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t, tt);
1922 if (integer_zerop (t))
1923 return NULL_TREE;
1925 if (flag_sanitize_trap & SANITIZE_FLOAT_CAST)
1926 fn = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
1927 else
1929 location_t *loc_ptr = NULL;
1930 unsigned num_locations = 0;
1931 /* Figure out if we can propagate location to ubsan_data and use new
1932 style handlers in libubsan. */
1933 if (ubsan_use_new_style_p (loc))
1935 loc_ptr = &loc;
1936 num_locations = 1;
1938 /* Create the __ubsan_handle_float_cast_overflow fn call. */
1939 tree data = ubsan_create_data ("__ubsan_float_cast_overflow_data",
1940 num_locations, loc_ptr,
1941 ubsan_type_descriptor (expr_type),
1942 ubsan_type_descriptor (type), NULL_TREE,
1943 NULL_TREE);
1944 enum built_in_function bcode
1945 = (flag_sanitize_recover & SANITIZE_FLOAT_CAST)
1946 ? BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW
1947 : BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW_ABORT;
1948 fn = builtin_decl_explicit (bcode);
1949 fn = build_call_expr_loc (loc, fn, 2,
1950 build_fold_addr_expr_loc (loc, data),
1951 ubsan_encode_value (expr));
1954 return fold_build3 (COND_EXPR, void_type_node, t, fn, integer_zero_node);
1957 /* Instrument values passed to function arguments with nonnull attribute. */
1959 static void
1960 instrument_nonnull_arg (gimple_stmt_iterator *gsi)
1962 gimple *stmt = gsi_stmt (*gsi);
1963 location_t loc[2];
1964 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
1965 while for nonnull sanitization it is clear. */
1966 int save_flag_delete_null_pointer_checks = flag_delete_null_pointer_checks;
1967 flag_delete_null_pointer_checks = 1;
1968 loc[0] = gimple_location (stmt);
1969 loc[1] = UNKNOWN_LOCATION;
1970 for (unsigned int i = 0; i < gimple_call_num_args (stmt); i++)
1972 tree arg = gimple_call_arg (stmt, i);
1973 if (POINTER_TYPE_P (TREE_TYPE (arg))
1974 && infer_nonnull_range_by_attribute (stmt, arg))
1976 gimple *g;
1977 if (!is_gimple_val (arg))
1979 g = gimple_build_assign (make_ssa_name (TREE_TYPE (arg)), arg);
1980 gimple_set_location (g, loc[0]);
1981 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1982 arg = gimple_assign_lhs (g);
1985 basic_block then_bb, fallthru_bb;
1986 *gsi = create_cond_insert_point (gsi, true, false, true,
1987 &then_bb, &fallthru_bb);
1988 g = gimple_build_cond (EQ_EXPR, arg,
1989 build_zero_cst (TREE_TYPE (arg)),
1990 NULL_TREE, NULL_TREE);
1991 gimple_set_location (g, loc[0]);
1992 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1994 *gsi = gsi_after_labels (then_bb);
1995 if (flag_sanitize_trap & SANITIZE_NONNULL_ATTRIBUTE)
1996 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1997 else
1999 tree data = ubsan_create_data ("__ubsan_nonnull_arg_data",
2000 2, loc, NULL_TREE,
2001 build_int_cst (integer_type_node,
2002 i + 1),
2003 NULL_TREE);
2004 data = build_fold_addr_expr_loc (loc[0], data);
2005 enum built_in_function bcode
2006 = (flag_sanitize_recover & SANITIZE_NONNULL_ATTRIBUTE)
2007 ? BUILT_IN_UBSAN_HANDLE_NONNULL_ARG
2008 : BUILT_IN_UBSAN_HANDLE_NONNULL_ARG_ABORT;
2009 tree fn = builtin_decl_explicit (bcode);
2011 g = gimple_build_call (fn, 1, data);
2013 gimple_set_location (g, loc[0]);
2014 gsi_insert_before (gsi, g, GSI_SAME_STMT);
2015 ubsan_create_edge (g);
2017 *gsi = gsi_for_stmt (stmt);
2019 flag_delete_null_pointer_checks = save_flag_delete_null_pointer_checks;
2022 /* Instrument returns in functions with returns_nonnull attribute. */
2024 static void
2025 instrument_nonnull_return (gimple_stmt_iterator *gsi)
2027 greturn *stmt = as_a <greturn *> (gsi_stmt (*gsi));
2028 location_t loc[2];
2029 tree arg = gimple_return_retval (stmt);
2030 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
2031 while for nonnull return sanitization it is clear. */
2032 int save_flag_delete_null_pointer_checks = flag_delete_null_pointer_checks;
2033 flag_delete_null_pointer_checks = 1;
2034 loc[0] = gimple_location (stmt);
2035 loc[1] = UNKNOWN_LOCATION;
2036 if (arg
2037 && POINTER_TYPE_P (TREE_TYPE (arg))
2038 && is_gimple_val (arg)
2039 && infer_nonnull_range_by_attribute (stmt, arg))
2041 basic_block then_bb, fallthru_bb;
2042 *gsi = create_cond_insert_point (gsi, true, false, true,
2043 &then_bb, &fallthru_bb);
2044 gimple *g = gimple_build_cond (EQ_EXPR, arg,
2045 build_zero_cst (TREE_TYPE (arg)),
2046 NULL_TREE, NULL_TREE);
2047 gimple_set_location (g, loc[0]);
2048 gsi_insert_after (gsi, g, GSI_NEW_STMT);
2050 *gsi = gsi_after_labels (then_bb);
2051 if (flag_sanitize_trap & SANITIZE_RETURNS_NONNULL_ATTRIBUTE)
2052 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
2053 else
2055 tree data = ubsan_create_data ("__ubsan_nonnull_return_data",
2056 1, &loc[1], NULL_TREE, NULL_TREE);
2057 data = build_fold_addr_expr_loc (loc[0], data);
2058 tree data2 = ubsan_create_data ("__ubsan_nonnull_return_data",
2059 1, &loc[0], NULL_TREE, NULL_TREE);
2060 data2 = build_fold_addr_expr_loc (loc[0], data2);
2061 enum built_in_function bcode
2062 = (flag_sanitize_recover & SANITIZE_RETURNS_NONNULL_ATTRIBUTE)
2063 ? BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_V1
2064 : BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_V1_ABORT;
2065 tree fn = builtin_decl_explicit (bcode);
2067 g = gimple_build_call (fn, 2, data, data2);
2069 gimple_set_location (g, loc[0]);
2070 gsi_insert_before (gsi, g, GSI_SAME_STMT);
2071 ubsan_create_edge (g);
2072 *gsi = gsi_for_stmt (stmt);
2074 flag_delete_null_pointer_checks = save_flag_delete_null_pointer_checks;
2077 /* Instrument memory references. Here we check whether the pointer
2078 points to an out-of-bounds location. */
2080 static void
2081 instrument_object_size (gimple_stmt_iterator *gsi, tree t, bool is_lhs)
2083 gimple *stmt = gsi_stmt (*gsi);
2084 location_t loc = gimple_location (stmt);
2085 tree type;
2086 tree index = NULL_TREE;
2087 HOST_WIDE_INT size_in_bytes;
2089 type = TREE_TYPE (t);
2090 if (VOID_TYPE_P (type))
2091 return;
2093 switch (TREE_CODE (t))
2095 case COMPONENT_REF:
2096 if (TREE_CODE (t) == COMPONENT_REF
2097 && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1)) != NULL_TREE)
2099 tree repr = DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1));
2100 t = build3 (COMPONENT_REF, TREE_TYPE (repr), TREE_OPERAND (t, 0),
2101 repr, TREE_OPERAND (t, 2));
2103 break;
2104 case ARRAY_REF:
2105 index = TREE_OPERAND (t, 1);
2106 break;
2107 case INDIRECT_REF:
2108 case MEM_REF:
2109 case VAR_DECL:
2110 case PARM_DECL:
2111 case RESULT_DECL:
2112 break;
2113 default:
2114 return;
2117 size_in_bytes = int_size_in_bytes (type);
2118 if (size_in_bytes <= 0)
2119 return;
2121 poly_int64 bitsize, bitpos;
2122 tree offset;
2123 machine_mode mode;
2124 int volatilep = 0, reversep, unsignedp = 0;
2125 tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset, &mode,
2126 &unsignedp, &reversep, &volatilep);
2128 if (!multiple_p (bitpos, BITS_PER_UNIT)
2129 || maybe_ne (bitsize, size_in_bytes * BITS_PER_UNIT))
2130 return;
2132 bool decl_p = DECL_P (inner);
2133 tree base;
2134 if (decl_p)
2136 if ((VAR_P (inner)
2137 || TREE_CODE (inner) == PARM_DECL
2138 || TREE_CODE (inner) == RESULT_DECL)
2139 && DECL_REGISTER (inner))
2140 return;
2141 if (t == inner && !is_global_var (t))
2142 return;
2143 base = inner;
2145 else if (TREE_CODE (inner) == MEM_REF)
2146 base = TREE_OPERAND (inner, 0);
2147 else
2148 return;
2149 tree ptr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (t)), t);
2151 while (TREE_CODE (base) == SSA_NAME)
2153 gimple *def_stmt = SSA_NAME_DEF_STMT (base);
2154 if (gimple_assign_ssa_name_copy_p (def_stmt)
2155 || (gimple_assign_cast_p (def_stmt)
2156 && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (def_stmt))))
2157 || (is_gimple_assign (def_stmt)
2158 && gimple_assign_rhs_code (def_stmt) == POINTER_PLUS_EXPR))
2160 tree rhs1 = gimple_assign_rhs1 (def_stmt);
2161 if (TREE_CODE (rhs1) == SSA_NAME
2162 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs1))
2163 break;
2164 else
2165 base = rhs1;
2167 else
2168 break;
2171 if (!POINTER_TYPE_P (TREE_TYPE (base)) && !DECL_P (base))
2172 return;
2174 tree sizet;
2175 tree base_addr = base;
2176 gimple *bos_stmt = NULL;
2177 if (decl_p)
2178 base_addr = build1 (ADDR_EXPR,
2179 build_pointer_type (TREE_TYPE (base)), base);
2180 if (compute_builtin_object_size (base_addr, OST_DYNAMIC, &sizet))
2182 else if (optimize)
2184 if (LOCATION_LOCUS (loc) == UNKNOWN_LOCATION)
2185 loc = input_location;
2186 /* Generate __builtin_dynamic_object_size call. */
2187 sizet = builtin_decl_explicit (BUILT_IN_DYNAMIC_OBJECT_SIZE);
2188 sizet = build_call_expr_loc (loc, sizet, 2, base_addr,
2189 integer_zero_node);
2190 sizet = force_gimple_operand_gsi (gsi, sizet, false, NULL_TREE, true,
2191 GSI_SAME_STMT);
2192 /* If the call above didn't end up being an integer constant, go one
2193 statement back and get the __builtin_object_size stmt. Save it,
2194 we might need it later. */
2195 if (SSA_VAR_P (sizet))
2197 gsi_prev (gsi);
2198 bos_stmt = gsi_stmt (*gsi);
2200 /* Move on to where we were. */
2201 gsi_next (gsi);
2204 else
2205 return;
2207 /* Generate UBSAN_OBJECT_SIZE (ptr, ptr+sizeof(*ptr)-base, objsize, ckind)
2208 call. */
2209 /* ptr + sizeof (*ptr) - base */
2210 t = fold_build2 (MINUS_EXPR, sizetype,
2211 fold_convert (pointer_sized_int_node, ptr),
2212 fold_convert (pointer_sized_int_node, base_addr));
2213 t = fold_build2 (PLUS_EXPR, sizetype, t, TYPE_SIZE_UNIT (type));
2215 /* Perhaps we can omit the check. */
2216 if (TREE_CODE (t) == INTEGER_CST
2217 && TREE_CODE (sizet) == INTEGER_CST
2218 && tree_int_cst_le (t, sizet))
2219 return;
2221 if (index != NULL_TREE
2222 && TREE_CODE (index) == SSA_NAME
2223 && TREE_CODE (sizet) == INTEGER_CST)
2225 gimple *def = SSA_NAME_DEF_STMT (index);
2226 if (is_gimple_assign (def)
2227 && gimple_assign_rhs_code (def) == BIT_AND_EXPR
2228 && TREE_CODE (gimple_assign_rhs2 (def)) == INTEGER_CST)
2230 tree cst = gimple_assign_rhs2 (def);
2231 tree sz = fold_build2 (EXACT_DIV_EXPR, sizetype, sizet,
2232 TYPE_SIZE_UNIT (type));
2233 if (tree_int_cst_sgn (cst) >= 0
2234 && tree_int_cst_lt (cst, sz))
2235 return;
2239 if (DECL_P (base)
2240 && decl_function_context (base) == current_function_decl
2241 && !TREE_ADDRESSABLE (base))
2242 mark_addressable (base);
2244 if (bos_stmt
2245 && gimple_call_builtin_p (bos_stmt, BUILT_IN_DYNAMIC_OBJECT_SIZE))
2246 ubsan_create_edge (bos_stmt);
2248 /* We have to emit the check. */
2249 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE, true,
2250 GSI_SAME_STMT);
2251 ptr = force_gimple_operand_gsi (gsi, ptr, true, NULL_TREE, true,
2252 GSI_SAME_STMT);
2253 tree ckind = build_int_cst (unsigned_char_type_node,
2254 is_lhs ? UBSAN_STORE_OF : UBSAN_LOAD_OF);
2255 gimple *g = gimple_build_call_internal (IFN_UBSAN_OBJECT_SIZE, 4,
2256 ptr, t, sizet, ckind);
2257 gimple_set_location (g, loc);
2258 gsi_insert_before (gsi, g, GSI_SAME_STMT);
2261 /* Instrument values passed to builtin functions. */
2263 static void
2264 instrument_builtin (gimple_stmt_iterator *gsi)
2266 gimple *stmt = gsi_stmt (*gsi);
2267 location_t loc = gimple_location (stmt);
2268 tree arg;
2269 enum built_in_function fcode
2270 = DECL_FUNCTION_CODE (gimple_call_fndecl (stmt));
2271 int kind = 0;
2272 switch (fcode)
2274 CASE_INT_FN (BUILT_IN_CLZ):
2275 kind = 1;
2276 gcc_fallthrough ();
2277 CASE_INT_FN (BUILT_IN_CTZ):
2278 arg = gimple_call_arg (stmt, 0);
2279 if (!integer_nonzerop (arg))
2281 gimple *g;
2282 if (!is_gimple_val (arg))
2284 g = gimple_build_assign (make_ssa_name (TREE_TYPE (arg)), arg);
2285 gimple_set_location (g, loc);
2286 gsi_insert_before (gsi, g, GSI_SAME_STMT);
2287 arg = gimple_assign_lhs (g);
2290 basic_block then_bb, fallthru_bb;
2291 *gsi = create_cond_insert_point (gsi, true, false, true,
2292 &then_bb, &fallthru_bb);
2293 g = gimple_build_cond (EQ_EXPR, arg,
2294 build_zero_cst (TREE_TYPE (arg)),
2295 NULL_TREE, NULL_TREE);
2296 gimple_set_location (g, loc);
2297 gsi_insert_after (gsi, g, GSI_NEW_STMT);
2299 *gsi = gsi_after_labels (then_bb);
2300 if (flag_sanitize_trap & SANITIZE_BUILTIN)
2301 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
2302 else
2304 tree t = build_int_cst (unsigned_char_type_node, kind);
2305 tree data = ubsan_create_data ("__ubsan_builtin_data",
2306 1, &loc, NULL_TREE, t, NULL_TREE);
2307 data = build_fold_addr_expr_loc (loc, data);
2308 enum built_in_function bcode
2309 = (flag_sanitize_recover & SANITIZE_BUILTIN)
2310 ? BUILT_IN_UBSAN_HANDLE_INVALID_BUILTIN
2311 : BUILT_IN_UBSAN_HANDLE_INVALID_BUILTIN_ABORT;
2312 tree fn = builtin_decl_explicit (bcode);
2314 g = gimple_build_call (fn, 1, data);
2316 gimple_set_location (g, loc);
2317 gsi_insert_before (gsi, g, GSI_SAME_STMT);
2318 ubsan_create_edge (g);
2320 *gsi = gsi_for_stmt (stmt);
2321 break;
2322 default:
2323 break;
2327 namespace {
2329 const pass_data pass_data_ubsan =
2331 GIMPLE_PASS, /* type */
2332 "ubsan", /* name */
2333 OPTGROUP_NONE, /* optinfo_flags */
2334 TV_TREE_UBSAN, /* tv_id */
2335 ( PROP_cfg | PROP_ssa ), /* properties_required */
2336 0, /* properties_provided */
2337 0, /* properties_destroyed */
2338 0, /* todo_flags_start */
2339 TODO_update_ssa, /* todo_flags_finish */
2342 class pass_ubsan : public gimple_opt_pass
2344 public:
2345 pass_ubsan (gcc::context *ctxt)
2346 : gimple_opt_pass (pass_data_ubsan, ctxt)
2349 /* opt_pass methods: */
2350 bool gate (function *) final override
2352 return sanitize_flags_p ((SANITIZE_NULL | SANITIZE_SI_OVERFLOW
2353 | SANITIZE_BOOL | SANITIZE_ENUM
2354 | SANITIZE_ALIGNMENT
2355 | SANITIZE_NONNULL_ATTRIBUTE
2356 | SANITIZE_RETURNS_NONNULL_ATTRIBUTE
2357 | SANITIZE_OBJECT_SIZE
2358 | SANITIZE_POINTER_OVERFLOW
2359 | SANITIZE_BUILTIN));
2362 unsigned int execute (function *) final override;
2364 }; // class pass_ubsan
2366 unsigned int
2367 pass_ubsan::execute (function *fun)
2369 basic_block bb;
2370 gimple_stmt_iterator gsi;
2371 unsigned int ret = 0;
2373 initialize_sanitizer_builtins ();
2375 FOR_EACH_BB_FN (bb, fun)
2377 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
2379 gimple *stmt = gsi_stmt (gsi);
2380 if (is_gimple_debug (stmt) || gimple_clobber_p (stmt))
2382 gsi_next (&gsi);
2383 continue;
2386 if ((sanitize_flags_p (SANITIZE_SI_OVERFLOW, fun->decl))
2387 && is_gimple_assign (stmt))
2388 instrument_si_overflow (gsi);
2390 if (sanitize_flags_p (SANITIZE_NULL | SANITIZE_ALIGNMENT, fun->decl))
2392 if (gimple_store_p (stmt))
2393 instrument_null (gsi, gimple_get_lhs (stmt), true);
2394 if (gimple_assign_single_p (stmt))
2395 instrument_null (gsi, gimple_assign_rhs1 (stmt), false);
2396 if (is_gimple_call (stmt))
2398 unsigned args_num = gimple_call_num_args (stmt);
2399 for (unsigned i = 0; i < args_num; ++i)
2401 tree arg = gimple_call_arg (stmt, i);
2402 if (is_gimple_reg (arg) || is_gimple_min_invariant (arg))
2403 continue;
2404 instrument_null (gsi, arg, false);
2409 if (sanitize_flags_p (SANITIZE_BOOL | SANITIZE_ENUM, fun->decl)
2410 && gimple_assign_load_p (stmt))
2412 instrument_bool_enum_load (&gsi);
2413 bb = gimple_bb (stmt);
2416 if (sanitize_flags_p (SANITIZE_NONNULL_ATTRIBUTE, fun->decl)
2417 && is_gimple_call (stmt)
2418 && !gimple_call_internal_p (stmt))
2420 instrument_nonnull_arg (&gsi);
2421 bb = gimple_bb (stmt);
2424 if (sanitize_flags_p (SANITIZE_BUILTIN, fun->decl)
2425 && gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
2427 instrument_builtin (&gsi);
2428 bb = gimple_bb (stmt);
2431 if (sanitize_flags_p (SANITIZE_RETURNS_NONNULL_ATTRIBUTE, fun->decl)
2432 && gimple_code (stmt) == GIMPLE_RETURN)
2434 instrument_nonnull_return (&gsi);
2435 bb = gimple_bb (stmt);
2438 if (sanitize_flags_p (SANITIZE_OBJECT_SIZE, fun->decl))
2440 if (gimple_store_p (stmt))
2441 instrument_object_size (&gsi, gimple_get_lhs (stmt), true);
2442 if (gimple_assign_load_p (stmt))
2443 instrument_object_size (&gsi, gimple_assign_rhs1 (stmt),
2444 false);
2445 if (is_gimple_call (stmt))
2447 unsigned args_num = gimple_call_num_args (stmt);
2448 for (unsigned i = 0; i < args_num; ++i)
2450 tree arg = gimple_call_arg (stmt, i);
2451 if (is_gimple_reg (arg) || is_gimple_min_invariant (arg))
2452 continue;
2453 instrument_object_size (&gsi, arg, false);
2458 if (sanitize_flags_p (SANITIZE_POINTER_OVERFLOW, fun->decl))
2460 if (is_gimple_assign (stmt)
2461 && gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
2462 instrument_pointer_overflow (&gsi,
2463 gimple_assign_rhs1 (stmt),
2464 gimple_assign_rhs2 (stmt));
2465 if (gimple_store_p (stmt))
2466 maybe_instrument_pointer_overflow (&gsi,
2467 gimple_get_lhs (stmt));
2468 if (gimple_assign_single_p (stmt))
2469 maybe_instrument_pointer_overflow (&gsi,
2470 gimple_assign_rhs1 (stmt));
2471 if (is_gimple_call (stmt))
2473 unsigned args_num = gimple_call_num_args (stmt);
2474 for (unsigned i = 0; i < args_num; ++i)
2476 tree arg = gimple_call_arg (stmt, i);
2477 if (is_gimple_reg (arg))
2478 continue;
2479 maybe_instrument_pointer_overflow (&gsi, arg);
2484 gsi_next (&gsi);
2486 if (gimple_purge_dead_eh_edges (bb))
2487 ret = TODO_cleanup_cfg;
2489 return ret;
2492 } // anon namespace
2494 gimple_opt_pass *
2495 make_pass_ubsan (gcc::context *ctxt)
2497 return new pass_ubsan (ctxt);
2500 #include "gt-ubsan.h"