gcc/
[official-gcc.git] / gcc / ubsan.c
blobded725a55d0480cec1dbc8dbe5447de41df4bd2d
1 /* UndefinedBehaviorSanitizer, undefined behavior detector.
2 Copyright (C) 2013-2015 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 "alias.h"
25 #include "symtab.h"
26 #include "options.h"
27 #include "tree.h"
28 #include "fold-const.h"
29 #include "stor-layout.h"
30 #include "stringpool.h"
31 #include "predict.h"
32 #include "dominance.h"
33 #include "cfg.h"
34 #include "cfganal.h"
35 #include "basic-block.h"
36 #include "plugin-api.h"
37 #include "tm.h"
38 #include "hard-reg-set.h"
39 #include "function.h"
40 #include "ipa-ref.h"
41 #include "cgraph.h"
42 #include "tree-pass.h"
43 #include "tree-ssa-alias.h"
44 #include "tree-pretty-print.h"
45 #include "internal-fn.h"
46 #include "gimple-expr.h"
47 #include "gimple.h"
48 #include "gimple-iterator.h"
49 #include "gimple-ssa.h"
50 #include "gimple-walk.h"
51 #include "output.h"
52 #include "tm_p.h"
53 #include "toplev.h"
54 #include "cfgloop.h"
55 #include "ubsan.h"
56 #include "c-family/c-common.h"
57 #include "rtl.h"
58 #include "flags.h"
59 #include "insn-config.h"
60 #include "expmed.h"
61 #include "dojump.h"
62 #include "explow.h"
63 #include "calls.h"
64 #include "emit-rtl.h"
65 #include "varasm.h"
66 #include "stmt.h"
67 #include "expr.h"
68 #include "tree-ssanames.h"
69 #include "asan.h"
70 #include "gimplify-me.h"
71 #include "intl.h"
72 #include "realmpfr.h"
73 #include "dfp.h"
74 #include "builtins.h"
75 #include "tree-object-size.h"
76 #include "tree-eh.h"
77 #include "tree-cfg.h"
79 /* Map from a tree to a VAR_DECL tree. */
81 struct GTY((for_user)) tree_type_map {
82 struct tree_map_base type;
83 tree decl;
86 struct tree_type_map_cache_hasher : ggc_cache_ptr_hash<tree_type_map>
88 static inline hashval_t
89 hash (tree_type_map *t)
91 return TYPE_UID (t->type.from);
94 static inline bool
95 equal (tree_type_map *a, tree_type_map *b)
97 return a->type.from == b->type.from;
100 static int
101 keep_cache_entry (tree_type_map *&m)
103 return ggc_marked_p (m->type.from);
107 static GTY ((cache))
108 hash_table<tree_type_map_cache_hasher> *decl_tree_for_type;
110 /* Lookup a VAR_DECL for TYPE, and return it if we find one. */
112 static tree
113 decl_for_type_lookup (tree type)
115 /* If the hash table is not initialized yet, create it now. */
116 if (decl_tree_for_type == NULL)
118 decl_tree_for_type
119 = hash_table<tree_type_map_cache_hasher>::create_ggc (10);
120 /* That also means we don't have to bother with the lookup. */
121 return NULL_TREE;
124 struct tree_type_map *h, in;
125 in.type.from = type;
127 h = decl_tree_for_type->find_with_hash (&in, TYPE_UID (type));
128 return h ? h->decl : NULL_TREE;
131 /* Insert a mapping TYPE->DECL in the VAR_DECL for type hashtable. */
133 static void
134 decl_for_type_insert (tree type, tree decl)
136 struct tree_type_map *h;
138 h = ggc_alloc<tree_type_map> ();
139 h->type.from = type;
140 h->decl = decl;
141 *decl_tree_for_type->find_slot_with_hash (h, TYPE_UID (type), INSERT) = h;
144 /* Helper routine, which encodes a value in the pointer_sized_int_node.
145 Arguments with precision <= POINTER_SIZE are passed directly,
146 the rest is passed by reference. T is a value we are to encode.
147 IN_EXPAND_P is true if this function is called during expansion. */
149 tree
150 ubsan_encode_value (tree t, bool in_expand_p)
152 tree type = TREE_TYPE (t);
153 const unsigned int bitsize = GET_MODE_BITSIZE (TYPE_MODE (type));
154 if (bitsize <= POINTER_SIZE)
155 switch (TREE_CODE (type))
157 case BOOLEAN_TYPE:
158 case ENUMERAL_TYPE:
159 case INTEGER_TYPE:
160 return fold_build1 (NOP_EXPR, pointer_sized_int_node, t);
161 case REAL_TYPE:
163 tree itype = build_nonstandard_integer_type (bitsize, true);
164 t = fold_build1 (VIEW_CONVERT_EXPR, itype, t);
165 return fold_convert (pointer_sized_int_node, t);
167 default:
168 gcc_unreachable ();
170 else
172 if (!DECL_P (t) || !TREE_ADDRESSABLE (t))
174 /* The reason for this is that we don't want to pessimize
175 code by making vars unnecessarily addressable. */
176 tree var = create_tmp_var (type);
177 tree tem = build2 (MODIFY_EXPR, void_type_node, var, t);
178 if (in_expand_p)
180 rtx mem
181 = assign_stack_temp_for_type (TYPE_MODE (type),
182 GET_MODE_SIZE (TYPE_MODE (type)),
183 type);
184 SET_DECL_RTL (var, mem);
185 expand_assignment (var, t, false);
186 return build_fold_addr_expr (var);
188 t = build_fold_addr_expr (var);
189 return build2 (COMPOUND_EXPR, TREE_TYPE (t), tem, t);
191 else
192 return build_fold_addr_expr (t);
196 /* Cached ubsan_get_type_descriptor_type () return value. */
197 static GTY(()) tree ubsan_type_descriptor_type;
199 /* Build
200 struct __ubsan_type_descriptor
202 unsigned short __typekind;
203 unsigned short __typeinfo;
204 char __typename[];
206 type. */
208 static tree
209 ubsan_get_type_descriptor_type (void)
211 static const char *field_names[3]
212 = { "__typekind", "__typeinfo", "__typename" };
213 tree fields[3], ret;
215 if (ubsan_type_descriptor_type)
216 return ubsan_type_descriptor_type;
218 tree itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
219 tree flex_arr_type = build_array_type (char_type_node, itype);
221 ret = make_node (RECORD_TYPE);
222 for (int i = 0; i < 3; i++)
224 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
225 get_identifier (field_names[i]),
226 (i == 2) ? flex_arr_type
227 : short_unsigned_type_node);
228 DECL_CONTEXT (fields[i]) = ret;
229 if (i)
230 DECL_CHAIN (fields[i - 1]) = fields[i];
232 tree type_decl = build_decl (input_location, TYPE_DECL,
233 get_identifier ("__ubsan_type_descriptor"),
234 ret);
235 DECL_IGNORED_P (type_decl) = 1;
236 DECL_ARTIFICIAL (type_decl) = 1;
237 TYPE_FIELDS (ret) = fields[0];
238 TYPE_NAME (ret) = type_decl;
239 TYPE_STUB_DECL (ret) = type_decl;
240 layout_type (ret);
241 ubsan_type_descriptor_type = ret;
242 return ret;
245 /* Cached ubsan_get_source_location_type () return value. */
246 static GTY(()) tree ubsan_source_location_type;
248 /* Build
249 struct __ubsan_source_location
251 const char *__filename;
252 unsigned int __line;
253 unsigned int __column;
255 type. */
257 tree
258 ubsan_get_source_location_type (void)
260 static const char *field_names[3]
261 = { "__filename", "__line", "__column" };
262 tree fields[3], ret;
263 if (ubsan_source_location_type)
264 return ubsan_source_location_type;
266 tree const_char_type = build_qualified_type (char_type_node,
267 TYPE_QUAL_CONST);
269 ret = make_node (RECORD_TYPE);
270 for (int i = 0; i < 3; i++)
272 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
273 get_identifier (field_names[i]),
274 (i == 0) ? build_pointer_type (const_char_type)
275 : unsigned_type_node);
276 DECL_CONTEXT (fields[i]) = ret;
277 if (i)
278 DECL_CHAIN (fields[i - 1]) = fields[i];
280 tree type_decl = build_decl (input_location, TYPE_DECL,
281 get_identifier ("__ubsan_source_location"),
282 ret);
283 DECL_IGNORED_P (type_decl) = 1;
284 DECL_ARTIFICIAL (type_decl) = 1;
285 TYPE_FIELDS (ret) = fields[0];
286 TYPE_NAME (ret) = type_decl;
287 TYPE_STUB_DECL (ret) = type_decl;
288 layout_type (ret);
289 ubsan_source_location_type = ret;
290 return ret;
293 /* Helper routine that returns a CONSTRUCTOR of __ubsan_source_location
294 type with its fields filled from a location_t LOC. */
296 static tree
297 ubsan_source_location (location_t loc)
299 expanded_location xloc;
300 tree type = ubsan_get_source_location_type ();
302 xloc = expand_location (loc);
303 tree str;
304 if (xloc.file == NULL)
306 str = build_int_cst (ptr_type_node, 0);
307 xloc.line = 0;
308 xloc.column = 0;
310 else
312 /* Fill in the values from LOC. */
313 size_t len = strlen (xloc.file) + 1;
314 str = build_string (len, xloc.file);
315 TREE_TYPE (str) = build_array_type_nelts (char_type_node, len);
316 TREE_READONLY (str) = 1;
317 TREE_STATIC (str) = 1;
318 str = build_fold_addr_expr (str);
320 tree ctor = build_constructor_va (type, 3, NULL_TREE, str, NULL_TREE,
321 build_int_cst (unsigned_type_node,
322 xloc.line), NULL_TREE,
323 build_int_cst (unsigned_type_node,
324 xloc.column));
325 TREE_CONSTANT (ctor) = 1;
326 TREE_STATIC (ctor) = 1;
328 return ctor;
331 /* This routine returns a magic number for TYPE. */
333 static unsigned short
334 get_ubsan_type_info_for_type (tree type)
336 gcc_assert (TYPE_SIZE (type) && tree_fits_uhwi_p (TYPE_SIZE (type)));
337 if (TREE_CODE (type) == REAL_TYPE)
338 return tree_to_uhwi (TYPE_SIZE (type));
339 else if (INTEGRAL_TYPE_P (type))
341 int prec = exact_log2 (tree_to_uhwi (TYPE_SIZE (type)));
342 gcc_assert (prec != -1);
343 return (prec << 1) | !TYPE_UNSIGNED (type);
345 else
346 return 0;
349 /* Helper routine that returns ADDR_EXPR of a VAR_DECL of a type
350 descriptor. It first looks into the hash table; if not found,
351 create the VAR_DECL, put it into the hash table and return the
352 ADDR_EXPR of it. TYPE describes a particular type. PSTYLE is
353 an enum controlling how we want to print the type. */
355 tree
356 ubsan_type_descriptor (tree type, enum ubsan_print_style pstyle)
358 /* See through any typedefs. */
359 type = TYPE_MAIN_VARIANT (type);
361 tree decl = decl_for_type_lookup (type);
362 /* It is possible that some of the earlier created DECLs were found
363 unused, in that case they weren't emitted and varpool_node::get
364 returns NULL node on them. But now we really need them. Thus,
365 renew them here. */
366 if (decl != NULL_TREE && varpool_node::get (decl))
367 return build_fold_addr_expr (decl);
369 tree dtype = ubsan_get_type_descriptor_type ();
370 tree type2 = type;
371 const char *tname = NULL;
372 pretty_printer pretty_name;
373 unsigned char deref_depth = 0;
374 unsigned short tkind, tinfo;
376 /* Get the name of the type, or the name of the pointer type. */
377 if (pstyle == UBSAN_PRINT_POINTER)
379 gcc_assert (POINTER_TYPE_P (type));
380 type2 = TREE_TYPE (type);
382 /* Remove any '*' operators from TYPE. */
383 while (POINTER_TYPE_P (type2))
384 deref_depth++, type2 = TREE_TYPE (type2);
386 if (TREE_CODE (type2) == METHOD_TYPE)
387 type2 = TYPE_METHOD_BASETYPE (type2);
390 /* If an array, get its type. */
391 type2 = strip_array_types (type2);
393 if (pstyle == UBSAN_PRINT_ARRAY)
395 while (POINTER_TYPE_P (type2))
396 deref_depth++, type2 = TREE_TYPE (type2);
399 if (TYPE_NAME (type2) != NULL)
401 if (TREE_CODE (TYPE_NAME (type2)) == IDENTIFIER_NODE)
402 tname = IDENTIFIER_POINTER (TYPE_NAME (type2));
403 else if (DECL_NAME (TYPE_NAME (type2)) != NULL)
404 tname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type2)));
407 if (tname == NULL)
408 /* We weren't able to determine the type name. */
409 tname = "<unknown>";
411 if (pstyle == UBSAN_PRINT_POINTER)
413 pp_printf (&pretty_name, "'%s%s%s%s%s%s%s",
414 TYPE_VOLATILE (type2) ? "volatile " : "",
415 TYPE_READONLY (type2) ? "const " : "",
416 TYPE_RESTRICT (type2) ? "restrict " : "",
417 TYPE_ATOMIC (type2) ? "_Atomic " : "",
418 TREE_CODE (type2) == RECORD_TYPE
419 ? "struct "
420 : TREE_CODE (type2) == UNION_TYPE
421 ? "union " : "", tname,
422 deref_depth == 0 ? "" : " ");
423 while (deref_depth-- > 0)
424 pp_star (&pretty_name);
425 pp_quote (&pretty_name);
427 else if (pstyle == UBSAN_PRINT_ARRAY)
429 /* Pretty print the array dimensions. */
430 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
431 tree t = type;
432 pp_printf (&pretty_name, "'%s ", tname);
433 while (deref_depth-- > 0)
434 pp_star (&pretty_name);
435 while (TREE_CODE (t) == ARRAY_TYPE)
437 pp_left_bracket (&pretty_name);
438 tree dom = TYPE_DOMAIN (t);
439 if (dom && TREE_CODE (TYPE_MAX_VALUE (dom)) == INTEGER_CST)
441 if (tree_fits_uhwi_p (TYPE_MAX_VALUE (dom))
442 && tree_to_uhwi (TYPE_MAX_VALUE (dom)) + 1 != 0)
443 pp_printf (&pretty_name, HOST_WIDE_INT_PRINT_DEC,
444 tree_to_uhwi (TYPE_MAX_VALUE (dom)) + 1);
445 else
446 pp_wide_int (&pretty_name,
447 wi::add (wi::to_widest (TYPE_MAX_VALUE (dom)), 1),
448 TYPE_SIGN (TREE_TYPE (dom)));
450 else
451 /* ??? We can't determine the variable name; print VLA unspec. */
452 pp_star (&pretty_name);
453 pp_right_bracket (&pretty_name);
454 t = TREE_TYPE (t);
456 pp_quote (&pretty_name);
458 /* Save the tree with stripped types. */
459 type = t;
461 else
462 pp_printf (&pretty_name, "'%s'", tname);
464 switch (TREE_CODE (type))
466 case BOOLEAN_TYPE:
467 case ENUMERAL_TYPE:
468 case INTEGER_TYPE:
469 tkind = 0x0000;
470 break;
471 case REAL_TYPE:
472 /* FIXME: libubsan right now only supports float, double and
473 long double type formats. */
474 if (TYPE_MODE (type) == TYPE_MODE (float_type_node)
475 || TYPE_MODE (type) == TYPE_MODE (double_type_node)
476 || TYPE_MODE (type) == TYPE_MODE (long_double_type_node))
477 tkind = 0x0001;
478 else
479 tkind = 0xffff;
480 break;
481 default:
482 tkind = 0xffff;
483 break;
485 tinfo = get_ubsan_type_info_for_type (type);
487 /* Create a new VAR_DECL of type descriptor. */
488 const char *tmp = pp_formatted_text (&pretty_name);
489 size_t len = strlen (tmp) + 1;
490 tree str = build_string (len, tmp);
491 TREE_TYPE (str) = build_array_type_nelts (char_type_node, len);
492 TREE_READONLY (str) = 1;
493 TREE_STATIC (str) = 1;
495 char tmp_name[32];
496 static unsigned int type_var_id_num;
497 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_type", type_var_id_num++);
498 decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name),
499 dtype);
500 TREE_STATIC (decl) = 1;
501 TREE_PUBLIC (decl) = 0;
502 DECL_ARTIFICIAL (decl) = 1;
503 DECL_IGNORED_P (decl) = 1;
504 DECL_EXTERNAL (decl) = 0;
505 DECL_SIZE (decl)
506 = size_binop (PLUS_EXPR, DECL_SIZE (decl), TYPE_SIZE (TREE_TYPE (str)));
507 DECL_SIZE_UNIT (decl)
508 = size_binop (PLUS_EXPR, DECL_SIZE_UNIT (decl),
509 TYPE_SIZE_UNIT (TREE_TYPE (str)));
511 tree ctor = build_constructor_va (dtype, 3, NULL_TREE,
512 build_int_cst (short_unsigned_type_node,
513 tkind), NULL_TREE,
514 build_int_cst (short_unsigned_type_node,
515 tinfo), NULL_TREE, str);
516 TREE_CONSTANT (ctor) = 1;
517 TREE_STATIC (ctor) = 1;
518 DECL_INITIAL (decl) = ctor;
519 varpool_node::finalize_decl (decl);
521 /* Save the VAR_DECL into the hash table. */
522 decl_for_type_insert (type, decl);
524 return build_fold_addr_expr (decl);
527 /* Create a structure for the ubsan library. NAME is a name of the new
528 structure. LOCCNT is number of locations, PLOC points to array of
529 locations. The arguments in ... are of __ubsan_type_descriptor type
530 and there are at most two of them, followed by NULL_TREE, followed
531 by optional extra arguments and another NULL_TREE. */
533 tree
534 ubsan_create_data (const char *name, int loccnt, const location_t *ploc, ...)
536 va_list args;
537 tree ret, t;
538 tree fields[6];
539 vec<tree, va_gc> *saved_args = NULL;
540 size_t i = 0;
541 int j;
543 /* Firstly, create a pointer to type descriptor type. */
544 tree td_type = ubsan_get_type_descriptor_type ();
545 td_type = build_pointer_type (td_type);
547 /* Create the structure type. */
548 ret = make_node (RECORD_TYPE);
549 for (j = 0; j < loccnt; j++)
551 gcc_checking_assert (i < 2);
552 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
553 ubsan_get_source_location_type ());
554 DECL_CONTEXT (fields[i]) = ret;
555 if (i)
556 DECL_CHAIN (fields[i - 1]) = fields[i];
557 i++;
560 va_start (args, ploc);
561 for (t = va_arg (args, tree); t != NULL_TREE;
562 i++, t = va_arg (args, tree))
564 gcc_checking_assert (i < 4);
565 /* Save the tree arguments for later use. */
566 vec_safe_push (saved_args, t);
567 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
568 td_type);
569 DECL_CONTEXT (fields[i]) = ret;
570 if (i)
571 DECL_CHAIN (fields[i - 1]) = fields[i];
574 for (t = va_arg (args, tree); t != NULL_TREE;
575 i++, t = va_arg (args, tree))
577 gcc_checking_assert (i < 6);
578 /* Save the tree arguments for later use. */
579 vec_safe_push (saved_args, t);
580 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
581 TREE_TYPE (t));
582 DECL_CONTEXT (fields[i]) = ret;
583 if (i)
584 DECL_CHAIN (fields[i - 1]) = fields[i];
586 va_end (args);
588 tree type_decl = build_decl (input_location, TYPE_DECL,
589 get_identifier (name), ret);
590 DECL_IGNORED_P (type_decl) = 1;
591 DECL_ARTIFICIAL (type_decl) = 1;
592 TYPE_FIELDS (ret) = fields[0];
593 TYPE_NAME (ret) = type_decl;
594 TYPE_STUB_DECL (ret) = type_decl;
595 layout_type (ret);
597 /* Now, fill in the type. */
598 char tmp_name[32];
599 static unsigned int ubsan_var_id_num;
600 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_data", ubsan_var_id_num++);
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_type = TREE_TYPE (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 (orig_index_type),
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 = force_gimple_operand_gsi (gsi, ubsan_encode_value (index),
734 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 = (flag_sanitize & SANITIZE_NULL) != 0;
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 = PROB_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 = REG_BR_PROB_BASE - PROB_VERY_UNLIKELY;
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 = PROB_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 = REG_BR_PROB_BASE - PROB_VERY_UNLIKELY;
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::ges_p (wi::to_widest (offset), -OBJSZ_MAX_OFFSET)
946 && wi::les_p (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::ges_p (wi::to_widest (offset), 0)
963 && wi::les_p (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 /* Cached __ubsan_vptr_type_cache decl. */
1037 static GTY(()) tree ubsan_vptr_type_cache_decl;
1039 /* Expand UBSAN_VPTR internal call. The type is kept on the ckind
1040 argument which is a constant, because the middle-end treats pointer
1041 conversions as useless and therefore the type of the first argument
1042 could be changed to any other pointer type. */
1044 bool
1045 ubsan_expand_vptr_ifn (gimple_stmt_iterator *gsip)
1047 gimple_stmt_iterator gsi = *gsip;
1048 gimple stmt = gsi_stmt (gsi);
1049 location_t loc = gimple_location (stmt);
1050 gcc_assert (gimple_call_num_args (stmt) == 5);
1051 tree op = gimple_call_arg (stmt, 0);
1052 tree vptr = gimple_call_arg (stmt, 1);
1053 tree str_hash = gimple_call_arg (stmt, 2);
1054 tree ti_decl_addr = gimple_call_arg (stmt, 3);
1055 tree ckind_tree = gimple_call_arg (stmt, 4);
1056 ubsan_null_ckind ckind = (ubsan_null_ckind) tree_to_uhwi (ckind_tree);
1057 tree type = TREE_TYPE (TREE_TYPE (ckind_tree));
1058 gimple g;
1059 basic_block fallthru_bb = NULL;
1061 if (ckind == UBSAN_DOWNCAST_POINTER)
1063 /* Guard everything with if (op != NULL) { ... }. */
1064 basic_block then_bb;
1065 gimple_stmt_iterator cond_insert_point
1066 = create_cond_insert_point (gsip, false, false, true,
1067 &then_bb, &fallthru_bb);
1068 g = gimple_build_cond (NE_EXPR, op, build_zero_cst (TREE_TYPE (op)),
1069 NULL_TREE, NULL_TREE);
1070 gimple_set_location (g, loc);
1071 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
1072 *gsip = gsi_after_labels (then_bb);
1073 gsi_remove (&gsi, false);
1074 gsi_insert_before (gsip, stmt, GSI_NEW_STMT);
1075 gsi = *gsip;
1078 tree htype = TREE_TYPE (str_hash);
1079 tree cst = wide_int_to_tree (htype,
1080 wi::uhwi (((uint64_t) 0x9ddfea08 << 32)
1081 | 0xeb382d69, 64));
1082 g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1083 vptr, str_hash);
1084 gimple_set_location (g, loc);
1085 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1086 g = gimple_build_assign (make_ssa_name (htype), MULT_EXPR,
1087 gimple_assign_lhs (g), cst);
1088 gimple_set_location (g, loc);
1089 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1090 tree t1 = gimple_assign_lhs (g);
1091 g = gimple_build_assign (make_ssa_name (htype), LSHIFT_EXPR,
1092 t1, build_int_cst (integer_type_node, 47));
1093 gimple_set_location (g, loc);
1094 tree t2 = gimple_assign_lhs (g);
1095 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1096 g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1097 vptr, t1);
1098 gimple_set_location (g, loc);
1099 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1100 g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1101 t2, gimple_assign_lhs (g));
1102 gimple_set_location (g, loc);
1103 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1104 g = gimple_build_assign (make_ssa_name (htype), MULT_EXPR,
1105 gimple_assign_lhs (g), cst);
1106 gimple_set_location (g, loc);
1107 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1108 tree t3 = gimple_assign_lhs (g);
1109 g = gimple_build_assign (make_ssa_name (htype), LSHIFT_EXPR,
1110 t3, build_int_cst (integer_type_node, 47));
1111 gimple_set_location (g, loc);
1112 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1113 g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1114 t3, gimple_assign_lhs (g));
1115 gimple_set_location (g, loc);
1116 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1117 g = gimple_build_assign (make_ssa_name (htype), MULT_EXPR,
1118 gimple_assign_lhs (g), cst);
1119 gimple_set_location (g, loc);
1120 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1121 if (!useless_type_conversion_p (pointer_sized_int_node, htype))
1123 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
1124 NOP_EXPR, gimple_assign_lhs (g));
1125 gimple_set_location (g, loc);
1126 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1128 tree hash = gimple_assign_lhs (g);
1130 if (ubsan_vptr_type_cache_decl == NULL_TREE)
1132 tree atype = build_array_type_nelts (pointer_sized_int_node, 128);
1133 tree array = build_decl (UNKNOWN_LOCATION, VAR_DECL,
1134 get_identifier ("__ubsan_vptr_type_cache"),
1135 atype);
1136 DECL_ARTIFICIAL (array) = 1;
1137 DECL_IGNORED_P (array) = 1;
1138 TREE_PUBLIC (array) = 1;
1139 TREE_STATIC (array) = 1;
1140 DECL_EXTERNAL (array) = 1;
1141 DECL_VISIBILITY (array) = VISIBILITY_DEFAULT;
1142 DECL_VISIBILITY_SPECIFIED (array) = 1;
1143 varpool_node::finalize_decl (array);
1144 ubsan_vptr_type_cache_decl = array;
1147 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
1148 BIT_AND_EXPR, hash,
1149 build_int_cst (pointer_sized_int_node, 127));
1150 gimple_set_location (g, loc);
1151 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1153 tree c = build4_loc (loc, ARRAY_REF, pointer_sized_int_node,
1154 ubsan_vptr_type_cache_decl, gimple_assign_lhs (g),
1155 NULL_TREE, NULL_TREE);
1156 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
1157 ARRAY_REF, c);
1158 gimple_set_location (g, loc);
1159 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1161 basic_block then_bb, fallthru2_bb;
1162 gimple_stmt_iterator cond_insert_point
1163 = create_cond_insert_point (gsip, false, false, true,
1164 &then_bb, &fallthru2_bb);
1165 g = gimple_build_cond (NE_EXPR, gimple_assign_lhs (g), hash,
1166 NULL_TREE, NULL_TREE);
1167 gimple_set_location (g, loc);
1168 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
1169 *gsip = gsi_after_labels (then_bb);
1170 if (fallthru_bb == NULL)
1171 fallthru_bb = fallthru2_bb;
1173 tree data
1174 = ubsan_create_data ("__ubsan_vptr_data", 1, &loc,
1175 ubsan_type_descriptor (type), NULL_TREE, ti_decl_addr,
1176 build_int_cst (unsigned_char_type_node, ckind),
1177 NULL_TREE);
1178 data = build_fold_addr_expr_loc (loc, data);
1179 enum built_in_function bcode
1180 = (flag_sanitize_recover & SANITIZE_VPTR)
1181 ? BUILT_IN_UBSAN_HANDLE_DYNAMIC_TYPE_CACHE_MISS
1182 : BUILT_IN_UBSAN_HANDLE_DYNAMIC_TYPE_CACHE_MISS_ABORT;
1184 g = gimple_build_call (builtin_decl_explicit (bcode), 3, data, op, hash);
1185 gimple_set_location (g, loc);
1186 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1188 /* Point GSI to next logical statement. */
1189 *gsip = gsi_start_bb (fallthru_bb);
1191 /* Get rid of the UBSAN_VPTR call from the IR. */
1192 unlink_stmt_vdef (stmt);
1193 gsi_remove (&gsi, true);
1194 return true;
1197 /* Instrument a memory reference. BASE is the base of MEM, IS_LHS says
1198 whether the pointer is on the left hand side of the assignment. */
1200 static void
1201 instrument_mem_ref (tree mem, tree base, gimple_stmt_iterator *iter,
1202 bool is_lhs)
1204 enum ubsan_null_ckind ikind = is_lhs ? UBSAN_STORE_OF : UBSAN_LOAD_OF;
1205 unsigned int align = 0;
1206 if (flag_sanitize & SANITIZE_ALIGNMENT)
1208 align = min_align_of_type (TREE_TYPE (base));
1209 if (align <= 1)
1210 align = 0;
1212 if (align == 0 && (flag_sanitize & SANITIZE_NULL) == 0)
1213 return;
1214 tree t = TREE_OPERAND (base, 0);
1215 if (!POINTER_TYPE_P (TREE_TYPE (t)))
1216 return;
1217 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (base)) && mem != base)
1218 ikind = UBSAN_MEMBER_ACCESS;
1219 tree kind = build_int_cst (build_pointer_type (TREE_TYPE (base)), ikind);
1220 tree alignt = build_int_cst (pointer_sized_int_node, align);
1221 gcall *g = gimple_build_call_internal (IFN_UBSAN_NULL, 3, t, kind, alignt);
1222 gimple_set_location (g, gimple_location (gsi_stmt (*iter)));
1223 gsi_insert_before (iter, g, GSI_SAME_STMT);
1226 /* Perform the pointer instrumentation. */
1228 static void
1229 instrument_null (gimple_stmt_iterator gsi, bool is_lhs)
1231 gimple stmt = gsi_stmt (gsi);
1232 tree t = is_lhs ? gimple_get_lhs (stmt) : gimple_assign_rhs1 (stmt);
1233 tree base = get_base_address (t);
1234 const enum tree_code code = TREE_CODE (base);
1235 if (code == MEM_REF
1236 && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
1237 instrument_mem_ref (t, base, &gsi, is_lhs);
1240 /* Build an ubsan builtin call for the signed-integer-overflow
1241 sanitization. CODE says what kind of builtin are we building,
1242 LOC is a location, LHSTYPE is the type of LHS, OP0 and OP1
1243 are operands of the binary operation. */
1245 tree
1246 ubsan_build_overflow_builtin (tree_code code, location_t loc, tree lhstype,
1247 tree op0, tree op1)
1249 if (flag_sanitize_undefined_trap_on_error)
1250 return build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
1252 tree data = ubsan_create_data ("__ubsan_overflow_data", 1, &loc,
1253 ubsan_type_descriptor (lhstype), NULL_TREE,
1254 NULL_TREE);
1255 enum built_in_function fn_code;
1257 switch (code)
1259 case PLUS_EXPR:
1260 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1261 ? BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW
1262 : BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW_ABORT;
1263 break;
1264 case MINUS_EXPR:
1265 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1266 ? BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW
1267 : BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW_ABORT;
1268 break;
1269 case MULT_EXPR:
1270 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1271 ? BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW
1272 : BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW_ABORT;
1273 break;
1274 case NEGATE_EXPR:
1275 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1276 ? BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW
1277 : BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW_ABORT;
1278 break;
1279 default:
1280 gcc_unreachable ();
1282 tree fn = builtin_decl_explicit (fn_code);
1283 return build_call_expr_loc (loc, fn, 2 + (code != NEGATE_EXPR),
1284 build_fold_addr_expr_loc (loc, data),
1285 ubsan_encode_value (op0, true),
1286 op1 ? ubsan_encode_value (op1, true)
1287 : NULL_TREE);
1290 /* Perform the signed integer instrumentation. GSI is the iterator
1291 pointing at statement we are trying to instrument. */
1293 static void
1294 instrument_si_overflow (gimple_stmt_iterator gsi)
1296 gimple stmt = gsi_stmt (gsi);
1297 tree_code code = gimple_assign_rhs_code (stmt);
1298 tree lhs = gimple_assign_lhs (stmt);
1299 tree lhstype = TREE_TYPE (lhs);
1300 tree a, b;
1301 gimple g;
1303 /* If this is not a signed operation, don't instrument anything here.
1304 Also punt on bit-fields. */
1305 if (!INTEGRAL_TYPE_P (lhstype)
1306 || TYPE_OVERFLOW_WRAPS (lhstype)
1307 || GET_MODE_BITSIZE (TYPE_MODE (lhstype)) != TYPE_PRECISION (lhstype))
1308 return;
1310 switch (code)
1312 case MINUS_EXPR:
1313 case PLUS_EXPR:
1314 case MULT_EXPR:
1315 /* Transform
1316 i = u {+,-,*} 5;
1317 into
1318 i = UBSAN_CHECK_{ADD,SUB,MUL} (u, 5); */
1319 a = gimple_assign_rhs1 (stmt);
1320 b = gimple_assign_rhs2 (stmt);
1321 g = gimple_build_call_internal (code == PLUS_EXPR
1322 ? IFN_UBSAN_CHECK_ADD
1323 : code == MINUS_EXPR
1324 ? IFN_UBSAN_CHECK_SUB
1325 : IFN_UBSAN_CHECK_MUL, 2, a, b);
1326 gimple_call_set_lhs (g, lhs);
1327 gsi_replace (&gsi, g, false);
1328 break;
1329 case NEGATE_EXPR:
1330 /* Represent i = -u;
1332 i = UBSAN_CHECK_SUB (0, u); */
1333 a = build_int_cst (lhstype, 0);
1334 b = gimple_assign_rhs1 (stmt);
1335 g = gimple_build_call_internal (IFN_UBSAN_CHECK_SUB, 2, a, b);
1336 gimple_call_set_lhs (g, lhs);
1337 gsi_replace (&gsi, g, false);
1338 break;
1339 case ABS_EXPR:
1340 /* Transform i = ABS_EXPR<u>;
1341 into
1342 _N = UBSAN_CHECK_SUB (0, u);
1343 i = ABS_EXPR<_N>; */
1344 a = build_int_cst (lhstype, 0);
1345 b = gimple_assign_rhs1 (stmt);
1346 g = gimple_build_call_internal (IFN_UBSAN_CHECK_SUB, 2, a, b);
1347 a = make_ssa_name (lhstype);
1348 gimple_call_set_lhs (g, a);
1349 gimple_set_location (g, gimple_location (stmt));
1350 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
1351 gimple_assign_set_rhs1 (stmt, a);
1352 update_stmt (stmt);
1353 break;
1354 default:
1355 break;
1359 /* Instrument loads from (non-bitfield) bool and C++ enum values
1360 to check if the memory value is outside of the range of the valid
1361 type values. */
1363 static void
1364 instrument_bool_enum_load (gimple_stmt_iterator *gsi)
1366 gimple stmt = gsi_stmt (*gsi);
1367 tree rhs = gimple_assign_rhs1 (stmt);
1368 tree type = TREE_TYPE (rhs);
1369 tree minv = NULL_TREE, maxv = NULL_TREE;
1371 if (TREE_CODE (type) == BOOLEAN_TYPE && (flag_sanitize & SANITIZE_BOOL))
1373 minv = boolean_false_node;
1374 maxv = boolean_true_node;
1376 else if (TREE_CODE (type) == ENUMERAL_TYPE
1377 && (flag_sanitize & SANITIZE_ENUM)
1378 && TREE_TYPE (type) != NULL_TREE
1379 && TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE
1380 && (TYPE_PRECISION (TREE_TYPE (type))
1381 < GET_MODE_PRECISION (TYPE_MODE (type))))
1383 minv = TYPE_MIN_VALUE (TREE_TYPE (type));
1384 maxv = TYPE_MAX_VALUE (TREE_TYPE (type));
1386 else
1387 return;
1389 int modebitsize = GET_MODE_BITSIZE (TYPE_MODE (type));
1390 HOST_WIDE_INT bitsize, bitpos;
1391 tree offset;
1392 machine_mode mode;
1393 int volatilep = 0, unsignedp = 0;
1394 tree base = get_inner_reference (rhs, &bitsize, &bitpos, &offset, &mode,
1395 &unsignedp, &volatilep, false);
1396 tree utype = build_nonstandard_integer_type (modebitsize, 1);
1398 if ((TREE_CODE (base) == VAR_DECL && DECL_HARD_REGISTER (base))
1399 || (bitpos % modebitsize) != 0
1400 || bitsize != modebitsize
1401 || GET_MODE_BITSIZE (TYPE_MODE (utype)) != modebitsize
1402 || TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME)
1403 return;
1405 bool ends_bb = stmt_ends_bb_p (stmt);
1406 location_t loc = gimple_location (stmt);
1407 tree lhs = gimple_assign_lhs (stmt);
1408 tree ptype = build_pointer_type (TREE_TYPE (rhs));
1409 tree atype = reference_alias_ptr_type (rhs);
1410 gimple g = gimple_build_assign (make_ssa_name (ptype),
1411 build_fold_addr_expr (rhs));
1412 gimple_set_location (g, loc);
1413 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1414 tree mem = build2 (MEM_REF, utype, gimple_assign_lhs (g),
1415 build_int_cst (atype, 0));
1416 tree urhs = make_ssa_name (utype);
1417 if (ends_bb)
1419 gimple_assign_set_lhs (stmt, urhs);
1420 g = gimple_build_assign (lhs, NOP_EXPR, urhs);
1421 gimple_set_location (g, loc);
1422 edge e = find_fallthru_edge (gimple_bb (stmt)->succs);
1423 gsi_insert_on_edge_immediate (e, g);
1424 gimple_assign_set_rhs_from_tree (gsi, mem);
1425 update_stmt (stmt);
1426 *gsi = gsi_for_stmt (g);
1427 g = stmt;
1429 else
1431 g = gimple_build_assign (urhs, mem);
1432 gimple_set_location (g, loc);
1433 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1435 minv = fold_convert (utype, minv);
1436 maxv = fold_convert (utype, maxv);
1437 if (!integer_zerop (minv))
1439 g = gimple_build_assign (make_ssa_name (utype), MINUS_EXPR, urhs, minv);
1440 gimple_set_location (g, loc);
1441 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1444 gimple_stmt_iterator gsi2 = *gsi;
1445 basic_block then_bb, fallthru_bb;
1446 *gsi = create_cond_insert_point (gsi, true, false, true,
1447 &then_bb, &fallthru_bb);
1448 g = gimple_build_cond (GT_EXPR, gimple_assign_lhs (g),
1449 int_const_binop (MINUS_EXPR, maxv, minv),
1450 NULL_TREE, NULL_TREE);
1451 gimple_set_location (g, loc);
1452 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1454 if (!ends_bb)
1456 gimple_assign_set_rhs_with_ops (&gsi2, NOP_EXPR, urhs);
1457 update_stmt (stmt);
1460 gsi2 = gsi_after_labels (then_bb);
1461 if (flag_sanitize_undefined_trap_on_error)
1462 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1463 else
1465 tree data = ubsan_create_data ("__ubsan_invalid_value_data", 1, &loc,
1466 ubsan_type_descriptor (type), NULL_TREE,
1467 NULL_TREE);
1468 data = build_fold_addr_expr_loc (loc, data);
1469 enum built_in_function bcode
1470 = (flag_sanitize_recover & (TREE_CODE (type) == BOOLEAN_TYPE
1471 ? SANITIZE_BOOL : SANITIZE_ENUM))
1472 ? BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE
1473 : BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE_ABORT;
1474 tree fn = builtin_decl_explicit (bcode);
1476 tree val = force_gimple_operand_gsi (&gsi2, ubsan_encode_value (urhs),
1477 true, NULL_TREE, true,
1478 GSI_SAME_STMT);
1479 g = gimple_build_call (fn, 2, data, val);
1481 gimple_set_location (g, loc);
1482 gsi_insert_before (&gsi2, g, GSI_SAME_STMT);
1483 ubsan_create_edge (g);
1484 *gsi = gsi_for_stmt (stmt);
1487 /* Instrument float point-to-integer conversion. TYPE is an integer type of
1488 destination, EXPR is floating-point expression. ARG is what to pass
1489 the libubsan call as value, often EXPR itself. */
1491 tree
1492 ubsan_instrument_float_cast (location_t loc, tree type, tree expr, tree arg)
1494 tree expr_type = TREE_TYPE (expr);
1495 tree t, tt, fn, min, max;
1496 machine_mode mode = TYPE_MODE (expr_type);
1497 int prec = TYPE_PRECISION (type);
1498 bool uns_p = TYPE_UNSIGNED (type);
1500 /* Float to integer conversion first truncates toward zero, so
1501 even signed char c = 127.875f; is not problematic.
1502 Therefore, we should complain only if EXPR is unordered or smaller
1503 or equal than TYPE_MIN_VALUE - 1.0 or greater or equal than
1504 TYPE_MAX_VALUE + 1.0. */
1505 if (REAL_MODE_FORMAT (mode)->b == 2)
1507 /* For maximum, TYPE_MAX_VALUE might not be representable
1508 in EXPR_TYPE, e.g. if TYPE is 64-bit long long and
1509 EXPR_TYPE is IEEE single float, but TYPE_MAX_VALUE + 1.0 is
1510 either representable or infinity. */
1511 REAL_VALUE_TYPE maxval = dconst1;
1512 SET_REAL_EXP (&maxval, REAL_EXP (&maxval) + prec - !uns_p);
1513 real_convert (&maxval, mode, &maxval);
1514 max = build_real (expr_type, maxval);
1516 /* For unsigned, assume -1.0 is always representable. */
1517 if (uns_p)
1518 min = build_minus_one_cst (expr_type);
1519 else
1521 /* TYPE_MIN_VALUE is generally representable (or -inf),
1522 but TYPE_MIN_VALUE - 1.0 might not be. */
1523 REAL_VALUE_TYPE minval = dconstm1, minval2;
1524 SET_REAL_EXP (&minval, REAL_EXP (&minval) + prec - 1);
1525 real_convert (&minval, mode, &minval);
1526 real_arithmetic (&minval2, MINUS_EXPR, &minval, &dconst1);
1527 real_convert (&minval2, mode, &minval2);
1528 if (real_compare (EQ_EXPR, &minval, &minval2)
1529 && !real_isinf (&minval))
1531 /* If TYPE_MIN_VALUE - 1.0 is not representable and
1532 rounds to TYPE_MIN_VALUE, we need to subtract
1533 more. As REAL_MODE_FORMAT (mode)->p is the number
1534 of base digits, we want to subtract a number that
1535 will be 1 << (REAL_MODE_FORMAT (mode)->p - 1)
1536 times smaller than minval. */
1537 minval2 = dconst1;
1538 gcc_assert (prec > REAL_MODE_FORMAT (mode)->p);
1539 SET_REAL_EXP (&minval2,
1540 REAL_EXP (&minval2) + prec - 1
1541 - REAL_MODE_FORMAT (mode)->p + 1);
1542 real_arithmetic (&minval2, MINUS_EXPR, &minval, &minval2);
1543 real_convert (&minval2, mode, &minval2);
1545 min = build_real (expr_type, minval2);
1548 else if (REAL_MODE_FORMAT (mode)->b == 10)
1550 /* For _Decimal128 up to 34 decimal digits, - sign,
1551 dot, e, exponent. */
1552 char buf[64];
1553 mpfr_t m;
1554 int p = REAL_MODE_FORMAT (mode)->p;
1555 REAL_VALUE_TYPE maxval, minval;
1557 /* Use mpfr_snprintf rounding to compute the smallest
1558 representable decimal number greater or equal than
1559 1 << (prec - !uns_p). */
1560 mpfr_init2 (m, prec + 2);
1561 mpfr_set_ui_2exp (m, 1, prec - !uns_p, GMP_RNDN);
1562 mpfr_snprintf (buf, sizeof buf, "%.*RUe", p - 1, m);
1563 decimal_real_from_string (&maxval, buf);
1564 max = build_real (expr_type, maxval);
1566 /* For unsigned, assume -1.0 is always representable. */
1567 if (uns_p)
1568 min = build_minus_one_cst (expr_type);
1569 else
1571 /* Use mpfr_snprintf rounding to compute the largest
1572 representable decimal number less or equal than
1573 (-1 << (prec - 1)) - 1. */
1574 mpfr_set_si_2exp (m, -1, prec - 1, GMP_RNDN);
1575 mpfr_sub_ui (m, m, 1, GMP_RNDN);
1576 mpfr_snprintf (buf, sizeof buf, "%.*RDe", p - 1, m);
1577 decimal_real_from_string (&minval, buf);
1578 min = build_real (expr_type, minval);
1580 mpfr_clear (m);
1582 else
1583 return NULL_TREE;
1585 t = fold_build2 (UNLE_EXPR, boolean_type_node, expr, min);
1586 tt = fold_build2 (UNGE_EXPR, boolean_type_node, expr, max);
1587 t = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t, tt);
1588 if (integer_zerop (t))
1589 return NULL_TREE;
1591 if (flag_sanitize_undefined_trap_on_error)
1592 fn = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
1593 else
1595 /* Create the __ubsan_handle_float_cast_overflow fn call. */
1596 tree data = ubsan_create_data ("__ubsan_float_cast_overflow_data", 0,
1597 NULL, ubsan_type_descriptor (expr_type),
1598 ubsan_type_descriptor (type), NULL_TREE,
1599 NULL_TREE);
1600 enum built_in_function bcode
1601 = (flag_sanitize_recover & SANITIZE_FLOAT_CAST)
1602 ? BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW
1603 : BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW_ABORT;
1604 fn = builtin_decl_explicit (bcode);
1605 fn = build_call_expr_loc (loc, fn, 2,
1606 build_fold_addr_expr_loc (loc, data),
1607 ubsan_encode_value (arg, false));
1610 return fold_build3 (COND_EXPR, void_type_node, t, fn, integer_zero_node);
1613 /* Instrument values passed to function arguments with nonnull attribute. */
1615 static void
1616 instrument_nonnull_arg (gimple_stmt_iterator *gsi)
1618 gimple stmt = gsi_stmt (*gsi);
1619 location_t loc[2];
1620 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
1621 while for nonnull sanitization it is clear. */
1622 int save_flag_delete_null_pointer_checks = flag_delete_null_pointer_checks;
1623 flag_delete_null_pointer_checks = 1;
1624 loc[0] = gimple_location (stmt);
1625 loc[1] = UNKNOWN_LOCATION;
1626 for (unsigned int i = 0; i < gimple_call_num_args (stmt); i++)
1628 tree arg = gimple_call_arg (stmt, i);
1629 if (POINTER_TYPE_P (TREE_TYPE (arg))
1630 && infer_nonnull_range (stmt, arg, false, true))
1632 gimple g;
1633 if (!is_gimple_val (arg))
1635 g = gimple_build_assign (make_ssa_name (TREE_TYPE (arg)), arg);
1636 gimple_set_location (g, loc[0]);
1637 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1638 arg = gimple_assign_lhs (g);
1641 basic_block then_bb, fallthru_bb;
1642 *gsi = create_cond_insert_point (gsi, true, false, true,
1643 &then_bb, &fallthru_bb);
1644 g = gimple_build_cond (EQ_EXPR, arg,
1645 build_zero_cst (TREE_TYPE (arg)),
1646 NULL_TREE, NULL_TREE);
1647 gimple_set_location (g, loc[0]);
1648 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1650 *gsi = gsi_after_labels (then_bb);
1651 if (flag_sanitize_undefined_trap_on_error)
1652 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1653 else
1655 tree data = ubsan_create_data ("__ubsan_nonnull_arg_data",
1656 2, loc, NULL_TREE,
1657 build_int_cst (integer_type_node,
1658 i + 1),
1659 NULL_TREE);
1660 data = build_fold_addr_expr_loc (loc[0], data);
1661 enum built_in_function bcode
1662 = (flag_sanitize_recover & SANITIZE_NONNULL_ATTRIBUTE)
1663 ? BUILT_IN_UBSAN_HANDLE_NONNULL_ARG
1664 : BUILT_IN_UBSAN_HANDLE_NONNULL_ARG_ABORT;
1665 tree fn = builtin_decl_explicit (bcode);
1667 g = gimple_build_call (fn, 1, data);
1669 gimple_set_location (g, loc[0]);
1670 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1671 ubsan_create_edge (g);
1673 *gsi = gsi_for_stmt (stmt);
1675 flag_delete_null_pointer_checks = save_flag_delete_null_pointer_checks;
1678 /* Instrument returns in functions with returns_nonnull attribute. */
1680 static void
1681 instrument_nonnull_return (gimple_stmt_iterator *gsi)
1683 greturn *stmt = as_a <greturn *> (gsi_stmt (*gsi));
1684 location_t loc[2];
1685 tree arg = gimple_return_retval (stmt);
1686 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
1687 while for nonnull return sanitization it is clear. */
1688 int save_flag_delete_null_pointer_checks = flag_delete_null_pointer_checks;
1689 flag_delete_null_pointer_checks = 1;
1690 loc[0] = gimple_location (stmt);
1691 loc[1] = UNKNOWN_LOCATION;
1692 if (arg
1693 && POINTER_TYPE_P (TREE_TYPE (arg))
1694 && is_gimple_val (arg)
1695 && infer_nonnull_range (stmt, arg, false, true))
1697 basic_block then_bb, fallthru_bb;
1698 *gsi = create_cond_insert_point (gsi, true, false, true,
1699 &then_bb, &fallthru_bb);
1700 gimple g = gimple_build_cond (EQ_EXPR, arg,
1701 build_zero_cst (TREE_TYPE (arg)),
1702 NULL_TREE, NULL_TREE);
1703 gimple_set_location (g, loc[0]);
1704 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1706 *gsi = gsi_after_labels (then_bb);
1707 if (flag_sanitize_undefined_trap_on_error)
1708 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1709 else
1711 tree data = ubsan_create_data ("__ubsan_nonnull_return_data",
1712 2, loc, NULL_TREE, NULL_TREE);
1713 data = build_fold_addr_expr_loc (loc[0], data);
1714 enum built_in_function bcode
1715 = (flag_sanitize_recover & SANITIZE_RETURNS_NONNULL_ATTRIBUTE)
1716 ? BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN
1717 : BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_ABORT;
1718 tree fn = builtin_decl_explicit (bcode);
1720 g = gimple_build_call (fn, 1, data);
1722 gimple_set_location (g, loc[0]);
1723 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1724 ubsan_create_edge (g);
1725 *gsi = gsi_for_stmt (stmt);
1727 flag_delete_null_pointer_checks = save_flag_delete_null_pointer_checks;
1730 /* Instrument memory references. Here we check whether the pointer
1731 points to an out-of-bounds location. */
1733 static void
1734 instrument_object_size (gimple_stmt_iterator *gsi, bool is_lhs)
1736 gimple stmt = gsi_stmt (*gsi);
1737 location_t loc = gimple_location (stmt);
1738 tree t = is_lhs ? gimple_get_lhs (stmt) : gimple_assign_rhs1 (stmt);
1739 tree type;
1740 tree index = NULL_TREE;
1741 HOST_WIDE_INT size_in_bytes;
1743 type = TREE_TYPE (t);
1744 if (VOID_TYPE_P (type))
1745 return;
1747 switch (TREE_CODE (t))
1749 case COMPONENT_REF:
1750 if (TREE_CODE (t) == COMPONENT_REF
1751 && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1)) != NULL_TREE)
1753 tree repr = DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1));
1754 t = build3 (COMPONENT_REF, TREE_TYPE (repr), TREE_OPERAND (t, 0),
1755 repr, NULL_TREE);
1757 break;
1758 case ARRAY_REF:
1759 index = TREE_OPERAND (t, 1);
1760 break;
1761 case INDIRECT_REF:
1762 case MEM_REF:
1763 case VAR_DECL:
1764 case PARM_DECL:
1765 case RESULT_DECL:
1766 break;
1767 default:
1768 return;
1771 size_in_bytes = int_size_in_bytes (type);
1772 if (size_in_bytes <= 0)
1773 return;
1775 HOST_WIDE_INT bitsize, bitpos;
1776 tree offset;
1777 machine_mode mode;
1778 int volatilep = 0, unsignedp = 0;
1779 tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset, &mode,
1780 &unsignedp, &volatilep, false);
1782 if (bitpos % BITS_PER_UNIT != 0
1783 || bitsize != size_in_bytes * BITS_PER_UNIT)
1784 return;
1786 bool decl_p = DECL_P (inner);
1787 tree base;
1788 if (decl_p)
1789 base = inner;
1790 else if (TREE_CODE (inner) == MEM_REF)
1791 base = TREE_OPERAND (inner, 0);
1792 else
1793 return;
1794 tree ptr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (t)), t);
1796 while (TREE_CODE (base) == SSA_NAME)
1798 gimple def_stmt = SSA_NAME_DEF_STMT (base);
1799 if (gimple_assign_ssa_name_copy_p (def_stmt)
1800 || (gimple_assign_cast_p (def_stmt)
1801 && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (def_stmt))))
1802 || (is_gimple_assign (def_stmt)
1803 && gimple_assign_rhs_code (def_stmt) == POINTER_PLUS_EXPR))
1805 tree rhs1 = gimple_assign_rhs1 (def_stmt);
1806 if (TREE_CODE (rhs1) == SSA_NAME
1807 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs1))
1808 break;
1809 else
1810 base = rhs1;
1812 else
1813 break;
1816 if (!POINTER_TYPE_P (TREE_TYPE (base)) && !DECL_P (base))
1817 return;
1819 tree sizet;
1820 tree base_addr = base;
1821 gimple bos_stmt = NULL;
1822 if (decl_p)
1823 base_addr = build1 (ADDR_EXPR,
1824 build_pointer_type (TREE_TYPE (base)), base);
1825 unsigned HOST_WIDE_INT size = compute_builtin_object_size (base_addr, 0);
1826 if (size != (unsigned HOST_WIDE_INT) -1)
1827 sizet = build_int_cst (sizetype, size);
1828 else if (optimize)
1830 if (LOCATION_LOCUS (loc) == UNKNOWN_LOCATION)
1831 loc = input_location;
1832 /* Generate __builtin_object_size call. */
1833 sizet = builtin_decl_explicit (BUILT_IN_OBJECT_SIZE);
1834 sizet = build_call_expr_loc (loc, sizet, 2, base_addr,
1835 integer_zero_node);
1836 sizet = force_gimple_operand_gsi (gsi, sizet, false, NULL_TREE, true,
1837 GSI_SAME_STMT);
1838 /* If the call above didn't end up being an integer constant, go one
1839 statement back and get the __builtin_object_size stmt. Save it,
1840 we might need it later. */
1841 if (SSA_VAR_P (sizet))
1843 gsi_prev (gsi);
1844 bos_stmt = gsi_stmt (*gsi);
1846 /* Move on to where we were. */
1847 gsi_next (gsi);
1850 else
1851 return;
1853 /* Generate UBSAN_OBJECT_SIZE (ptr, ptr+sizeof(*ptr)-base, objsize, ckind)
1854 call. */
1855 /* ptr + sizeof (*ptr) - base */
1856 t = fold_build2 (MINUS_EXPR, sizetype,
1857 fold_convert (pointer_sized_int_node, ptr),
1858 fold_convert (pointer_sized_int_node, base_addr));
1859 t = fold_build2 (PLUS_EXPR, sizetype, t, TYPE_SIZE_UNIT (type));
1861 /* Perhaps we can omit the check. */
1862 if (TREE_CODE (t) == INTEGER_CST
1863 && TREE_CODE (sizet) == INTEGER_CST
1864 && tree_int_cst_le (t, sizet))
1865 return;
1867 if (index != NULL_TREE
1868 && TREE_CODE (index) == SSA_NAME
1869 && TREE_CODE (sizet) == INTEGER_CST)
1871 gimple def = SSA_NAME_DEF_STMT (index);
1872 if (is_gimple_assign (def)
1873 && gimple_assign_rhs_code (def) == BIT_AND_EXPR
1874 && TREE_CODE (gimple_assign_rhs2 (def)) == INTEGER_CST)
1876 tree cst = gimple_assign_rhs2 (def);
1877 tree sz = fold_build2 (EXACT_DIV_EXPR, sizetype, sizet,
1878 TYPE_SIZE_UNIT (type));
1879 if (tree_int_cst_sgn (cst) >= 0
1880 && tree_int_cst_lt (cst, sz))
1881 return;
1885 if (bos_stmt && gimple_call_builtin_p (bos_stmt, BUILT_IN_OBJECT_SIZE))
1886 ubsan_create_edge (bos_stmt);
1888 /* We have to emit the check. */
1889 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE, true,
1890 GSI_SAME_STMT);
1891 ptr = force_gimple_operand_gsi (gsi, ptr, true, NULL_TREE, true,
1892 GSI_SAME_STMT);
1893 tree ckind = build_int_cst (unsigned_char_type_node,
1894 is_lhs ? UBSAN_STORE_OF : UBSAN_LOAD_OF);
1895 gimple g = gimple_build_call_internal (IFN_UBSAN_OBJECT_SIZE, 4,
1896 ptr, t, sizet, ckind);
1897 gimple_set_location (g, loc);
1898 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1901 /* True if we want to play UBSan games in the current function. */
1903 bool
1904 do_ubsan_in_current_function ()
1906 return (current_function_decl != NULL_TREE
1907 && !lookup_attribute ("no_sanitize_undefined",
1908 DECL_ATTRIBUTES (current_function_decl)));
1911 namespace {
1913 const pass_data pass_data_ubsan =
1915 GIMPLE_PASS, /* type */
1916 "ubsan", /* name */
1917 OPTGROUP_NONE, /* optinfo_flags */
1918 TV_TREE_UBSAN, /* tv_id */
1919 ( PROP_cfg | PROP_ssa ), /* properties_required */
1920 0, /* properties_provided */
1921 0, /* properties_destroyed */
1922 0, /* todo_flags_start */
1923 TODO_update_ssa, /* todo_flags_finish */
1926 class pass_ubsan : public gimple_opt_pass
1928 public:
1929 pass_ubsan (gcc::context *ctxt)
1930 : gimple_opt_pass (pass_data_ubsan, ctxt)
1933 /* opt_pass methods: */
1934 virtual bool gate (function *)
1936 return flag_sanitize & (SANITIZE_NULL | SANITIZE_SI_OVERFLOW
1937 | SANITIZE_BOOL | SANITIZE_ENUM
1938 | SANITIZE_ALIGNMENT
1939 | SANITIZE_NONNULL_ATTRIBUTE
1940 | SANITIZE_RETURNS_NONNULL_ATTRIBUTE
1941 | SANITIZE_OBJECT_SIZE)
1942 && do_ubsan_in_current_function ();
1945 virtual unsigned int execute (function *);
1947 }; // class pass_ubsan
1949 unsigned int
1950 pass_ubsan::execute (function *fun)
1952 basic_block bb;
1953 gimple_stmt_iterator gsi;
1955 initialize_sanitizer_builtins ();
1957 FOR_EACH_BB_FN (bb, fun)
1959 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
1961 gimple stmt = gsi_stmt (gsi);
1962 if (is_gimple_debug (stmt) || gimple_clobber_p (stmt))
1964 gsi_next (&gsi);
1965 continue;
1968 if ((flag_sanitize & SANITIZE_SI_OVERFLOW)
1969 && is_gimple_assign (stmt))
1970 instrument_si_overflow (gsi);
1972 if (flag_sanitize & (SANITIZE_NULL | SANITIZE_ALIGNMENT))
1974 if (gimple_store_p (stmt))
1975 instrument_null (gsi, true);
1976 if (gimple_assign_load_p (stmt))
1977 instrument_null (gsi, false);
1980 if (flag_sanitize & (SANITIZE_BOOL | SANITIZE_ENUM)
1981 && gimple_assign_load_p (stmt))
1983 instrument_bool_enum_load (&gsi);
1984 bb = gimple_bb (stmt);
1987 if ((flag_sanitize & SANITIZE_NONNULL_ATTRIBUTE)
1988 && is_gimple_call (stmt)
1989 && !gimple_call_internal_p (stmt))
1991 instrument_nonnull_arg (&gsi);
1992 bb = gimple_bb (stmt);
1995 if ((flag_sanitize & SANITIZE_RETURNS_NONNULL_ATTRIBUTE)
1996 && gimple_code (stmt) == GIMPLE_RETURN)
1998 instrument_nonnull_return (&gsi);
1999 bb = gimple_bb (stmt);
2002 if (flag_sanitize & SANITIZE_OBJECT_SIZE)
2004 if (gimple_store_p (stmt))
2005 instrument_object_size (&gsi, true);
2006 if (gimple_assign_load_p (stmt))
2007 instrument_object_size (&gsi, false);
2010 gsi_next (&gsi);
2013 return 0;
2016 } // anon namespace
2018 gimple_opt_pass *
2019 make_pass_ubsan (gcc::context *ctxt)
2021 return new pass_ubsan (ctxt);
2024 #include "gt-ubsan.h"