PR target/80969 - Fix ICE with -mabi=ms -mavx512f, reduce wasted space when realignin...
[official-gcc.git] / gcc / ubsan.c
blob49e38fa6c09a69432c134b08a2cdf591ae68d58c
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 const unsigned int bitsize = GET_MODE_BITSIZE (TYPE_MODE (type));
128 if (bitsize <= POINTER_SIZE)
129 switch (TREE_CODE (type))
131 case BOOLEAN_TYPE:
132 case ENUMERAL_TYPE:
133 case INTEGER_TYPE:
134 return fold_build1 (NOP_EXPR, pointer_sized_int_node, t);
135 case REAL_TYPE:
137 tree itype = build_nonstandard_integer_type (bitsize, true);
138 t = fold_build1 (VIEW_CONVERT_EXPR, itype, t);
139 return fold_convert (pointer_sized_int_node, t);
141 default:
142 gcc_unreachable ();
144 else
146 if (!DECL_P (t) || !TREE_ADDRESSABLE (t))
148 /* The reason for this is that we don't want to pessimize
149 code by making vars unnecessarily addressable. */
150 tree var;
151 if (phase != UBSAN_ENCODE_VALUE_GENERIC)
153 var = create_tmp_var (type);
154 mark_addressable (var);
156 else
158 var = create_tmp_var_raw (type);
159 TREE_ADDRESSABLE (var) = 1;
160 DECL_CONTEXT (var) = current_function_decl;
162 if (phase == UBSAN_ENCODE_VALUE_RTL)
164 rtx mem
165 = assign_stack_temp_for_type (TYPE_MODE (type),
166 GET_MODE_SIZE (TYPE_MODE (type)),
167 type);
168 SET_DECL_RTL (var, mem);
169 expand_assignment (var, t, false);
170 return build_fold_addr_expr (var);
172 if (phase != UBSAN_ENCODE_VALUE_GENERIC)
174 tree tem = build2 (MODIFY_EXPR, void_type_node, var, t);
175 t = build_fold_addr_expr (var);
176 return build2 (COMPOUND_EXPR, TREE_TYPE (t), tem, t);
178 else
180 var = build4 (TARGET_EXPR, type, var, t, NULL_TREE, NULL_TREE);
181 return build_fold_addr_expr (var);
184 else
185 return build_fold_addr_expr (t);
189 /* Cached ubsan_get_type_descriptor_type () return value. */
190 static GTY(()) tree ubsan_type_descriptor_type;
192 /* Build
193 struct __ubsan_type_descriptor
195 unsigned short __typekind;
196 unsigned short __typeinfo;
197 char __typename[];
199 type. */
201 static tree
202 ubsan_get_type_descriptor_type (void)
204 static const char *field_names[3]
205 = { "__typekind", "__typeinfo", "__typename" };
206 tree fields[3], ret;
208 if (ubsan_type_descriptor_type)
209 return ubsan_type_descriptor_type;
211 tree itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
212 tree flex_arr_type = build_array_type (char_type_node, itype);
214 ret = make_node (RECORD_TYPE);
215 for (int i = 0; i < 3; i++)
217 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
218 get_identifier (field_names[i]),
219 (i == 2) ? flex_arr_type
220 : short_unsigned_type_node);
221 DECL_CONTEXT (fields[i]) = ret;
222 if (i)
223 DECL_CHAIN (fields[i - 1]) = fields[i];
225 tree type_decl = build_decl (input_location, TYPE_DECL,
226 get_identifier ("__ubsan_type_descriptor"),
227 ret);
228 DECL_IGNORED_P (type_decl) = 1;
229 DECL_ARTIFICIAL (type_decl) = 1;
230 TYPE_FIELDS (ret) = fields[0];
231 TYPE_NAME (ret) = type_decl;
232 TYPE_STUB_DECL (ret) = type_decl;
233 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 layout_type (ret);
282 ubsan_source_location_type = ret;
283 return ret;
286 /* Helper routine that returns a CONSTRUCTOR of __ubsan_source_location
287 type with its fields filled from a location_t LOC. */
289 static tree
290 ubsan_source_location (location_t loc)
292 expanded_location xloc;
293 tree type = ubsan_get_source_location_type ();
295 xloc = expand_location (loc);
296 tree str;
297 if (xloc.file == NULL)
299 str = build_int_cst (ptr_type_node, 0);
300 xloc.line = 0;
301 xloc.column = 0;
303 else
305 /* Fill in the values from LOC. */
306 size_t len = strlen (xloc.file) + 1;
307 str = build_string (len, xloc.file);
308 TREE_TYPE (str) = build_array_type_nelts (char_type_node, len);
309 TREE_READONLY (str) = 1;
310 TREE_STATIC (str) = 1;
311 str = build_fold_addr_expr (str);
313 tree ctor = build_constructor_va (type, 3, NULL_TREE, str, NULL_TREE,
314 build_int_cst (unsigned_type_node,
315 xloc.line), NULL_TREE,
316 build_int_cst (unsigned_type_node,
317 xloc.column));
318 TREE_CONSTANT (ctor) = 1;
319 TREE_STATIC (ctor) = 1;
321 return ctor;
324 /* This routine returns a magic number for TYPE. */
326 static unsigned short
327 get_ubsan_type_info_for_type (tree type)
329 if (TREE_CODE (type) == REAL_TYPE)
330 return tree_to_uhwi (TYPE_SIZE (type));
331 else if (INTEGRAL_TYPE_P (type))
333 int prec = exact_log2 (tree_to_uhwi (TYPE_SIZE (type)));
334 gcc_assert (prec != -1);
335 return (prec << 1) | !TYPE_UNSIGNED (type);
337 else
338 return 0;
341 /* Counters for internal labels. ubsan_ids[0] for Lubsan_type,
342 ubsan_ids[1] for Lubsan_data labels. */
343 static GTY(()) unsigned int ubsan_ids[2];
345 /* Helper routine that returns ADDR_EXPR of a VAR_DECL of a type
346 descriptor. It first looks into the hash table; if not found,
347 create the VAR_DECL, put it into the hash table and return the
348 ADDR_EXPR of it. TYPE describes a particular type. PSTYLE is
349 an enum controlling how we want to print the type. */
351 tree
352 ubsan_type_descriptor (tree type, enum ubsan_print_style pstyle)
354 /* See through any typedefs. */
355 type = TYPE_MAIN_VARIANT (type);
357 tree decl = decl_for_type_lookup (type);
358 /* It is possible that some of the earlier created DECLs were found
359 unused, in that case they weren't emitted and varpool_node::get
360 returns NULL node on them. But now we really need them. Thus,
361 renew them here. */
362 if (decl != NULL_TREE && varpool_node::get (decl))
363 return build_fold_addr_expr (decl);
365 tree dtype = ubsan_get_type_descriptor_type ();
366 tree type2 = type;
367 const char *tname = NULL;
368 pretty_printer pretty_name;
369 unsigned char deref_depth = 0;
370 unsigned short tkind, tinfo;
372 /* Get the name of the type, or the name of the pointer type. */
373 if (pstyle == UBSAN_PRINT_POINTER)
375 gcc_assert (POINTER_TYPE_P (type));
376 type2 = TREE_TYPE (type);
378 /* Remove any '*' operators from TYPE. */
379 while (POINTER_TYPE_P (type2))
380 deref_depth++, type2 = TREE_TYPE (type2);
382 if (TREE_CODE (type2) == METHOD_TYPE)
383 type2 = TYPE_METHOD_BASETYPE (type2);
386 /* If an array, get its type. */
387 type2 = strip_array_types (type2);
389 if (pstyle == UBSAN_PRINT_ARRAY)
391 while (POINTER_TYPE_P (type2))
392 deref_depth++, type2 = TREE_TYPE (type2);
395 if (TYPE_NAME (type2) != NULL)
397 if (TREE_CODE (TYPE_NAME (type2)) == IDENTIFIER_NODE)
398 tname = IDENTIFIER_POINTER (TYPE_NAME (type2));
399 else if (DECL_NAME (TYPE_NAME (type2)) != NULL)
400 tname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type2)));
403 if (tname == NULL)
404 /* We weren't able to determine the type name. */
405 tname = "<unknown>";
407 tree eltype = type;
408 if (pstyle == UBSAN_PRINT_POINTER)
410 pp_printf (&pretty_name, "'%s%s%s%s%s%s%s",
411 TYPE_VOLATILE (type2) ? "volatile " : "",
412 TYPE_READONLY (type2) ? "const " : "",
413 TYPE_RESTRICT (type2) ? "restrict " : "",
414 TYPE_ATOMIC (type2) ? "_Atomic " : "",
415 TREE_CODE (type2) == RECORD_TYPE
416 ? "struct "
417 : TREE_CODE (type2) == UNION_TYPE
418 ? "union " : "", tname,
419 deref_depth == 0 ? "" : " ");
420 while (deref_depth-- > 0)
421 pp_star (&pretty_name);
422 pp_quote (&pretty_name);
424 else if (pstyle == UBSAN_PRINT_ARRAY)
426 /* Pretty print the array dimensions. */
427 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
428 tree t = type;
429 pp_printf (&pretty_name, "'%s ", tname);
430 while (deref_depth-- > 0)
431 pp_star (&pretty_name);
432 while (TREE_CODE (t) == ARRAY_TYPE)
434 pp_left_bracket (&pretty_name);
435 tree dom = TYPE_DOMAIN (t);
436 if (dom != NULL_TREE
437 && TYPE_MAX_VALUE (dom) != NULL_TREE
438 && TREE_CODE (TYPE_MAX_VALUE (dom)) == INTEGER_CST)
440 if (tree_fits_uhwi_p (TYPE_MAX_VALUE (dom))
441 && tree_to_uhwi (TYPE_MAX_VALUE (dom)) + 1 != 0)
442 pp_printf (&pretty_name, HOST_WIDE_INT_PRINT_DEC,
443 tree_to_uhwi (TYPE_MAX_VALUE (dom)) + 1);
444 else
445 pp_wide_int (&pretty_name,
446 wi::add (wi::to_widest (TYPE_MAX_VALUE (dom)), 1),
447 TYPE_SIGN (TREE_TYPE (dom)));
449 else
450 /* ??? We can't determine the variable name; print VLA unspec. */
451 pp_star (&pretty_name);
452 pp_right_bracket (&pretty_name);
453 t = TREE_TYPE (t);
455 pp_quote (&pretty_name);
457 /* Save the tree with stripped types. */
458 eltype = t;
460 else
461 pp_printf (&pretty_name, "'%s'", tname);
463 switch (TREE_CODE (eltype))
465 case BOOLEAN_TYPE:
466 case ENUMERAL_TYPE:
467 case INTEGER_TYPE:
468 tkind = 0x0000;
469 break;
470 case REAL_TYPE:
471 /* FIXME: libubsan right now only supports float, double and
472 long double type formats. */
473 if (TYPE_MODE (eltype) == TYPE_MODE (float_type_node)
474 || TYPE_MODE (eltype) == TYPE_MODE (double_type_node)
475 || TYPE_MODE (eltype) == TYPE_MODE (long_double_type_node))
476 tkind = 0x0001;
477 else
478 tkind = 0xffff;
479 break;
480 default:
481 tkind = 0xffff;
482 break;
484 tinfo = get_ubsan_type_info_for_type (eltype);
486 /* Create a new VAR_DECL of type descriptor. */
487 const char *tmp = pp_formatted_text (&pretty_name);
488 size_t len = strlen (tmp) + 1;
489 tree str = build_string (len, tmp);
490 TREE_TYPE (str) = build_array_type_nelts (char_type_node, len);
491 TREE_READONLY (str) = 1;
492 TREE_STATIC (str) = 1;
494 char tmp_name[32];
495 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_type", ubsan_ids[0]++);
496 decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name),
497 dtype);
498 TREE_STATIC (decl) = 1;
499 TREE_PUBLIC (decl) = 0;
500 DECL_ARTIFICIAL (decl) = 1;
501 DECL_IGNORED_P (decl) = 1;
502 DECL_EXTERNAL (decl) = 0;
503 DECL_SIZE (decl)
504 = size_binop (PLUS_EXPR, DECL_SIZE (decl), TYPE_SIZE (TREE_TYPE (str)));
505 DECL_SIZE_UNIT (decl)
506 = size_binop (PLUS_EXPR, DECL_SIZE_UNIT (decl),
507 TYPE_SIZE_UNIT (TREE_TYPE (str)));
509 tree ctor = build_constructor_va (dtype, 3, NULL_TREE,
510 build_int_cst (short_unsigned_type_node,
511 tkind), NULL_TREE,
512 build_int_cst (short_unsigned_type_node,
513 tinfo), NULL_TREE, str);
514 TREE_CONSTANT (ctor) = 1;
515 TREE_STATIC (ctor) = 1;
516 DECL_INITIAL (decl) = ctor;
517 varpool_node::finalize_decl (decl);
519 /* Save the VAR_DECL into the hash table. */
520 decl_for_type_insert (type, decl);
522 return build_fold_addr_expr (decl);
525 /* Create a structure for the ubsan library. NAME is a name of the new
526 structure. LOCCNT is number of locations, PLOC points to array of
527 locations. The arguments in ... are of __ubsan_type_descriptor type
528 and there are at most two of them, followed by NULL_TREE, followed
529 by optional extra arguments and another NULL_TREE. */
531 tree
532 ubsan_create_data (const char *name, int loccnt, const location_t *ploc, ...)
534 va_list args;
535 tree ret, t;
536 tree fields[6];
537 vec<tree, va_gc> *saved_args = NULL;
538 size_t i = 0;
539 int j;
541 /* It is possible that PCH zapped table with definitions of sanitizer
542 builtins. Reinitialize them if needed. */
543 initialize_sanitizer_builtins ();
545 /* Firstly, create a pointer to type descriptor type. */
546 tree td_type = ubsan_get_type_descriptor_type ();
547 td_type = build_pointer_type (td_type);
549 /* Create the structure type. */
550 ret = make_node (RECORD_TYPE);
551 for (j = 0; j < loccnt; j++)
553 gcc_checking_assert (i < 2);
554 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
555 ubsan_get_source_location_type ());
556 DECL_CONTEXT (fields[i]) = ret;
557 if (i)
558 DECL_CHAIN (fields[i - 1]) = fields[i];
559 i++;
562 va_start (args, ploc);
563 for (t = va_arg (args, tree); t != NULL_TREE;
564 i++, t = va_arg (args, tree))
566 gcc_checking_assert (i < 4);
567 /* Save the tree arguments for later use. */
568 vec_safe_push (saved_args, t);
569 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
570 td_type);
571 DECL_CONTEXT (fields[i]) = ret;
572 if (i)
573 DECL_CHAIN (fields[i - 1]) = fields[i];
576 for (t = va_arg (args, tree); t != NULL_TREE;
577 i++, t = va_arg (args, tree))
579 gcc_checking_assert (i < 6);
580 /* Save the tree arguments for later use. */
581 vec_safe_push (saved_args, t);
582 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
583 TREE_TYPE (t));
584 DECL_CONTEXT (fields[i]) = ret;
585 if (i)
586 DECL_CHAIN (fields[i - 1]) = fields[i];
588 va_end (args);
590 tree type_decl = build_decl (input_location, TYPE_DECL,
591 get_identifier (name), ret);
592 DECL_IGNORED_P (type_decl) = 1;
593 DECL_ARTIFICIAL (type_decl) = 1;
594 TYPE_FIELDS (ret) = fields[0];
595 TYPE_NAME (ret) = type_decl;
596 TYPE_STUB_DECL (ret) = type_decl;
597 layout_type (ret);
599 /* Now, fill in the type. */
600 char tmp_name[32];
601 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_data", ubsan_ids[1]++);
602 tree var = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name),
603 ret);
604 TREE_STATIC (var) = 1;
605 TREE_PUBLIC (var) = 0;
606 DECL_ARTIFICIAL (var) = 1;
607 DECL_IGNORED_P (var) = 1;
608 DECL_EXTERNAL (var) = 0;
610 vec<constructor_elt, va_gc> *v;
611 vec_alloc (v, i);
612 tree ctor = build_constructor (ret, v);
614 /* If desirable, set the __ubsan_source_location element. */
615 for (j = 0; j < loccnt; j++)
617 location_t loc = LOCATION_LOCUS (ploc[j]);
618 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, ubsan_source_location (loc));
621 size_t nelts = vec_safe_length (saved_args);
622 for (i = 0; i < nelts; i++)
624 t = (*saved_args)[i];
625 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, t);
628 TREE_CONSTANT (ctor) = 1;
629 TREE_STATIC (ctor) = 1;
630 DECL_INITIAL (var) = ctor;
631 varpool_node::finalize_decl (var);
633 return var;
636 /* Instrument the __builtin_unreachable call. We just call the libubsan
637 routine instead. */
639 bool
640 ubsan_instrument_unreachable (gimple_stmt_iterator *gsi)
642 gimple *g;
643 location_t loc = gimple_location (gsi_stmt (*gsi));
645 if (flag_sanitize_undefined_trap_on_error)
646 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
647 else
649 tree data = ubsan_create_data ("__ubsan_unreachable_data", 1, &loc,
650 NULL_TREE, NULL_TREE);
651 data = build_fold_addr_expr_loc (loc, data);
652 tree fn
653 = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE);
654 g = gimple_build_call (fn, 1, data);
656 gimple_set_location (g, loc);
657 gsi_replace (gsi, g, false);
658 return false;
661 /* Return true if T is a call to a libubsan routine. */
663 bool
664 is_ubsan_builtin_p (tree t)
666 return TREE_CODE (t) == FUNCTION_DECL
667 && DECL_BUILT_IN_CLASS (t) == BUILT_IN_NORMAL
668 && strncmp (IDENTIFIER_POINTER (DECL_NAME (t)),
669 "__builtin___ubsan_", 18) == 0;
672 /* Create a callgraph edge for statement STMT. */
674 static void
675 ubsan_create_edge (gimple *stmt)
677 gcall *call_stmt = dyn_cast <gcall *> (stmt);
678 basic_block bb = gimple_bb (stmt);
679 int freq = compute_call_stmt_bb_frequency (current_function_decl, bb);
680 cgraph_node *node = cgraph_node::get (current_function_decl);
681 tree decl = gimple_call_fndecl (call_stmt);
682 if (decl)
683 node->create_edge (cgraph_node::get_create (decl), call_stmt, bb->count,
684 freq);
687 /* Expand the UBSAN_BOUNDS special builtin function. */
689 bool
690 ubsan_expand_bounds_ifn (gimple_stmt_iterator *gsi)
692 gimple *stmt = gsi_stmt (*gsi);
693 location_t loc = gimple_location (stmt);
694 gcc_assert (gimple_call_num_args (stmt) == 3);
696 /* Pick up the arguments of the UBSAN_BOUNDS call. */
697 tree type = TREE_TYPE (TREE_TYPE (gimple_call_arg (stmt, 0)));
698 tree index = gimple_call_arg (stmt, 1);
699 tree orig_index = index;
700 tree bound = gimple_call_arg (stmt, 2);
702 gimple_stmt_iterator gsi_orig = *gsi;
704 /* Create condition "if (index > bound)". */
705 basic_block then_bb, fallthru_bb;
706 gimple_stmt_iterator cond_insert_point
707 = create_cond_insert_point (gsi, false, false, true,
708 &then_bb, &fallthru_bb);
709 index = fold_convert (TREE_TYPE (bound), index);
710 index = force_gimple_operand_gsi (&cond_insert_point, index,
711 true, NULL_TREE,
712 false, GSI_NEW_STMT);
713 gimple *g = gimple_build_cond (GT_EXPR, index, bound, NULL_TREE, NULL_TREE);
714 gimple_set_location (g, loc);
715 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
717 /* Generate __ubsan_handle_out_of_bounds call. */
718 *gsi = gsi_after_labels (then_bb);
719 if (flag_sanitize_undefined_trap_on_error)
720 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
721 else
723 tree data
724 = ubsan_create_data ("__ubsan_out_of_bounds_data", 1, &loc,
725 ubsan_type_descriptor (type, UBSAN_PRINT_ARRAY),
726 ubsan_type_descriptor (TREE_TYPE (orig_index)),
727 NULL_TREE, NULL_TREE);
728 data = build_fold_addr_expr_loc (loc, data);
729 enum built_in_function bcode
730 = (flag_sanitize_recover & SANITIZE_BOUNDS)
731 ? BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS
732 : BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS_ABORT;
733 tree fn = builtin_decl_explicit (bcode);
734 tree val = ubsan_encode_value (orig_index, UBSAN_ENCODE_VALUE_GIMPLE);
735 val = force_gimple_operand_gsi (gsi, val, true, NULL_TREE, true,
736 GSI_SAME_STMT);
737 g = gimple_build_call (fn, 2, data, val);
739 gimple_set_location (g, loc);
740 gsi_insert_before (gsi, g, GSI_SAME_STMT);
742 /* Get rid of the UBSAN_BOUNDS call from the IR. */
743 unlink_stmt_vdef (stmt);
744 gsi_remove (&gsi_orig, true);
746 /* Point GSI to next logical statement. */
747 *gsi = gsi_start_bb (fallthru_bb);
748 return true;
751 /* Expand UBSAN_NULL internal call. The type is kept on the ckind
752 argument which is a constant, because the middle-end treats pointer
753 conversions as useless and therefore the type of the first argument
754 could be changed to any other pointer type. */
756 bool
757 ubsan_expand_null_ifn (gimple_stmt_iterator *gsip)
759 gimple_stmt_iterator gsi = *gsip;
760 gimple *stmt = gsi_stmt (gsi);
761 location_t loc = gimple_location (stmt);
762 gcc_assert (gimple_call_num_args (stmt) == 3);
763 tree ptr = gimple_call_arg (stmt, 0);
764 tree ckind = gimple_call_arg (stmt, 1);
765 tree align = gimple_call_arg (stmt, 2);
766 tree check_align = NULL_TREE;
767 bool check_null;
769 basic_block cur_bb = gsi_bb (gsi);
771 gimple *g;
772 if (!integer_zerop (align))
774 unsigned int ptralign = get_pointer_alignment (ptr) / BITS_PER_UNIT;
775 if (compare_tree_int (align, ptralign) == 1)
777 check_align = make_ssa_name (pointer_sized_int_node);
778 g = gimple_build_assign (check_align, NOP_EXPR, ptr);
779 gimple_set_location (g, loc);
780 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
783 check_null = sanitize_flags_p (SANITIZE_NULL);
785 if (check_align == NULL_TREE && !check_null)
787 gsi_remove (gsip, true);
788 /* Unlink the UBSAN_NULLs vops before replacing it. */
789 unlink_stmt_vdef (stmt);
790 return true;
793 /* Split the original block holding the pointer dereference. */
794 edge e = split_block (cur_bb, stmt);
796 /* Get a hold on the 'condition block', the 'then block' and the
797 'else block'. */
798 basic_block cond_bb = e->src;
799 basic_block fallthru_bb = e->dest;
800 basic_block then_bb = create_empty_bb (cond_bb);
801 add_bb_to_loop (then_bb, cond_bb->loop_father);
802 loops_state_set (LOOPS_NEED_FIXUP);
804 /* Make an edge coming from the 'cond block' into the 'then block';
805 this edge is unlikely taken, so set up the probability accordingly. */
806 e = make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
807 e->probability = profile_probability::very_unlikely ();
809 /* Connect 'then block' with the 'else block'. This is needed
810 as the ubsan routines we call in the 'then block' are not noreturn.
811 The 'then block' only has one outcoming edge. */
812 make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);
814 /* Set up the fallthrough basic block. */
815 e = find_edge (cond_bb, fallthru_bb);
816 e->flags = EDGE_FALSE_VALUE;
817 e->count = cond_bb->count;
818 e->probability = profile_probability::very_likely ();
820 /* Update dominance info for the newly created then_bb; note that
821 fallthru_bb's dominance info has already been updated by
822 split_block. */
823 if (dom_info_available_p (CDI_DOMINATORS))
824 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
826 /* Put the ubsan builtin call into the newly created BB. */
827 if (flag_sanitize_undefined_trap_on_error)
828 g = gimple_build_call (builtin_decl_implicit (BUILT_IN_TRAP), 0);
829 else
831 enum built_in_function bcode
832 = (flag_sanitize_recover & ((check_align ? SANITIZE_ALIGNMENT : 0)
833 | (check_null ? SANITIZE_NULL : 0)))
834 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
835 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT;
836 tree fn = builtin_decl_implicit (bcode);
837 tree data
838 = ubsan_create_data ("__ubsan_null_data", 1, &loc,
839 ubsan_type_descriptor (TREE_TYPE (ckind),
840 UBSAN_PRINT_POINTER),
841 NULL_TREE,
842 align,
843 fold_convert (unsigned_char_type_node, ckind),
844 NULL_TREE);
845 data = build_fold_addr_expr_loc (loc, data);
846 g = gimple_build_call (fn, 2, data,
847 check_align ? check_align
848 : build_zero_cst (pointer_sized_int_node));
850 gimple_stmt_iterator gsi2 = gsi_start_bb (then_bb);
851 gimple_set_location (g, loc);
852 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
854 /* Unlink the UBSAN_NULLs vops before replacing it. */
855 unlink_stmt_vdef (stmt);
857 if (check_null)
859 g = gimple_build_cond (EQ_EXPR, ptr, build_int_cst (TREE_TYPE (ptr), 0),
860 NULL_TREE, NULL_TREE);
861 gimple_set_location (g, loc);
863 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
864 gsi_replace (&gsi, g, false);
865 stmt = g;
868 if (check_align)
870 if (check_null)
872 /* Split the block with the condition again. */
873 e = split_block (cond_bb, stmt);
874 basic_block cond1_bb = e->src;
875 basic_block cond2_bb = e->dest;
877 /* Make an edge coming from the 'cond1 block' into the 'then block';
878 this edge is unlikely taken, so set up the probability
879 accordingly. */
880 e = make_edge (cond1_bb, then_bb, EDGE_TRUE_VALUE);
881 e->probability = profile_probability::very_unlikely ();
883 /* Set up the fallthrough basic block. */
884 e = find_edge (cond1_bb, cond2_bb);
885 e->flags = EDGE_FALSE_VALUE;
886 e->count = cond1_bb->count;
887 e->probability = profile_probability::very_likely ();
889 /* Update dominance info. */
890 if (dom_info_available_p (CDI_DOMINATORS))
892 set_immediate_dominator (CDI_DOMINATORS, fallthru_bb, cond1_bb);
893 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond1_bb);
896 gsi2 = gsi_start_bb (cond2_bb);
899 tree mask = build_int_cst (pointer_sized_int_node,
900 tree_to_uhwi (align) - 1);
901 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
902 BIT_AND_EXPR, check_align, mask);
903 gimple_set_location (g, loc);
904 if (check_null)
905 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
906 else
907 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
909 g = gimple_build_cond (NE_EXPR, gimple_assign_lhs (g),
910 build_int_cst (pointer_sized_int_node, 0),
911 NULL_TREE, NULL_TREE);
912 gimple_set_location (g, loc);
913 if (check_null)
914 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
915 else
916 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
917 gsi_replace (&gsi, g, false);
919 return false;
922 #define OBJSZ_MAX_OFFSET (1024 * 16)
924 /* Expand UBSAN_OBJECT_SIZE internal call. */
926 bool
927 ubsan_expand_objsize_ifn (gimple_stmt_iterator *gsi)
929 gimple *stmt = gsi_stmt (*gsi);
930 location_t loc = gimple_location (stmt);
931 gcc_assert (gimple_call_num_args (stmt) == 4);
933 tree ptr = gimple_call_arg (stmt, 0);
934 tree offset = gimple_call_arg (stmt, 1);
935 tree size = gimple_call_arg (stmt, 2);
936 tree ckind = gimple_call_arg (stmt, 3);
937 gimple_stmt_iterator gsi_orig = *gsi;
938 gimple *g;
940 /* See if we can discard the check. */
941 if (TREE_CODE (size) != INTEGER_CST
942 || integer_all_onesp (size))
943 /* Yes, __builtin_object_size couldn't determine the
944 object size. */;
945 else if (TREE_CODE (offset) == INTEGER_CST
946 && wi::to_widest (offset) >= -OBJSZ_MAX_OFFSET
947 && wi::to_widest (offset) <= -1)
948 /* The offset is in range [-16K, -1]. */;
949 else
951 /* if (offset > objsize) */
952 basic_block then_bb, fallthru_bb;
953 gimple_stmt_iterator cond_insert_point
954 = create_cond_insert_point (gsi, false, false, true,
955 &then_bb, &fallthru_bb);
956 g = gimple_build_cond (GT_EXPR, offset, size, NULL_TREE, NULL_TREE);
957 gimple_set_location (g, loc);
958 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
960 /* If the offset is small enough, we don't need the second
961 run-time check. */
962 if (TREE_CODE (offset) == INTEGER_CST
963 && wi::to_widest (offset) >= 0
964 && wi::to_widest (offset) <= OBJSZ_MAX_OFFSET)
965 *gsi = gsi_after_labels (then_bb);
966 else
968 /* Don't issue run-time error if (ptr > ptr + offset). That
969 may happen when computing a POINTER_PLUS_EXPR. */
970 basic_block then2_bb, fallthru2_bb;
972 gimple_stmt_iterator gsi2 = gsi_after_labels (then_bb);
973 cond_insert_point = create_cond_insert_point (&gsi2, false, false,
974 true, &then2_bb,
975 &fallthru2_bb);
976 /* Convert the pointer to an integer type. */
977 tree p = make_ssa_name (pointer_sized_int_node);
978 g = gimple_build_assign (p, NOP_EXPR, ptr);
979 gimple_set_location (g, loc);
980 gsi_insert_before (&cond_insert_point, g, GSI_NEW_STMT);
981 p = gimple_assign_lhs (g);
982 /* Compute ptr + offset. */
983 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
984 PLUS_EXPR, p, offset);
985 gimple_set_location (g, loc);
986 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
987 /* Now build the conditional and put it into the IR. */
988 g = gimple_build_cond (LE_EXPR, p, gimple_assign_lhs (g),
989 NULL_TREE, NULL_TREE);
990 gimple_set_location (g, loc);
991 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
992 *gsi = gsi_after_labels (then2_bb);
995 /* Generate __ubsan_handle_type_mismatch call. */
996 if (flag_sanitize_undefined_trap_on_error)
997 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
998 else
1000 tree data
1001 = ubsan_create_data ("__ubsan_objsz_data", 1, &loc,
1002 ubsan_type_descriptor (TREE_TYPE (ptr),
1003 UBSAN_PRINT_POINTER),
1004 NULL_TREE,
1005 build_zero_cst (pointer_sized_int_node),
1006 ckind,
1007 NULL_TREE);
1008 data = build_fold_addr_expr_loc (loc, data);
1009 enum built_in_function bcode
1010 = (flag_sanitize_recover & SANITIZE_OBJECT_SIZE)
1011 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
1012 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT;
1013 tree p = make_ssa_name (pointer_sized_int_node);
1014 g = gimple_build_assign (p, NOP_EXPR, ptr);
1015 gimple_set_location (g, loc);
1016 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1017 g = gimple_build_call (builtin_decl_explicit (bcode), 2, data, p);
1019 gimple_set_location (g, loc);
1020 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1022 /* Point GSI to next logical statement. */
1023 *gsi = gsi_start_bb (fallthru_bb);
1025 /* Get rid of the UBSAN_OBJECT_SIZE call from the IR. */
1026 unlink_stmt_vdef (stmt);
1027 gsi_remove (&gsi_orig, true);
1028 return true;
1031 /* Get rid of the UBSAN_OBJECT_SIZE call from the IR. */
1032 unlink_stmt_vdef (stmt);
1033 gsi_remove (gsi, true);
1034 return true;
1037 /* Expand UBSAN_PTR internal call. */
1039 bool
1040 ubsan_expand_ptr_ifn (gimple_stmt_iterator *gsip)
1042 gimple_stmt_iterator gsi = *gsip;
1043 gimple *stmt = gsi_stmt (gsi);
1044 location_t loc = gimple_location (stmt);
1045 gcc_assert (gimple_call_num_args (stmt) == 2);
1046 tree ptr = gimple_call_arg (stmt, 0);
1047 tree off = gimple_call_arg (stmt, 1);
1049 if (integer_zerop (off))
1051 gsi_remove (gsip, true);
1052 unlink_stmt_vdef (stmt);
1053 return true;
1056 basic_block cur_bb = gsi_bb (gsi);
1057 tree ptrplusoff = make_ssa_name (pointer_sized_int_node);
1058 tree ptri = make_ssa_name (pointer_sized_int_node);
1059 int pos_neg = get_range_pos_neg (off);
1061 /* Split the original block holding the pointer dereference. */
1062 edge e = split_block (cur_bb, stmt);
1064 /* Get a hold on the 'condition block', the 'then block' and the
1065 'else block'. */
1066 basic_block cond_bb = e->src;
1067 basic_block fallthru_bb = e->dest;
1068 basic_block then_bb = create_empty_bb (cond_bb);
1069 basic_block cond_pos_bb = NULL, cond_neg_bb = NULL;
1070 add_bb_to_loop (then_bb, cond_bb->loop_father);
1071 loops_state_set (LOOPS_NEED_FIXUP);
1073 /* Set up the fallthrough basic block. */
1074 e->flags = EDGE_FALSE_VALUE;
1075 if (pos_neg != 3)
1077 e->count = cond_bb->count;
1078 e->probability = profile_probability::very_likely ();
1080 /* Connect 'then block' with the 'else block'. This is needed
1081 as the ubsan routines we call in the 'then block' are not noreturn.
1082 The 'then block' only has one outcoming edge. */
1083 make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);
1085 /* Make an edge coming from the 'cond block' into the 'then block';
1086 this edge is unlikely taken, so set up the probability
1087 accordingly. */
1088 e = make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
1089 e->probability = profile_probability::very_unlikely ();
1091 else
1093 profile_count count = cond_bb->count.apply_probability (PROB_EVEN);
1094 e->count = count;
1095 e->probability = profile_probability::even ();
1097 e = split_block (fallthru_bb, (gimple *) NULL);
1098 cond_neg_bb = e->src;
1099 fallthru_bb = e->dest;
1100 e->count = count;
1101 e->probability = profile_probability::very_likely ();
1102 e->flags = EDGE_FALSE_VALUE;
1104 e = make_edge (cond_neg_bb, then_bb, EDGE_TRUE_VALUE);
1105 e->probability = profile_probability::very_unlikely ();
1107 cond_pos_bb = create_empty_bb (cond_bb);
1108 add_bb_to_loop (cond_pos_bb, cond_bb->loop_father);
1110 e = make_edge (cond_bb, cond_pos_bb, EDGE_TRUE_VALUE);
1111 e->count = count;
1112 e->probability = profile_probability::even ();
1114 e = make_edge (cond_pos_bb, then_bb, EDGE_TRUE_VALUE);
1115 e->probability = profile_probability::very_unlikely ();
1117 e = make_edge (cond_pos_bb, fallthru_bb, EDGE_FALSE_VALUE);
1118 e->count = count;
1119 e->probability = profile_probability::very_likely ();
1121 make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);
1124 gimple *g = gimple_build_assign (ptri, NOP_EXPR, ptr);
1125 gimple_set_location (g, loc);
1126 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
1127 g = gimple_build_assign (ptrplusoff, PLUS_EXPR, ptri, off);
1128 gimple_set_location (g, loc);
1129 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
1131 /* Update dominance info for the newly created then_bb; note that
1132 fallthru_bb's dominance info has already been updated by
1133 split_block. */
1134 if (dom_info_available_p (CDI_DOMINATORS))
1136 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
1137 if (pos_neg == 3)
1139 set_immediate_dominator (CDI_DOMINATORS, cond_pos_bb, cond_bb);
1140 set_immediate_dominator (CDI_DOMINATORS, fallthru_bb, cond_bb);
1144 /* Put the ubsan builtin call into the newly created BB. */
1145 if (flag_sanitize_undefined_trap_on_error)
1146 g = gimple_build_call (builtin_decl_implicit (BUILT_IN_TRAP), 0);
1147 else
1149 enum built_in_function bcode
1150 = (flag_sanitize_recover & SANITIZE_POINTER_OVERFLOW)
1151 ? BUILT_IN_UBSAN_HANDLE_POINTER_OVERFLOW
1152 : BUILT_IN_UBSAN_HANDLE_POINTER_OVERFLOW_ABORT;
1153 tree fn = builtin_decl_implicit (bcode);
1154 tree data
1155 = ubsan_create_data ("__ubsan_ptrovf_data", 1, &loc,
1156 NULL_TREE, NULL_TREE);
1157 data = build_fold_addr_expr_loc (loc, data);
1158 g = gimple_build_call (fn, 3, data, ptr, ptrplusoff);
1160 gimple_stmt_iterator gsi2 = gsi_start_bb (then_bb);
1161 gimple_set_location (g, loc);
1162 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
1164 /* Unlink the UBSAN_PTRs vops before replacing it. */
1165 unlink_stmt_vdef (stmt);
1167 if (TREE_CODE (off) == INTEGER_CST)
1168 g = gimple_build_cond (wi::neg_p (off) ? LT_EXPR : GE_EXPR, ptri,
1169 fold_build1 (NEGATE_EXPR, sizetype, off),
1170 NULL_TREE, NULL_TREE);
1171 else if (pos_neg != 3)
1172 g = gimple_build_cond (pos_neg == 1 ? LT_EXPR : GT_EXPR,
1173 ptrplusoff, ptri, NULL_TREE, NULL_TREE);
1174 else
1176 gsi2 = gsi_start_bb (cond_pos_bb);
1177 g = gimple_build_cond (LT_EXPR, ptrplusoff, ptri, NULL_TREE, NULL_TREE);
1178 gimple_set_location (g, loc);
1179 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
1181 gsi2 = gsi_start_bb (cond_neg_bb);
1182 g = gimple_build_cond (GT_EXPR, ptrplusoff, ptri, NULL_TREE, NULL_TREE);
1183 gimple_set_location (g, loc);
1184 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
1186 gimple_seq seq = NULL;
1187 tree t = gimple_build (&seq, loc, NOP_EXPR, ssizetype, off);
1188 t = gimple_build (&seq, loc, GE_EXPR, boolean_type_node,
1189 t, ssize_int (0));
1190 gsi_insert_seq_before (&gsi, seq, GSI_SAME_STMT);
1191 g = gimple_build_cond (NE_EXPR, t, boolean_false_node,
1192 NULL_TREE, NULL_TREE);
1194 gimple_set_location (g, loc);
1195 /* Replace the UBSAN_PTR with a GIMPLE_COND stmt. */
1196 gsi_replace (&gsi, g, false);
1197 return false;
1201 /* Cached __ubsan_vptr_type_cache decl. */
1202 static GTY(()) tree ubsan_vptr_type_cache_decl;
1204 /* Expand UBSAN_VPTR internal call. The type is kept on the ckind
1205 argument which is a constant, because the middle-end treats pointer
1206 conversions as useless and therefore the type of the first argument
1207 could be changed to any other pointer type. */
1209 bool
1210 ubsan_expand_vptr_ifn (gimple_stmt_iterator *gsip)
1212 gimple_stmt_iterator gsi = *gsip;
1213 gimple *stmt = gsi_stmt (gsi);
1214 location_t loc = gimple_location (stmt);
1215 gcc_assert (gimple_call_num_args (stmt) == 5);
1216 tree op = gimple_call_arg (stmt, 0);
1217 tree vptr = gimple_call_arg (stmt, 1);
1218 tree str_hash = gimple_call_arg (stmt, 2);
1219 tree ti_decl_addr = gimple_call_arg (stmt, 3);
1220 tree ckind_tree = gimple_call_arg (stmt, 4);
1221 ubsan_null_ckind ckind = (ubsan_null_ckind) tree_to_uhwi (ckind_tree);
1222 tree type = TREE_TYPE (TREE_TYPE (ckind_tree));
1223 gimple *g;
1224 basic_block fallthru_bb = NULL;
1226 if (ckind == UBSAN_DOWNCAST_POINTER)
1228 /* Guard everything with if (op != NULL) { ... }. */
1229 basic_block then_bb;
1230 gimple_stmt_iterator cond_insert_point
1231 = create_cond_insert_point (gsip, false, false, true,
1232 &then_bb, &fallthru_bb);
1233 g = gimple_build_cond (NE_EXPR, op, build_zero_cst (TREE_TYPE (op)),
1234 NULL_TREE, NULL_TREE);
1235 gimple_set_location (g, loc);
1236 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
1237 *gsip = gsi_after_labels (then_bb);
1238 gsi_remove (&gsi, false);
1239 gsi_insert_before (gsip, stmt, GSI_NEW_STMT);
1240 gsi = *gsip;
1243 tree htype = TREE_TYPE (str_hash);
1244 tree cst = wide_int_to_tree (htype,
1245 wi::uhwi (((uint64_t) 0x9ddfea08 << 32)
1246 | 0xeb382d69, 64));
1247 g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1248 vptr, str_hash);
1249 gimple_set_location (g, loc);
1250 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1251 g = gimple_build_assign (make_ssa_name (htype), MULT_EXPR,
1252 gimple_assign_lhs (g), cst);
1253 gimple_set_location (g, loc);
1254 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1255 tree t1 = gimple_assign_lhs (g);
1256 g = gimple_build_assign (make_ssa_name (htype), LSHIFT_EXPR,
1257 t1, build_int_cst (integer_type_node, 47));
1258 gimple_set_location (g, loc);
1259 tree t2 = gimple_assign_lhs (g);
1260 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1261 g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1262 vptr, t1);
1263 gimple_set_location (g, loc);
1264 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1265 g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1266 t2, gimple_assign_lhs (g));
1267 gimple_set_location (g, loc);
1268 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1269 g = gimple_build_assign (make_ssa_name (htype), MULT_EXPR,
1270 gimple_assign_lhs (g), cst);
1271 gimple_set_location (g, loc);
1272 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1273 tree t3 = gimple_assign_lhs (g);
1274 g = gimple_build_assign (make_ssa_name (htype), LSHIFT_EXPR,
1275 t3, build_int_cst (integer_type_node, 47));
1276 gimple_set_location (g, loc);
1277 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1278 g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1279 t3, gimple_assign_lhs (g));
1280 gimple_set_location (g, loc);
1281 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1282 g = gimple_build_assign (make_ssa_name (htype), MULT_EXPR,
1283 gimple_assign_lhs (g), cst);
1284 gimple_set_location (g, loc);
1285 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1286 if (!useless_type_conversion_p (pointer_sized_int_node, htype))
1288 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
1289 NOP_EXPR, gimple_assign_lhs (g));
1290 gimple_set_location (g, loc);
1291 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1293 tree hash = gimple_assign_lhs (g);
1295 if (ubsan_vptr_type_cache_decl == NULL_TREE)
1297 tree atype = build_array_type_nelts (pointer_sized_int_node, 128);
1298 tree array = build_decl (UNKNOWN_LOCATION, VAR_DECL,
1299 get_identifier ("__ubsan_vptr_type_cache"),
1300 atype);
1301 DECL_ARTIFICIAL (array) = 1;
1302 DECL_IGNORED_P (array) = 1;
1303 TREE_PUBLIC (array) = 1;
1304 TREE_STATIC (array) = 1;
1305 DECL_EXTERNAL (array) = 1;
1306 DECL_VISIBILITY (array) = VISIBILITY_DEFAULT;
1307 DECL_VISIBILITY_SPECIFIED (array) = 1;
1308 varpool_node::finalize_decl (array);
1309 ubsan_vptr_type_cache_decl = array;
1312 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
1313 BIT_AND_EXPR, hash,
1314 build_int_cst (pointer_sized_int_node, 127));
1315 gimple_set_location (g, loc);
1316 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1318 tree c = build4_loc (loc, ARRAY_REF, pointer_sized_int_node,
1319 ubsan_vptr_type_cache_decl, gimple_assign_lhs (g),
1320 NULL_TREE, NULL_TREE);
1321 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
1322 ARRAY_REF, c);
1323 gimple_set_location (g, loc);
1324 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1326 basic_block then_bb, fallthru2_bb;
1327 gimple_stmt_iterator cond_insert_point
1328 = create_cond_insert_point (gsip, false, false, true,
1329 &then_bb, &fallthru2_bb);
1330 g = gimple_build_cond (NE_EXPR, gimple_assign_lhs (g), hash,
1331 NULL_TREE, NULL_TREE);
1332 gimple_set_location (g, loc);
1333 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
1334 *gsip = gsi_after_labels (then_bb);
1335 if (fallthru_bb == NULL)
1336 fallthru_bb = fallthru2_bb;
1338 tree data
1339 = ubsan_create_data ("__ubsan_vptr_data", 1, &loc,
1340 ubsan_type_descriptor (type), NULL_TREE, ti_decl_addr,
1341 build_int_cst (unsigned_char_type_node, ckind),
1342 NULL_TREE);
1343 data = build_fold_addr_expr_loc (loc, data);
1344 enum built_in_function bcode
1345 = (flag_sanitize_recover & SANITIZE_VPTR)
1346 ? BUILT_IN_UBSAN_HANDLE_DYNAMIC_TYPE_CACHE_MISS
1347 : BUILT_IN_UBSAN_HANDLE_DYNAMIC_TYPE_CACHE_MISS_ABORT;
1349 g = gimple_build_call (builtin_decl_explicit (bcode), 3, data, op, hash);
1350 gimple_set_location (g, loc);
1351 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1353 /* Point GSI to next logical statement. */
1354 *gsip = gsi_start_bb (fallthru_bb);
1356 /* Get rid of the UBSAN_VPTR call from the IR. */
1357 unlink_stmt_vdef (stmt);
1358 gsi_remove (&gsi, true);
1359 return true;
1362 /* Instrument a memory reference. BASE is the base of MEM, IS_LHS says
1363 whether the pointer is on the left hand side of the assignment. */
1365 static void
1366 instrument_mem_ref (tree mem, tree base, gimple_stmt_iterator *iter,
1367 bool is_lhs)
1369 enum ubsan_null_ckind ikind = is_lhs ? UBSAN_STORE_OF : UBSAN_LOAD_OF;
1370 unsigned int align = 0;
1371 if (sanitize_flags_p (SANITIZE_ALIGNMENT))
1373 align = min_align_of_type (TREE_TYPE (base));
1374 if (align <= 1)
1375 align = 0;
1377 if (align == 0 && !sanitize_flags_p (SANITIZE_NULL))
1378 return;
1379 tree t = TREE_OPERAND (base, 0);
1380 if (!POINTER_TYPE_P (TREE_TYPE (t)))
1381 return;
1382 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (base)) && mem != base)
1383 ikind = UBSAN_MEMBER_ACCESS;
1384 tree kind = build_int_cst (build_pointer_type (TREE_TYPE (base)), ikind);
1385 tree alignt = build_int_cst (pointer_sized_int_node, align);
1386 gcall *g = gimple_build_call_internal (IFN_UBSAN_NULL, 3, t, kind, alignt);
1387 gimple_set_location (g, gimple_location (gsi_stmt (*iter)));
1388 gsi_insert_before (iter, g, GSI_SAME_STMT);
1391 /* Perform the pointer instrumentation. */
1393 static void
1394 instrument_null (gimple_stmt_iterator gsi, tree t, bool is_lhs)
1396 /* Handle also e.g. &s->i. */
1397 if (TREE_CODE (t) == ADDR_EXPR)
1398 t = TREE_OPERAND (t, 0);
1399 tree base = get_base_address (t);
1400 if (base != NULL_TREE
1401 && TREE_CODE (base) == MEM_REF
1402 && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
1403 instrument_mem_ref (t, base, &gsi, is_lhs);
1406 /* Instrument pointer arithmetics PTR p+ OFF. */
1408 static void
1409 instrument_pointer_overflow (gimple_stmt_iterator *gsi, tree ptr, tree off)
1411 if (TYPE_PRECISION (sizetype) != POINTER_SIZE)
1412 return;
1413 gcall *g = gimple_build_call_internal (IFN_UBSAN_PTR, 2, ptr, off);
1414 gimple_set_location (g, gimple_location (gsi_stmt (*gsi)));
1415 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1418 /* Instrument pointer arithmetics if any. */
1420 static void
1421 maybe_instrument_pointer_overflow (gimple_stmt_iterator *gsi, tree t)
1423 if (TYPE_PRECISION (sizetype) != POINTER_SIZE)
1424 return;
1426 /* Handle also e.g. &s->i. */
1427 if (TREE_CODE (t) == ADDR_EXPR)
1428 t = TREE_OPERAND (t, 0);
1430 if (!handled_component_p (t) && TREE_CODE (t) != MEM_REF)
1431 return;
1433 HOST_WIDE_INT bitsize, bitpos, bytepos;
1434 tree offset;
1435 machine_mode mode;
1436 int volatilep = 0, reversep, unsignedp = 0;
1437 tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset, &mode,
1438 &unsignedp, &reversep, &volatilep);
1439 tree moff = NULL_TREE;
1441 bool decl_p = DECL_P (inner);
1442 tree base;
1443 if (decl_p)
1445 if (DECL_REGISTER (inner))
1446 return;
1447 base = inner;
1448 /* If BASE is a fixed size automatic variable or
1449 global variable defined in the current TU and bitpos
1450 fits, don't instrument anything. */
1451 if (offset == NULL_TREE
1452 && bitpos > 0
1453 && (VAR_P (base)
1454 || TREE_CODE (base) == PARM_DECL
1455 || TREE_CODE (base) == RESULT_DECL)
1456 && DECL_SIZE (base)
1457 && TREE_CODE (DECL_SIZE (base)) == INTEGER_CST
1458 && compare_tree_int (DECL_SIZE (base), bitpos) >= 0
1459 && (!is_global_var (base) || decl_binds_to_current_def_p (base)))
1460 return;
1462 else if (TREE_CODE (inner) == MEM_REF)
1464 base = TREE_OPERAND (inner, 0);
1465 if (TREE_CODE (base) == ADDR_EXPR
1466 && DECL_P (TREE_OPERAND (base, 0))
1467 && !TREE_ADDRESSABLE (TREE_OPERAND (base, 0))
1468 && !is_global_var (TREE_OPERAND (base, 0)))
1469 return;
1470 moff = TREE_OPERAND (inner, 1);
1471 if (integer_zerop (moff))
1472 moff = NULL_TREE;
1474 else
1475 return;
1477 if (!POINTER_TYPE_P (TREE_TYPE (base)) && !DECL_P (base))
1478 return;
1479 bytepos = bitpos / BITS_PER_UNIT;
1480 if (offset == NULL_TREE && bytepos == 0 && moff == NULL_TREE)
1481 return;
1483 tree base_addr = base;
1484 if (decl_p)
1485 base_addr = build1 (ADDR_EXPR,
1486 build_pointer_type (TREE_TYPE (base)), base);
1487 t = offset;
1488 if (bytepos)
1490 if (t)
1491 t = fold_build2 (PLUS_EXPR, TREE_TYPE (t), t,
1492 build_int_cst (TREE_TYPE (t), bytepos));
1493 else
1494 t = size_int (bytepos);
1496 if (moff)
1498 if (t)
1499 t = fold_build2 (PLUS_EXPR, TREE_TYPE (t), t,
1500 fold_convert (TREE_TYPE (t), moff));
1501 else
1502 t = fold_convert (sizetype, moff);
1504 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE, true,
1505 GSI_SAME_STMT);
1506 base_addr = force_gimple_operand_gsi (gsi, base_addr, true, NULL_TREE, true,
1507 GSI_SAME_STMT);
1508 instrument_pointer_overflow (gsi, base_addr, t);
1511 /* Build an ubsan builtin call for the signed-integer-overflow
1512 sanitization. CODE says what kind of builtin are we building,
1513 LOC is a location, LHSTYPE is the type of LHS, OP0 and OP1
1514 are operands of the binary operation. */
1516 tree
1517 ubsan_build_overflow_builtin (tree_code code, location_t loc, tree lhstype,
1518 tree op0, tree op1, tree *datap)
1520 if (flag_sanitize_undefined_trap_on_error)
1521 return build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
1523 tree data;
1524 if (datap && *datap)
1525 data = *datap;
1526 else
1527 data = ubsan_create_data ("__ubsan_overflow_data", 1, &loc,
1528 ubsan_type_descriptor (lhstype), NULL_TREE,
1529 NULL_TREE);
1530 if (datap)
1531 *datap = data;
1532 enum built_in_function fn_code;
1534 switch (code)
1536 case PLUS_EXPR:
1537 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1538 ? BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW
1539 : BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW_ABORT;
1540 break;
1541 case MINUS_EXPR:
1542 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1543 ? BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW
1544 : BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW_ABORT;
1545 break;
1546 case MULT_EXPR:
1547 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1548 ? BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW
1549 : BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW_ABORT;
1550 break;
1551 case NEGATE_EXPR:
1552 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1553 ? BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW
1554 : BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW_ABORT;
1555 break;
1556 default:
1557 gcc_unreachable ();
1559 tree fn = builtin_decl_explicit (fn_code);
1560 return build_call_expr_loc (loc, fn, 2 + (code != NEGATE_EXPR),
1561 build_fold_addr_expr_loc (loc, data),
1562 ubsan_encode_value (op0, UBSAN_ENCODE_VALUE_RTL),
1564 ? ubsan_encode_value (op1,
1565 UBSAN_ENCODE_VALUE_RTL)
1566 : NULL_TREE);
1569 /* Perform the signed integer instrumentation. GSI is the iterator
1570 pointing at statement we are trying to instrument. */
1572 static void
1573 instrument_si_overflow (gimple_stmt_iterator gsi)
1575 gimple *stmt = gsi_stmt (gsi);
1576 tree_code code = gimple_assign_rhs_code (stmt);
1577 tree lhs = gimple_assign_lhs (stmt);
1578 tree lhstype = TREE_TYPE (lhs);
1579 tree lhsinner = VECTOR_TYPE_P (lhstype) ? TREE_TYPE (lhstype) : lhstype;
1580 tree a, b;
1581 gimple *g;
1583 /* If this is not a signed operation, don't instrument anything here.
1584 Also punt on bit-fields. */
1585 if (!INTEGRAL_TYPE_P (lhsinner)
1586 || TYPE_OVERFLOW_WRAPS (lhsinner)
1587 || GET_MODE_BITSIZE (TYPE_MODE (lhsinner)) != TYPE_PRECISION (lhsinner))
1588 return;
1590 switch (code)
1592 case MINUS_EXPR:
1593 case PLUS_EXPR:
1594 case MULT_EXPR:
1595 /* Transform
1596 i = u {+,-,*} 5;
1597 into
1598 i = UBSAN_CHECK_{ADD,SUB,MUL} (u, 5); */
1599 a = gimple_assign_rhs1 (stmt);
1600 b = gimple_assign_rhs2 (stmt);
1601 g = gimple_build_call_internal (code == PLUS_EXPR
1602 ? IFN_UBSAN_CHECK_ADD
1603 : code == MINUS_EXPR
1604 ? IFN_UBSAN_CHECK_SUB
1605 : IFN_UBSAN_CHECK_MUL, 2, a, b);
1606 gimple_call_set_lhs (g, lhs);
1607 gsi_replace (&gsi, g, true);
1608 break;
1609 case NEGATE_EXPR:
1610 /* Represent i = -u;
1612 i = UBSAN_CHECK_SUB (0, u); */
1613 a = build_zero_cst (lhstype);
1614 b = gimple_assign_rhs1 (stmt);
1615 g = gimple_build_call_internal (IFN_UBSAN_CHECK_SUB, 2, a, b);
1616 gimple_call_set_lhs (g, lhs);
1617 gsi_replace (&gsi, g, true);
1618 break;
1619 case ABS_EXPR:
1620 /* Transform i = ABS_EXPR<u>;
1621 into
1622 _N = UBSAN_CHECK_SUB (0, u);
1623 i = ABS_EXPR<_N>; */
1624 a = build_zero_cst (lhstype);
1625 b = gimple_assign_rhs1 (stmt);
1626 g = gimple_build_call_internal (IFN_UBSAN_CHECK_SUB, 2, a, b);
1627 a = make_ssa_name (lhstype);
1628 gimple_call_set_lhs (g, a);
1629 gimple_set_location (g, gimple_location (stmt));
1630 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
1631 gimple_assign_set_rhs1 (stmt, a);
1632 update_stmt (stmt);
1633 break;
1634 default:
1635 break;
1639 /* Instrument loads from (non-bitfield) bool and C++ enum values
1640 to check if the memory value is outside of the range of the valid
1641 type values. */
1643 static void
1644 instrument_bool_enum_load (gimple_stmt_iterator *gsi)
1646 gimple *stmt = gsi_stmt (*gsi);
1647 tree rhs = gimple_assign_rhs1 (stmt);
1648 tree type = TREE_TYPE (rhs);
1649 tree minv = NULL_TREE, maxv = NULL_TREE;
1651 if (TREE_CODE (type) == BOOLEAN_TYPE
1652 && sanitize_flags_p (SANITIZE_BOOL))
1654 minv = boolean_false_node;
1655 maxv = boolean_true_node;
1657 else if (TREE_CODE (type) == ENUMERAL_TYPE
1658 && sanitize_flags_p (SANITIZE_ENUM)
1659 && TREE_TYPE (type) != NULL_TREE
1660 && TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE
1661 && (TYPE_PRECISION (TREE_TYPE (type))
1662 < GET_MODE_PRECISION (TYPE_MODE (type))))
1664 minv = TYPE_MIN_VALUE (TREE_TYPE (type));
1665 maxv = TYPE_MAX_VALUE (TREE_TYPE (type));
1667 else
1668 return;
1670 int modebitsize = GET_MODE_BITSIZE (TYPE_MODE (type));
1671 HOST_WIDE_INT bitsize, bitpos;
1672 tree offset;
1673 machine_mode mode;
1674 int volatilep = 0, reversep, unsignedp = 0;
1675 tree base = get_inner_reference (rhs, &bitsize, &bitpos, &offset, &mode,
1676 &unsignedp, &reversep, &volatilep);
1677 tree utype = build_nonstandard_integer_type (modebitsize, 1);
1679 if ((VAR_P (base) && DECL_HARD_REGISTER (base))
1680 || (bitpos % modebitsize) != 0
1681 || bitsize != modebitsize
1682 || GET_MODE_BITSIZE (TYPE_MODE (utype)) != modebitsize
1683 || TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME)
1684 return;
1686 bool ends_bb = stmt_ends_bb_p (stmt);
1687 location_t loc = gimple_location (stmt);
1688 tree lhs = gimple_assign_lhs (stmt);
1689 tree ptype = build_pointer_type (TREE_TYPE (rhs));
1690 tree atype = reference_alias_ptr_type (rhs);
1691 gimple *g = gimple_build_assign (make_ssa_name (ptype),
1692 build_fold_addr_expr (rhs));
1693 gimple_set_location (g, loc);
1694 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1695 tree mem = build2 (MEM_REF, utype, gimple_assign_lhs (g),
1696 build_int_cst (atype, 0));
1697 tree urhs = make_ssa_name (utype);
1698 if (ends_bb)
1700 gimple_assign_set_lhs (stmt, urhs);
1701 g = gimple_build_assign (lhs, NOP_EXPR, urhs);
1702 gimple_set_location (g, loc);
1703 edge e = find_fallthru_edge (gimple_bb (stmt)->succs);
1704 gsi_insert_on_edge_immediate (e, g);
1705 gimple_assign_set_rhs_from_tree (gsi, mem);
1706 update_stmt (stmt);
1707 *gsi = gsi_for_stmt (g);
1708 g = stmt;
1710 else
1712 g = gimple_build_assign (urhs, mem);
1713 gimple_set_location (g, loc);
1714 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1716 minv = fold_convert (utype, minv);
1717 maxv = fold_convert (utype, maxv);
1718 if (!integer_zerop (minv))
1720 g = gimple_build_assign (make_ssa_name (utype), MINUS_EXPR, urhs, minv);
1721 gimple_set_location (g, loc);
1722 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1725 gimple_stmt_iterator gsi2 = *gsi;
1726 basic_block then_bb, fallthru_bb;
1727 *gsi = create_cond_insert_point (gsi, true, false, true,
1728 &then_bb, &fallthru_bb);
1729 g = gimple_build_cond (GT_EXPR, gimple_assign_lhs (g),
1730 int_const_binop (MINUS_EXPR, maxv, minv),
1731 NULL_TREE, NULL_TREE);
1732 gimple_set_location (g, loc);
1733 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1735 if (!ends_bb)
1737 gimple_assign_set_rhs_with_ops (&gsi2, NOP_EXPR, urhs);
1738 update_stmt (stmt);
1741 gsi2 = gsi_after_labels (then_bb);
1742 if (flag_sanitize_undefined_trap_on_error)
1743 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1744 else
1746 tree data = ubsan_create_data ("__ubsan_invalid_value_data", 1, &loc,
1747 ubsan_type_descriptor (type), NULL_TREE,
1748 NULL_TREE);
1749 data = build_fold_addr_expr_loc (loc, data);
1750 enum built_in_function bcode
1751 = (flag_sanitize_recover & (TREE_CODE (type) == BOOLEAN_TYPE
1752 ? SANITIZE_BOOL : SANITIZE_ENUM))
1753 ? BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE
1754 : BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE_ABORT;
1755 tree fn = builtin_decl_explicit (bcode);
1757 tree val = ubsan_encode_value (urhs, UBSAN_ENCODE_VALUE_GIMPLE);
1758 val = force_gimple_operand_gsi (&gsi2, val, true, NULL_TREE, true,
1759 GSI_SAME_STMT);
1760 g = gimple_build_call (fn, 2, data, val);
1762 gimple_set_location (g, loc);
1763 gsi_insert_before (&gsi2, g, GSI_SAME_STMT);
1764 ubsan_create_edge (g);
1765 *gsi = gsi_for_stmt (stmt);
1768 /* Determine if we can propagate given LOCATION to ubsan_data descriptor to use
1769 new style handlers. Libubsan uses heuristics to destinguish between old and
1770 new styles and relies on these properties for filename:
1772 a) Location's filename must not be NULL.
1773 b) Location's filename must not be equal to "".
1774 c) Location's filename must not be equal to "\1".
1775 d) First two bytes of filename must not contain '\xff' symbol. */
1777 static bool
1778 ubsan_use_new_style_p (location_t loc)
1780 if (loc == UNKNOWN_LOCATION)
1781 return false;
1783 expanded_location xloc = expand_location (loc);
1784 if (xloc.file == NULL || strncmp (xloc.file, "\1", 2) == 0
1785 || xloc.file[0] == '\0' || xloc.file[0] == '\xff'
1786 || xloc.file[1] == '\xff')
1787 return false;
1789 return true;
1792 /* Instrument float point-to-integer conversion. TYPE is an integer type of
1793 destination, EXPR is floating-point expression. */
1795 tree
1796 ubsan_instrument_float_cast (location_t loc, tree type, tree expr)
1798 tree expr_type = TREE_TYPE (expr);
1799 tree t, tt, fn, min, max;
1800 machine_mode mode = TYPE_MODE (expr_type);
1801 int prec = TYPE_PRECISION (type);
1802 bool uns_p = TYPE_UNSIGNED (type);
1803 if (loc == UNKNOWN_LOCATION)
1804 loc = input_location;
1806 /* Float to integer conversion first truncates toward zero, so
1807 even signed char c = 127.875f; is not problematic.
1808 Therefore, we should complain only if EXPR is unordered or smaller
1809 or equal than TYPE_MIN_VALUE - 1.0 or greater or equal than
1810 TYPE_MAX_VALUE + 1.0. */
1811 if (REAL_MODE_FORMAT (mode)->b == 2)
1813 /* For maximum, TYPE_MAX_VALUE might not be representable
1814 in EXPR_TYPE, e.g. if TYPE is 64-bit long long and
1815 EXPR_TYPE is IEEE single float, but TYPE_MAX_VALUE + 1.0 is
1816 either representable or infinity. */
1817 REAL_VALUE_TYPE maxval = dconst1;
1818 SET_REAL_EXP (&maxval, REAL_EXP (&maxval) + prec - !uns_p);
1819 real_convert (&maxval, mode, &maxval);
1820 max = build_real (expr_type, maxval);
1822 /* For unsigned, assume -1.0 is always representable. */
1823 if (uns_p)
1824 min = build_minus_one_cst (expr_type);
1825 else
1827 /* TYPE_MIN_VALUE is generally representable (or -inf),
1828 but TYPE_MIN_VALUE - 1.0 might not be. */
1829 REAL_VALUE_TYPE minval = dconstm1, minval2;
1830 SET_REAL_EXP (&minval, REAL_EXP (&minval) + prec - 1);
1831 real_convert (&minval, mode, &minval);
1832 real_arithmetic (&minval2, MINUS_EXPR, &minval, &dconst1);
1833 real_convert (&minval2, mode, &minval2);
1834 if (real_compare (EQ_EXPR, &minval, &minval2)
1835 && !real_isinf (&minval))
1837 /* If TYPE_MIN_VALUE - 1.0 is not representable and
1838 rounds to TYPE_MIN_VALUE, we need to subtract
1839 more. As REAL_MODE_FORMAT (mode)->p is the number
1840 of base digits, we want to subtract a number that
1841 will be 1 << (REAL_MODE_FORMAT (mode)->p - 1)
1842 times smaller than minval. */
1843 minval2 = dconst1;
1844 gcc_assert (prec > REAL_MODE_FORMAT (mode)->p);
1845 SET_REAL_EXP (&minval2,
1846 REAL_EXP (&minval2) + prec - 1
1847 - REAL_MODE_FORMAT (mode)->p + 1);
1848 real_arithmetic (&minval2, MINUS_EXPR, &minval, &minval2);
1849 real_convert (&minval2, mode, &minval2);
1851 min = build_real (expr_type, minval2);
1854 else if (REAL_MODE_FORMAT (mode)->b == 10)
1856 /* For _Decimal128 up to 34 decimal digits, - sign,
1857 dot, e, exponent. */
1858 char buf[64];
1859 mpfr_t m;
1860 int p = REAL_MODE_FORMAT (mode)->p;
1861 REAL_VALUE_TYPE maxval, minval;
1863 /* Use mpfr_snprintf rounding to compute the smallest
1864 representable decimal number greater or equal than
1865 1 << (prec - !uns_p). */
1866 mpfr_init2 (m, prec + 2);
1867 mpfr_set_ui_2exp (m, 1, prec - !uns_p, GMP_RNDN);
1868 mpfr_snprintf (buf, sizeof buf, "%.*RUe", p - 1, m);
1869 decimal_real_from_string (&maxval, buf);
1870 max = build_real (expr_type, maxval);
1872 /* For unsigned, assume -1.0 is always representable. */
1873 if (uns_p)
1874 min = build_minus_one_cst (expr_type);
1875 else
1877 /* Use mpfr_snprintf rounding to compute the largest
1878 representable decimal number less or equal than
1879 (-1 << (prec - 1)) - 1. */
1880 mpfr_set_si_2exp (m, -1, prec - 1, GMP_RNDN);
1881 mpfr_sub_ui (m, m, 1, GMP_RNDN);
1882 mpfr_snprintf (buf, sizeof buf, "%.*RDe", p - 1, m);
1883 decimal_real_from_string (&minval, buf);
1884 min = build_real (expr_type, minval);
1886 mpfr_clear (m);
1888 else
1889 return NULL_TREE;
1891 t = fold_build2 (UNLE_EXPR, boolean_type_node, expr, min);
1892 tt = fold_build2 (UNGE_EXPR, boolean_type_node, expr, max);
1893 t = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t, tt);
1894 if (integer_zerop (t))
1895 return NULL_TREE;
1897 if (flag_sanitize_undefined_trap_on_error)
1898 fn = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
1899 else
1901 location_t *loc_ptr = NULL;
1902 unsigned num_locations = 0;
1903 /* Figure out if we can propagate location to ubsan_data and use new
1904 style handlers in libubsan. */
1905 if (ubsan_use_new_style_p (loc))
1907 loc_ptr = &loc;
1908 num_locations = 1;
1910 /* Create the __ubsan_handle_float_cast_overflow fn call. */
1911 tree data = ubsan_create_data ("__ubsan_float_cast_overflow_data",
1912 num_locations, loc_ptr,
1913 ubsan_type_descriptor (expr_type),
1914 ubsan_type_descriptor (type), NULL_TREE,
1915 NULL_TREE);
1916 enum built_in_function bcode
1917 = (flag_sanitize_recover & SANITIZE_FLOAT_CAST)
1918 ? BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW
1919 : BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW_ABORT;
1920 fn = builtin_decl_explicit (bcode);
1921 fn = build_call_expr_loc (loc, fn, 2,
1922 build_fold_addr_expr_loc (loc, data),
1923 ubsan_encode_value (expr));
1926 return fold_build3 (COND_EXPR, void_type_node, t, fn, integer_zero_node);
1929 /* Instrument values passed to function arguments with nonnull attribute. */
1931 static void
1932 instrument_nonnull_arg (gimple_stmt_iterator *gsi)
1934 gimple *stmt = gsi_stmt (*gsi);
1935 location_t loc[2];
1936 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
1937 while for nonnull sanitization it is clear. */
1938 int save_flag_delete_null_pointer_checks = flag_delete_null_pointer_checks;
1939 flag_delete_null_pointer_checks = 1;
1940 loc[0] = gimple_location (stmt);
1941 loc[1] = UNKNOWN_LOCATION;
1942 for (unsigned int i = 0; i < gimple_call_num_args (stmt); i++)
1944 tree arg = gimple_call_arg (stmt, i);
1945 if (POINTER_TYPE_P (TREE_TYPE (arg))
1946 && infer_nonnull_range_by_attribute (stmt, arg))
1948 gimple *g;
1949 if (!is_gimple_val (arg))
1951 g = gimple_build_assign (make_ssa_name (TREE_TYPE (arg)), arg);
1952 gimple_set_location (g, loc[0]);
1953 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1954 arg = gimple_assign_lhs (g);
1957 basic_block then_bb, fallthru_bb;
1958 *gsi = create_cond_insert_point (gsi, true, false, true,
1959 &then_bb, &fallthru_bb);
1960 g = gimple_build_cond (EQ_EXPR, arg,
1961 build_zero_cst (TREE_TYPE (arg)),
1962 NULL_TREE, NULL_TREE);
1963 gimple_set_location (g, loc[0]);
1964 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1966 *gsi = gsi_after_labels (then_bb);
1967 if (flag_sanitize_undefined_trap_on_error)
1968 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1969 else
1971 tree data = ubsan_create_data ("__ubsan_nonnull_arg_data",
1972 2, loc, NULL_TREE,
1973 build_int_cst (integer_type_node,
1974 i + 1),
1975 NULL_TREE);
1976 data = build_fold_addr_expr_loc (loc[0], data);
1977 enum built_in_function bcode
1978 = (flag_sanitize_recover & SANITIZE_NONNULL_ATTRIBUTE)
1979 ? BUILT_IN_UBSAN_HANDLE_NONNULL_ARG
1980 : BUILT_IN_UBSAN_HANDLE_NONNULL_ARG_ABORT;
1981 tree fn = builtin_decl_explicit (bcode);
1983 g = gimple_build_call (fn, 1, data);
1985 gimple_set_location (g, loc[0]);
1986 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1987 ubsan_create_edge (g);
1989 *gsi = gsi_for_stmt (stmt);
1991 flag_delete_null_pointer_checks = save_flag_delete_null_pointer_checks;
1994 /* Instrument returns in functions with returns_nonnull attribute. */
1996 static void
1997 instrument_nonnull_return (gimple_stmt_iterator *gsi)
1999 greturn *stmt = as_a <greturn *> (gsi_stmt (*gsi));
2000 location_t loc[2];
2001 tree arg = gimple_return_retval (stmt);
2002 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
2003 while for nonnull return sanitization it is clear. */
2004 int save_flag_delete_null_pointer_checks = flag_delete_null_pointer_checks;
2005 flag_delete_null_pointer_checks = 1;
2006 loc[0] = gimple_location (stmt);
2007 loc[1] = UNKNOWN_LOCATION;
2008 if (arg
2009 && POINTER_TYPE_P (TREE_TYPE (arg))
2010 && is_gimple_val (arg)
2011 && infer_nonnull_range_by_attribute (stmt, arg))
2013 basic_block then_bb, fallthru_bb;
2014 *gsi = create_cond_insert_point (gsi, true, false, true,
2015 &then_bb, &fallthru_bb);
2016 gimple *g = gimple_build_cond (EQ_EXPR, arg,
2017 build_zero_cst (TREE_TYPE (arg)),
2018 NULL_TREE, NULL_TREE);
2019 gimple_set_location (g, loc[0]);
2020 gsi_insert_after (gsi, g, GSI_NEW_STMT);
2022 *gsi = gsi_after_labels (then_bb);
2023 if (flag_sanitize_undefined_trap_on_error)
2024 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
2025 else
2027 tree data = ubsan_create_data ("__ubsan_nonnull_return_data",
2028 2, loc, NULL_TREE, NULL_TREE);
2029 data = build_fold_addr_expr_loc (loc[0], data);
2030 enum built_in_function bcode
2031 = (flag_sanitize_recover & SANITIZE_RETURNS_NONNULL_ATTRIBUTE)
2032 ? BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN
2033 : BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_ABORT;
2034 tree fn = builtin_decl_explicit (bcode);
2036 g = gimple_build_call (fn, 1, data);
2038 gimple_set_location (g, loc[0]);
2039 gsi_insert_before (gsi, g, GSI_SAME_STMT);
2040 ubsan_create_edge (g);
2041 *gsi = gsi_for_stmt (stmt);
2043 flag_delete_null_pointer_checks = save_flag_delete_null_pointer_checks;
2046 /* Instrument memory references. Here we check whether the pointer
2047 points to an out-of-bounds location. */
2049 static void
2050 instrument_object_size (gimple_stmt_iterator *gsi, tree t, bool is_lhs)
2052 gimple *stmt = gsi_stmt (*gsi);
2053 location_t loc = gimple_location (stmt);
2054 tree type;
2055 tree index = NULL_TREE;
2056 HOST_WIDE_INT size_in_bytes;
2058 type = TREE_TYPE (t);
2059 if (VOID_TYPE_P (type))
2060 return;
2062 switch (TREE_CODE (t))
2064 case COMPONENT_REF:
2065 if (TREE_CODE (t) == COMPONENT_REF
2066 && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1)) != NULL_TREE)
2068 tree repr = DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1));
2069 t = build3 (COMPONENT_REF, TREE_TYPE (repr), TREE_OPERAND (t, 0),
2070 repr, TREE_OPERAND (t, 2));
2072 break;
2073 case ARRAY_REF:
2074 index = TREE_OPERAND (t, 1);
2075 break;
2076 case INDIRECT_REF:
2077 case MEM_REF:
2078 case VAR_DECL:
2079 case PARM_DECL:
2080 case RESULT_DECL:
2081 break;
2082 default:
2083 return;
2086 size_in_bytes = int_size_in_bytes (type);
2087 if (size_in_bytes <= 0)
2088 return;
2090 HOST_WIDE_INT bitsize, bitpos;
2091 tree offset;
2092 machine_mode mode;
2093 int volatilep = 0, reversep, unsignedp = 0;
2094 tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset, &mode,
2095 &unsignedp, &reversep, &volatilep);
2097 if (bitpos % BITS_PER_UNIT != 0
2098 || bitsize != size_in_bytes * BITS_PER_UNIT)
2099 return;
2101 bool decl_p = DECL_P (inner);
2102 tree base;
2103 if (decl_p)
2105 if (DECL_REGISTER (inner))
2106 return;
2107 base = inner;
2109 else if (TREE_CODE (inner) == MEM_REF)
2110 base = TREE_OPERAND (inner, 0);
2111 else
2112 return;
2113 tree ptr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (t)), t);
2115 while (TREE_CODE (base) == SSA_NAME)
2117 gimple *def_stmt = SSA_NAME_DEF_STMT (base);
2118 if (gimple_assign_ssa_name_copy_p (def_stmt)
2119 || (gimple_assign_cast_p (def_stmt)
2120 && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (def_stmt))))
2121 || (is_gimple_assign (def_stmt)
2122 && gimple_assign_rhs_code (def_stmt) == POINTER_PLUS_EXPR))
2124 tree rhs1 = gimple_assign_rhs1 (def_stmt);
2125 if (TREE_CODE (rhs1) == SSA_NAME
2126 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs1))
2127 break;
2128 else
2129 base = rhs1;
2131 else
2132 break;
2135 if (!POINTER_TYPE_P (TREE_TYPE (base)) && !DECL_P (base))
2136 return;
2138 tree sizet;
2139 tree base_addr = base;
2140 gimple *bos_stmt = NULL;
2141 if (decl_p)
2142 base_addr = build1 (ADDR_EXPR,
2143 build_pointer_type (TREE_TYPE (base)), base);
2144 unsigned HOST_WIDE_INT size;
2145 if (compute_builtin_object_size (base_addr, 0, &size))
2146 sizet = build_int_cst (sizetype, size);
2147 else if (optimize)
2149 if (LOCATION_LOCUS (loc) == UNKNOWN_LOCATION)
2150 loc = input_location;
2151 /* Generate __builtin_object_size call. */
2152 sizet = builtin_decl_explicit (BUILT_IN_OBJECT_SIZE);
2153 sizet = build_call_expr_loc (loc, sizet, 2, base_addr,
2154 integer_zero_node);
2155 sizet = force_gimple_operand_gsi (gsi, sizet, false, NULL_TREE, true,
2156 GSI_SAME_STMT);
2157 /* If the call above didn't end up being an integer constant, go one
2158 statement back and get the __builtin_object_size stmt. Save it,
2159 we might need it later. */
2160 if (SSA_VAR_P (sizet))
2162 gsi_prev (gsi);
2163 bos_stmt = gsi_stmt (*gsi);
2165 /* Move on to where we were. */
2166 gsi_next (gsi);
2169 else
2170 return;
2172 /* Generate UBSAN_OBJECT_SIZE (ptr, ptr+sizeof(*ptr)-base, objsize, ckind)
2173 call. */
2174 /* ptr + sizeof (*ptr) - base */
2175 t = fold_build2 (MINUS_EXPR, sizetype,
2176 fold_convert (pointer_sized_int_node, ptr),
2177 fold_convert (pointer_sized_int_node, base_addr));
2178 t = fold_build2 (PLUS_EXPR, sizetype, t, TYPE_SIZE_UNIT (type));
2180 /* Perhaps we can omit the check. */
2181 if (TREE_CODE (t) == INTEGER_CST
2182 && TREE_CODE (sizet) == INTEGER_CST
2183 && tree_int_cst_le (t, sizet))
2184 return;
2186 if (index != NULL_TREE
2187 && TREE_CODE (index) == SSA_NAME
2188 && TREE_CODE (sizet) == INTEGER_CST)
2190 gimple *def = SSA_NAME_DEF_STMT (index);
2191 if (is_gimple_assign (def)
2192 && gimple_assign_rhs_code (def) == BIT_AND_EXPR
2193 && TREE_CODE (gimple_assign_rhs2 (def)) == INTEGER_CST)
2195 tree cst = gimple_assign_rhs2 (def);
2196 tree sz = fold_build2 (EXACT_DIV_EXPR, sizetype, sizet,
2197 TYPE_SIZE_UNIT (type));
2198 if (tree_int_cst_sgn (cst) >= 0
2199 && tree_int_cst_lt (cst, sz))
2200 return;
2204 if (bos_stmt && gimple_call_builtin_p (bos_stmt, BUILT_IN_OBJECT_SIZE))
2205 ubsan_create_edge (bos_stmt);
2207 /* We have to emit the check. */
2208 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE, true,
2209 GSI_SAME_STMT);
2210 ptr = force_gimple_operand_gsi (gsi, ptr, true, NULL_TREE, true,
2211 GSI_SAME_STMT);
2212 tree ckind = build_int_cst (unsigned_char_type_node,
2213 is_lhs ? UBSAN_STORE_OF : UBSAN_LOAD_OF);
2214 gimple *g = gimple_build_call_internal (IFN_UBSAN_OBJECT_SIZE, 4,
2215 ptr, t, sizet, ckind);
2216 gimple_set_location (g, loc);
2217 gsi_insert_before (gsi, g, GSI_SAME_STMT);
2220 namespace {
2222 const pass_data pass_data_ubsan =
2224 GIMPLE_PASS, /* type */
2225 "ubsan", /* name */
2226 OPTGROUP_NONE, /* optinfo_flags */
2227 TV_TREE_UBSAN, /* tv_id */
2228 ( PROP_cfg | PROP_ssa ), /* properties_required */
2229 0, /* properties_provided */
2230 0, /* properties_destroyed */
2231 0, /* todo_flags_start */
2232 TODO_update_ssa, /* todo_flags_finish */
2235 class pass_ubsan : public gimple_opt_pass
2237 public:
2238 pass_ubsan (gcc::context *ctxt)
2239 : gimple_opt_pass (pass_data_ubsan, ctxt)
2242 /* opt_pass methods: */
2243 virtual bool gate (function *)
2245 return sanitize_flags_p ((SANITIZE_NULL | SANITIZE_SI_OVERFLOW
2246 | SANITIZE_BOOL | SANITIZE_ENUM
2247 | SANITIZE_ALIGNMENT
2248 | SANITIZE_NONNULL_ATTRIBUTE
2249 | SANITIZE_RETURNS_NONNULL_ATTRIBUTE
2250 | SANITIZE_OBJECT_SIZE
2251 | SANITIZE_POINTER_OVERFLOW));
2254 virtual unsigned int execute (function *);
2256 }; // class pass_ubsan
2258 unsigned int
2259 pass_ubsan::execute (function *fun)
2261 basic_block bb;
2262 gimple_stmt_iterator gsi;
2263 unsigned int ret = 0;
2265 initialize_sanitizer_builtins ();
2267 FOR_EACH_BB_FN (bb, fun)
2269 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
2271 gimple *stmt = gsi_stmt (gsi);
2272 if (is_gimple_debug (stmt) || gimple_clobber_p (stmt))
2274 gsi_next (&gsi);
2275 continue;
2278 if ((sanitize_flags_p (SANITIZE_SI_OVERFLOW, fun->decl))
2279 && is_gimple_assign (stmt))
2280 instrument_si_overflow (gsi);
2282 if (sanitize_flags_p (SANITIZE_NULL | SANITIZE_ALIGNMENT, fun->decl))
2284 if (gimple_store_p (stmt))
2285 instrument_null (gsi, gimple_get_lhs (stmt), true);
2286 if (gimple_assign_single_p (stmt))
2287 instrument_null (gsi, gimple_assign_rhs1 (stmt), false);
2288 if (is_gimple_call (stmt))
2290 unsigned args_num = gimple_call_num_args (stmt);
2291 for (unsigned i = 0; i < args_num; ++i)
2293 tree arg = gimple_call_arg (stmt, i);
2294 if (is_gimple_reg (arg) || is_gimple_min_invariant (arg))
2295 continue;
2296 instrument_null (gsi, arg, false);
2301 if (sanitize_flags_p (SANITIZE_BOOL | SANITIZE_ENUM, fun->decl)
2302 && gimple_assign_load_p (stmt))
2304 instrument_bool_enum_load (&gsi);
2305 bb = gimple_bb (stmt);
2308 if (sanitize_flags_p (SANITIZE_NONNULL_ATTRIBUTE, fun->decl)
2309 && is_gimple_call (stmt)
2310 && !gimple_call_internal_p (stmt))
2312 instrument_nonnull_arg (&gsi);
2313 bb = gimple_bb (stmt);
2316 if (sanitize_flags_p (SANITIZE_RETURNS_NONNULL_ATTRIBUTE, fun->decl)
2317 && gimple_code (stmt) == GIMPLE_RETURN)
2319 instrument_nonnull_return (&gsi);
2320 bb = gimple_bb (stmt);
2323 if (sanitize_flags_p (SANITIZE_OBJECT_SIZE, fun->decl))
2325 if (gimple_store_p (stmt))
2326 instrument_object_size (&gsi, gimple_get_lhs (stmt), true);
2327 if (gimple_assign_load_p (stmt))
2328 instrument_object_size (&gsi, gimple_assign_rhs1 (stmt),
2329 false);
2330 if (is_gimple_call (stmt))
2332 unsigned args_num = gimple_call_num_args (stmt);
2333 for (unsigned i = 0; i < args_num; ++i)
2335 tree arg = gimple_call_arg (stmt, i);
2336 if (is_gimple_reg (arg) || is_gimple_min_invariant (arg))
2337 continue;
2338 instrument_object_size (&gsi, arg, false);
2343 if (sanitize_flags_p (SANITIZE_POINTER_OVERFLOW, fun->decl))
2345 if (is_gimple_assign (stmt)
2346 && gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
2347 instrument_pointer_overflow (&gsi,
2348 gimple_assign_rhs1 (stmt),
2349 gimple_assign_rhs2 (stmt));
2350 if (gimple_store_p (stmt))
2351 maybe_instrument_pointer_overflow (&gsi,
2352 gimple_get_lhs (stmt));
2353 if (gimple_assign_single_p (stmt))
2354 maybe_instrument_pointer_overflow (&gsi,
2355 gimple_assign_rhs1 (stmt));
2356 if (is_gimple_call (stmt))
2358 unsigned args_num = gimple_call_num_args (stmt);
2359 for (unsigned i = 0; i < args_num; ++i)
2361 tree arg = gimple_call_arg (stmt, i);
2362 if (is_gimple_reg (arg))
2363 continue;
2364 maybe_instrument_pointer_overflow (&gsi, arg);
2369 gsi_next (&gsi);
2371 if (gimple_purge_dead_eh_edges (bb))
2372 ret = TODO_cleanup_cfg;
2374 return ret;
2377 } // anon namespace
2379 gimple_opt_pass *
2380 make_pass_ubsan (gcc::context *ctxt)
2382 return new pass_ubsan (ctxt);
2385 #include "gt-ubsan.h"