* i386.c (has_dispatch): Disable for Ryzen.
[official-gcc.git] / gcc / ubsan.c
blob1030168e6b7ac5b7c1b8348d37a90b4e4676b987
1 /* UndefinedBehaviorSanitizer, undefined behavior detector.
2 Copyright (C) 2013-2017 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 layout_type (ret);
233 ubsan_type_descriptor_type = ret;
234 return ret;
237 /* Cached ubsan_get_source_location_type () return value. */
238 static GTY(()) tree ubsan_source_location_type;
240 /* Build
241 struct __ubsan_source_location
243 const char *__filename;
244 unsigned int __line;
245 unsigned int __column;
247 type. */
249 tree
250 ubsan_get_source_location_type (void)
252 static const char *field_names[3]
253 = { "__filename", "__line", "__column" };
254 tree fields[3], ret;
255 if (ubsan_source_location_type)
256 return ubsan_source_location_type;
258 tree const_char_type = build_qualified_type (char_type_node,
259 TYPE_QUAL_CONST);
261 ret = make_node (RECORD_TYPE);
262 for (int i = 0; i < 3; i++)
264 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
265 get_identifier (field_names[i]),
266 (i == 0) ? build_pointer_type (const_char_type)
267 : unsigned_type_node);
268 DECL_CONTEXT (fields[i]) = ret;
269 if (i)
270 DECL_CHAIN (fields[i - 1]) = fields[i];
272 tree type_decl = build_decl (input_location, TYPE_DECL,
273 get_identifier ("__ubsan_source_location"),
274 ret);
275 DECL_IGNORED_P (type_decl) = 1;
276 DECL_ARTIFICIAL (type_decl) = 1;
277 TYPE_FIELDS (ret) = fields[0];
278 TYPE_NAME (ret) = type_decl;
279 TYPE_STUB_DECL (ret) = type_decl;
280 layout_type (ret);
281 ubsan_source_location_type = ret;
282 return ret;
285 /* Helper routine that returns a CONSTRUCTOR of __ubsan_source_location
286 type with its fields filled from a location_t LOC. */
288 static tree
289 ubsan_source_location (location_t loc)
291 expanded_location xloc;
292 tree type = ubsan_get_source_location_type ();
294 xloc = expand_location (loc);
295 tree str;
296 if (xloc.file == NULL)
298 str = build_int_cst (ptr_type_node, 0);
299 xloc.line = 0;
300 xloc.column = 0;
302 else
304 /* Fill in the values from LOC. */
305 size_t len = strlen (xloc.file) + 1;
306 str = build_string (len, xloc.file);
307 TREE_TYPE (str) = build_array_type_nelts (char_type_node, len);
308 TREE_READONLY (str) = 1;
309 TREE_STATIC (str) = 1;
310 str = build_fold_addr_expr (str);
312 tree ctor = build_constructor_va (type, 3, NULL_TREE, str, NULL_TREE,
313 build_int_cst (unsigned_type_node,
314 xloc.line), NULL_TREE,
315 build_int_cst (unsigned_type_node,
316 xloc.column));
317 TREE_CONSTANT (ctor) = 1;
318 TREE_STATIC (ctor) = 1;
320 return ctor;
323 /* This routine returns a magic number for TYPE. */
325 static unsigned short
326 get_ubsan_type_info_for_type (tree type)
328 if (TREE_CODE (type) == REAL_TYPE)
329 return tree_to_uhwi (TYPE_SIZE (type));
330 else if (INTEGRAL_TYPE_P (type))
332 int prec = exact_log2 (tree_to_uhwi (TYPE_SIZE (type)));
333 gcc_assert (prec != -1);
334 return (prec << 1) | !TYPE_UNSIGNED (type);
336 else
337 return 0;
340 /* Counters for internal labels. ubsan_ids[0] for Lubsan_type,
341 ubsan_ids[1] for Lubsan_data labels. */
342 static GTY(()) unsigned int ubsan_ids[2];
344 /* Helper routine that returns ADDR_EXPR of a VAR_DECL of a type
345 descriptor. It first looks into the hash table; if not found,
346 create the VAR_DECL, put it into the hash table and return the
347 ADDR_EXPR of it. TYPE describes a particular type. PSTYLE is
348 an enum controlling how we want to print the type. */
350 tree
351 ubsan_type_descriptor (tree type, enum ubsan_print_style pstyle)
353 /* See through any typedefs. */
354 type = TYPE_MAIN_VARIANT (type);
356 tree decl = decl_for_type_lookup (type);
357 /* It is possible that some of the earlier created DECLs were found
358 unused, in that case they weren't emitted and varpool_node::get
359 returns NULL node on them. But now we really need them. Thus,
360 renew them here. */
361 if (decl != NULL_TREE && varpool_node::get (decl))
362 return build_fold_addr_expr (decl);
364 tree dtype = ubsan_get_type_descriptor_type ();
365 tree type2 = type;
366 const char *tname = NULL;
367 pretty_printer pretty_name;
368 unsigned char deref_depth = 0;
369 unsigned short tkind, tinfo;
371 /* Get the name of the type, or the name of the pointer type. */
372 if (pstyle == UBSAN_PRINT_POINTER)
374 gcc_assert (POINTER_TYPE_P (type));
375 type2 = TREE_TYPE (type);
377 /* Remove any '*' operators from TYPE. */
378 while (POINTER_TYPE_P (type2))
379 deref_depth++, type2 = TREE_TYPE (type2);
381 if (TREE_CODE (type2) == METHOD_TYPE)
382 type2 = TYPE_METHOD_BASETYPE (type2);
385 /* If an array, get its type. */
386 type2 = strip_array_types (type2);
388 if (pstyle == UBSAN_PRINT_ARRAY)
390 while (POINTER_TYPE_P (type2))
391 deref_depth++, type2 = TREE_TYPE (type2);
394 if (TYPE_NAME (type2) != NULL)
396 if (TREE_CODE (TYPE_NAME (type2)) == IDENTIFIER_NODE)
397 tname = IDENTIFIER_POINTER (TYPE_NAME (type2));
398 else if (DECL_NAME (TYPE_NAME (type2)) != NULL)
399 tname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type2)));
402 if (tname == NULL)
403 /* We weren't able to determine the type name. */
404 tname = "<unknown>";
406 tree eltype = type;
407 if (pstyle == UBSAN_PRINT_POINTER)
409 pp_printf (&pretty_name, "'%s%s%s%s%s%s%s",
410 TYPE_VOLATILE (type2) ? "volatile " : "",
411 TYPE_READONLY (type2) ? "const " : "",
412 TYPE_RESTRICT (type2) ? "restrict " : "",
413 TYPE_ATOMIC (type2) ? "_Atomic " : "",
414 TREE_CODE (type2) == RECORD_TYPE
415 ? "struct "
416 : TREE_CODE (type2) == UNION_TYPE
417 ? "union " : "", tname,
418 deref_depth == 0 ? "" : " ");
419 while (deref_depth-- > 0)
420 pp_star (&pretty_name);
421 pp_quote (&pretty_name);
423 else if (pstyle == UBSAN_PRINT_ARRAY)
425 /* Pretty print the array dimensions. */
426 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
427 tree t = type;
428 pp_printf (&pretty_name, "'%s ", tname);
429 while (deref_depth-- > 0)
430 pp_star (&pretty_name);
431 while (TREE_CODE (t) == ARRAY_TYPE)
433 pp_left_bracket (&pretty_name);
434 tree dom = TYPE_DOMAIN (t);
435 if (dom != NULL_TREE
436 && TYPE_MAX_VALUE (dom) != NULL_TREE
437 && TREE_CODE (TYPE_MAX_VALUE (dom)) == INTEGER_CST)
439 if (tree_fits_uhwi_p (TYPE_MAX_VALUE (dom))
440 && tree_to_uhwi (TYPE_MAX_VALUE (dom)) + 1 != 0)
441 pp_printf (&pretty_name, HOST_WIDE_INT_PRINT_DEC,
442 tree_to_uhwi (TYPE_MAX_VALUE (dom)) + 1);
443 else
444 pp_wide_int (&pretty_name,
445 wi::add (wi::to_widest (TYPE_MAX_VALUE (dom)), 1),
446 TYPE_SIGN (TREE_TYPE (dom)));
448 else
449 /* ??? We can't determine the variable name; print VLA unspec. */
450 pp_star (&pretty_name);
451 pp_right_bracket (&pretty_name);
452 t = TREE_TYPE (t);
454 pp_quote (&pretty_name);
456 /* Save the tree with stripped types. */
457 eltype = t;
459 else
460 pp_printf (&pretty_name, "'%s'", tname);
462 switch (TREE_CODE (eltype))
464 case BOOLEAN_TYPE:
465 case ENUMERAL_TYPE:
466 case INTEGER_TYPE:
467 tkind = 0x0000;
468 break;
469 case REAL_TYPE:
470 /* FIXME: libubsan right now only supports float, double and
471 long double type formats. */
472 if (TYPE_MODE (eltype) == TYPE_MODE (float_type_node)
473 || TYPE_MODE (eltype) == TYPE_MODE (double_type_node)
474 || TYPE_MODE (eltype) == TYPE_MODE (long_double_type_node))
475 tkind = 0x0001;
476 else
477 tkind = 0xffff;
478 break;
479 default:
480 tkind = 0xffff;
481 break;
483 tinfo = get_ubsan_type_info_for_type (eltype);
485 /* Create a new VAR_DECL of type descriptor. */
486 const char *tmp = pp_formatted_text (&pretty_name);
487 size_t len = strlen (tmp) + 1;
488 tree str = build_string (len, tmp);
489 TREE_TYPE (str) = build_array_type_nelts (char_type_node, len);
490 TREE_READONLY (str) = 1;
491 TREE_STATIC (str) = 1;
493 char tmp_name[32];
494 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_type", ubsan_ids[0]++);
495 decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name),
496 dtype);
497 TREE_STATIC (decl) = 1;
498 TREE_PUBLIC (decl) = 0;
499 DECL_ARTIFICIAL (decl) = 1;
500 DECL_IGNORED_P (decl) = 1;
501 DECL_EXTERNAL (decl) = 0;
502 DECL_SIZE (decl)
503 = size_binop (PLUS_EXPR, DECL_SIZE (decl), TYPE_SIZE (TREE_TYPE (str)));
504 DECL_SIZE_UNIT (decl)
505 = size_binop (PLUS_EXPR, DECL_SIZE_UNIT (decl),
506 TYPE_SIZE_UNIT (TREE_TYPE (str)));
508 tree ctor = build_constructor_va (dtype, 3, NULL_TREE,
509 build_int_cst (short_unsigned_type_node,
510 tkind), NULL_TREE,
511 build_int_cst (short_unsigned_type_node,
512 tinfo), NULL_TREE, str);
513 TREE_CONSTANT (ctor) = 1;
514 TREE_STATIC (ctor) = 1;
515 DECL_INITIAL (decl) = ctor;
516 varpool_node::finalize_decl (decl);
518 /* Save the VAR_DECL into the hash table. */
519 decl_for_type_insert (type, decl);
521 return build_fold_addr_expr (decl);
524 /* Create a structure for the ubsan library. NAME is a name of the new
525 structure. LOCCNT is number of locations, PLOC points to array of
526 locations. The arguments in ... are of __ubsan_type_descriptor type
527 and there are at most two of them, followed by NULL_TREE, followed
528 by optional extra arguments and another NULL_TREE. */
530 tree
531 ubsan_create_data (const char *name, int loccnt, const location_t *ploc, ...)
533 va_list args;
534 tree ret, t;
535 tree fields[6];
536 vec<tree, va_gc> *saved_args = NULL;
537 size_t i = 0;
538 int j;
540 /* It is possible that PCH zapped table with definitions of sanitizer
541 builtins. Reinitialize them if needed. */
542 initialize_sanitizer_builtins ();
544 /* Firstly, create a pointer to type descriptor type. */
545 tree td_type = ubsan_get_type_descriptor_type ();
546 td_type = build_pointer_type (td_type);
548 /* Create the structure type. */
549 ret = make_node (RECORD_TYPE);
550 for (j = 0; j < loccnt; j++)
552 gcc_checking_assert (i < 2);
553 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
554 ubsan_get_source_location_type ());
555 DECL_CONTEXT (fields[i]) = ret;
556 if (i)
557 DECL_CHAIN (fields[i - 1]) = fields[i];
558 i++;
561 va_start (args, ploc);
562 for (t = va_arg (args, tree); t != NULL_TREE;
563 i++, t = va_arg (args, tree))
565 gcc_checking_assert (i < 4);
566 /* Save the tree arguments for later use. */
567 vec_safe_push (saved_args, t);
568 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
569 td_type);
570 DECL_CONTEXT (fields[i]) = ret;
571 if (i)
572 DECL_CHAIN (fields[i - 1]) = fields[i];
575 for (t = va_arg (args, tree); t != NULL_TREE;
576 i++, t = va_arg (args, tree))
578 gcc_checking_assert (i < 6);
579 /* Save the tree arguments for later use. */
580 vec_safe_push (saved_args, t);
581 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
582 TREE_TYPE (t));
583 DECL_CONTEXT (fields[i]) = ret;
584 if (i)
585 DECL_CHAIN (fields[i - 1]) = fields[i];
587 va_end (args);
589 tree type_decl = build_decl (input_location, TYPE_DECL,
590 get_identifier (name), ret);
591 DECL_IGNORED_P (type_decl) = 1;
592 DECL_ARTIFICIAL (type_decl) = 1;
593 TYPE_FIELDS (ret) = fields[0];
594 TYPE_NAME (ret) = type_decl;
595 TYPE_STUB_DECL (ret) = type_decl;
596 layout_type (ret);
598 /* Now, fill in the type. */
599 char tmp_name[32];
600 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_data", ubsan_ids[1]++);
601 tree var = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name),
602 ret);
603 TREE_STATIC (var) = 1;
604 TREE_PUBLIC (var) = 0;
605 DECL_ARTIFICIAL (var) = 1;
606 DECL_IGNORED_P (var) = 1;
607 DECL_EXTERNAL (var) = 0;
609 vec<constructor_elt, va_gc> *v;
610 vec_alloc (v, i);
611 tree ctor = build_constructor (ret, v);
613 /* If desirable, set the __ubsan_source_location element. */
614 for (j = 0; j < loccnt; j++)
616 location_t loc = LOCATION_LOCUS (ploc[j]);
617 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, ubsan_source_location (loc));
620 size_t nelts = vec_safe_length (saved_args);
621 for (i = 0; i < nelts; i++)
623 t = (*saved_args)[i];
624 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, t);
627 TREE_CONSTANT (ctor) = 1;
628 TREE_STATIC (ctor) = 1;
629 DECL_INITIAL (var) = ctor;
630 varpool_node::finalize_decl (var);
632 return var;
635 /* Instrument the __builtin_unreachable call. We just call the libubsan
636 routine instead. */
638 bool
639 ubsan_instrument_unreachable (gimple_stmt_iterator *gsi)
641 gimple *g;
642 location_t loc = gimple_location (gsi_stmt (*gsi));
644 if (flag_sanitize_undefined_trap_on_error)
645 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
646 else
648 tree data = ubsan_create_data ("__ubsan_unreachable_data", 1, &loc,
649 NULL_TREE, NULL_TREE);
650 data = build_fold_addr_expr_loc (loc, data);
651 tree fn
652 = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE);
653 g = gimple_build_call (fn, 1, data);
655 gimple_set_location (g, loc);
656 gsi_replace (gsi, g, false);
657 return false;
660 /* Return true if T is a call to a libubsan routine. */
662 bool
663 is_ubsan_builtin_p (tree t)
665 return TREE_CODE (t) == FUNCTION_DECL
666 && DECL_BUILT_IN_CLASS (t) == BUILT_IN_NORMAL
667 && strncmp (IDENTIFIER_POINTER (DECL_NAME (t)),
668 "__builtin___ubsan_", 18) == 0;
671 /* Create a callgraph edge for statement STMT. */
673 static void
674 ubsan_create_edge (gimple *stmt)
676 gcall *call_stmt = dyn_cast <gcall *> (stmt);
677 basic_block bb = gimple_bb (stmt);
678 int freq = compute_call_stmt_bb_frequency (current_function_decl, bb);
679 cgraph_node *node = cgraph_node::get (current_function_decl);
680 tree decl = gimple_call_fndecl (call_stmt);
681 if (decl)
682 node->create_edge (cgraph_node::get_create (decl), call_stmt, bb->count,
683 freq);
686 /* Expand the UBSAN_BOUNDS special builtin function. */
688 bool
689 ubsan_expand_bounds_ifn (gimple_stmt_iterator *gsi)
691 gimple *stmt = gsi_stmt (*gsi);
692 location_t loc = gimple_location (stmt);
693 gcc_assert (gimple_call_num_args (stmt) == 3);
695 /* Pick up the arguments of the UBSAN_BOUNDS call. */
696 tree type = TREE_TYPE (TREE_TYPE (gimple_call_arg (stmt, 0)));
697 tree index = gimple_call_arg (stmt, 1);
698 tree orig_index = index;
699 tree bound = gimple_call_arg (stmt, 2);
701 gimple_stmt_iterator gsi_orig = *gsi;
703 /* Create condition "if (index > bound)". */
704 basic_block then_bb, fallthru_bb;
705 gimple_stmt_iterator cond_insert_point
706 = create_cond_insert_point (gsi, false, false, true,
707 &then_bb, &fallthru_bb);
708 index = fold_convert (TREE_TYPE (bound), index);
709 index = force_gimple_operand_gsi (&cond_insert_point, index,
710 true, NULL_TREE,
711 false, GSI_NEW_STMT);
712 gimple *g = gimple_build_cond (GT_EXPR, index, bound, NULL_TREE, NULL_TREE);
713 gimple_set_location (g, loc);
714 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
716 /* Generate __ubsan_handle_out_of_bounds call. */
717 *gsi = gsi_after_labels (then_bb);
718 if (flag_sanitize_undefined_trap_on_error)
719 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
720 else
722 tree data
723 = ubsan_create_data ("__ubsan_out_of_bounds_data", 1, &loc,
724 ubsan_type_descriptor (type, UBSAN_PRINT_ARRAY),
725 ubsan_type_descriptor (TREE_TYPE (orig_index)),
726 NULL_TREE, NULL_TREE);
727 data = build_fold_addr_expr_loc (loc, data);
728 enum built_in_function bcode
729 = (flag_sanitize_recover & SANITIZE_BOUNDS)
730 ? BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS
731 : BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS_ABORT;
732 tree fn = builtin_decl_explicit (bcode);
733 tree val = ubsan_encode_value (orig_index, UBSAN_ENCODE_VALUE_GIMPLE);
734 val = force_gimple_operand_gsi (gsi, val, true, NULL_TREE, true,
735 GSI_SAME_STMT);
736 g = gimple_build_call (fn, 2, data, val);
738 gimple_set_location (g, loc);
739 gsi_insert_before (gsi, g, GSI_SAME_STMT);
741 /* Get rid of the UBSAN_BOUNDS call from the IR. */
742 unlink_stmt_vdef (stmt);
743 gsi_remove (&gsi_orig, true);
745 /* Point GSI to next logical statement. */
746 *gsi = gsi_start_bb (fallthru_bb);
747 return true;
750 /* Expand UBSAN_NULL internal call. The type is kept on the ckind
751 argument which is a constant, because the middle-end treats pointer
752 conversions as useless and therefore the type of the first argument
753 could be changed to any other pointer type. */
755 bool
756 ubsan_expand_null_ifn (gimple_stmt_iterator *gsip)
758 gimple_stmt_iterator gsi = *gsip;
759 gimple *stmt = gsi_stmt (gsi);
760 location_t loc = gimple_location (stmt);
761 gcc_assert (gimple_call_num_args (stmt) == 3);
762 tree ptr = gimple_call_arg (stmt, 0);
763 tree ckind = gimple_call_arg (stmt, 1);
764 tree align = gimple_call_arg (stmt, 2);
765 tree check_align = NULL_TREE;
766 bool check_null;
768 basic_block cur_bb = gsi_bb (gsi);
770 gimple *g;
771 if (!integer_zerop (align))
773 unsigned int ptralign = get_pointer_alignment (ptr) / BITS_PER_UNIT;
774 if (compare_tree_int (align, ptralign) == 1)
776 check_align = make_ssa_name (pointer_sized_int_node);
777 g = gimple_build_assign (check_align, NOP_EXPR, ptr);
778 gimple_set_location (g, loc);
779 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
782 check_null = sanitize_flags_p (SANITIZE_NULL);
784 if (check_align == NULL_TREE && !check_null)
786 gsi_remove (gsip, true);
787 /* Unlink the UBSAN_NULLs vops before replacing it. */
788 unlink_stmt_vdef (stmt);
789 return true;
792 /* Split the original block holding the pointer dereference. */
793 edge e = split_block (cur_bb, stmt);
795 /* Get a hold on the 'condition block', the 'then block' and the
796 'else block'. */
797 basic_block cond_bb = e->src;
798 basic_block fallthru_bb = e->dest;
799 basic_block then_bb = create_empty_bb (cond_bb);
800 add_bb_to_loop (then_bb, cond_bb->loop_father);
801 loops_state_set (LOOPS_NEED_FIXUP);
803 /* Make an edge coming from the 'cond block' into the 'then block';
804 this edge is unlikely taken, so set up the probability accordingly. */
805 e = make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
806 e->probability = profile_probability::very_unlikely ();
808 /* Connect 'then block' with the 'else block'. This is needed
809 as the ubsan routines we call in the 'then block' are not noreturn.
810 The 'then block' only has one outcoming edge. */
811 make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);
813 /* Set up the fallthrough basic block. */
814 e = find_edge (cond_bb, fallthru_bb);
815 e->flags = EDGE_FALSE_VALUE;
816 e->count = cond_bb->count;
817 e->probability = profile_probability::very_likely ();
819 /* Update dominance info for the newly created then_bb; note that
820 fallthru_bb's dominance info has already been updated by
821 split_block. */
822 if (dom_info_available_p (CDI_DOMINATORS))
823 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
825 /* Put the ubsan builtin call into the newly created BB. */
826 if (flag_sanitize_undefined_trap_on_error)
827 g = gimple_build_call (builtin_decl_implicit (BUILT_IN_TRAP), 0);
828 else
830 enum built_in_function bcode
831 = (flag_sanitize_recover & ((check_align ? SANITIZE_ALIGNMENT : 0)
832 | (check_null ? SANITIZE_NULL : 0)))
833 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
834 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT;
835 tree fn = builtin_decl_implicit (bcode);
836 tree data
837 = ubsan_create_data ("__ubsan_null_data", 1, &loc,
838 ubsan_type_descriptor (TREE_TYPE (ckind),
839 UBSAN_PRINT_POINTER),
840 NULL_TREE,
841 align,
842 fold_convert (unsigned_char_type_node, ckind),
843 NULL_TREE);
844 data = build_fold_addr_expr_loc (loc, data);
845 g = gimple_build_call (fn, 2, data,
846 check_align ? check_align
847 : build_zero_cst (pointer_sized_int_node));
849 gimple_stmt_iterator gsi2 = gsi_start_bb (then_bb);
850 gimple_set_location (g, loc);
851 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
853 /* Unlink the UBSAN_NULLs vops before replacing it. */
854 unlink_stmt_vdef (stmt);
856 if (check_null)
858 g = gimple_build_cond (EQ_EXPR, ptr, build_int_cst (TREE_TYPE (ptr), 0),
859 NULL_TREE, NULL_TREE);
860 gimple_set_location (g, loc);
862 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
863 gsi_replace (&gsi, g, false);
864 stmt = g;
867 if (check_align)
869 if (check_null)
871 /* Split the block with the condition again. */
872 e = split_block (cond_bb, stmt);
873 basic_block cond1_bb = e->src;
874 basic_block cond2_bb = e->dest;
876 /* Make an edge coming from the 'cond1 block' into the 'then block';
877 this edge is unlikely taken, so set up the probability
878 accordingly. */
879 e = make_edge (cond1_bb, then_bb, EDGE_TRUE_VALUE);
880 e->probability = profile_probability::very_unlikely ();
882 /* Set up the fallthrough basic block. */
883 e = find_edge (cond1_bb, cond2_bb);
884 e->flags = EDGE_FALSE_VALUE;
885 e->count = cond1_bb->count;
886 e->probability = profile_probability::very_likely ();
888 /* Update dominance info. */
889 if (dom_info_available_p (CDI_DOMINATORS))
891 set_immediate_dominator (CDI_DOMINATORS, fallthru_bb, cond1_bb);
892 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond1_bb);
895 gsi2 = gsi_start_bb (cond2_bb);
898 tree mask = build_int_cst (pointer_sized_int_node,
899 tree_to_uhwi (align) - 1);
900 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
901 BIT_AND_EXPR, check_align, mask);
902 gimple_set_location (g, loc);
903 if (check_null)
904 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
905 else
906 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
908 g = gimple_build_cond (NE_EXPR, gimple_assign_lhs (g),
909 build_int_cst (pointer_sized_int_node, 0),
910 NULL_TREE, NULL_TREE);
911 gimple_set_location (g, loc);
912 if (check_null)
913 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
914 else
915 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
916 gsi_replace (&gsi, g, false);
918 return false;
921 #define OBJSZ_MAX_OFFSET (1024 * 16)
923 /* Expand UBSAN_OBJECT_SIZE internal call. */
925 bool
926 ubsan_expand_objsize_ifn (gimple_stmt_iterator *gsi)
928 gimple *stmt = gsi_stmt (*gsi);
929 location_t loc = gimple_location (stmt);
930 gcc_assert (gimple_call_num_args (stmt) == 4);
932 tree ptr = gimple_call_arg (stmt, 0);
933 tree offset = gimple_call_arg (stmt, 1);
934 tree size = gimple_call_arg (stmt, 2);
935 tree ckind = gimple_call_arg (stmt, 3);
936 gimple_stmt_iterator gsi_orig = *gsi;
937 gimple *g;
939 /* See if we can discard the check. */
940 if (TREE_CODE (size) != INTEGER_CST
941 || integer_all_onesp (size))
942 /* Yes, __builtin_object_size couldn't determine the
943 object size. */;
944 else if (TREE_CODE (offset) == INTEGER_CST
945 && wi::to_widest (offset) >= -OBJSZ_MAX_OFFSET
946 && wi::to_widest (offset) <= -1)
947 /* The offset is in range [-16K, -1]. */;
948 else
950 /* if (offset > objsize) */
951 basic_block then_bb, fallthru_bb;
952 gimple_stmt_iterator cond_insert_point
953 = create_cond_insert_point (gsi, false, false, true,
954 &then_bb, &fallthru_bb);
955 g = gimple_build_cond (GT_EXPR, offset, size, NULL_TREE, NULL_TREE);
956 gimple_set_location (g, loc);
957 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
959 /* If the offset is small enough, we don't need the second
960 run-time check. */
961 if (TREE_CODE (offset) == INTEGER_CST
962 && wi::to_widest (offset) >= 0
963 && wi::to_widest (offset) <= OBJSZ_MAX_OFFSET)
964 *gsi = gsi_after_labels (then_bb);
965 else
967 /* Don't issue run-time error if (ptr > ptr + offset). That
968 may happen when computing a POINTER_PLUS_EXPR. */
969 basic_block then2_bb, fallthru2_bb;
971 gimple_stmt_iterator gsi2 = gsi_after_labels (then_bb);
972 cond_insert_point = create_cond_insert_point (&gsi2, false, false,
973 true, &then2_bb,
974 &fallthru2_bb);
975 /* Convert the pointer to an integer type. */
976 tree p = make_ssa_name (pointer_sized_int_node);
977 g = gimple_build_assign (p, NOP_EXPR, ptr);
978 gimple_set_location (g, loc);
979 gsi_insert_before (&cond_insert_point, g, GSI_NEW_STMT);
980 p = gimple_assign_lhs (g);
981 /* Compute ptr + offset. */
982 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
983 PLUS_EXPR, p, offset);
984 gimple_set_location (g, loc);
985 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
986 /* Now build the conditional and put it into the IR. */
987 g = gimple_build_cond (LE_EXPR, p, gimple_assign_lhs (g),
988 NULL_TREE, NULL_TREE);
989 gimple_set_location (g, loc);
990 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
991 *gsi = gsi_after_labels (then2_bb);
994 /* Generate __ubsan_handle_type_mismatch call. */
995 if (flag_sanitize_undefined_trap_on_error)
996 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
997 else
999 tree data
1000 = ubsan_create_data ("__ubsan_objsz_data", 1, &loc,
1001 ubsan_type_descriptor (TREE_TYPE (ptr),
1002 UBSAN_PRINT_POINTER),
1003 NULL_TREE,
1004 build_zero_cst (pointer_sized_int_node),
1005 ckind,
1006 NULL_TREE);
1007 data = build_fold_addr_expr_loc (loc, data);
1008 enum built_in_function bcode
1009 = (flag_sanitize_recover & SANITIZE_OBJECT_SIZE)
1010 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
1011 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT;
1012 tree p = make_ssa_name (pointer_sized_int_node);
1013 g = gimple_build_assign (p, NOP_EXPR, ptr);
1014 gimple_set_location (g, loc);
1015 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1016 g = gimple_build_call (builtin_decl_explicit (bcode), 2, data, p);
1018 gimple_set_location (g, loc);
1019 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1021 /* Point GSI to next logical statement. */
1022 *gsi = gsi_start_bb (fallthru_bb);
1024 /* Get rid of the UBSAN_OBJECT_SIZE call from the IR. */
1025 unlink_stmt_vdef (stmt);
1026 gsi_remove (&gsi_orig, true);
1027 return true;
1030 /* Get rid of the UBSAN_OBJECT_SIZE call from the IR. */
1031 unlink_stmt_vdef (stmt);
1032 gsi_remove (gsi, true);
1033 return true;
1036 /* Expand UBSAN_PTR internal call. */
1038 bool
1039 ubsan_expand_ptr_ifn (gimple_stmt_iterator *gsip)
1041 gimple_stmt_iterator gsi = *gsip;
1042 gimple *stmt = gsi_stmt (gsi);
1043 location_t loc = gimple_location (stmt);
1044 gcc_assert (gimple_call_num_args (stmt) == 2);
1045 tree ptr = gimple_call_arg (stmt, 0);
1046 tree off = gimple_call_arg (stmt, 1);
1048 if (integer_zerop (off))
1050 gsi_remove (gsip, true);
1051 unlink_stmt_vdef (stmt);
1052 return true;
1055 basic_block cur_bb = gsi_bb (gsi);
1056 tree ptrplusoff = make_ssa_name (pointer_sized_int_node);
1057 tree ptri = make_ssa_name (pointer_sized_int_node);
1058 int pos_neg = get_range_pos_neg (off);
1060 /* Split the original block holding the pointer dereference. */
1061 edge e = split_block (cur_bb, stmt);
1063 /* Get a hold on the 'condition block', the 'then block' and the
1064 'else block'. */
1065 basic_block cond_bb = e->src;
1066 basic_block fallthru_bb = e->dest;
1067 basic_block then_bb = create_empty_bb (cond_bb);
1068 basic_block cond_pos_bb = NULL, cond_neg_bb = NULL;
1069 add_bb_to_loop (then_bb, cond_bb->loop_father);
1070 loops_state_set (LOOPS_NEED_FIXUP);
1072 /* Set up the fallthrough basic block. */
1073 e->flags = EDGE_FALSE_VALUE;
1074 if (pos_neg != 3)
1076 e->count = cond_bb->count;
1077 e->probability = profile_probability::very_likely ();
1079 /* Connect 'then block' with the 'else block'. This is needed
1080 as the ubsan routines we call in the 'then block' are not noreturn.
1081 The 'then block' only has one outcoming edge. */
1082 make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);
1084 /* Make an edge coming from the 'cond block' into the 'then block';
1085 this edge is unlikely taken, so set up the probability
1086 accordingly. */
1087 e = make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
1088 e->probability = profile_probability::very_unlikely ();
1090 else
1092 profile_count count = cond_bb->count.apply_probability (PROB_EVEN);
1093 e->count = count;
1094 e->probability = profile_probability::even ();
1096 e = split_block (fallthru_bb, (gimple *) NULL);
1097 cond_neg_bb = e->src;
1098 fallthru_bb = e->dest;
1099 e->count = count;
1100 e->probability = profile_probability::very_likely ();
1101 e->flags = EDGE_FALSE_VALUE;
1103 e = make_edge (cond_neg_bb, then_bb, EDGE_TRUE_VALUE);
1104 e->probability = profile_probability::very_unlikely ();
1106 cond_pos_bb = create_empty_bb (cond_bb);
1107 add_bb_to_loop (cond_pos_bb, cond_bb->loop_father);
1109 e = make_edge (cond_bb, cond_pos_bb, EDGE_TRUE_VALUE);
1110 e->count = count;
1111 e->probability = profile_probability::even ();
1113 e = make_edge (cond_pos_bb, then_bb, EDGE_TRUE_VALUE);
1114 e->probability = profile_probability::very_unlikely ();
1116 e = make_edge (cond_pos_bb, fallthru_bb, EDGE_FALSE_VALUE);
1117 e->count = count;
1118 e->probability = profile_probability::very_likely ();
1120 make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);
1123 gimple *g = gimple_build_assign (ptri, NOP_EXPR, ptr);
1124 gimple_set_location (g, loc);
1125 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
1126 g = gimple_build_assign (ptrplusoff, PLUS_EXPR, ptri, off);
1127 gimple_set_location (g, loc);
1128 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
1130 /* Update dominance info for the newly created then_bb; note that
1131 fallthru_bb's dominance info has already been updated by
1132 split_block. */
1133 if (dom_info_available_p (CDI_DOMINATORS))
1135 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
1136 if (pos_neg == 3)
1138 set_immediate_dominator (CDI_DOMINATORS, cond_pos_bb, cond_bb);
1139 set_immediate_dominator (CDI_DOMINATORS, fallthru_bb, cond_bb);
1143 /* Put the ubsan builtin call into the newly created BB. */
1144 if (flag_sanitize_undefined_trap_on_error)
1145 g = gimple_build_call (builtin_decl_implicit (BUILT_IN_TRAP), 0);
1146 else
1148 enum built_in_function bcode
1149 = (flag_sanitize_recover & SANITIZE_POINTER_OVERFLOW)
1150 ? BUILT_IN_UBSAN_HANDLE_POINTER_OVERFLOW
1151 : BUILT_IN_UBSAN_HANDLE_POINTER_OVERFLOW_ABORT;
1152 tree fn = builtin_decl_implicit (bcode);
1153 tree data
1154 = ubsan_create_data ("__ubsan_ptrovf_data", 1, &loc,
1155 NULL_TREE, NULL_TREE);
1156 data = build_fold_addr_expr_loc (loc, data);
1157 g = gimple_build_call (fn, 3, data, ptr, ptrplusoff);
1159 gimple_stmt_iterator gsi2 = gsi_start_bb (then_bb);
1160 gimple_set_location (g, loc);
1161 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
1163 /* Unlink the UBSAN_PTRs vops before replacing it. */
1164 unlink_stmt_vdef (stmt);
1166 if (TREE_CODE (off) == INTEGER_CST)
1167 g = gimple_build_cond (wi::neg_p (off) ? LT_EXPR : GE_EXPR, ptri,
1168 fold_build1 (NEGATE_EXPR, sizetype, off),
1169 NULL_TREE, NULL_TREE);
1170 else if (pos_neg != 3)
1171 g = gimple_build_cond (pos_neg == 1 ? LT_EXPR : GT_EXPR,
1172 ptrplusoff, ptri, NULL_TREE, NULL_TREE);
1173 else
1175 gsi2 = gsi_start_bb (cond_pos_bb);
1176 g = gimple_build_cond (LT_EXPR, ptrplusoff, ptri, NULL_TREE, NULL_TREE);
1177 gimple_set_location (g, loc);
1178 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
1180 gsi2 = gsi_start_bb (cond_neg_bb);
1181 g = gimple_build_cond (GT_EXPR, ptrplusoff, ptri, NULL_TREE, NULL_TREE);
1182 gimple_set_location (g, loc);
1183 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
1185 gimple_seq seq = NULL;
1186 tree t = gimple_build (&seq, loc, NOP_EXPR, ssizetype, off);
1187 t = gimple_build (&seq, loc, GE_EXPR, boolean_type_node,
1188 t, ssize_int (0));
1189 gsi_insert_seq_before (&gsi, seq, GSI_SAME_STMT);
1190 g = gimple_build_cond (NE_EXPR, t, boolean_false_node,
1191 NULL_TREE, NULL_TREE);
1193 gimple_set_location (g, loc);
1194 /* Replace the UBSAN_PTR with a GIMPLE_COND stmt. */
1195 gsi_replace (&gsi, g, false);
1196 return false;
1200 /* Cached __ubsan_vptr_type_cache decl. */
1201 static GTY(()) tree ubsan_vptr_type_cache_decl;
1203 /* Expand UBSAN_VPTR internal call. The type is kept on the ckind
1204 argument which is a constant, because the middle-end treats pointer
1205 conversions as useless and therefore the type of the first argument
1206 could be changed to any other pointer type. */
1208 bool
1209 ubsan_expand_vptr_ifn (gimple_stmt_iterator *gsip)
1211 gimple_stmt_iterator gsi = *gsip;
1212 gimple *stmt = gsi_stmt (gsi);
1213 location_t loc = gimple_location (stmt);
1214 gcc_assert (gimple_call_num_args (stmt) == 5);
1215 tree op = gimple_call_arg (stmt, 0);
1216 tree vptr = gimple_call_arg (stmt, 1);
1217 tree str_hash = gimple_call_arg (stmt, 2);
1218 tree ti_decl_addr = gimple_call_arg (stmt, 3);
1219 tree ckind_tree = gimple_call_arg (stmt, 4);
1220 ubsan_null_ckind ckind = (ubsan_null_ckind) tree_to_uhwi (ckind_tree);
1221 tree type = TREE_TYPE (TREE_TYPE (ckind_tree));
1222 gimple *g;
1223 basic_block fallthru_bb = NULL;
1225 if (ckind == UBSAN_DOWNCAST_POINTER)
1227 /* Guard everything with if (op != NULL) { ... }. */
1228 basic_block then_bb;
1229 gimple_stmt_iterator cond_insert_point
1230 = create_cond_insert_point (gsip, false, false, true,
1231 &then_bb, &fallthru_bb);
1232 g = gimple_build_cond (NE_EXPR, op, build_zero_cst (TREE_TYPE (op)),
1233 NULL_TREE, NULL_TREE);
1234 gimple_set_location (g, loc);
1235 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
1236 *gsip = gsi_after_labels (then_bb);
1237 gsi_remove (&gsi, false);
1238 gsi_insert_before (gsip, stmt, GSI_NEW_STMT);
1239 gsi = *gsip;
1242 tree htype = TREE_TYPE (str_hash);
1243 tree cst = wide_int_to_tree (htype,
1244 wi::uhwi (((uint64_t) 0x9ddfea08 << 32)
1245 | 0xeb382d69, 64));
1246 g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1247 vptr, str_hash);
1248 gimple_set_location (g, loc);
1249 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1250 g = gimple_build_assign (make_ssa_name (htype), MULT_EXPR,
1251 gimple_assign_lhs (g), cst);
1252 gimple_set_location (g, loc);
1253 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1254 tree t1 = gimple_assign_lhs (g);
1255 g = gimple_build_assign (make_ssa_name (htype), LSHIFT_EXPR,
1256 t1, build_int_cst (integer_type_node, 47));
1257 gimple_set_location (g, loc);
1258 tree t2 = gimple_assign_lhs (g);
1259 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1260 g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1261 vptr, t1);
1262 gimple_set_location (g, loc);
1263 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1264 g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1265 t2, gimple_assign_lhs (g));
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 t3 = gimple_assign_lhs (g);
1273 g = gimple_build_assign (make_ssa_name (htype), LSHIFT_EXPR,
1274 t3, build_int_cst (integer_type_node, 47));
1275 gimple_set_location (g, loc);
1276 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1277 g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1278 t3, gimple_assign_lhs (g));
1279 gimple_set_location (g, loc);
1280 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1281 g = gimple_build_assign (make_ssa_name (htype), MULT_EXPR,
1282 gimple_assign_lhs (g), cst);
1283 gimple_set_location (g, loc);
1284 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1285 if (!useless_type_conversion_p (pointer_sized_int_node, htype))
1287 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
1288 NOP_EXPR, gimple_assign_lhs (g));
1289 gimple_set_location (g, loc);
1290 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1292 tree hash = gimple_assign_lhs (g);
1294 if (ubsan_vptr_type_cache_decl == NULL_TREE)
1296 tree atype = build_array_type_nelts (pointer_sized_int_node, 128);
1297 tree array = build_decl (UNKNOWN_LOCATION, VAR_DECL,
1298 get_identifier ("__ubsan_vptr_type_cache"),
1299 atype);
1300 DECL_ARTIFICIAL (array) = 1;
1301 DECL_IGNORED_P (array) = 1;
1302 TREE_PUBLIC (array) = 1;
1303 TREE_STATIC (array) = 1;
1304 DECL_EXTERNAL (array) = 1;
1305 DECL_VISIBILITY (array) = VISIBILITY_DEFAULT;
1306 DECL_VISIBILITY_SPECIFIED (array) = 1;
1307 varpool_node::finalize_decl (array);
1308 ubsan_vptr_type_cache_decl = array;
1311 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
1312 BIT_AND_EXPR, hash,
1313 build_int_cst (pointer_sized_int_node, 127));
1314 gimple_set_location (g, loc);
1315 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1317 tree c = build4_loc (loc, ARRAY_REF, pointer_sized_int_node,
1318 ubsan_vptr_type_cache_decl, gimple_assign_lhs (g),
1319 NULL_TREE, NULL_TREE);
1320 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
1321 ARRAY_REF, c);
1322 gimple_set_location (g, loc);
1323 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1325 basic_block then_bb, fallthru2_bb;
1326 gimple_stmt_iterator cond_insert_point
1327 = create_cond_insert_point (gsip, false, false, true,
1328 &then_bb, &fallthru2_bb);
1329 g = gimple_build_cond (NE_EXPR, gimple_assign_lhs (g), hash,
1330 NULL_TREE, NULL_TREE);
1331 gimple_set_location (g, loc);
1332 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
1333 *gsip = gsi_after_labels (then_bb);
1334 if (fallthru_bb == NULL)
1335 fallthru_bb = fallthru2_bb;
1337 tree data
1338 = ubsan_create_data ("__ubsan_vptr_data", 1, &loc,
1339 ubsan_type_descriptor (type), NULL_TREE, ti_decl_addr,
1340 build_int_cst (unsigned_char_type_node, ckind),
1341 NULL_TREE);
1342 data = build_fold_addr_expr_loc (loc, data);
1343 enum built_in_function bcode
1344 = (flag_sanitize_recover & SANITIZE_VPTR)
1345 ? BUILT_IN_UBSAN_HANDLE_DYNAMIC_TYPE_CACHE_MISS
1346 : BUILT_IN_UBSAN_HANDLE_DYNAMIC_TYPE_CACHE_MISS_ABORT;
1348 g = gimple_build_call (builtin_decl_explicit (bcode), 3, data, op, hash);
1349 gimple_set_location (g, loc);
1350 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1352 /* Point GSI to next logical statement. */
1353 *gsip = gsi_start_bb (fallthru_bb);
1355 /* Get rid of the UBSAN_VPTR call from the IR. */
1356 unlink_stmt_vdef (stmt);
1357 gsi_remove (&gsi, true);
1358 return true;
1361 /* Instrument a memory reference. BASE is the base of MEM, IS_LHS says
1362 whether the pointer is on the left hand side of the assignment. */
1364 static void
1365 instrument_mem_ref (tree mem, tree base, gimple_stmt_iterator *iter,
1366 bool is_lhs)
1368 enum ubsan_null_ckind ikind = is_lhs ? UBSAN_STORE_OF : UBSAN_LOAD_OF;
1369 unsigned int align = 0;
1370 if (sanitize_flags_p (SANITIZE_ALIGNMENT))
1372 align = min_align_of_type (TREE_TYPE (base));
1373 if (align <= 1)
1374 align = 0;
1376 if (align == 0 && !sanitize_flags_p (SANITIZE_NULL))
1377 return;
1378 tree t = TREE_OPERAND (base, 0);
1379 if (!POINTER_TYPE_P (TREE_TYPE (t)))
1380 return;
1381 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (base)) && mem != base)
1382 ikind = UBSAN_MEMBER_ACCESS;
1383 tree kind = build_int_cst (build_pointer_type (TREE_TYPE (base)), ikind);
1384 tree alignt = build_int_cst (pointer_sized_int_node, align);
1385 gcall *g = gimple_build_call_internal (IFN_UBSAN_NULL, 3, t, kind, alignt);
1386 gimple_set_location (g, gimple_location (gsi_stmt (*iter)));
1387 gsi_insert_before (iter, g, GSI_SAME_STMT);
1390 /* Perform the pointer instrumentation. */
1392 static void
1393 instrument_null (gimple_stmt_iterator gsi, tree t, bool is_lhs)
1395 /* Handle also e.g. &s->i. */
1396 if (TREE_CODE (t) == ADDR_EXPR)
1397 t = TREE_OPERAND (t, 0);
1398 tree base = get_base_address (t);
1399 if (base != NULL_TREE
1400 && TREE_CODE (base) == MEM_REF
1401 && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
1402 instrument_mem_ref (t, base, &gsi, is_lhs);
1405 /* Instrument pointer arithmetics PTR p+ OFF. */
1407 static void
1408 instrument_pointer_overflow (gimple_stmt_iterator *gsi, tree ptr, tree off)
1410 if (TYPE_PRECISION (sizetype) != POINTER_SIZE)
1411 return;
1412 gcall *g = gimple_build_call_internal (IFN_UBSAN_PTR, 2, ptr, off);
1413 gimple_set_location (g, gimple_location (gsi_stmt (*gsi)));
1414 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1417 /* Instrument pointer arithmetics if any. */
1419 static void
1420 maybe_instrument_pointer_overflow (gimple_stmt_iterator *gsi, tree t)
1422 if (TYPE_PRECISION (sizetype) != POINTER_SIZE)
1423 return;
1425 /* Handle also e.g. &s->i. */
1426 if (TREE_CODE (t) == ADDR_EXPR)
1427 t = TREE_OPERAND (t, 0);
1429 if (!handled_component_p (t) && TREE_CODE (t) != MEM_REF)
1430 return;
1432 HOST_WIDE_INT bitsize, bitpos, bytepos;
1433 tree offset;
1434 machine_mode mode;
1435 int volatilep = 0, reversep, unsignedp = 0;
1436 tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset, &mode,
1437 &unsignedp, &reversep, &volatilep);
1438 tree moff = NULL_TREE;
1440 bool decl_p = DECL_P (inner);
1441 tree base;
1442 if (decl_p)
1444 if (DECL_REGISTER (inner))
1445 return;
1446 base = inner;
1447 /* If BASE is a fixed size automatic variable or
1448 global variable defined in the current TU and bitpos
1449 fits, don't instrument anything. */
1450 if (offset == NULL_TREE
1451 && bitpos > 0
1452 && (VAR_P (base)
1453 || TREE_CODE (base) == PARM_DECL
1454 || TREE_CODE (base) == RESULT_DECL)
1455 && DECL_SIZE (base)
1456 && TREE_CODE (DECL_SIZE (base)) == INTEGER_CST
1457 && compare_tree_int (DECL_SIZE (base), bitpos) >= 0
1458 && (!is_global_var (base) || decl_binds_to_current_def_p (base)))
1459 return;
1461 else if (TREE_CODE (inner) == MEM_REF)
1463 base = TREE_OPERAND (inner, 0);
1464 if (TREE_CODE (base) == ADDR_EXPR
1465 && DECL_P (TREE_OPERAND (base, 0))
1466 && !TREE_ADDRESSABLE (TREE_OPERAND (base, 0))
1467 && !is_global_var (TREE_OPERAND (base, 0)))
1468 return;
1469 moff = TREE_OPERAND (inner, 1);
1470 if (integer_zerop (moff))
1471 moff = NULL_TREE;
1473 else
1474 return;
1476 if (!POINTER_TYPE_P (TREE_TYPE (base)) && !DECL_P (base))
1477 return;
1478 bytepos = bitpos / BITS_PER_UNIT;
1479 if (offset == NULL_TREE && bytepos == 0 && moff == NULL_TREE)
1480 return;
1482 tree base_addr = base;
1483 if (decl_p)
1484 base_addr = build1 (ADDR_EXPR,
1485 build_pointer_type (TREE_TYPE (base)), base);
1486 t = offset;
1487 if (bytepos)
1489 if (t)
1490 t = fold_build2 (PLUS_EXPR, TREE_TYPE (t), t,
1491 build_int_cst (TREE_TYPE (t), bytepos));
1492 else
1493 t = size_int (bytepos);
1495 if (moff)
1497 if (t)
1498 t = fold_build2 (PLUS_EXPR, TREE_TYPE (t), t,
1499 fold_convert (TREE_TYPE (t), moff));
1500 else
1501 t = fold_convert (sizetype, moff);
1503 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE, true,
1504 GSI_SAME_STMT);
1505 base_addr = force_gimple_operand_gsi (gsi, base_addr, true, NULL_TREE, true,
1506 GSI_SAME_STMT);
1507 instrument_pointer_overflow (gsi, base_addr, t);
1510 /* Build an ubsan builtin call for the signed-integer-overflow
1511 sanitization. CODE says what kind of builtin are we building,
1512 LOC is a location, LHSTYPE is the type of LHS, OP0 and OP1
1513 are operands of the binary operation. */
1515 tree
1516 ubsan_build_overflow_builtin (tree_code code, location_t loc, tree lhstype,
1517 tree op0, tree op1, tree *datap)
1519 if (flag_sanitize_undefined_trap_on_error)
1520 return build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
1522 tree data;
1523 if (datap && *datap)
1524 data = *datap;
1525 else
1526 data = ubsan_create_data ("__ubsan_overflow_data", 1, &loc,
1527 ubsan_type_descriptor (lhstype), NULL_TREE,
1528 NULL_TREE);
1529 if (datap)
1530 *datap = data;
1531 enum built_in_function fn_code;
1533 switch (code)
1535 case PLUS_EXPR:
1536 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1537 ? BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW
1538 : BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW_ABORT;
1539 break;
1540 case MINUS_EXPR:
1541 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1542 ? BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW
1543 : BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW_ABORT;
1544 break;
1545 case MULT_EXPR:
1546 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1547 ? BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW
1548 : BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW_ABORT;
1549 break;
1550 case NEGATE_EXPR:
1551 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1552 ? BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW
1553 : BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW_ABORT;
1554 break;
1555 default:
1556 gcc_unreachable ();
1558 tree fn = builtin_decl_explicit (fn_code);
1559 return build_call_expr_loc (loc, fn, 2 + (code != NEGATE_EXPR),
1560 build_fold_addr_expr_loc (loc, data),
1561 ubsan_encode_value (op0, UBSAN_ENCODE_VALUE_RTL),
1563 ? ubsan_encode_value (op1,
1564 UBSAN_ENCODE_VALUE_RTL)
1565 : NULL_TREE);
1568 /* Perform the signed integer instrumentation. GSI is the iterator
1569 pointing at statement we are trying to instrument. */
1571 static void
1572 instrument_si_overflow (gimple_stmt_iterator gsi)
1574 gimple *stmt = gsi_stmt (gsi);
1575 tree_code code = gimple_assign_rhs_code (stmt);
1576 tree lhs = gimple_assign_lhs (stmt);
1577 tree lhstype = TREE_TYPE (lhs);
1578 tree lhsinner = VECTOR_TYPE_P (lhstype) ? TREE_TYPE (lhstype) : lhstype;
1579 tree a, b;
1580 gimple *g;
1582 /* If this is not a signed operation, don't instrument anything here.
1583 Also punt on bit-fields. */
1584 if (!INTEGRAL_TYPE_P (lhsinner)
1585 || TYPE_OVERFLOW_WRAPS (lhsinner)
1586 || GET_MODE_BITSIZE (TYPE_MODE (lhsinner)) != TYPE_PRECISION (lhsinner))
1587 return;
1589 switch (code)
1591 case MINUS_EXPR:
1592 case PLUS_EXPR:
1593 case MULT_EXPR:
1594 /* Transform
1595 i = u {+,-,*} 5;
1596 into
1597 i = UBSAN_CHECK_{ADD,SUB,MUL} (u, 5); */
1598 a = gimple_assign_rhs1 (stmt);
1599 b = gimple_assign_rhs2 (stmt);
1600 g = gimple_build_call_internal (code == PLUS_EXPR
1601 ? IFN_UBSAN_CHECK_ADD
1602 : code == MINUS_EXPR
1603 ? IFN_UBSAN_CHECK_SUB
1604 : IFN_UBSAN_CHECK_MUL, 2, a, b);
1605 gimple_call_set_lhs (g, lhs);
1606 gsi_replace (&gsi, g, true);
1607 break;
1608 case NEGATE_EXPR:
1609 /* Represent i = -u;
1611 i = UBSAN_CHECK_SUB (0, u); */
1612 a = build_zero_cst (lhstype);
1613 b = gimple_assign_rhs1 (stmt);
1614 g = gimple_build_call_internal (IFN_UBSAN_CHECK_SUB, 2, a, b);
1615 gimple_call_set_lhs (g, lhs);
1616 gsi_replace (&gsi, g, true);
1617 break;
1618 case ABS_EXPR:
1619 /* Transform i = ABS_EXPR<u>;
1620 into
1621 _N = UBSAN_CHECK_SUB (0, u);
1622 i = ABS_EXPR<_N>; */
1623 a = build_zero_cst (lhstype);
1624 b = gimple_assign_rhs1 (stmt);
1625 g = gimple_build_call_internal (IFN_UBSAN_CHECK_SUB, 2, a, b);
1626 a = make_ssa_name (lhstype);
1627 gimple_call_set_lhs (g, a);
1628 gimple_set_location (g, gimple_location (stmt));
1629 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
1630 gimple_assign_set_rhs1 (stmt, a);
1631 update_stmt (stmt);
1632 break;
1633 default:
1634 break;
1638 /* Instrument loads from (non-bitfield) bool and C++ enum values
1639 to check if the memory value is outside of the range of the valid
1640 type values. */
1642 static void
1643 instrument_bool_enum_load (gimple_stmt_iterator *gsi)
1645 gimple *stmt = gsi_stmt (*gsi);
1646 tree rhs = gimple_assign_rhs1 (stmt);
1647 tree type = TREE_TYPE (rhs);
1648 tree minv = NULL_TREE, maxv = NULL_TREE;
1650 if (TREE_CODE (type) == BOOLEAN_TYPE
1651 && sanitize_flags_p (SANITIZE_BOOL))
1653 minv = boolean_false_node;
1654 maxv = boolean_true_node;
1656 else if (TREE_CODE (type) == ENUMERAL_TYPE
1657 && sanitize_flags_p (SANITIZE_ENUM)
1658 && TREE_TYPE (type) != NULL_TREE
1659 && TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE
1660 && (TYPE_PRECISION (TREE_TYPE (type))
1661 < GET_MODE_PRECISION (SCALAR_INT_TYPE_MODE (type))))
1663 minv = TYPE_MIN_VALUE (TREE_TYPE (type));
1664 maxv = TYPE_MAX_VALUE (TREE_TYPE (type));
1666 else
1667 return;
1669 int modebitsize = GET_MODE_BITSIZE (SCALAR_INT_TYPE_MODE (type));
1670 HOST_WIDE_INT bitsize, bitpos;
1671 tree offset;
1672 machine_mode mode;
1673 int volatilep = 0, reversep, unsignedp = 0;
1674 tree base = get_inner_reference (rhs, &bitsize, &bitpos, &offset, &mode,
1675 &unsignedp, &reversep, &volatilep);
1676 tree utype = build_nonstandard_integer_type (modebitsize, 1);
1678 if ((VAR_P (base) && DECL_HARD_REGISTER (base))
1679 || (bitpos % modebitsize) != 0
1680 || bitsize != modebitsize
1681 || GET_MODE_BITSIZE (SCALAR_INT_TYPE_MODE (utype)) != modebitsize
1682 || TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME)
1683 return;
1685 bool ends_bb = stmt_ends_bb_p (stmt);
1686 location_t loc = gimple_location (stmt);
1687 tree lhs = gimple_assign_lhs (stmt);
1688 tree ptype = build_pointer_type (TREE_TYPE (rhs));
1689 tree atype = reference_alias_ptr_type (rhs);
1690 gimple *g = gimple_build_assign (make_ssa_name (ptype),
1691 build_fold_addr_expr (rhs));
1692 gimple_set_location (g, loc);
1693 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1694 tree mem = build2 (MEM_REF, utype, gimple_assign_lhs (g),
1695 build_int_cst (atype, 0));
1696 tree urhs = make_ssa_name (utype);
1697 if (ends_bb)
1699 gimple_assign_set_lhs (stmt, urhs);
1700 g = gimple_build_assign (lhs, NOP_EXPR, urhs);
1701 gimple_set_location (g, loc);
1702 edge e = find_fallthru_edge (gimple_bb (stmt)->succs);
1703 gsi_insert_on_edge_immediate (e, g);
1704 gimple_assign_set_rhs_from_tree (gsi, mem);
1705 update_stmt (stmt);
1706 *gsi = gsi_for_stmt (g);
1707 g = stmt;
1709 else
1711 g = gimple_build_assign (urhs, mem);
1712 gimple_set_location (g, loc);
1713 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1715 minv = fold_convert (utype, minv);
1716 maxv = fold_convert (utype, maxv);
1717 if (!integer_zerop (minv))
1719 g = gimple_build_assign (make_ssa_name (utype), MINUS_EXPR, urhs, minv);
1720 gimple_set_location (g, loc);
1721 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1724 gimple_stmt_iterator gsi2 = *gsi;
1725 basic_block then_bb, fallthru_bb;
1726 *gsi = create_cond_insert_point (gsi, true, false, true,
1727 &then_bb, &fallthru_bb);
1728 g = gimple_build_cond (GT_EXPR, gimple_assign_lhs (g),
1729 int_const_binop (MINUS_EXPR, maxv, minv),
1730 NULL_TREE, NULL_TREE);
1731 gimple_set_location (g, loc);
1732 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1734 if (!ends_bb)
1736 gimple_assign_set_rhs_with_ops (&gsi2, NOP_EXPR, urhs);
1737 update_stmt (stmt);
1740 gsi2 = gsi_after_labels (then_bb);
1741 if (flag_sanitize_undefined_trap_on_error)
1742 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1743 else
1745 tree data = ubsan_create_data ("__ubsan_invalid_value_data", 1, &loc,
1746 ubsan_type_descriptor (type), NULL_TREE,
1747 NULL_TREE);
1748 data = build_fold_addr_expr_loc (loc, data);
1749 enum built_in_function bcode
1750 = (flag_sanitize_recover & (TREE_CODE (type) == BOOLEAN_TYPE
1751 ? SANITIZE_BOOL : SANITIZE_ENUM))
1752 ? BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE
1753 : BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE_ABORT;
1754 tree fn = builtin_decl_explicit (bcode);
1756 tree val = ubsan_encode_value (urhs, UBSAN_ENCODE_VALUE_GIMPLE);
1757 val = force_gimple_operand_gsi (&gsi2, val, true, NULL_TREE, true,
1758 GSI_SAME_STMT);
1759 g = gimple_build_call (fn, 2, data, val);
1761 gimple_set_location (g, loc);
1762 gsi_insert_before (&gsi2, g, GSI_SAME_STMT);
1763 ubsan_create_edge (g);
1764 *gsi = gsi_for_stmt (stmt);
1767 /* Determine if we can propagate given LOCATION to ubsan_data descriptor to use
1768 new style handlers. Libubsan uses heuristics to destinguish between old and
1769 new styles and relies on these properties for filename:
1771 a) Location's filename must not be NULL.
1772 b) Location's filename must not be equal to "".
1773 c) Location's filename must not be equal to "\1".
1774 d) First two bytes of filename must not contain '\xff' symbol. */
1776 static bool
1777 ubsan_use_new_style_p (location_t loc)
1779 if (loc == UNKNOWN_LOCATION)
1780 return false;
1782 expanded_location xloc = expand_location (loc);
1783 if (xloc.file == NULL || strncmp (xloc.file, "\1", 2) == 0
1784 || xloc.file[0] == '\0' || xloc.file[0] == '\xff'
1785 || xloc.file[1] == '\xff')
1786 return false;
1788 return true;
1791 /* Instrument float point-to-integer conversion. TYPE is an integer type of
1792 destination, EXPR is floating-point expression. */
1794 tree
1795 ubsan_instrument_float_cast (location_t loc, tree type, tree expr)
1797 tree expr_type = TREE_TYPE (expr);
1798 tree t, tt, fn, min, max;
1799 machine_mode mode = TYPE_MODE (expr_type);
1800 int prec = TYPE_PRECISION (type);
1801 bool uns_p = TYPE_UNSIGNED (type);
1802 if (loc == UNKNOWN_LOCATION)
1803 loc = input_location;
1805 /* Float to integer conversion first truncates toward zero, so
1806 even signed char c = 127.875f; is not problematic.
1807 Therefore, we should complain only if EXPR is unordered or smaller
1808 or equal than TYPE_MIN_VALUE - 1.0 or greater or equal than
1809 TYPE_MAX_VALUE + 1.0. */
1810 if (REAL_MODE_FORMAT (mode)->b == 2)
1812 /* For maximum, TYPE_MAX_VALUE might not be representable
1813 in EXPR_TYPE, e.g. if TYPE is 64-bit long long and
1814 EXPR_TYPE is IEEE single float, but TYPE_MAX_VALUE + 1.0 is
1815 either representable or infinity. */
1816 REAL_VALUE_TYPE maxval = dconst1;
1817 SET_REAL_EXP (&maxval, REAL_EXP (&maxval) + prec - !uns_p);
1818 real_convert (&maxval, mode, &maxval);
1819 max = build_real (expr_type, maxval);
1821 /* For unsigned, assume -1.0 is always representable. */
1822 if (uns_p)
1823 min = build_minus_one_cst (expr_type);
1824 else
1826 /* TYPE_MIN_VALUE is generally representable (or -inf),
1827 but TYPE_MIN_VALUE - 1.0 might not be. */
1828 REAL_VALUE_TYPE minval = dconstm1, minval2;
1829 SET_REAL_EXP (&minval, REAL_EXP (&minval) + prec - 1);
1830 real_convert (&minval, mode, &minval);
1831 real_arithmetic (&minval2, MINUS_EXPR, &minval, &dconst1);
1832 real_convert (&minval2, mode, &minval2);
1833 if (real_compare (EQ_EXPR, &minval, &minval2)
1834 && !real_isinf (&minval))
1836 /* If TYPE_MIN_VALUE - 1.0 is not representable and
1837 rounds to TYPE_MIN_VALUE, we need to subtract
1838 more. As REAL_MODE_FORMAT (mode)->p is the number
1839 of base digits, we want to subtract a number that
1840 will be 1 << (REAL_MODE_FORMAT (mode)->p - 1)
1841 times smaller than minval. */
1842 minval2 = dconst1;
1843 gcc_assert (prec > REAL_MODE_FORMAT (mode)->p);
1844 SET_REAL_EXP (&minval2,
1845 REAL_EXP (&minval2) + prec - 1
1846 - REAL_MODE_FORMAT (mode)->p + 1);
1847 real_arithmetic (&minval2, MINUS_EXPR, &minval, &minval2);
1848 real_convert (&minval2, mode, &minval2);
1850 min = build_real (expr_type, minval2);
1853 else if (REAL_MODE_FORMAT (mode)->b == 10)
1855 /* For _Decimal128 up to 34 decimal digits, - sign,
1856 dot, e, exponent. */
1857 char buf[64];
1858 mpfr_t m;
1859 int p = REAL_MODE_FORMAT (mode)->p;
1860 REAL_VALUE_TYPE maxval, minval;
1862 /* Use mpfr_snprintf rounding to compute the smallest
1863 representable decimal number greater or equal than
1864 1 << (prec - !uns_p). */
1865 mpfr_init2 (m, prec + 2);
1866 mpfr_set_ui_2exp (m, 1, prec - !uns_p, GMP_RNDN);
1867 mpfr_snprintf (buf, sizeof buf, "%.*RUe", p - 1, m);
1868 decimal_real_from_string (&maxval, buf);
1869 max = build_real (expr_type, maxval);
1871 /* For unsigned, assume -1.0 is always representable. */
1872 if (uns_p)
1873 min = build_minus_one_cst (expr_type);
1874 else
1876 /* Use mpfr_snprintf rounding to compute the largest
1877 representable decimal number less or equal than
1878 (-1 << (prec - 1)) - 1. */
1879 mpfr_set_si_2exp (m, -1, prec - 1, GMP_RNDN);
1880 mpfr_sub_ui (m, m, 1, GMP_RNDN);
1881 mpfr_snprintf (buf, sizeof buf, "%.*RDe", p - 1, m);
1882 decimal_real_from_string (&minval, buf);
1883 min = build_real (expr_type, minval);
1885 mpfr_clear (m);
1887 else
1888 return NULL_TREE;
1890 t = fold_build2 (UNLE_EXPR, boolean_type_node, expr, min);
1891 tt = fold_build2 (UNGE_EXPR, boolean_type_node, expr, max);
1892 t = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t, tt);
1893 if (integer_zerop (t))
1894 return NULL_TREE;
1896 if (flag_sanitize_undefined_trap_on_error)
1897 fn = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
1898 else
1900 location_t *loc_ptr = NULL;
1901 unsigned num_locations = 0;
1902 /* Figure out if we can propagate location to ubsan_data and use new
1903 style handlers in libubsan. */
1904 if (ubsan_use_new_style_p (loc))
1906 loc_ptr = &loc;
1907 num_locations = 1;
1909 /* Create the __ubsan_handle_float_cast_overflow fn call. */
1910 tree data = ubsan_create_data ("__ubsan_float_cast_overflow_data",
1911 num_locations, loc_ptr,
1912 ubsan_type_descriptor (expr_type),
1913 ubsan_type_descriptor (type), NULL_TREE,
1914 NULL_TREE);
1915 enum built_in_function bcode
1916 = (flag_sanitize_recover & SANITIZE_FLOAT_CAST)
1917 ? BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW
1918 : BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW_ABORT;
1919 fn = builtin_decl_explicit (bcode);
1920 fn = build_call_expr_loc (loc, fn, 2,
1921 build_fold_addr_expr_loc (loc, data),
1922 ubsan_encode_value (expr));
1925 return fold_build3 (COND_EXPR, void_type_node, t, fn, integer_zero_node);
1928 /* Instrument values passed to function arguments with nonnull attribute. */
1930 static void
1931 instrument_nonnull_arg (gimple_stmt_iterator *gsi)
1933 gimple *stmt = gsi_stmt (*gsi);
1934 location_t loc[2];
1935 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
1936 while for nonnull sanitization it is clear. */
1937 int save_flag_delete_null_pointer_checks = flag_delete_null_pointer_checks;
1938 flag_delete_null_pointer_checks = 1;
1939 loc[0] = gimple_location (stmt);
1940 loc[1] = UNKNOWN_LOCATION;
1941 for (unsigned int i = 0; i < gimple_call_num_args (stmt); i++)
1943 tree arg = gimple_call_arg (stmt, i);
1944 if (POINTER_TYPE_P (TREE_TYPE (arg))
1945 && infer_nonnull_range_by_attribute (stmt, arg))
1947 gimple *g;
1948 if (!is_gimple_val (arg))
1950 g = gimple_build_assign (make_ssa_name (TREE_TYPE (arg)), arg);
1951 gimple_set_location (g, loc[0]);
1952 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1953 arg = gimple_assign_lhs (g);
1956 basic_block then_bb, fallthru_bb;
1957 *gsi = create_cond_insert_point (gsi, true, false, true,
1958 &then_bb, &fallthru_bb);
1959 g = gimple_build_cond (EQ_EXPR, arg,
1960 build_zero_cst (TREE_TYPE (arg)),
1961 NULL_TREE, NULL_TREE);
1962 gimple_set_location (g, loc[0]);
1963 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1965 *gsi = gsi_after_labels (then_bb);
1966 if (flag_sanitize_undefined_trap_on_error)
1967 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1968 else
1970 tree data = ubsan_create_data ("__ubsan_nonnull_arg_data",
1971 2, loc, NULL_TREE,
1972 build_int_cst (integer_type_node,
1973 i + 1),
1974 NULL_TREE);
1975 data = build_fold_addr_expr_loc (loc[0], data);
1976 enum built_in_function bcode
1977 = (flag_sanitize_recover & SANITIZE_NONNULL_ATTRIBUTE)
1978 ? BUILT_IN_UBSAN_HANDLE_NONNULL_ARG
1979 : BUILT_IN_UBSAN_HANDLE_NONNULL_ARG_ABORT;
1980 tree fn = builtin_decl_explicit (bcode);
1982 g = gimple_build_call (fn, 1, data);
1984 gimple_set_location (g, loc[0]);
1985 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1986 ubsan_create_edge (g);
1988 *gsi = gsi_for_stmt (stmt);
1990 flag_delete_null_pointer_checks = save_flag_delete_null_pointer_checks;
1993 /* Instrument returns in functions with returns_nonnull attribute. */
1995 static void
1996 instrument_nonnull_return (gimple_stmt_iterator *gsi)
1998 greturn *stmt = as_a <greturn *> (gsi_stmt (*gsi));
1999 location_t loc[2];
2000 tree arg = gimple_return_retval (stmt);
2001 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
2002 while for nonnull return sanitization it is clear. */
2003 int save_flag_delete_null_pointer_checks = flag_delete_null_pointer_checks;
2004 flag_delete_null_pointer_checks = 1;
2005 loc[0] = gimple_location (stmt);
2006 loc[1] = UNKNOWN_LOCATION;
2007 if (arg
2008 && POINTER_TYPE_P (TREE_TYPE (arg))
2009 && is_gimple_val (arg)
2010 && infer_nonnull_range_by_attribute (stmt, arg))
2012 basic_block then_bb, fallthru_bb;
2013 *gsi = create_cond_insert_point (gsi, true, false, true,
2014 &then_bb, &fallthru_bb);
2015 gimple *g = gimple_build_cond (EQ_EXPR, arg,
2016 build_zero_cst (TREE_TYPE (arg)),
2017 NULL_TREE, NULL_TREE);
2018 gimple_set_location (g, loc[0]);
2019 gsi_insert_after (gsi, g, GSI_NEW_STMT);
2021 *gsi = gsi_after_labels (then_bb);
2022 if (flag_sanitize_undefined_trap_on_error)
2023 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
2024 else
2026 tree data = ubsan_create_data ("__ubsan_nonnull_return_data",
2027 2, loc, NULL_TREE, NULL_TREE);
2028 data = build_fold_addr_expr_loc (loc[0], data);
2029 enum built_in_function bcode
2030 = (flag_sanitize_recover & SANITIZE_RETURNS_NONNULL_ATTRIBUTE)
2031 ? BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN
2032 : BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_ABORT;
2033 tree fn = builtin_decl_explicit (bcode);
2035 g = gimple_build_call (fn, 1, data);
2037 gimple_set_location (g, loc[0]);
2038 gsi_insert_before (gsi, g, GSI_SAME_STMT);
2039 ubsan_create_edge (g);
2040 *gsi = gsi_for_stmt (stmt);
2042 flag_delete_null_pointer_checks = save_flag_delete_null_pointer_checks;
2045 /* Instrument memory references. Here we check whether the pointer
2046 points to an out-of-bounds location. */
2048 static void
2049 instrument_object_size (gimple_stmt_iterator *gsi, tree t, bool is_lhs)
2051 gimple *stmt = gsi_stmt (*gsi);
2052 location_t loc = gimple_location (stmt);
2053 tree type;
2054 tree index = NULL_TREE;
2055 HOST_WIDE_INT size_in_bytes;
2057 type = TREE_TYPE (t);
2058 if (VOID_TYPE_P (type))
2059 return;
2061 switch (TREE_CODE (t))
2063 case COMPONENT_REF:
2064 if (TREE_CODE (t) == COMPONENT_REF
2065 && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1)) != NULL_TREE)
2067 tree repr = DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1));
2068 t = build3 (COMPONENT_REF, TREE_TYPE (repr), TREE_OPERAND (t, 0),
2069 repr, TREE_OPERAND (t, 2));
2071 break;
2072 case ARRAY_REF:
2073 index = TREE_OPERAND (t, 1);
2074 break;
2075 case INDIRECT_REF:
2076 case MEM_REF:
2077 case VAR_DECL:
2078 case PARM_DECL:
2079 case RESULT_DECL:
2080 break;
2081 default:
2082 return;
2085 size_in_bytes = int_size_in_bytes (type);
2086 if (size_in_bytes <= 0)
2087 return;
2089 HOST_WIDE_INT bitsize, bitpos;
2090 tree offset;
2091 machine_mode mode;
2092 int volatilep = 0, reversep, unsignedp = 0;
2093 tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset, &mode,
2094 &unsignedp, &reversep, &volatilep);
2096 if (bitpos % BITS_PER_UNIT != 0
2097 || bitsize != size_in_bytes * BITS_PER_UNIT)
2098 return;
2100 bool decl_p = DECL_P (inner);
2101 tree base;
2102 if (decl_p)
2104 if (DECL_REGISTER (inner))
2105 return;
2106 base = inner;
2108 else if (TREE_CODE (inner) == MEM_REF)
2109 base = TREE_OPERAND (inner, 0);
2110 else
2111 return;
2112 tree ptr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (t)), t);
2114 while (TREE_CODE (base) == SSA_NAME)
2116 gimple *def_stmt = SSA_NAME_DEF_STMT (base);
2117 if (gimple_assign_ssa_name_copy_p (def_stmt)
2118 || (gimple_assign_cast_p (def_stmt)
2119 && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (def_stmt))))
2120 || (is_gimple_assign (def_stmt)
2121 && gimple_assign_rhs_code (def_stmt) == POINTER_PLUS_EXPR))
2123 tree rhs1 = gimple_assign_rhs1 (def_stmt);
2124 if (TREE_CODE (rhs1) == SSA_NAME
2125 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs1))
2126 break;
2127 else
2128 base = rhs1;
2130 else
2131 break;
2134 if (!POINTER_TYPE_P (TREE_TYPE (base)) && !DECL_P (base))
2135 return;
2137 tree sizet;
2138 tree base_addr = base;
2139 gimple *bos_stmt = NULL;
2140 if (decl_p)
2141 base_addr = build1 (ADDR_EXPR,
2142 build_pointer_type (TREE_TYPE (base)), base);
2143 unsigned HOST_WIDE_INT size;
2144 if (compute_builtin_object_size (base_addr, 0, &size))
2145 sizet = build_int_cst (sizetype, size);
2146 else if (optimize)
2148 if (LOCATION_LOCUS (loc) == UNKNOWN_LOCATION)
2149 loc = input_location;
2150 /* Generate __builtin_object_size call. */
2151 sizet = builtin_decl_explicit (BUILT_IN_OBJECT_SIZE);
2152 sizet = build_call_expr_loc (loc, sizet, 2, base_addr,
2153 integer_zero_node);
2154 sizet = force_gimple_operand_gsi (gsi, sizet, false, NULL_TREE, true,
2155 GSI_SAME_STMT);
2156 /* If the call above didn't end up being an integer constant, go one
2157 statement back and get the __builtin_object_size stmt. Save it,
2158 we might need it later. */
2159 if (SSA_VAR_P (sizet))
2161 gsi_prev (gsi);
2162 bos_stmt = gsi_stmt (*gsi);
2164 /* Move on to where we were. */
2165 gsi_next (gsi);
2168 else
2169 return;
2171 /* Generate UBSAN_OBJECT_SIZE (ptr, ptr+sizeof(*ptr)-base, objsize, ckind)
2172 call. */
2173 /* ptr + sizeof (*ptr) - base */
2174 t = fold_build2 (MINUS_EXPR, sizetype,
2175 fold_convert (pointer_sized_int_node, ptr),
2176 fold_convert (pointer_sized_int_node, base_addr));
2177 t = fold_build2 (PLUS_EXPR, sizetype, t, TYPE_SIZE_UNIT (type));
2179 /* Perhaps we can omit the check. */
2180 if (TREE_CODE (t) == INTEGER_CST
2181 && TREE_CODE (sizet) == INTEGER_CST
2182 && tree_int_cst_le (t, sizet))
2183 return;
2185 if (index != NULL_TREE
2186 && TREE_CODE (index) == SSA_NAME
2187 && TREE_CODE (sizet) == INTEGER_CST)
2189 gimple *def = SSA_NAME_DEF_STMT (index);
2190 if (is_gimple_assign (def)
2191 && gimple_assign_rhs_code (def) == BIT_AND_EXPR
2192 && TREE_CODE (gimple_assign_rhs2 (def)) == INTEGER_CST)
2194 tree cst = gimple_assign_rhs2 (def);
2195 tree sz = fold_build2 (EXACT_DIV_EXPR, sizetype, sizet,
2196 TYPE_SIZE_UNIT (type));
2197 if (tree_int_cst_sgn (cst) >= 0
2198 && tree_int_cst_lt (cst, sz))
2199 return;
2203 if (bos_stmt && gimple_call_builtin_p (bos_stmt, BUILT_IN_OBJECT_SIZE))
2204 ubsan_create_edge (bos_stmt);
2206 /* We have to emit the check. */
2207 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE, true,
2208 GSI_SAME_STMT);
2209 ptr = force_gimple_operand_gsi (gsi, ptr, true, NULL_TREE, true,
2210 GSI_SAME_STMT);
2211 tree ckind = build_int_cst (unsigned_char_type_node,
2212 is_lhs ? UBSAN_STORE_OF : UBSAN_LOAD_OF);
2213 gimple *g = gimple_build_call_internal (IFN_UBSAN_OBJECT_SIZE, 4,
2214 ptr, t, sizet, ckind);
2215 gimple_set_location (g, loc);
2216 gsi_insert_before (gsi, g, GSI_SAME_STMT);
2219 namespace {
2221 const pass_data pass_data_ubsan =
2223 GIMPLE_PASS, /* type */
2224 "ubsan", /* name */
2225 OPTGROUP_NONE, /* optinfo_flags */
2226 TV_TREE_UBSAN, /* tv_id */
2227 ( PROP_cfg | PROP_ssa ), /* properties_required */
2228 0, /* properties_provided */
2229 0, /* properties_destroyed */
2230 0, /* todo_flags_start */
2231 TODO_update_ssa, /* todo_flags_finish */
2234 class pass_ubsan : public gimple_opt_pass
2236 public:
2237 pass_ubsan (gcc::context *ctxt)
2238 : gimple_opt_pass (pass_data_ubsan, ctxt)
2241 /* opt_pass methods: */
2242 virtual bool gate (function *)
2244 return sanitize_flags_p ((SANITIZE_NULL | SANITIZE_SI_OVERFLOW
2245 | SANITIZE_BOOL | SANITIZE_ENUM
2246 | SANITIZE_ALIGNMENT
2247 | SANITIZE_NONNULL_ATTRIBUTE
2248 | SANITIZE_RETURNS_NONNULL_ATTRIBUTE
2249 | SANITIZE_OBJECT_SIZE
2250 | SANITIZE_POINTER_OVERFLOW));
2253 virtual unsigned int execute (function *);
2255 }; // class pass_ubsan
2257 unsigned int
2258 pass_ubsan::execute (function *fun)
2260 basic_block bb;
2261 gimple_stmt_iterator gsi;
2262 unsigned int ret = 0;
2264 initialize_sanitizer_builtins ();
2266 FOR_EACH_BB_FN (bb, fun)
2268 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
2270 gimple *stmt = gsi_stmt (gsi);
2271 if (is_gimple_debug (stmt) || gimple_clobber_p (stmt))
2273 gsi_next (&gsi);
2274 continue;
2277 if ((sanitize_flags_p (SANITIZE_SI_OVERFLOW, fun->decl))
2278 && is_gimple_assign (stmt))
2279 instrument_si_overflow (gsi);
2281 if (sanitize_flags_p (SANITIZE_NULL | SANITIZE_ALIGNMENT, fun->decl))
2283 if (gimple_store_p (stmt))
2284 instrument_null (gsi, gimple_get_lhs (stmt), true);
2285 if (gimple_assign_single_p (stmt))
2286 instrument_null (gsi, gimple_assign_rhs1 (stmt), false);
2287 if (is_gimple_call (stmt))
2289 unsigned args_num = gimple_call_num_args (stmt);
2290 for (unsigned i = 0; i < args_num; ++i)
2292 tree arg = gimple_call_arg (stmt, i);
2293 if (is_gimple_reg (arg) || is_gimple_min_invariant (arg))
2294 continue;
2295 instrument_null (gsi, arg, false);
2300 if (sanitize_flags_p (SANITIZE_BOOL | SANITIZE_ENUM, fun->decl)
2301 && gimple_assign_load_p (stmt))
2303 instrument_bool_enum_load (&gsi);
2304 bb = gimple_bb (stmt);
2307 if (sanitize_flags_p (SANITIZE_NONNULL_ATTRIBUTE, fun->decl)
2308 && is_gimple_call (stmt)
2309 && !gimple_call_internal_p (stmt))
2311 instrument_nonnull_arg (&gsi);
2312 bb = gimple_bb (stmt);
2315 if (sanitize_flags_p (SANITIZE_RETURNS_NONNULL_ATTRIBUTE, fun->decl)
2316 && gimple_code (stmt) == GIMPLE_RETURN)
2318 instrument_nonnull_return (&gsi);
2319 bb = gimple_bb (stmt);
2322 if (sanitize_flags_p (SANITIZE_OBJECT_SIZE, fun->decl))
2324 if (gimple_store_p (stmt))
2325 instrument_object_size (&gsi, gimple_get_lhs (stmt), true);
2326 if (gimple_assign_load_p (stmt))
2327 instrument_object_size (&gsi, gimple_assign_rhs1 (stmt),
2328 false);
2329 if (is_gimple_call (stmt))
2331 unsigned args_num = gimple_call_num_args (stmt);
2332 for (unsigned i = 0; i < args_num; ++i)
2334 tree arg = gimple_call_arg (stmt, i);
2335 if (is_gimple_reg (arg) || is_gimple_min_invariant (arg))
2336 continue;
2337 instrument_object_size (&gsi, arg, false);
2342 if (sanitize_flags_p (SANITIZE_POINTER_OVERFLOW, fun->decl))
2344 if (is_gimple_assign (stmt)
2345 && gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
2346 instrument_pointer_overflow (&gsi,
2347 gimple_assign_rhs1 (stmt),
2348 gimple_assign_rhs2 (stmt));
2349 if (gimple_store_p (stmt))
2350 maybe_instrument_pointer_overflow (&gsi,
2351 gimple_get_lhs (stmt));
2352 if (gimple_assign_single_p (stmt))
2353 maybe_instrument_pointer_overflow (&gsi,
2354 gimple_assign_rhs1 (stmt));
2355 if (is_gimple_call (stmt))
2357 unsigned args_num = gimple_call_num_args (stmt);
2358 for (unsigned i = 0; i < args_num; ++i)
2360 tree arg = gimple_call_arg (stmt, i);
2361 if (is_gimple_reg (arg))
2362 continue;
2363 maybe_instrument_pointer_overflow (&gsi, arg);
2368 gsi_next (&gsi);
2370 if (gimple_purge_dead_eh_edges (bb))
2371 ret = TODO_cleanup_cfg;
2373 return ret;
2376 } // anon namespace
2378 gimple_opt_pass *
2379 make_pass_ubsan (gcc::context *ctxt)
2381 return new pass_ubsan (ctxt);
2384 #include "gt-ubsan.h"