gccrs: Add another test case for passing associated type-bounds
[official-gcc.git] / gcc / ubsan.cc
blob08c1127c8bdbce5ea224cc4f366a14aa135d5212
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"
53 /* Map from a tree to a VAR_DECL tree. */
55 struct GTY((for_user)) tree_type_map {
56 struct tree_map_base type;
57 tree decl;
60 struct tree_type_map_cache_hasher : ggc_cache_ptr_hash<tree_type_map>
62 static inline hashval_t
63 hash (tree_type_map *t)
65 return TYPE_UID (t->type.from);
68 static inline bool
69 equal (tree_type_map *a, tree_type_map *b)
71 return a->type.from == b->type.from;
74 static int
75 keep_cache_entry (tree_type_map *&m)
77 return ggc_marked_p (m->type.from);
81 static GTY ((cache))
82 hash_table<tree_type_map_cache_hasher> *decl_tree_for_type;
84 /* Lookup a VAR_DECL for TYPE, and return it if we find one. */
86 static tree
87 decl_for_type_lookup (tree type)
89 /* If the hash table is not initialized yet, create it now. */
90 if (decl_tree_for_type == NULL)
92 decl_tree_for_type
93 = hash_table<tree_type_map_cache_hasher>::create_ggc (10);
94 /* That also means we don't have to bother with the lookup. */
95 return NULL_TREE;
98 struct tree_type_map *h, in;
99 in.type.from = type;
101 h = decl_tree_for_type->find_with_hash (&in, TYPE_UID (type));
102 return h ? h->decl : NULL_TREE;
105 /* Insert a mapping TYPE->DECL in the VAR_DECL for type hashtable. */
107 static void
108 decl_for_type_insert (tree type, tree decl)
110 struct tree_type_map *h;
112 h = ggc_alloc<tree_type_map> ();
113 h->type.from = type;
114 h->decl = decl;
115 *decl_tree_for_type->find_slot_with_hash (h, TYPE_UID (type), INSERT) = h;
118 /* Helper routine, which encodes a value in the pointer_sized_int_node.
119 Arguments with precision <= POINTER_SIZE are passed directly,
120 the rest is passed by reference. T is a value we are to encode.
121 PHASE determines when this function is called. */
123 tree
124 ubsan_encode_value (tree t, enum ubsan_encode_value_phase phase)
126 tree type = TREE_TYPE (t);
127 scalar_mode mode = SCALAR_TYPE_MODE (type);
128 const unsigned int bitsize = GET_MODE_BITSIZE (mode);
129 if (bitsize <= POINTER_SIZE)
130 switch (TREE_CODE (type))
132 case BOOLEAN_TYPE:
133 case ENUMERAL_TYPE:
134 case INTEGER_TYPE:
135 return fold_build1 (NOP_EXPR, pointer_sized_int_node, t);
136 case REAL_TYPE:
138 tree itype = build_nonstandard_integer_type (bitsize, true);
139 t = fold_build1 (VIEW_CONVERT_EXPR, itype, t);
140 return fold_convert (pointer_sized_int_node, t);
142 default:
143 gcc_unreachable ();
145 else
147 if (!DECL_P (t) || !TREE_ADDRESSABLE (t))
149 /* The reason for this is that we don't want to pessimize
150 code by making vars unnecessarily addressable. */
151 tree var;
152 if (phase != UBSAN_ENCODE_VALUE_GENERIC)
154 var = create_tmp_var (type);
155 mark_addressable (var);
157 else
159 var = create_tmp_var_raw (type);
160 TREE_ADDRESSABLE (var) = 1;
161 DECL_CONTEXT (var) = current_function_decl;
163 if (phase == UBSAN_ENCODE_VALUE_RTL)
165 rtx mem = assign_stack_temp_for_type (mode, GET_MODE_SIZE (mode),
166 type);
167 SET_DECL_RTL (var, mem);
168 expand_assignment (var, t, false);
169 return build_fold_addr_expr (var);
171 if (phase != UBSAN_ENCODE_VALUE_GENERIC)
173 tree tem = build2 (MODIFY_EXPR, void_type_node, var, t);
174 t = build_fold_addr_expr (var);
175 return build2 (COMPOUND_EXPR, TREE_TYPE (t), tem, t);
177 else
179 var = build4 (TARGET_EXPR, type, var, t, NULL_TREE, NULL_TREE);
180 return build_fold_addr_expr (var);
183 else
184 return build_fold_addr_expr (t);
188 /* Cached ubsan_get_type_descriptor_type () return value. */
189 static GTY(()) tree ubsan_type_descriptor_type;
191 /* Build
192 struct __ubsan_type_descriptor
194 unsigned short __typekind;
195 unsigned short __typeinfo;
196 char __typename[];
198 type. */
200 static tree
201 ubsan_get_type_descriptor_type (void)
203 static const char *field_names[3]
204 = { "__typekind", "__typeinfo", "__typename" };
205 tree fields[3], ret;
207 if (ubsan_type_descriptor_type)
208 return ubsan_type_descriptor_type;
210 tree itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
211 tree flex_arr_type = build_array_type (char_type_node, itype);
213 ret = make_node (RECORD_TYPE);
214 for (int i = 0; i < 3; i++)
216 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
217 get_identifier (field_names[i]),
218 (i == 2) ? flex_arr_type
219 : short_unsigned_type_node);
220 DECL_CONTEXT (fields[i]) = ret;
221 if (i)
222 DECL_CHAIN (fields[i - 1]) = fields[i];
224 tree type_decl = build_decl (input_location, TYPE_DECL,
225 get_identifier ("__ubsan_type_descriptor"),
226 ret);
227 DECL_IGNORED_P (type_decl) = 1;
228 DECL_ARTIFICIAL (type_decl) = 1;
229 TYPE_FIELDS (ret) = fields[0];
230 TYPE_NAME (ret) = type_decl;
231 TYPE_STUB_DECL (ret) = type_decl;
232 TYPE_ARTIFICIAL (ret) = 1;
233 layout_type (ret);
234 ubsan_type_descriptor_type = ret;
235 return ret;
238 /* Cached ubsan_get_source_location_type () return value. */
239 static GTY(()) tree ubsan_source_location_type;
241 /* Build
242 struct __ubsan_source_location
244 const char *__filename;
245 unsigned int __line;
246 unsigned int __column;
248 type. */
250 tree
251 ubsan_get_source_location_type (void)
253 static const char *field_names[3]
254 = { "__filename", "__line", "__column" };
255 tree fields[3], ret;
256 if (ubsan_source_location_type)
257 return ubsan_source_location_type;
259 tree const_char_type = build_qualified_type (char_type_node,
260 TYPE_QUAL_CONST);
262 ret = make_node (RECORD_TYPE);
263 for (int i = 0; i < 3; i++)
265 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
266 get_identifier (field_names[i]),
267 (i == 0) ? build_pointer_type (const_char_type)
268 : unsigned_type_node);
269 DECL_CONTEXT (fields[i]) = ret;
270 if (i)
271 DECL_CHAIN (fields[i - 1]) = fields[i];
273 tree type_decl = build_decl (input_location, TYPE_DECL,
274 get_identifier ("__ubsan_source_location"),
275 ret);
276 DECL_IGNORED_P (type_decl) = 1;
277 DECL_ARTIFICIAL (type_decl) = 1;
278 TYPE_FIELDS (ret) = fields[0];
279 TYPE_NAME (ret) = type_decl;
280 TYPE_STUB_DECL (ret) = type_decl;
281 TYPE_ARTIFICIAL (ret) = 1;
282 layout_type (ret);
283 ubsan_source_location_type = ret;
284 return ret;
287 /* Helper routine that returns a CONSTRUCTOR of __ubsan_source_location
288 type with its fields filled from a location_t LOC. */
290 static tree
291 ubsan_source_location (location_t loc)
293 expanded_location xloc;
294 tree type = ubsan_get_source_location_type ();
296 xloc = expand_location (loc);
297 tree str;
298 if (xloc.file == NULL)
300 str = build_int_cst (ptr_type_node, 0);
301 xloc.line = 0;
302 xloc.column = 0;
304 else
306 /* Fill in the values from LOC. */
307 size_t len = strlen (xloc.file) + 1;
308 str = build_string (len, xloc.file);
309 TREE_TYPE (str) = build_array_type_nelts (char_type_node, len);
310 TREE_READONLY (str) = 1;
311 TREE_STATIC (str) = 1;
312 str = build_fold_addr_expr (str);
314 tree ctor = build_constructor_va (type, 3, NULL_TREE, str, NULL_TREE,
315 build_int_cst (unsigned_type_node,
316 xloc.line), NULL_TREE,
317 build_int_cst (unsigned_type_node,
318 xloc.column));
319 TREE_CONSTANT (ctor) = 1;
320 TREE_STATIC (ctor) = 1;
322 return ctor;
325 /* This routine returns a magic number for TYPE. */
327 static unsigned short
328 get_ubsan_type_info_for_type (tree type)
330 if (TREE_CODE (type) == REAL_TYPE)
331 return tree_to_uhwi (TYPE_SIZE (type));
332 else if (INTEGRAL_TYPE_P (type))
334 int prec = exact_log2 (tree_to_uhwi (TYPE_SIZE (type)));
335 gcc_assert (prec != -1);
336 return (prec << 1) | !TYPE_UNSIGNED (type);
338 else
339 return 0;
342 /* Counters for internal labels. ubsan_ids[0] for Lubsan_type,
343 ubsan_ids[1] for Lubsan_data labels. */
344 static GTY(()) unsigned int ubsan_ids[2];
346 /* Helper routine that returns ADDR_EXPR of a VAR_DECL of a type
347 descriptor. It first looks into the hash table; if not found,
348 create the VAR_DECL, put it into the hash table and return the
349 ADDR_EXPR of it. TYPE describes a particular type. PSTYLE is
350 an enum controlling how we want to print the type. */
352 tree
353 ubsan_type_descriptor (tree type, enum ubsan_print_style pstyle)
355 /* See through any typedefs. */
356 type = TYPE_MAIN_VARIANT (type);
358 tree decl = decl_for_type_lookup (type);
359 /* It is possible that some of the earlier created DECLs were found
360 unused, in that case they weren't emitted and varpool_node::get
361 returns NULL node on them. But now we really need them. Thus,
362 renew them here. */
363 if (decl != NULL_TREE && varpool_node::get (decl))
364 return build_fold_addr_expr (decl);
366 tree dtype = ubsan_get_type_descriptor_type ();
367 tree type2 = type;
368 const char *tname = NULL;
369 pretty_printer pretty_name;
370 unsigned char deref_depth = 0;
371 unsigned short tkind, tinfo;
373 /* Get the name of the type, or the name of the pointer type. */
374 if (pstyle == UBSAN_PRINT_POINTER)
376 gcc_assert (POINTER_TYPE_P (type));
377 type2 = TREE_TYPE (type);
379 /* Remove any '*' operators from TYPE. */
380 while (POINTER_TYPE_P (type2))
381 deref_depth++, type2 = TREE_TYPE (type2);
383 if (TREE_CODE (type2) == METHOD_TYPE)
384 type2 = TYPE_METHOD_BASETYPE (type2);
387 /* If an array, get its type. */
388 type2 = strip_array_types (type2);
390 if (pstyle == UBSAN_PRINT_ARRAY)
392 while (POINTER_TYPE_P (type2))
393 deref_depth++, type2 = TREE_TYPE (type2);
396 if (TYPE_NAME (type2) != NULL)
398 if (TREE_CODE (TYPE_NAME (type2)) == IDENTIFIER_NODE)
399 tname = IDENTIFIER_POINTER (TYPE_NAME (type2));
400 else if (DECL_NAME (TYPE_NAME (type2)) != NULL)
401 tname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type2)));
404 if (tname == NULL)
405 /* We weren't able to determine the type name. */
406 tname = "<unknown>";
408 pp_quote (&pretty_name);
410 tree eltype = type;
411 if (pstyle == UBSAN_PRINT_POINTER)
413 pp_printf (&pretty_name, "%s%s%s%s%s%s%s",
414 TYPE_VOLATILE (type2) ? "volatile " : "",
415 TYPE_READONLY (type2) ? "const " : "",
416 TYPE_RESTRICT (type2) ? "restrict " : "",
417 TYPE_ATOMIC (type2) ? "_Atomic " : "",
418 TREE_CODE (type2) == RECORD_TYPE
419 ? "struct "
420 : TREE_CODE (type2) == UNION_TYPE
421 ? "union " : "", tname,
422 deref_depth == 0 ? "" : " ");
423 while (deref_depth-- > 0)
424 pp_star (&pretty_name);
426 else if (pstyle == UBSAN_PRINT_ARRAY)
428 /* Pretty print the array dimensions. */
429 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
430 tree t = type;
431 pp_string (&pretty_name, tname);
432 pp_space (&pretty_name);
433 while (deref_depth-- > 0)
434 pp_star (&pretty_name);
435 while (TREE_CODE (t) == ARRAY_TYPE)
437 pp_left_bracket (&pretty_name);
438 tree dom = TYPE_DOMAIN (t);
439 if (dom != NULL_TREE
440 && TYPE_MAX_VALUE (dom) != NULL_TREE
441 && TREE_CODE (TYPE_MAX_VALUE (dom)) == INTEGER_CST)
443 unsigned HOST_WIDE_INT m;
444 if (tree_fits_uhwi_p (TYPE_MAX_VALUE (dom))
445 && (m = tree_to_uhwi (TYPE_MAX_VALUE (dom))) + 1 != 0)
446 pp_unsigned_wide_integer (&pretty_name, m + 1);
447 else
448 pp_wide_int (&pretty_name,
449 wi::add (wi::to_widest (TYPE_MAX_VALUE (dom)), 1),
450 TYPE_SIGN (TREE_TYPE (dom)));
452 else
453 /* ??? We can't determine the variable name; print VLA unspec. */
454 pp_star (&pretty_name);
455 pp_right_bracket (&pretty_name);
456 t = TREE_TYPE (t);
459 /* Save the tree with stripped types. */
460 eltype = t;
462 else
463 pp_string (&pretty_name, tname);
465 pp_quote (&pretty_name);
467 switch (TREE_CODE (eltype))
469 case BOOLEAN_TYPE:
470 case ENUMERAL_TYPE:
471 case INTEGER_TYPE:
472 tkind = 0x0000;
473 break;
474 case REAL_TYPE:
475 /* FIXME: libubsan right now only supports float, double and
476 long double type formats. */
477 if (TYPE_MODE (eltype) == TYPE_MODE (float_type_node)
478 || TYPE_MODE (eltype) == TYPE_MODE (double_type_node)
479 || TYPE_MODE (eltype) == TYPE_MODE (long_double_type_node))
480 tkind = 0x0001;
481 else
482 tkind = 0xffff;
483 break;
484 default:
485 tkind = 0xffff;
486 break;
488 tinfo = get_ubsan_type_info_for_type (eltype);
490 /* Create a new VAR_DECL of type descriptor. */
491 const char *tmp = pp_formatted_text (&pretty_name);
492 size_t len = strlen (tmp) + 1;
493 tree str = build_string (len, tmp);
494 TREE_TYPE (str) = build_array_type_nelts (char_type_node, len);
495 TREE_READONLY (str) = 1;
496 TREE_STATIC (str) = 1;
498 char tmp_name[32];
499 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_type", ubsan_ids[0]++);
500 decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name),
501 dtype);
502 TREE_STATIC (decl) = 1;
503 TREE_PUBLIC (decl) = 0;
504 DECL_ARTIFICIAL (decl) = 1;
505 DECL_IGNORED_P (decl) = 1;
506 DECL_EXTERNAL (decl) = 0;
507 DECL_SIZE (decl)
508 = size_binop (PLUS_EXPR, DECL_SIZE (decl), TYPE_SIZE (TREE_TYPE (str)));
509 DECL_SIZE_UNIT (decl)
510 = size_binop (PLUS_EXPR, DECL_SIZE_UNIT (decl),
511 TYPE_SIZE_UNIT (TREE_TYPE (str)));
513 tree ctor = build_constructor_va (dtype, 3, NULL_TREE,
514 build_int_cst (short_unsigned_type_node,
515 tkind), NULL_TREE,
516 build_int_cst (short_unsigned_type_node,
517 tinfo), NULL_TREE, str);
518 TREE_CONSTANT (ctor) = 1;
519 TREE_STATIC (ctor) = 1;
520 DECL_INITIAL (decl) = ctor;
521 varpool_node::finalize_decl (decl);
523 /* Save the VAR_DECL into the hash table. */
524 decl_for_type_insert (type, decl);
526 return build_fold_addr_expr (decl);
529 /* Create a structure for the ubsan library. NAME is a name of the new
530 structure. LOCCNT is number of locations, PLOC points to array of
531 locations. The arguments in ... are of __ubsan_type_descriptor type
532 and there are at most two of them, followed by NULL_TREE, followed
533 by optional extra arguments and another NULL_TREE. */
535 tree
536 ubsan_create_data (const char *name, int loccnt, const location_t *ploc, ...)
538 va_list args;
539 tree ret, t;
540 tree fields[6];
541 vec<tree, va_gc> *saved_args = NULL;
542 size_t i = 0;
543 int j;
545 /* It is possible that PCH zapped table with definitions of sanitizer
546 builtins. Reinitialize them if needed. */
547 initialize_sanitizer_builtins ();
549 /* Firstly, create a pointer to type descriptor type. */
550 tree td_type = ubsan_get_type_descriptor_type ();
551 td_type = build_pointer_type (td_type);
553 /* Create the structure type. */
554 ret = make_node (RECORD_TYPE);
555 for (j = 0; j < loccnt; j++)
557 gcc_checking_assert (i < 2);
558 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
559 ubsan_get_source_location_type ());
560 DECL_CONTEXT (fields[i]) = ret;
561 if (i)
562 DECL_CHAIN (fields[i - 1]) = fields[i];
563 i++;
566 va_start (args, ploc);
567 for (t = va_arg (args, tree); t != NULL_TREE;
568 i++, t = va_arg (args, tree))
570 gcc_checking_assert (i < 4);
571 /* Save the tree arguments for later use. */
572 vec_safe_push (saved_args, t);
573 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
574 td_type);
575 DECL_CONTEXT (fields[i]) = ret;
576 if (i)
577 DECL_CHAIN (fields[i - 1]) = fields[i];
580 for (t = va_arg (args, tree); t != NULL_TREE;
581 i++, t = va_arg (args, tree))
583 gcc_checking_assert (i < 6);
584 /* Save the tree arguments for later use. */
585 vec_safe_push (saved_args, t);
586 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
587 TREE_TYPE (t));
588 DECL_CONTEXT (fields[i]) = ret;
589 if (i)
590 DECL_CHAIN (fields[i - 1]) = fields[i];
592 va_end (args);
594 tree type_decl = build_decl (input_location, TYPE_DECL,
595 get_identifier (name), ret);
596 DECL_IGNORED_P (type_decl) = 1;
597 DECL_ARTIFICIAL (type_decl) = 1;
598 TYPE_FIELDS (ret) = fields[0];
599 TYPE_NAME (ret) = type_decl;
600 TYPE_STUB_DECL (ret) = type_decl;
601 TYPE_ARTIFICIAL (ret) = 1;
602 layout_type (ret);
604 /* Now, fill in the type. */
605 char tmp_name[32];
606 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_data", ubsan_ids[1]++);
607 tree var = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name),
608 ret);
609 TREE_STATIC (var) = 1;
610 TREE_PUBLIC (var) = 0;
611 DECL_ARTIFICIAL (var) = 1;
612 DECL_IGNORED_P (var) = 1;
613 DECL_EXTERNAL (var) = 0;
615 vec<constructor_elt, va_gc> *v;
616 vec_alloc (v, i);
617 tree ctor = build_constructor (ret, v);
619 /* If desirable, set the __ubsan_source_location element. */
620 for (j = 0; j < loccnt; j++)
622 location_t loc = LOCATION_LOCUS (ploc[j]);
623 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, ubsan_source_location (loc));
626 size_t nelts = vec_safe_length (saved_args);
627 for (i = 0; i < nelts; i++)
629 t = (*saved_args)[i];
630 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, t);
633 TREE_CONSTANT (ctor) = 1;
634 TREE_STATIC (ctor) = 1;
635 DECL_INITIAL (var) = ctor;
636 varpool_node::finalize_decl (var);
638 return var;
641 /* Shared between *build_builtin_unreachable. */
643 tree
644 sanitize_unreachable_fn (tree *data, location_t loc)
646 tree fn = NULL_TREE;
647 bool san = sanitize_flags_p (SANITIZE_UNREACHABLE);
648 if (san
649 ? (flag_sanitize_trap & SANITIZE_UNREACHABLE)
650 : flag_unreachable_traps)
652 fn = builtin_decl_explicit (BUILT_IN_UNREACHABLE_TRAP);
653 *data = NULL_TREE;
655 else if (san)
657 /* Call ubsan_create_data first as it initializes SANITIZER built-ins. */
658 *data = ubsan_create_data ("__ubsan_unreachable_data", 1, &loc,
659 NULL_TREE, NULL_TREE);
660 fn = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE);
661 *data = build_fold_addr_expr_loc (loc, *data);
663 else
665 fn = builtin_decl_explicit (BUILT_IN_UNREACHABLE);
666 *data = NULL_TREE;
668 return fn;
671 /* Rewrite a gcall to __builtin_unreachable for -fsanitize=unreachable. Called
672 by the sanopt pass. */
674 bool
675 ubsan_instrument_unreachable (gimple_stmt_iterator *gsi)
677 location_t loc = gimple_location (gsi_stmt (*gsi));
678 gimple *g = gimple_build_builtin_unreachable (loc);
679 gsi_replace (gsi, g, false);
680 return false;
683 /* Return true if T is a call to a libubsan routine. */
685 bool
686 is_ubsan_builtin_p (tree t)
688 return TREE_CODE (t) == FUNCTION_DECL
689 && fndecl_built_in_p (t, BUILT_IN_NORMAL)
690 && strncmp (IDENTIFIER_POINTER (DECL_NAME (t)),
691 "__builtin___ubsan_", 18) == 0;
694 /* Create a callgraph edge for statement STMT. */
696 static void
697 ubsan_create_edge (gimple *stmt)
699 gcall *call_stmt = dyn_cast <gcall *> (stmt);
700 basic_block bb = gimple_bb (stmt);
701 cgraph_node *node = cgraph_node::get (current_function_decl);
702 tree decl = gimple_call_fndecl (call_stmt);
703 if (decl)
704 node->create_edge (cgraph_node::get_create (decl), call_stmt, bb->count);
707 /* Expand the UBSAN_BOUNDS special builtin function. */
709 bool
710 ubsan_expand_bounds_ifn (gimple_stmt_iterator *gsi)
712 gimple *stmt = gsi_stmt (*gsi);
713 location_t loc = gimple_location (stmt);
714 gcc_assert (gimple_call_num_args (stmt) == 3);
716 /* Pick up the arguments of the UBSAN_BOUNDS call. */
717 tree type = TREE_TYPE (TREE_TYPE (gimple_call_arg (stmt, 0)));
718 tree index = gimple_call_arg (stmt, 1);
719 tree orig_index = index;
720 tree bound = gimple_call_arg (stmt, 2);
722 gimple_stmt_iterator gsi_orig = *gsi;
724 /* Create condition "if (index >= bound)". */
725 basic_block then_bb, fallthru_bb;
726 gimple_stmt_iterator cond_insert_point
727 = create_cond_insert_point (gsi, false, false, true,
728 &then_bb, &fallthru_bb);
729 index = fold_convert (TREE_TYPE (bound), index);
730 index = force_gimple_operand_gsi (&cond_insert_point, index,
731 true, NULL_TREE,
732 false, GSI_NEW_STMT);
733 gimple *g = gimple_build_cond (GE_EXPR, index, bound, NULL_TREE, NULL_TREE);
734 gimple_set_location (g, loc);
735 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
737 /* Generate __ubsan_handle_out_of_bounds call. */
738 *gsi = gsi_after_labels (then_bb);
739 if (flag_sanitize_trap & SANITIZE_BOUNDS)
740 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
741 else
743 tree data
744 = ubsan_create_data ("__ubsan_out_of_bounds_data", 1, &loc,
745 ubsan_type_descriptor (type, UBSAN_PRINT_ARRAY),
746 ubsan_type_descriptor (TREE_TYPE (orig_index)),
747 NULL_TREE, NULL_TREE);
748 data = build_fold_addr_expr_loc (loc, data);
749 enum built_in_function bcode
750 = (flag_sanitize_recover & SANITIZE_BOUNDS)
751 ? BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS
752 : BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS_ABORT;
753 tree fn = builtin_decl_explicit (bcode);
754 tree val = ubsan_encode_value (orig_index, UBSAN_ENCODE_VALUE_GIMPLE);
755 val = force_gimple_operand_gsi (gsi, val, true, NULL_TREE, true,
756 GSI_SAME_STMT);
757 g = gimple_build_call (fn, 2, data, val);
759 gimple_set_location (g, loc);
760 gsi_insert_before (gsi, g, GSI_SAME_STMT);
762 /* Get rid of the UBSAN_BOUNDS call from the IR. */
763 unlink_stmt_vdef (stmt);
764 gsi_remove (&gsi_orig, true);
766 /* Point GSI to next logical statement. */
767 *gsi = gsi_start_bb (fallthru_bb);
768 return true;
771 /* Expand UBSAN_NULL internal call. The type is kept on the ckind
772 argument which is a constant, because the middle-end treats pointer
773 conversions as useless and therefore the type of the first argument
774 could be changed to any other pointer type. */
776 bool
777 ubsan_expand_null_ifn (gimple_stmt_iterator *gsip)
779 gimple_stmt_iterator gsi = *gsip;
780 gimple *stmt = gsi_stmt (gsi);
781 location_t loc = gimple_location (stmt);
782 gcc_assert (gimple_call_num_args (stmt) == 3);
783 tree ptr = gimple_call_arg (stmt, 0);
784 tree ckind = gimple_call_arg (stmt, 1);
785 tree align = gimple_call_arg (stmt, 2);
786 tree check_align = NULL_TREE;
787 bool check_null;
789 basic_block cur_bb = gsi_bb (gsi);
791 gimple *g;
792 if (!integer_zerop (align))
794 unsigned int ptralign = get_pointer_alignment (ptr) / BITS_PER_UNIT;
795 if (compare_tree_int (align, ptralign) == 1)
797 check_align = make_ssa_name (pointer_sized_int_node);
798 g = gimple_build_assign (check_align, NOP_EXPR, ptr);
799 gimple_set_location (g, loc);
800 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
803 check_null = sanitize_flags_p (SANITIZE_NULL);
805 if (check_align == NULL_TREE && !check_null)
807 gsi_remove (gsip, true);
808 /* Unlink the UBSAN_NULLs vops before replacing it. */
809 unlink_stmt_vdef (stmt);
810 return true;
813 /* Split the original block holding the pointer dereference. */
814 edge e = split_block (cur_bb, stmt);
816 /* Get a hold on the 'condition block', the 'then block' and the
817 'else block'. */
818 basic_block cond_bb = e->src;
819 basic_block fallthru_bb = e->dest;
820 basic_block then_bb = create_empty_bb (cond_bb);
821 add_bb_to_loop (then_bb, cond_bb->loop_father);
822 loops_state_set (LOOPS_NEED_FIXUP);
824 /* Make an edge coming from the 'cond block' into the 'then block';
825 this edge is unlikely taken, so set up the probability accordingly. */
826 e = make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
827 e->probability = profile_probability::very_unlikely ();
828 then_bb->count = e->count ();
830 /* Connect 'then block' with the 'else block'. This is needed
831 as the ubsan routines we call in the 'then block' are not noreturn.
832 The 'then block' only has one outcoming edge. */
833 make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);
835 /* Set up the fallthrough basic block. */
836 e = find_edge (cond_bb, fallthru_bb);
837 e->flags = EDGE_FALSE_VALUE;
838 e->probability = profile_probability::very_likely ();
840 /* Update dominance info for the newly created then_bb; note that
841 fallthru_bb's dominance info has already been updated by
842 split_block. */
843 if (dom_info_available_p (CDI_DOMINATORS))
844 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
846 /* Put the ubsan builtin call into the newly created BB. */
847 if (flag_sanitize_trap & ((check_align ? SANITIZE_ALIGNMENT + 0 : 0)
848 | (check_null ? SANITIZE_NULL + 0 : 0)))
849 g = gimple_build_call (builtin_decl_implicit (BUILT_IN_TRAP), 0);
850 else
852 enum built_in_function bcode
853 = (flag_sanitize_recover & ((check_align ? SANITIZE_ALIGNMENT + 0 : 0)
854 | (check_null ? SANITIZE_NULL + 0 : 0)))
855 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_V1
856 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_V1_ABORT;
857 tree fn = builtin_decl_implicit (bcode);
858 int align_log = tree_log2 (align);
859 tree data
860 = ubsan_create_data ("__ubsan_null_data", 1, &loc,
861 ubsan_type_descriptor (TREE_TYPE (ckind),
862 UBSAN_PRINT_POINTER),
863 NULL_TREE,
864 build_int_cst (unsigned_char_type_node,
865 MAX (align_log, 0)),
866 fold_convert (unsigned_char_type_node, ckind),
867 NULL_TREE);
868 data = build_fold_addr_expr_loc (loc, data);
869 g = gimple_build_call (fn, 2, data,
870 check_align ? check_align
871 : build_zero_cst (pointer_sized_int_node));
873 gimple_stmt_iterator gsi2 = gsi_start_bb (then_bb);
874 gimple_set_location (g, loc);
875 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
877 /* Unlink the UBSAN_NULLs vops before replacing it. */
878 unlink_stmt_vdef (stmt);
880 if (check_null)
882 g = gimple_build_cond (EQ_EXPR, ptr, build_int_cst (TREE_TYPE (ptr), 0),
883 NULL_TREE, NULL_TREE);
884 gimple_set_location (g, loc);
886 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
887 gsi_replace (&gsi, g, false);
888 stmt = g;
891 if (check_align)
893 if (check_null)
895 /* Split the block with the condition again. */
896 e = split_block (cond_bb, stmt);
897 basic_block cond1_bb = e->src;
898 basic_block cond2_bb = e->dest;
900 /* Make an edge coming from the 'cond1 block' into the 'then block';
901 this edge is unlikely taken, so set up the probability
902 accordingly. */
903 e = make_edge (cond1_bb, then_bb, EDGE_TRUE_VALUE);
904 e->probability = profile_probability::very_unlikely ();
906 /* Set up the fallthrough basic block. */
907 e = find_edge (cond1_bb, cond2_bb);
908 e->flags = EDGE_FALSE_VALUE;
909 e->probability = profile_probability::very_likely ();
911 /* Update dominance info. */
912 if (dom_info_available_p (CDI_DOMINATORS))
914 set_immediate_dominator (CDI_DOMINATORS, fallthru_bb, cond1_bb);
915 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond1_bb);
918 gsi2 = gsi_start_bb (cond2_bb);
921 tree mask = build_int_cst (pointer_sized_int_node,
922 tree_to_uhwi (align) - 1);
923 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
924 BIT_AND_EXPR, check_align, mask);
925 gimple_set_location (g, loc);
926 if (check_null)
927 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
928 else
929 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
931 g = gimple_build_cond (NE_EXPR, gimple_assign_lhs (g),
932 build_int_cst (pointer_sized_int_node, 0),
933 NULL_TREE, NULL_TREE);
934 gimple_set_location (g, loc);
935 if (check_null)
936 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
937 else
938 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
939 gsi_replace (&gsi, g, false);
941 return false;
944 #define OBJSZ_MAX_OFFSET (1024 * 16)
946 /* Expand UBSAN_OBJECT_SIZE internal call. */
948 bool
949 ubsan_expand_objsize_ifn (gimple_stmt_iterator *gsi)
951 gimple *stmt = gsi_stmt (*gsi);
952 location_t loc = gimple_location (stmt);
953 gcc_assert (gimple_call_num_args (stmt) == 4);
955 tree ptr = gimple_call_arg (stmt, 0);
956 tree offset = gimple_call_arg (stmt, 1);
957 tree size = gimple_call_arg (stmt, 2);
958 tree ckind = gimple_call_arg (stmt, 3);
959 gimple_stmt_iterator gsi_orig = *gsi;
960 gimple *g;
962 /* See if we can discard the check. */
963 if (TREE_CODE (size) == INTEGER_CST
964 && integer_all_onesp (size))
965 /* Yes, __builtin_object_size couldn't determine the
966 object size. */;
967 else if (TREE_CODE (offset) == INTEGER_CST
968 && wi::to_widest (offset) >= -OBJSZ_MAX_OFFSET
969 && wi::to_widest (offset) <= -1)
970 /* The offset is in range [-16K, -1]. */;
971 else
973 /* if (offset > objsize) */
974 basic_block then_bb, fallthru_bb;
975 gimple_stmt_iterator cond_insert_point
976 = create_cond_insert_point (gsi, false, false, true,
977 &then_bb, &fallthru_bb);
978 g = gimple_build_cond (GT_EXPR, offset, size, NULL_TREE, NULL_TREE);
979 gimple_set_location (g, loc);
980 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
982 /* If the offset is small enough, we don't need the second
983 run-time check. */
984 if (TREE_CODE (offset) == INTEGER_CST
985 && wi::to_widest (offset) >= 0
986 && wi::to_widest (offset) <= OBJSZ_MAX_OFFSET)
987 *gsi = gsi_after_labels (then_bb);
988 else
990 /* Don't issue run-time error if (ptr > ptr + offset). That
991 may happen when computing a POINTER_PLUS_EXPR. */
992 basic_block then2_bb, fallthru2_bb;
994 gimple_stmt_iterator gsi2 = gsi_after_labels (then_bb);
995 cond_insert_point = create_cond_insert_point (&gsi2, false, false,
996 true, &then2_bb,
997 &fallthru2_bb);
998 /* Convert the pointer to an integer type. */
999 tree p = make_ssa_name (pointer_sized_int_node);
1000 g = gimple_build_assign (p, NOP_EXPR, ptr);
1001 gimple_set_location (g, loc);
1002 gsi_insert_before (&cond_insert_point, g, GSI_NEW_STMT);
1003 p = gimple_assign_lhs (g);
1004 /* Compute ptr + offset. */
1005 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
1006 PLUS_EXPR, p, offset);
1007 gimple_set_location (g, loc);
1008 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
1009 /* Now build the conditional and put it into the IR. */
1010 g = gimple_build_cond (LE_EXPR, p, gimple_assign_lhs (g),
1011 NULL_TREE, NULL_TREE);
1012 gimple_set_location (g, loc);
1013 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
1014 *gsi = gsi_after_labels (then2_bb);
1017 /* Generate __ubsan_handle_type_mismatch call. */
1018 if (flag_sanitize_trap & SANITIZE_OBJECT_SIZE)
1019 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1020 else
1022 tree data
1023 = ubsan_create_data ("__ubsan_objsz_data", 1, &loc,
1024 ubsan_type_descriptor (TREE_TYPE (ptr),
1025 UBSAN_PRINT_POINTER),
1026 NULL_TREE,
1027 build_zero_cst (unsigned_char_type_node),
1028 ckind,
1029 NULL_TREE);
1030 data = build_fold_addr_expr_loc (loc, data);
1031 enum built_in_function bcode
1032 = (flag_sanitize_recover & SANITIZE_OBJECT_SIZE)
1033 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_V1
1034 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_V1_ABORT;
1035 tree p = make_ssa_name (pointer_sized_int_node);
1036 g = gimple_build_assign (p, NOP_EXPR, ptr);
1037 gimple_set_location (g, loc);
1038 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1039 g = gimple_build_call (builtin_decl_explicit (bcode), 2, data, p);
1041 gimple_set_location (g, loc);
1042 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1044 /* Point GSI to next logical statement. */
1045 *gsi = gsi_start_bb (fallthru_bb);
1047 /* Get rid of the UBSAN_OBJECT_SIZE call from the IR. */
1048 unlink_stmt_vdef (stmt);
1049 gsi_remove (&gsi_orig, true);
1050 return true;
1053 /* Get rid of the UBSAN_OBJECT_SIZE call from the IR. */
1054 unlink_stmt_vdef (stmt);
1055 gsi_remove (gsi, true);
1056 return true;
1059 /* Expand UBSAN_PTR internal call. */
1061 bool
1062 ubsan_expand_ptr_ifn (gimple_stmt_iterator *gsip)
1064 gimple_stmt_iterator gsi = *gsip;
1065 gimple *stmt = gsi_stmt (gsi);
1066 location_t loc = gimple_location (stmt);
1067 gcc_assert (gimple_call_num_args (stmt) == 2);
1068 tree ptr = gimple_call_arg (stmt, 0);
1069 tree off = gimple_call_arg (stmt, 1);
1071 if (integer_zerop (off))
1073 gsi_remove (gsip, true);
1074 unlink_stmt_vdef (stmt);
1075 return true;
1078 basic_block cur_bb = gsi_bb (gsi);
1079 tree ptrplusoff = make_ssa_name (pointer_sized_int_node);
1080 tree ptri = make_ssa_name (pointer_sized_int_node);
1081 int pos_neg = get_range_pos_neg (off);
1083 /* Split the original block holding the pointer dereference. */
1084 edge e = split_block (cur_bb, stmt);
1086 /* Get a hold on the 'condition block', the 'then block' and the
1087 'else block'. */
1088 basic_block cond_bb = e->src;
1089 basic_block fallthru_bb = e->dest;
1090 basic_block then_bb = create_empty_bb (cond_bb);
1091 basic_block cond_pos_bb = NULL, cond_neg_bb = NULL;
1092 add_bb_to_loop (then_bb, cond_bb->loop_father);
1093 loops_state_set (LOOPS_NEED_FIXUP);
1095 /* Set up the fallthrough basic block. */
1096 e->flags = EDGE_FALSE_VALUE;
1097 if (pos_neg != 3)
1099 e->probability = profile_probability::very_likely ();
1101 /* Connect 'then block' with the 'else block'. This is needed
1102 as the ubsan routines we call in the 'then block' are not noreturn.
1103 The 'then block' only has one outcoming edge. */
1104 make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);
1106 /* Make an edge coming from the 'cond block' into the 'then block';
1107 this edge is unlikely taken, so set up the probability
1108 accordingly. */
1109 e = make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
1110 e->probability = profile_probability::very_unlikely ();
1111 then_bb->count = e->count ();
1113 else
1115 e->probability = profile_probability::even ();
1117 e = split_block (fallthru_bb, (gimple *) NULL);
1118 cond_neg_bb = e->src;
1119 fallthru_bb = e->dest;
1120 e->probability = profile_probability::very_likely ();
1121 e->flags = EDGE_FALSE_VALUE;
1123 e = make_edge (cond_neg_bb, then_bb, EDGE_TRUE_VALUE);
1124 e->probability = profile_probability::very_unlikely ();
1125 then_bb->count = e->count ();
1127 cond_pos_bb = create_empty_bb (cond_bb);
1128 add_bb_to_loop (cond_pos_bb, cond_bb->loop_father);
1130 e = make_edge (cond_bb, cond_pos_bb, EDGE_TRUE_VALUE);
1131 e->probability = profile_probability::even ();
1132 cond_pos_bb->count = e->count ();
1134 e = make_edge (cond_pos_bb, then_bb, EDGE_TRUE_VALUE);
1135 e->probability = profile_probability::very_unlikely ();
1137 e = make_edge (cond_pos_bb, fallthru_bb, EDGE_FALSE_VALUE);
1138 e->probability = profile_probability::very_likely ();
1140 make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);
1143 gimple *g = gimple_build_assign (ptri, NOP_EXPR, ptr);
1144 gimple_set_location (g, loc);
1145 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
1146 g = gimple_build_assign (ptrplusoff, PLUS_EXPR, ptri, off);
1147 gimple_set_location (g, loc);
1148 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
1150 /* Update dominance info for the newly created then_bb; note that
1151 fallthru_bb's dominance info has already been updated by
1152 split_block. */
1153 if (dom_info_available_p (CDI_DOMINATORS))
1155 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
1156 if (pos_neg == 3)
1158 set_immediate_dominator (CDI_DOMINATORS, cond_pos_bb, cond_bb);
1159 set_immediate_dominator (CDI_DOMINATORS, fallthru_bb, cond_bb);
1163 /* Put the ubsan builtin call into the newly created BB. */
1164 if (flag_sanitize_trap & SANITIZE_POINTER_OVERFLOW)
1165 g = gimple_build_call (builtin_decl_implicit (BUILT_IN_TRAP), 0);
1166 else
1168 enum built_in_function bcode
1169 = (flag_sanitize_recover & SANITIZE_POINTER_OVERFLOW)
1170 ? BUILT_IN_UBSAN_HANDLE_POINTER_OVERFLOW
1171 : BUILT_IN_UBSAN_HANDLE_POINTER_OVERFLOW_ABORT;
1172 tree fn = builtin_decl_implicit (bcode);
1173 tree data
1174 = ubsan_create_data ("__ubsan_ptrovf_data", 1, &loc,
1175 NULL_TREE, NULL_TREE);
1176 data = build_fold_addr_expr_loc (loc, data);
1177 g = gimple_build_call (fn, 3, data, ptr, ptrplusoff);
1179 gimple_stmt_iterator gsi2 = gsi_start_bb (then_bb);
1180 gimple_set_location (g, loc);
1181 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
1183 /* Unlink the UBSAN_PTRs vops before replacing it. */
1184 unlink_stmt_vdef (stmt);
1186 if (TREE_CODE (off) == INTEGER_CST)
1187 g = gimple_build_cond (wi::neg_p (wi::to_wide (off)) ? LT_EXPR : GE_EXPR,
1188 ptri, fold_build1 (NEGATE_EXPR, sizetype, off),
1189 NULL_TREE, NULL_TREE);
1190 else if (pos_neg != 3)
1191 g = gimple_build_cond (pos_neg == 1 ? LT_EXPR : GT_EXPR,
1192 ptrplusoff, ptri, NULL_TREE, NULL_TREE);
1193 else
1195 gsi2 = gsi_start_bb (cond_pos_bb);
1196 g = gimple_build_cond (LT_EXPR, ptrplusoff, ptri, NULL_TREE, NULL_TREE);
1197 gimple_set_location (g, loc);
1198 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
1200 gsi2 = gsi_start_bb (cond_neg_bb);
1201 g = gimple_build_cond (GT_EXPR, ptrplusoff, ptri, NULL_TREE, NULL_TREE);
1202 gimple_set_location (g, loc);
1203 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
1205 tree t = gimple_build (&gsi, true, GSI_SAME_STMT,
1206 loc, NOP_EXPR, ssizetype, off);
1207 g = gimple_build_cond (GE_EXPR, t, ssize_int (0),
1208 NULL_TREE, NULL_TREE);
1210 gimple_set_location (g, loc);
1211 /* Replace the UBSAN_PTR with a GIMPLE_COND stmt. */
1212 gsi_replace (&gsi, g, false);
1213 return false;
1217 /* Cached __ubsan_vptr_type_cache decl. */
1218 static GTY(()) tree ubsan_vptr_type_cache_decl;
1220 /* Expand UBSAN_VPTR internal call. The type is kept on the ckind
1221 argument which is a constant, because the middle-end treats pointer
1222 conversions as useless and therefore the type of the first argument
1223 could be changed to any other pointer type. */
1225 bool
1226 ubsan_expand_vptr_ifn (gimple_stmt_iterator *gsip)
1228 gimple_stmt_iterator gsi = *gsip;
1229 gimple *stmt = gsi_stmt (gsi);
1230 location_t loc = gimple_location (stmt);
1231 gcc_assert (gimple_call_num_args (stmt) == 5);
1232 tree op = gimple_call_arg (stmt, 0);
1233 tree vptr = gimple_call_arg (stmt, 1);
1234 tree str_hash = gimple_call_arg (stmt, 2);
1235 tree ti_decl_addr = gimple_call_arg (stmt, 3);
1236 tree ckind_tree = gimple_call_arg (stmt, 4);
1237 ubsan_null_ckind ckind = (ubsan_null_ckind) tree_to_uhwi (ckind_tree);
1238 tree type = TREE_TYPE (TREE_TYPE (ckind_tree));
1239 gimple *g;
1240 basic_block fallthru_bb = NULL;
1242 if (ckind == UBSAN_DOWNCAST_POINTER)
1244 /* Guard everything with if (op != NULL) { ... }. */
1245 basic_block then_bb;
1246 gimple_stmt_iterator cond_insert_point
1247 = create_cond_insert_point (gsip, false, false, true,
1248 &then_bb, &fallthru_bb);
1249 g = gimple_build_cond (NE_EXPR, op, build_zero_cst (TREE_TYPE (op)),
1250 NULL_TREE, NULL_TREE);
1251 gimple_set_location (g, loc);
1252 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
1253 *gsip = gsi_after_labels (then_bb);
1254 gsi_remove (&gsi, false);
1255 gsi_insert_before (gsip, stmt, GSI_NEW_STMT);
1256 gsi = *gsip;
1259 tree htype = TREE_TYPE (str_hash);
1260 tree cst = wide_int_to_tree (htype,
1261 wi::uhwi (((uint64_t) 0x9ddfea08 << 32)
1262 | 0xeb382d69, 64));
1263 g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1264 vptr, str_hash);
1265 gimple_set_location (g, loc);
1266 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1267 g = gimple_build_assign (make_ssa_name (htype), MULT_EXPR,
1268 gimple_assign_lhs (g), cst);
1269 gimple_set_location (g, loc);
1270 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1271 tree t1 = gimple_assign_lhs (g);
1272 g = gimple_build_assign (make_ssa_name (htype), LSHIFT_EXPR,
1273 t1, build_int_cst (integer_type_node, 47));
1274 gimple_set_location (g, loc);
1275 tree t2 = gimple_assign_lhs (g);
1276 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1277 g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1278 vptr, t1);
1279 gimple_set_location (g, loc);
1280 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1281 g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1282 t2, gimple_assign_lhs (g));
1283 gimple_set_location (g, loc);
1284 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1285 g = gimple_build_assign (make_ssa_name (htype), MULT_EXPR,
1286 gimple_assign_lhs (g), cst);
1287 gimple_set_location (g, loc);
1288 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1289 tree t3 = gimple_assign_lhs (g);
1290 g = gimple_build_assign (make_ssa_name (htype), LSHIFT_EXPR,
1291 t3, build_int_cst (integer_type_node, 47));
1292 gimple_set_location (g, loc);
1293 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1294 g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1295 t3, gimple_assign_lhs (g));
1296 gimple_set_location (g, loc);
1297 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1298 g = gimple_build_assign (make_ssa_name (htype), MULT_EXPR,
1299 gimple_assign_lhs (g), cst);
1300 gimple_set_location (g, loc);
1301 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1302 if (!useless_type_conversion_p (pointer_sized_int_node, htype))
1304 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
1305 NOP_EXPR, gimple_assign_lhs (g));
1306 gimple_set_location (g, loc);
1307 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1309 tree hash = gimple_assign_lhs (g);
1311 if (ubsan_vptr_type_cache_decl == NULL_TREE)
1313 tree atype = build_array_type_nelts (pointer_sized_int_node, 128);
1314 tree array = build_decl (UNKNOWN_LOCATION, VAR_DECL,
1315 get_identifier ("__ubsan_vptr_type_cache"),
1316 atype);
1317 DECL_ARTIFICIAL (array) = 1;
1318 DECL_IGNORED_P (array) = 1;
1319 TREE_PUBLIC (array) = 1;
1320 TREE_STATIC (array) = 1;
1321 DECL_EXTERNAL (array) = 1;
1322 DECL_VISIBILITY (array) = VISIBILITY_DEFAULT;
1323 DECL_VISIBILITY_SPECIFIED (array) = 1;
1324 varpool_node::finalize_decl (array);
1325 ubsan_vptr_type_cache_decl = array;
1328 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
1329 BIT_AND_EXPR, hash,
1330 build_int_cst (pointer_sized_int_node, 127));
1331 gimple_set_location (g, loc);
1332 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1334 tree c = build4_loc (loc, ARRAY_REF, pointer_sized_int_node,
1335 ubsan_vptr_type_cache_decl, gimple_assign_lhs (g),
1336 NULL_TREE, NULL_TREE);
1337 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
1338 ARRAY_REF, c);
1339 gimple_set_location (g, loc);
1340 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1342 basic_block then_bb, fallthru2_bb;
1343 gimple_stmt_iterator cond_insert_point
1344 = create_cond_insert_point (gsip, false, false, true,
1345 &then_bb, &fallthru2_bb);
1346 g = gimple_build_cond (NE_EXPR, gimple_assign_lhs (g), hash,
1347 NULL_TREE, NULL_TREE);
1348 gimple_set_location (g, loc);
1349 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
1350 *gsip = gsi_after_labels (then_bb);
1351 if (fallthru_bb == NULL)
1352 fallthru_bb = fallthru2_bb;
1354 tree data
1355 = ubsan_create_data ("__ubsan_vptr_data", 1, &loc,
1356 ubsan_type_descriptor (type), NULL_TREE, ti_decl_addr,
1357 build_int_cst (unsigned_char_type_node, ckind),
1358 NULL_TREE);
1359 data = build_fold_addr_expr_loc (loc, data);
1360 enum built_in_function bcode
1361 = (flag_sanitize_recover & SANITIZE_VPTR)
1362 ? BUILT_IN_UBSAN_HANDLE_DYNAMIC_TYPE_CACHE_MISS
1363 : BUILT_IN_UBSAN_HANDLE_DYNAMIC_TYPE_CACHE_MISS_ABORT;
1365 g = gimple_build_call (builtin_decl_explicit (bcode), 3, data, op, hash);
1366 gimple_set_location (g, loc);
1367 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1369 /* Point GSI to next logical statement. */
1370 *gsip = gsi_start_bb (fallthru_bb);
1372 /* Get rid of the UBSAN_VPTR call from the IR. */
1373 unlink_stmt_vdef (stmt);
1374 gsi_remove (&gsi, true);
1375 return true;
1378 /* Instrument a memory reference. BASE is the base of MEM, IS_LHS says
1379 whether the pointer is on the left hand side of the assignment. */
1381 static void
1382 instrument_mem_ref (tree mem, tree base, gimple_stmt_iterator *iter,
1383 bool is_lhs)
1385 enum ubsan_null_ckind ikind = is_lhs ? UBSAN_STORE_OF : UBSAN_LOAD_OF;
1386 unsigned int align = 0;
1387 if (sanitize_flags_p (SANITIZE_ALIGNMENT))
1389 align = min_align_of_type (TREE_TYPE (base));
1390 if (align <= 1)
1391 align = 0;
1393 if (align == 0 && !sanitize_flags_p (SANITIZE_NULL))
1394 return;
1395 tree t = TREE_OPERAND (base, 0);
1396 if (!POINTER_TYPE_P (TREE_TYPE (t)))
1397 return;
1398 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (base)) && mem != base)
1399 ikind = UBSAN_MEMBER_ACCESS;
1400 tree kind = build_int_cst (build_pointer_type (TREE_TYPE (base)), ikind);
1401 tree alignt = build_int_cst (pointer_sized_int_node, align);
1402 gcall *g = gimple_build_call_internal (IFN_UBSAN_NULL, 3, t, kind, alignt);
1403 gimple_set_location (g, gimple_location (gsi_stmt (*iter)));
1404 gsi_insert_before (iter, g, GSI_SAME_STMT);
1407 /* Perform the pointer instrumentation. */
1409 static void
1410 instrument_null (gimple_stmt_iterator gsi, tree t, bool is_lhs)
1412 /* Handle also e.g. &s->i. */
1413 if (TREE_CODE (t) == ADDR_EXPR)
1414 t = TREE_OPERAND (t, 0);
1415 tree base = get_base_address (t);
1416 if (base != NULL_TREE
1417 && TREE_CODE (base) == MEM_REF
1418 && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
1419 instrument_mem_ref (t, base, &gsi, is_lhs);
1422 /* Instrument pointer arithmetics PTR p+ OFF. */
1424 static void
1425 instrument_pointer_overflow (gimple_stmt_iterator *gsi, tree ptr, tree off)
1427 if (TYPE_PRECISION (sizetype) != POINTER_SIZE)
1428 return;
1429 gcall *g = gimple_build_call_internal (IFN_UBSAN_PTR, 2, ptr, off);
1430 gimple_set_location (g, gimple_location (gsi_stmt (*gsi)));
1431 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1434 /* Instrument pointer arithmetics if any. */
1436 static void
1437 maybe_instrument_pointer_overflow (gimple_stmt_iterator *gsi, tree t)
1439 if (TYPE_PRECISION (sizetype) != POINTER_SIZE)
1440 return;
1442 /* Handle also e.g. &s->i. */
1443 if (TREE_CODE (t) == ADDR_EXPR)
1444 t = TREE_OPERAND (t, 0);
1446 if (!handled_component_p (t) && TREE_CODE (t) != MEM_REF)
1447 return;
1449 poly_int64 bitsize, bitpos, bytepos;
1450 tree offset;
1451 machine_mode mode;
1452 int volatilep = 0, reversep, unsignedp = 0;
1453 tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset, &mode,
1454 &unsignedp, &reversep, &volatilep);
1455 tree moff = NULL_TREE;
1457 bool decl_p = DECL_P (inner);
1458 tree base;
1459 if (decl_p)
1461 if ((VAR_P (inner)
1462 || TREE_CODE (inner) == PARM_DECL
1463 || TREE_CODE (inner) == RESULT_DECL)
1464 && DECL_REGISTER (inner))
1465 return;
1466 base = inner;
1467 /* If BASE is a fixed size automatic variable or
1468 global variable defined in the current TU and bitpos
1469 fits, don't instrument anything. */
1470 poly_int64 base_size;
1471 if (offset == NULL_TREE
1472 && maybe_ne (bitpos, 0)
1473 && (VAR_P (base)
1474 || TREE_CODE (base) == PARM_DECL
1475 || TREE_CODE (base) == RESULT_DECL)
1476 && poly_int_tree_p (DECL_SIZE (base), &base_size)
1477 && known_ge (base_size, bitpos)
1478 && (!is_global_var (base) || decl_binds_to_current_def_p (base)))
1479 return;
1481 else if (TREE_CODE (inner) == MEM_REF)
1483 base = TREE_OPERAND (inner, 0);
1484 if (TREE_CODE (base) == ADDR_EXPR
1485 && DECL_P (TREE_OPERAND (base, 0))
1486 && !TREE_ADDRESSABLE (TREE_OPERAND (base, 0))
1487 && !is_global_var (TREE_OPERAND (base, 0)))
1488 return;
1489 moff = TREE_OPERAND (inner, 1);
1490 if (integer_zerop (moff))
1491 moff = NULL_TREE;
1493 else
1494 return;
1496 if (!POINTER_TYPE_P (TREE_TYPE (base)) && !DECL_P (base))
1497 return;
1498 bytepos = bits_to_bytes_round_down (bitpos);
1499 if (offset == NULL_TREE && known_eq (bytepos, 0) && moff == NULL_TREE)
1500 return;
1502 tree base_addr = base;
1503 if (decl_p)
1504 base_addr = build1 (ADDR_EXPR,
1505 build_pointer_type (TREE_TYPE (base)), base);
1506 t = offset;
1507 if (maybe_ne (bytepos, 0))
1509 if (t)
1510 t = fold_build2 (PLUS_EXPR, TREE_TYPE (t), t,
1511 build_int_cst (TREE_TYPE (t), bytepos));
1512 else
1513 t = size_int (bytepos);
1515 if (moff)
1517 if (t)
1518 t = fold_build2 (PLUS_EXPR, TREE_TYPE (t), t,
1519 fold_convert (TREE_TYPE (t), moff));
1520 else
1521 t = fold_convert (sizetype, moff);
1523 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE, true,
1524 GSI_SAME_STMT);
1525 base_addr = force_gimple_operand_gsi (gsi, base_addr, true, NULL_TREE, true,
1526 GSI_SAME_STMT);
1527 instrument_pointer_overflow (gsi, base_addr, t);
1530 /* Build an ubsan builtin call for the signed-integer-overflow
1531 sanitization. CODE says what kind of builtin are we building,
1532 LOC is a location, LHSTYPE is the type of LHS, OP0 and OP1
1533 are operands of the binary operation. */
1535 tree
1536 ubsan_build_overflow_builtin (tree_code code, location_t loc, tree lhstype,
1537 tree op0, tree op1, tree *datap)
1539 if (flag_sanitize_trap & SANITIZE_SI_OVERFLOW)
1540 return build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
1542 tree data;
1543 if (datap && *datap)
1544 data = *datap;
1545 else
1546 data = ubsan_create_data ("__ubsan_overflow_data", 1, &loc,
1547 ubsan_type_descriptor (lhstype), NULL_TREE,
1548 NULL_TREE);
1549 if (datap)
1550 *datap = data;
1551 enum built_in_function fn_code;
1553 switch (code)
1555 case PLUS_EXPR:
1556 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1557 ? BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW
1558 : BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW_ABORT;
1559 break;
1560 case MINUS_EXPR:
1561 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1562 ? BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW
1563 : BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW_ABORT;
1564 break;
1565 case MULT_EXPR:
1566 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1567 ? BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW
1568 : BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW_ABORT;
1569 break;
1570 case NEGATE_EXPR:
1571 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1572 ? BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW
1573 : BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW_ABORT;
1574 break;
1575 default:
1576 gcc_unreachable ();
1578 tree fn = builtin_decl_explicit (fn_code);
1579 return build_call_expr_loc (loc, fn, 2 + (code != NEGATE_EXPR),
1580 build_fold_addr_expr_loc (loc, data),
1581 ubsan_encode_value (op0, UBSAN_ENCODE_VALUE_RTL),
1583 ? ubsan_encode_value (op1,
1584 UBSAN_ENCODE_VALUE_RTL)
1585 : NULL_TREE);
1588 /* Perform the signed integer instrumentation. GSI is the iterator
1589 pointing at statement we are trying to instrument. */
1591 static void
1592 instrument_si_overflow (gimple_stmt_iterator gsi)
1594 gimple *stmt = gsi_stmt (gsi);
1595 tree_code code = gimple_assign_rhs_code (stmt);
1596 tree lhs = gimple_assign_lhs (stmt);
1597 tree lhstype = TREE_TYPE (lhs);
1598 tree lhsinner = VECTOR_TYPE_P (lhstype) ? TREE_TYPE (lhstype) : lhstype;
1599 tree a, b;
1600 gimple *g;
1602 /* If this is not a signed operation, don't instrument anything here.
1603 Also punt on bit-fields. */
1604 if (!INTEGRAL_TYPE_P (lhsinner)
1605 || TYPE_OVERFLOW_WRAPS (lhsinner)
1606 || maybe_ne (GET_MODE_BITSIZE (TYPE_MODE (lhsinner)),
1607 TYPE_PRECISION (lhsinner)))
1608 return;
1610 switch (code)
1612 case MINUS_EXPR:
1613 case PLUS_EXPR:
1614 case MULT_EXPR:
1615 /* Transform
1616 i = u {+,-,*} 5;
1617 into
1618 i = UBSAN_CHECK_{ADD,SUB,MUL} (u, 5); */
1619 a = gimple_assign_rhs1 (stmt);
1620 b = gimple_assign_rhs2 (stmt);
1621 g = gimple_build_call_internal (code == PLUS_EXPR
1622 ? IFN_UBSAN_CHECK_ADD
1623 : code == MINUS_EXPR
1624 ? IFN_UBSAN_CHECK_SUB
1625 : IFN_UBSAN_CHECK_MUL, 2, a, b);
1626 gimple_call_set_lhs (g, lhs);
1627 gsi_replace (&gsi, g, true);
1628 break;
1629 case NEGATE_EXPR:
1630 /* Represent i = -u;
1632 i = UBSAN_CHECK_SUB (0, u); */
1633 a = build_zero_cst (lhstype);
1634 b = gimple_assign_rhs1 (stmt);
1635 g = gimple_build_call_internal (IFN_UBSAN_CHECK_SUB, 2, a, b);
1636 gimple_call_set_lhs (g, lhs);
1637 gsi_replace (&gsi, g, true);
1638 break;
1639 case ABS_EXPR:
1640 /* Transform i = ABS_EXPR<u>;
1641 into
1642 _N = UBSAN_CHECK_SUB (0, u);
1643 i = ABS_EXPR<_N>; */
1644 a = build_zero_cst (lhstype);
1645 b = gimple_assign_rhs1 (stmt);
1646 g = gimple_build_call_internal (IFN_UBSAN_CHECK_SUB, 2, a, b);
1647 a = make_ssa_name (lhstype);
1648 gimple_call_set_lhs (g, a);
1649 gimple_set_location (g, gimple_location (stmt));
1650 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
1651 gimple_assign_set_rhs1 (stmt, a);
1652 update_stmt (stmt);
1653 break;
1654 default:
1655 break;
1659 /* Instrument loads from (non-bitfield) bool and C++ enum values
1660 to check if the memory value is outside of the range of the valid
1661 type values. */
1663 static void
1664 instrument_bool_enum_load (gimple_stmt_iterator *gsi)
1666 gimple *stmt = gsi_stmt (*gsi);
1667 tree rhs = gimple_assign_rhs1 (stmt);
1668 tree type = TREE_TYPE (rhs);
1669 tree minv = NULL_TREE, maxv = NULL_TREE;
1671 if (TREE_CODE (type) == BOOLEAN_TYPE
1672 && sanitize_flags_p (SANITIZE_BOOL))
1674 minv = boolean_false_node;
1675 maxv = boolean_true_node;
1677 else if (TREE_CODE (type) == ENUMERAL_TYPE
1678 && sanitize_flags_p (SANITIZE_ENUM)
1679 && TREE_TYPE (type) != NULL_TREE
1680 && TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE
1681 && (TYPE_PRECISION (TREE_TYPE (type))
1682 < GET_MODE_PRECISION (SCALAR_INT_TYPE_MODE (type))))
1684 minv = TYPE_MIN_VALUE (TREE_TYPE (type));
1685 maxv = TYPE_MAX_VALUE (TREE_TYPE (type));
1687 else
1688 return;
1690 int modebitsize = GET_MODE_BITSIZE (SCALAR_INT_TYPE_MODE (type));
1691 poly_int64 bitsize, bitpos;
1692 tree offset;
1693 machine_mode mode;
1694 int volatilep = 0, reversep, unsignedp = 0;
1695 tree base = get_inner_reference (rhs, &bitsize, &bitpos, &offset, &mode,
1696 &unsignedp, &reversep, &volatilep);
1697 tree utype = build_nonstandard_integer_type (modebitsize, 1);
1699 if ((VAR_P (base) && DECL_HARD_REGISTER (base))
1700 || !multiple_p (bitpos, modebitsize)
1701 || maybe_ne (bitsize, modebitsize)
1702 || GET_MODE_BITSIZE (SCALAR_INT_TYPE_MODE (utype)) != modebitsize
1703 || TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME)
1704 return;
1706 bool ends_bb = stmt_ends_bb_p (stmt);
1707 location_t loc = gimple_location (stmt);
1708 tree lhs = gimple_assign_lhs (stmt);
1709 tree ptype = build_pointer_type (TREE_TYPE (rhs));
1710 tree atype = reference_alias_ptr_type (rhs);
1711 gimple *g = gimple_build_assign (make_ssa_name (ptype),
1712 build_fold_addr_expr (rhs));
1713 gimple_set_location (g, loc);
1714 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1715 tree mem = build2 (MEM_REF, utype, gimple_assign_lhs (g),
1716 build_int_cst (atype, 0));
1717 tree urhs = make_ssa_name (utype);
1718 if (ends_bb)
1720 gimple_assign_set_lhs (stmt, urhs);
1721 g = gimple_build_assign (lhs, NOP_EXPR, urhs);
1722 gimple_set_location (g, loc);
1723 edge e = find_fallthru_edge (gimple_bb (stmt)->succs);
1724 gsi_insert_on_edge_immediate (e, g);
1725 gimple_assign_set_rhs_from_tree (gsi, mem);
1726 update_stmt (stmt);
1727 *gsi = gsi_for_stmt (g);
1728 g = stmt;
1730 else
1732 g = gimple_build_assign (urhs, mem);
1733 gimple_set_location (g, loc);
1734 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1736 minv = fold_convert (utype, minv);
1737 maxv = fold_convert (utype, maxv);
1738 if (!integer_zerop (minv))
1740 g = gimple_build_assign (make_ssa_name (utype), MINUS_EXPR, urhs, minv);
1741 gimple_set_location (g, loc);
1742 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1745 gimple_stmt_iterator gsi2 = *gsi;
1746 basic_block then_bb, fallthru_bb;
1747 *gsi = create_cond_insert_point (gsi, true, false, true,
1748 &then_bb, &fallthru_bb);
1749 g = gimple_build_cond (GT_EXPR, gimple_assign_lhs (g),
1750 int_const_binop (MINUS_EXPR, maxv, minv),
1751 NULL_TREE, NULL_TREE);
1752 gimple_set_location (g, loc);
1753 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1755 if (!ends_bb)
1757 gimple_assign_set_rhs_with_ops (&gsi2, NOP_EXPR, urhs);
1758 update_stmt (stmt);
1761 gsi2 = gsi_after_labels (then_bb);
1762 if (flag_sanitize_trap & (TREE_CODE (type) == BOOLEAN_TYPE
1763 ? SANITIZE_BOOL : SANITIZE_ENUM))
1764 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1765 else
1767 tree data = ubsan_create_data ("__ubsan_invalid_value_data", 1, &loc,
1768 ubsan_type_descriptor (type), NULL_TREE,
1769 NULL_TREE);
1770 data = build_fold_addr_expr_loc (loc, data);
1771 enum built_in_function bcode
1772 = (flag_sanitize_recover & (TREE_CODE (type) == BOOLEAN_TYPE
1773 ? SANITIZE_BOOL : SANITIZE_ENUM))
1774 ? BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE
1775 : BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE_ABORT;
1776 tree fn = builtin_decl_explicit (bcode);
1778 tree val = ubsan_encode_value (urhs, UBSAN_ENCODE_VALUE_GIMPLE);
1779 val = force_gimple_operand_gsi (&gsi2, val, true, NULL_TREE, true,
1780 GSI_SAME_STMT);
1781 g = gimple_build_call (fn, 2, data, val);
1783 gimple_set_location (g, loc);
1784 gsi_insert_before (&gsi2, g, GSI_SAME_STMT);
1785 ubsan_create_edge (g);
1786 *gsi = gsi_for_stmt (stmt);
1789 /* Determine if we can propagate given LOCATION to ubsan_data descriptor to use
1790 new style handlers. Libubsan uses heuristics to destinguish between old and
1791 new styles and relies on these properties for filename:
1793 a) Location's filename must not be NULL.
1794 b) Location's filename must not be equal to "".
1795 c) Location's filename must not be equal to "\1".
1796 d) First two bytes of filename must not contain '\xff' symbol. */
1798 static bool
1799 ubsan_use_new_style_p (location_t loc)
1801 if (loc == UNKNOWN_LOCATION)
1802 return false;
1804 expanded_location xloc = expand_location (loc);
1805 if (xloc.file == NULL || startswith (xloc.file, "\1")
1806 || xloc.file[0] == '\0' || xloc.file[0] == '\xff'
1807 || xloc.file[1] == '\xff')
1808 return false;
1810 return true;
1813 /* Instrument float point-to-integer conversion. TYPE is an integer type of
1814 destination, EXPR is floating-point expression. */
1816 tree
1817 ubsan_instrument_float_cast (location_t loc, tree type, tree expr)
1819 tree expr_type = TREE_TYPE (expr);
1820 tree t, tt, fn, min, max;
1821 machine_mode mode = TYPE_MODE (expr_type);
1822 int prec = TYPE_PRECISION (type);
1823 bool uns_p = TYPE_UNSIGNED (type);
1824 if (loc == UNKNOWN_LOCATION)
1825 loc = input_location;
1827 /* Float to integer conversion first truncates toward zero, so
1828 even signed char c = 127.875f; is not problematic.
1829 Therefore, we should complain only if EXPR is unordered or smaller
1830 or equal than TYPE_MIN_VALUE - 1.0 or greater or equal than
1831 TYPE_MAX_VALUE + 1.0. */
1832 if (REAL_MODE_FORMAT (mode)->b == 2)
1834 /* For maximum, TYPE_MAX_VALUE might not be representable
1835 in EXPR_TYPE, e.g. if TYPE is 64-bit long long and
1836 EXPR_TYPE is IEEE single float, but TYPE_MAX_VALUE + 1.0 is
1837 either representable or infinity. */
1838 REAL_VALUE_TYPE maxval = dconst1;
1839 SET_REAL_EXP (&maxval, REAL_EXP (&maxval) + prec - !uns_p);
1840 real_convert (&maxval, mode, &maxval);
1841 max = build_real (expr_type, maxval);
1843 /* For unsigned, assume -1.0 is always representable. */
1844 if (uns_p)
1845 min = build_minus_one_cst (expr_type);
1846 else
1848 /* TYPE_MIN_VALUE is generally representable (or -inf),
1849 but TYPE_MIN_VALUE - 1.0 might not be. */
1850 REAL_VALUE_TYPE minval = dconstm1, minval2;
1851 SET_REAL_EXP (&minval, REAL_EXP (&minval) + prec - 1);
1852 real_convert (&minval, mode, &minval);
1853 real_arithmetic (&minval2, MINUS_EXPR, &minval, &dconst1);
1854 real_convert (&minval2, mode, &minval2);
1855 if (real_compare (EQ_EXPR, &minval, &minval2)
1856 && !real_isinf (&minval))
1858 /* If TYPE_MIN_VALUE - 1.0 is not representable and
1859 rounds to TYPE_MIN_VALUE, we need to subtract
1860 more. As REAL_MODE_FORMAT (mode)->p is the number
1861 of base digits, we want to subtract a number that
1862 will be 1 << (REAL_MODE_FORMAT (mode)->p - 1)
1863 times smaller than minval. */
1864 minval2 = dconst1;
1865 gcc_assert (prec > REAL_MODE_FORMAT (mode)->p);
1866 SET_REAL_EXP (&minval2,
1867 REAL_EXP (&minval2) + prec - 1
1868 - REAL_MODE_FORMAT (mode)->p + 1);
1869 real_arithmetic (&minval2, MINUS_EXPR, &minval, &minval2);
1870 real_convert (&minval2, mode, &minval2);
1872 min = build_real (expr_type, minval2);
1875 else if (REAL_MODE_FORMAT (mode)->b == 10)
1877 /* For _Decimal128 up to 34 decimal digits, - sign,
1878 dot, e, exponent. */
1879 char buf[64];
1880 mpfr_t m;
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 mpfr_init2 (m, prec + 2);
1888 mpfr_set_ui_2exp (m, 1, prec - !uns_p, MPFR_RNDN);
1889 mpfr_snprintf (buf, sizeof buf, "%.*RUe", p - 1, 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, m);
1904 decimal_real_from_string (&minval, buf);
1905 min = build_real (expr_type, minval);
1907 mpfr_clear (m);
1909 else
1910 return NULL_TREE;
1912 if (HONOR_NANS (mode))
1914 t = fold_build2 (UNLE_EXPR, boolean_type_node, expr, min);
1915 tt = fold_build2 (UNGE_EXPR, boolean_type_node, expr, max);
1917 else
1919 t = fold_build2 (LE_EXPR, boolean_type_node, expr, min);
1920 tt = fold_build2 (GE_EXPR, boolean_type_node, expr, max);
1922 t = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t, tt);
1923 if (integer_zerop (t))
1924 return NULL_TREE;
1926 if (flag_sanitize_trap & SANITIZE_FLOAT_CAST)
1927 fn = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
1928 else
1930 location_t *loc_ptr = NULL;
1931 unsigned num_locations = 0;
1932 /* Figure out if we can propagate location to ubsan_data and use new
1933 style handlers in libubsan. */
1934 if (ubsan_use_new_style_p (loc))
1936 loc_ptr = &loc;
1937 num_locations = 1;
1939 /* Create the __ubsan_handle_float_cast_overflow fn call. */
1940 tree data = ubsan_create_data ("__ubsan_float_cast_overflow_data",
1941 num_locations, loc_ptr,
1942 ubsan_type_descriptor (expr_type),
1943 ubsan_type_descriptor (type), NULL_TREE,
1944 NULL_TREE);
1945 enum built_in_function bcode
1946 = (flag_sanitize_recover & SANITIZE_FLOAT_CAST)
1947 ? BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW
1948 : BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW_ABORT;
1949 fn = builtin_decl_explicit (bcode);
1950 fn = build_call_expr_loc (loc, fn, 2,
1951 build_fold_addr_expr_loc (loc, data),
1952 ubsan_encode_value (expr));
1955 return fold_build3 (COND_EXPR, void_type_node, t, fn, integer_zero_node);
1958 /* Instrument values passed to function arguments with nonnull attribute. */
1960 static void
1961 instrument_nonnull_arg (gimple_stmt_iterator *gsi)
1963 gimple *stmt = gsi_stmt (*gsi);
1964 location_t loc[2];
1965 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
1966 while for nonnull sanitization it is clear. */
1967 int save_flag_delete_null_pointer_checks = flag_delete_null_pointer_checks;
1968 flag_delete_null_pointer_checks = 1;
1969 loc[0] = gimple_location (stmt);
1970 loc[1] = UNKNOWN_LOCATION;
1971 for (unsigned int i = 0; i < gimple_call_num_args (stmt); i++)
1973 tree arg = gimple_call_arg (stmt, i);
1974 if (POINTER_TYPE_P (TREE_TYPE (arg))
1975 && infer_nonnull_range_by_attribute (stmt, arg))
1977 gimple *g;
1978 if (!is_gimple_val (arg))
1980 g = gimple_build_assign (make_ssa_name (TREE_TYPE (arg)), arg);
1981 gimple_set_location (g, loc[0]);
1982 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1983 arg = gimple_assign_lhs (g);
1986 basic_block then_bb, fallthru_bb;
1987 *gsi = create_cond_insert_point (gsi, true, false, true,
1988 &then_bb, &fallthru_bb);
1989 g = gimple_build_cond (EQ_EXPR, arg,
1990 build_zero_cst (TREE_TYPE (arg)),
1991 NULL_TREE, NULL_TREE);
1992 gimple_set_location (g, loc[0]);
1993 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1995 *gsi = gsi_after_labels (then_bb);
1996 if (flag_sanitize_trap & SANITIZE_NONNULL_ATTRIBUTE)
1997 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1998 else
2000 tree data = ubsan_create_data ("__ubsan_nonnull_arg_data",
2001 2, loc, NULL_TREE,
2002 build_int_cst (integer_type_node,
2003 i + 1),
2004 NULL_TREE);
2005 data = build_fold_addr_expr_loc (loc[0], data);
2006 enum built_in_function bcode
2007 = (flag_sanitize_recover & SANITIZE_NONNULL_ATTRIBUTE)
2008 ? BUILT_IN_UBSAN_HANDLE_NONNULL_ARG
2009 : BUILT_IN_UBSAN_HANDLE_NONNULL_ARG_ABORT;
2010 tree fn = builtin_decl_explicit (bcode);
2012 g = gimple_build_call (fn, 1, data);
2014 gimple_set_location (g, loc[0]);
2015 gsi_insert_before (gsi, g, GSI_SAME_STMT);
2016 ubsan_create_edge (g);
2018 *gsi = gsi_for_stmt (stmt);
2020 flag_delete_null_pointer_checks = save_flag_delete_null_pointer_checks;
2023 /* Instrument returns in functions with returns_nonnull attribute. */
2025 static void
2026 instrument_nonnull_return (gimple_stmt_iterator *gsi)
2028 greturn *stmt = as_a <greturn *> (gsi_stmt (*gsi));
2029 location_t loc[2];
2030 tree arg = gimple_return_retval (stmt);
2031 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
2032 while for nonnull return sanitization it is clear. */
2033 int save_flag_delete_null_pointer_checks = flag_delete_null_pointer_checks;
2034 flag_delete_null_pointer_checks = 1;
2035 loc[0] = gimple_location (stmt);
2036 loc[1] = UNKNOWN_LOCATION;
2037 if (arg
2038 && POINTER_TYPE_P (TREE_TYPE (arg))
2039 && is_gimple_val (arg)
2040 && infer_nonnull_range_by_attribute (stmt, arg))
2042 basic_block then_bb, fallthru_bb;
2043 *gsi = create_cond_insert_point (gsi, true, false, true,
2044 &then_bb, &fallthru_bb);
2045 gimple *g = gimple_build_cond (EQ_EXPR, arg,
2046 build_zero_cst (TREE_TYPE (arg)),
2047 NULL_TREE, NULL_TREE);
2048 gimple_set_location (g, loc[0]);
2049 gsi_insert_after (gsi, g, GSI_NEW_STMT);
2051 *gsi = gsi_after_labels (then_bb);
2052 if (flag_sanitize_trap & SANITIZE_RETURNS_NONNULL_ATTRIBUTE)
2053 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
2054 else
2056 tree data = ubsan_create_data ("__ubsan_nonnull_return_data",
2057 1, &loc[1], NULL_TREE, NULL_TREE);
2058 data = build_fold_addr_expr_loc (loc[0], data);
2059 tree data2 = ubsan_create_data ("__ubsan_nonnull_return_data",
2060 1, &loc[0], NULL_TREE, NULL_TREE);
2061 data2 = build_fold_addr_expr_loc (loc[0], data2);
2062 enum built_in_function bcode
2063 = (flag_sanitize_recover & SANITIZE_RETURNS_NONNULL_ATTRIBUTE)
2064 ? BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_V1
2065 : BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_V1_ABORT;
2066 tree fn = builtin_decl_explicit (bcode);
2068 g = gimple_build_call (fn, 2, data, data2);
2070 gimple_set_location (g, loc[0]);
2071 gsi_insert_before (gsi, g, GSI_SAME_STMT);
2072 ubsan_create_edge (g);
2073 *gsi = gsi_for_stmt (stmt);
2075 flag_delete_null_pointer_checks = save_flag_delete_null_pointer_checks;
2078 /* Instrument memory references. Here we check whether the pointer
2079 points to an out-of-bounds location. */
2081 static void
2082 instrument_object_size (gimple_stmt_iterator *gsi, tree t, bool is_lhs)
2084 gimple *stmt = gsi_stmt (*gsi);
2085 location_t loc = gimple_location (stmt);
2086 tree type;
2087 tree index = NULL_TREE;
2088 HOST_WIDE_INT size_in_bytes;
2090 type = TREE_TYPE (t);
2091 if (VOID_TYPE_P (type))
2092 return;
2094 switch (TREE_CODE (t))
2096 case COMPONENT_REF:
2097 if (TREE_CODE (t) == COMPONENT_REF
2098 && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1)) != NULL_TREE)
2100 tree repr = DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1));
2101 t = build3 (COMPONENT_REF, TREE_TYPE (repr), TREE_OPERAND (t, 0),
2102 repr, TREE_OPERAND (t, 2));
2104 break;
2105 case ARRAY_REF:
2106 index = TREE_OPERAND (t, 1);
2107 break;
2108 case INDIRECT_REF:
2109 case MEM_REF:
2110 case VAR_DECL:
2111 case PARM_DECL:
2112 case RESULT_DECL:
2113 break;
2114 default:
2115 return;
2118 size_in_bytes = int_size_in_bytes (type);
2119 if (size_in_bytes <= 0)
2120 return;
2122 poly_int64 bitsize, bitpos;
2123 tree offset;
2124 machine_mode mode;
2125 int volatilep = 0, reversep, unsignedp = 0;
2126 tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset, &mode,
2127 &unsignedp, &reversep, &volatilep);
2129 if (!multiple_p (bitpos, BITS_PER_UNIT)
2130 || maybe_ne (bitsize, size_in_bytes * BITS_PER_UNIT))
2131 return;
2133 bool decl_p = DECL_P (inner);
2134 tree base;
2135 if (decl_p)
2137 if ((VAR_P (inner)
2138 || TREE_CODE (inner) == PARM_DECL
2139 || TREE_CODE (inner) == RESULT_DECL)
2140 && DECL_REGISTER (inner))
2141 return;
2142 if (t == inner && !is_global_var (t))
2143 return;
2144 base = inner;
2146 else if (TREE_CODE (inner) == MEM_REF)
2147 base = TREE_OPERAND (inner, 0);
2148 else
2149 return;
2150 tree ptr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (t)), t);
2152 while (TREE_CODE (base) == SSA_NAME)
2154 gimple *def_stmt = SSA_NAME_DEF_STMT (base);
2155 if (gimple_assign_ssa_name_copy_p (def_stmt)
2156 || (gimple_assign_cast_p (def_stmt)
2157 && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (def_stmt))))
2158 || (is_gimple_assign (def_stmt)
2159 && gimple_assign_rhs_code (def_stmt) == POINTER_PLUS_EXPR))
2161 tree rhs1 = gimple_assign_rhs1 (def_stmt);
2162 if (TREE_CODE (rhs1) == SSA_NAME
2163 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs1))
2164 break;
2165 else
2166 base = rhs1;
2168 else
2169 break;
2172 if (!POINTER_TYPE_P (TREE_TYPE (base)) && !DECL_P (base))
2173 return;
2175 tree sizet;
2176 tree base_addr = base;
2177 gimple *bos_stmt = NULL;
2178 if (decl_p)
2179 base_addr = build1 (ADDR_EXPR,
2180 build_pointer_type (TREE_TYPE (base)), base);
2181 if (compute_builtin_object_size (base_addr, OST_DYNAMIC, &sizet))
2183 else if (optimize)
2185 if (LOCATION_LOCUS (loc) == UNKNOWN_LOCATION)
2186 loc = input_location;
2187 /* Generate __builtin_dynamic_object_size call. */
2188 sizet = builtin_decl_explicit (BUILT_IN_DYNAMIC_OBJECT_SIZE);
2189 sizet = build_call_expr_loc (loc, sizet, 2, base_addr,
2190 integer_zero_node);
2191 sizet = force_gimple_operand_gsi (gsi, sizet, false, NULL_TREE, true,
2192 GSI_SAME_STMT);
2193 /* If the call above didn't end up being an integer constant, go one
2194 statement back and get the __builtin_object_size stmt. Save it,
2195 we might need it later. */
2196 if (SSA_VAR_P (sizet))
2198 gsi_prev (gsi);
2199 bos_stmt = gsi_stmt (*gsi);
2201 /* Move on to where we were. */
2202 gsi_next (gsi);
2205 else
2206 return;
2208 /* Generate UBSAN_OBJECT_SIZE (ptr, ptr+sizeof(*ptr)-base, objsize, ckind)
2209 call. */
2210 /* ptr + sizeof (*ptr) - base */
2211 t = fold_build2 (MINUS_EXPR, sizetype,
2212 fold_convert (pointer_sized_int_node, ptr),
2213 fold_convert (pointer_sized_int_node, base_addr));
2214 t = fold_build2 (PLUS_EXPR, sizetype, t, TYPE_SIZE_UNIT (type));
2216 /* Perhaps we can omit the check. */
2217 if (TREE_CODE (t) == INTEGER_CST
2218 && TREE_CODE (sizet) == INTEGER_CST
2219 && tree_int_cst_le (t, sizet))
2220 return;
2222 if (index != NULL_TREE
2223 && TREE_CODE (index) == SSA_NAME
2224 && TREE_CODE (sizet) == INTEGER_CST)
2226 gimple *def = SSA_NAME_DEF_STMT (index);
2227 if (is_gimple_assign (def)
2228 && gimple_assign_rhs_code (def) == BIT_AND_EXPR
2229 && TREE_CODE (gimple_assign_rhs2 (def)) == INTEGER_CST)
2231 tree cst = gimple_assign_rhs2 (def);
2232 tree sz = fold_build2 (EXACT_DIV_EXPR, sizetype, sizet,
2233 TYPE_SIZE_UNIT (type));
2234 if (tree_int_cst_sgn (cst) >= 0
2235 && tree_int_cst_lt (cst, sz))
2236 return;
2240 if (DECL_P (base)
2241 && decl_function_context (base) == current_function_decl
2242 && !TREE_ADDRESSABLE (base))
2243 mark_addressable (base);
2245 if (bos_stmt
2246 && gimple_call_builtin_p (bos_stmt, BUILT_IN_DYNAMIC_OBJECT_SIZE))
2247 ubsan_create_edge (bos_stmt);
2249 /* We have to emit the check. */
2250 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE, true,
2251 GSI_SAME_STMT);
2252 ptr = force_gimple_operand_gsi (gsi, ptr, true, NULL_TREE, true,
2253 GSI_SAME_STMT);
2254 tree ckind = build_int_cst (unsigned_char_type_node,
2255 is_lhs ? UBSAN_STORE_OF : UBSAN_LOAD_OF);
2256 gimple *g = gimple_build_call_internal (IFN_UBSAN_OBJECT_SIZE, 4,
2257 ptr, t, sizet, ckind);
2258 gimple_set_location (g, loc);
2259 gsi_insert_before (gsi, g, GSI_SAME_STMT);
2262 /* Instrument values passed to builtin functions. */
2264 static void
2265 instrument_builtin (gimple_stmt_iterator *gsi)
2267 gimple *stmt = gsi_stmt (*gsi);
2268 location_t loc = gimple_location (stmt);
2269 tree arg;
2270 enum built_in_function fcode
2271 = DECL_FUNCTION_CODE (gimple_call_fndecl (stmt));
2272 int kind = 0;
2273 switch (fcode)
2275 CASE_INT_FN (BUILT_IN_CLZ):
2276 kind = 1;
2277 gcc_fallthrough ();
2278 CASE_INT_FN (BUILT_IN_CTZ):
2279 arg = gimple_call_arg (stmt, 0);
2280 if (!integer_nonzerop (arg))
2282 gimple *g;
2283 if (!is_gimple_val (arg))
2285 g = gimple_build_assign (make_ssa_name (TREE_TYPE (arg)), arg);
2286 gimple_set_location (g, loc);
2287 gsi_insert_before (gsi, g, GSI_SAME_STMT);
2288 arg = gimple_assign_lhs (g);
2291 basic_block then_bb, fallthru_bb;
2292 *gsi = create_cond_insert_point (gsi, true, false, true,
2293 &then_bb, &fallthru_bb);
2294 g = gimple_build_cond (EQ_EXPR, arg,
2295 build_zero_cst (TREE_TYPE (arg)),
2296 NULL_TREE, NULL_TREE);
2297 gimple_set_location (g, loc);
2298 gsi_insert_after (gsi, g, GSI_NEW_STMT);
2300 *gsi = gsi_after_labels (then_bb);
2301 if (flag_sanitize_trap & SANITIZE_BUILTIN)
2302 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
2303 else
2305 tree t = build_int_cst (unsigned_char_type_node, kind);
2306 tree data = ubsan_create_data ("__ubsan_builtin_data",
2307 1, &loc, NULL_TREE, t, NULL_TREE);
2308 data = build_fold_addr_expr_loc (loc, data);
2309 enum built_in_function bcode
2310 = (flag_sanitize_recover & SANITIZE_BUILTIN)
2311 ? BUILT_IN_UBSAN_HANDLE_INVALID_BUILTIN
2312 : BUILT_IN_UBSAN_HANDLE_INVALID_BUILTIN_ABORT;
2313 tree fn = builtin_decl_explicit (bcode);
2315 g = gimple_build_call (fn, 1, data);
2317 gimple_set_location (g, loc);
2318 gsi_insert_before (gsi, g, GSI_SAME_STMT);
2319 ubsan_create_edge (g);
2321 *gsi = gsi_for_stmt (stmt);
2322 break;
2323 default:
2324 break;
2328 namespace {
2330 const pass_data pass_data_ubsan =
2332 GIMPLE_PASS, /* type */
2333 "ubsan", /* name */
2334 OPTGROUP_NONE, /* optinfo_flags */
2335 TV_TREE_UBSAN, /* tv_id */
2336 ( PROP_cfg | PROP_ssa ), /* properties_required */
2337 0, /* properties_provided */
2338 0, /* properties_destroyed */
2339 0, /* todo_flags_start */
2340 TODO_update_ssa, /* todo_flags_finish */
2343 class pass_ubsan : public gimple_opt_pass
2345 public:
2346 pass_ubsan (gcc::context *ctxt)
2347 : gimple_opt_pass (pass_data_ubsan, ctxt)
2350 /* opt_pass methods: */
2351 bool gate (function *) final override
2353 return sanitize_flags_p ((SANITIZE_NULL | SANITIZE_SI_OVERFLOW
2354 | SANITIZE_BOOL | SANITIZE_ENUM
2355 | SANITIZE_ALIGNMENT
2356 | SANITIZE_NONNULL_ATTRIBUTE
2357 | SANITIZE_RETURNS_NONNULL_ATTRIBUTE
2358 | SANITIZE_OBJECT_SIZE
2359 | SANITIZE_POINTER_OVERFLOW
2360 | SANITIZE_BUILTIN));
2363 unsigned int execute (function *) final override;
2365 }; // class pass_ubsan
2367 unsigned int
2368 pass_ubsan::execute (function *fun)
2370 basic_block bb;
2371 gimple_stmt_iterator gsi;
2372 unsigned int ret = 0;
2374 initialize_sanitizer_builtins ();
2376 FOR_EACH_BB_FN (bb, fun)
2378 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
2380 gimple *stmt = gsi_stmt (gsi);
2381 if (is_gimple_debug (stmt) || gimple_clobber_p (stmt))
2383 gsi_next (&gsi);
2384 continue;
2387 if ((sanitize_flags_p (SANITIZE_SI_OVERFLOW, fun->decl))
2388 && is_gimple_assign (stmt))
2389 instrument_si_overflow (gsi);
2391 if (sanitize_flags_p (SANITIZE_NULL | SANITIZE_ALIGNMENT, fun->decl))
2393 if (gimple_store_p (stmt))
2394 instrument_null (gsi, gimple_get_lhs (stmt), true);
2395 if (gimple_assign_single_p (stmt))
2396 instrument_null (gsi, gimple_assign_rhs1 (stmt), false);
2397 if (is_gimple_call (stmt))
2399 unsigned args_num = gimple_call_num_args (stmt);
2400 for (unsigned i = 0; i < args_num; ++i)
2402 tree arg = gimple_call_arg (stmt, i);
2403 if (is_gimple_reg (arg) || is_gimple_min_invariant (arg))
2404 continue;
2405 instrument_null (gsi, arg, false);
2410 if (sanitize_flags_p (SANITIZE_BOOL | SANITIZE_ENUM, fun->decl)
2411 && gimple_assign_load_p (stmt))
2413 instrument_bool_enum_load (&gsi);
2414 bb = gimple_bb (stmt);
2417 if (sanitize_flags_p (SANITIZE_NONNULL_ATTRIBUTE, fun->decl)
2418 && is_gimple_call (stmt)
2419 && !gimple_call_internal_p (stmt))
2421 instrument_nonnull_arg (&gsi);
2422 bb = gimple_bb (stmt);
2425 if (sanitize_flags_p (SANITIZE_BUILTIN, fun->decl)
2426 && gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
2428 instrument_builtin (&gsi);
2429 bb = gimple_bb (stmt);
2432 if (sanitize_flags_p (SANITIZE_RETURNS_NONNULL_ATTRIBUTE, fun->decl)
2433 && gimple_code (stmt) == GIMPLE_RETURN)
2435 instrument_nonnull_return (&gsi);
2436 bb = gimple_bb (stmt);
2439 if (sanitize_flags_p (SANITIZE_OBJECT_SIZE, fun->decl))
2441 if (gimple_store_p (stmt))
2442 instrument_object_size (&gsi, gimple_get_lhs (stmt), true);
2443 if (gimple_assign_load_p (stmt))
2444 instrument_object_size (&gsi, gimple_assign_rhs1 (stmt),
2445 false);
2446 if (is_gimple_call (stmt))
2448 unsigned args_num = gimple_call_num_args (stmt);
2449 for (unsigned i = 0; i < args_num; ++i)
2451 tree arg = gimple_call_arg (stmt, i);
2452 if (is_gimple_reg (arg) || is_gimple_min_invariant (arg))
2453 continue;
2454 instrument_object_size (&gsi, arg, false);
2459 if (sanitize_flags_p (SANITIZE_POINTER_OVERFLOW, fun->decl))
2461 if (is_gimple_assign (stmt)
2462 && gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
2463 instrument_pointer_overflow (&gsi,
2464 gimple_assign_rhs1 (stmt),
2465 gimple_assign_rhs2 (stmt));
2466 if (gimple_store_p (stmt))
2467 maybe_instrument_pointer_overflow (&gsi,
2468 gimple_get_lhs (stmt));
2469 if (gimple_assign_single_p (stmt))
2470 maybe_instrument_pointer_overflow (&gsi,
2471 gimple_assign_rhs1 (stmt));
2472 if (is_gimple_call (stmt))
2474 unsigned args_num = gimple_call_num_args (stmt);
2475 for (unsigned i = 0; i < args_num; ++i)
2477 tree arg = gimple_call_arg (stmt, i);
2478 if (is_gimple_reg (arg))
2479 continue;
2480 maybe_instrument_pointer_overflow (&gsi, arg);
2485 gsi_next (&gsi);
2487 if (gimple_purge_dead_eh_edges (bb))
2488 ret = TODO_cleanup_cfg;
2490 return ret;
2493 } // anon namespace
2495 gimple_opt_pass *
2496 make_pass_ubsan (gcc::context *ctxt)
2498 return new pass_ubsan (ctxt);
2501 #include "gt-ubsan.h"