* include/bits/alloc_traits.h (__alloctr_rebind): Remove.
[official-gcc.git] / gcc / ubsan.c
blob19eafabe8d922f4e9dd0364edc8de802296fd48f
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 "tm.h"
37 #include "hard-reg-set.h"
38 #include "function.h"
39 #include "cgraph.h"
40 #include "tree-pass.h"
41 #include "tree-ssa-alias.h"
42 #include "tree-pretty-print.h"
43 #include "internal-fn.h"
44 #include "gimple-expr.h"
45 #include "gimple.h"
46 #include "gimple-iterator.h"
47 #include "gimple-ssa.h"
48 #include "gimple-walk.h"
49 #include "output.h"
50 #include "tm_p.h"
51 #include "toplev.h"
52 #include "cfgloop.h"
53 #include "ubsan.h"
54 #include "c-family/c-common.h"
55 #include "rtl.h"
56 #include "flags.h"
57 #include "insn-config.h"
58 #include "expmed.h"
59 #include "dojump.h"
60 #include "explow.h"
61 #include "calls.h"
62 #include "emit-rtl.h"
63 #include "varasm.h"
64 #include "stmt.h"
65 #include "expr.h"
66 #include "tree-ssanames.h"
67 #include "asan.h"
68 #include "gimplify-me.h"
69 #include "intl.h"
70 #include "realmpfr.h"
71 #include "dfp.h"
72 #include "builtins.h"
73 #include "tree-object-size.h"
74 #include "tree-eh.h"
75 #include "tree-cfg.h"
77 /* Map from a tree to a VAR_DECL tree. */
79 struct GTY((for_user)) tree_type_map {
80 struct tree_map_base type;
81 tree decl;
84 struct tree_type_map_cache_hasher : ggc_cache_ptr_hash<tree_type_map>
86 static inline hashval_t
87 hash (tree_type_map *t)
89 return TYPE_UID (t->type.from);
92 static inline bool
93 equal (tree_type_map *a, tree_type_map *b)
95 return a->type.from == b->type.from;
98 static int
99 keep_cache_entry (tree_type_map *&m)
101 return ggc_marked_p (m->type.from);
105 static GTY ((cache))
106 hash_table<tree_type_map_cache_hasher> *decl_tree_for_type;
108 /* Lookup a VAR_DECL for TYPE, and return it if we find one. */
110 static tree
111 decl_for_type_lookup (tree type)
113 /* If the hash table is not initialized yet, create it now. */
114 if (decl_tree_for_type == NULL)
116 decl_tree_for_type
117 = hash_table<tree_type_map_cache_hasher>::create_ggc (10);
118 /* That also means we don't have to bother with the lookup. */
119 return NULL_TREE;
122 struct tree_type_map *h, in;
123 in.type.from = type;
125 h = decl_tree_for_type->find_with_hash (&in, TYPE_UID (type));
126 return h ? h->decl : NULL_TREE;
129 /* Insert a mapping TYPE->DECL in the VAR_DECL for type hashtable. */
131 static void
132 decl_for_type_insert (tree type, tree decl)
134 struct tree_type_map *h;
136 h = ggc_alloc<tree_type_map> ();
137 h->type.from = type;
138 h->decl = decl;
139 *decl_tree_for_type->find_slot_with_hash (h, TYPE_UID (type), INSERT) = h;
142 /* Helper routine, which encodes a value in the pointer_sized_int_node.
143 Arguments with precision <= POINTER_SIZE are passed directly,
144 the rest is passed by reference. T is a value we are to encode.
145 IN_EXPAND_P is true if this function is called during expansion. */
147 tree
148 ubsan_encode_value (tree t, bool in_expand_p)
150 tree type = TREE_TYPE (t);
151 const unsigned int bitsize = GET_MODE_BITSIZE (TYPE_MODE (type));
152 if (bitsize <= POINTER_SIZE)
153 switch (TREE_CODE (type))
155 case BOOLEAN_TYPE:
156 case ENUMERAL_TYPE:
157 case INTEGER_TYPE:
158 return fold_build1 (NOP_EXPR, pointer_sized_int_node, t);
159 case REAL_TYPE:
161 tree itype = build_nonstandard_integer_type (bitsize, true);
162 t = fold_build1 (VIEW_CONVERT_EXPR, itype, t);
163 return fold_convert (pointer_sized_int_node, t);
165 default:
166 gcc_unreachable ();
168 else
170 if (!DECL_P (t) || !TREE_ADDRESSABLE (t))
172 /* The reason for this is that we don't want to pessimize
173 code by making vars unnecessarily addressable. */
174 tree var = create_tmp_var (type);
175 tree tem = build2 (MODIFY_EXPR, void_type_node, var, t);
176 if (in_expand_p)
178 rtx mem
179 = assign_stack_temp_for_type (TYPE_MODE (type),
180 GET_MODE_SIZE (TYPE_MODE (type)),
181 type);
182 SET_DECL_RTL (var, mem);
183 expand_assignment (var, t, false);
184 return build_fold_addr_expr (var);
186 t = build_fold_addr_expr (var);
187 return build2 (COMPOUND_EXPR, TREE_TYPE (t), tem, t);
189 else
190 return build_fold_addr_expr (t);
194 /* Cached ubsan_get_type_descriptor_type () return value. */
195 static GTY(()) tree ubsan_type_descriptor_type;
197 /* Build
198 struct __ubsan_type_descriptor
200 unsigned short __typekind;
201 unsigned short __typeinfo;
202 char __typename[];
204 type. */
206 static tree
207 ubsan_get_type_descriptor_type (void)
209 static const char *field_names[3]
210 = { "__typekind", "__typeinfo", "__typename" };
211 tree fields[3], ret;
213 if (ubsan_type_descriptor_type)
214 return ubsan_type_descriptor_type;
216 tree itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
217 tree flex_arr_type = build_array_type (char_type_node, itype);
219 ret = make_node (RECORD_TYPE);
220 for (int i = 0; i < 3; i++)
222 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
223 get_identifier (field_names[i]),
224 (i == 2) ? flex_arr_type
225 : short_unsigned_type_node);
226 DECL_CONTEXT (fields[i]) = ret;
227 if (i)
228 DECL_CHAIN (fields[i - 1]) = fields[i];
230 tree type_decl = build_decl (input_location, TYPE_DECL,
231 get_identifier ("__ubsan_type_descriptor"),
232 ret);
233 DECL_IGNORED_P (type_decl) = 1;
234 DECL_ARTIFICIAL (type_decl) = 1;
235 TYPE_FIELDS (ret) = fields[0];
236 TYPE_NAME (ret) = type_decl;
237 TYPE_STUB_DECL (ret) = type_decl;
238 layout_type (ret);
239 ubsan_type_descriptor_type = ret;
240 return ret;
243 /* Cached ubsan_get_source_location_type () return value. */
244 static GTY(()) tree ubsan_source_location_type;
246 /* Build
247 struct __ubsan_source_location
249 const char *__filename;
250 unsigned int __line;
251 unsigned int __column;
253 type. */
255 tree
256 ubsan_get_source_location_type (void)
258 static const char *field_names[3]
259 = { "__filename", "__line", "__column" };
260 tree fields[3], ret;
261 if (ubsan_source_location_type)
262 return ubsan_source_location_type;
264 tree const_char_type = build_qualified_type (char_type_node,
265 TYPE_QUAL_CONST);
267 ret = make_node (RECORD_TYPE);
268 for (int i = 0; i < 3; i++)
270 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
271 get_identifier (field_names[i]),
272 (i == 0) ? build_pointer_type (const_char_type)
273 : unsigned_type_node);
274 DECL_CONTEXT (fields[i]) = ret;
275 if (i)
276 DECL_CHAIN (fields[i - 1]) = fields[i];
278 tree type_decl = build_decl (input_location, TYPE_DECL,
279 get_identifier ("__ubsan_source_location"),
280 ret);
281 DECL_IGNORED_P (type_decl) = 1;
282 DECL_ARTIFICIAL (type_decl) = 1;
283 TYPE_FIELDS (ret) = fields[0];
284 TYPE_NAME (ret) = type_decl;
285 TYPE_STUB_DECL (ret) = type_decl;
286 layout_type (ret);
287 ubsan_source_location_type = ret;
288 return ret;
291 /* Helper routine that returns a CONSTRUCTOR of __ubsan_source_location
292 type with its fields filled from a location_t LOC. */
294 static tree
295 ubsan_source_location (location_t loc)
297 expanded_location xloc;
298 tree type = ubsan_get_source_location_type ();
300 xloc = expand_location (loc);
301 tree str;
302 if (xloc.file == NULL)
304 str = build_int_cst (ptr_type_node, 0);
305 xloc.line = 0;
306 xloc.column = 0;
308 else
310 /* Fill in the values from LOC. */
311 size_t len = strlen (xloc.file) + 1;
312 str = build_string (len, xloc.file);
313 TREE_TYPE (str) = build_array_type_nelts (char_type_node, len);
314 TREE_READONLY (str) = 1;
315 TREE_STATIC (str) = 1;
316 str = build_fold_addr_expr (str);
318 tree ctor = build_constructor_va (type, 3, NULL_TREE, str, NULL_TREE,
319 build_int_cst (unsigned_type_node,
320 xloc.line), NULL_TREE,
321 build_int_cst (unsigned_type_node,
322 xloc.column));
323 TREE_CONSTANT (ctor) = 1;
324 TREE_STATIC (ctor) = 1;
326 return ctor;
329 /* This routine returns a magic number for TYPE. */
331 static unsigned short
332 get_ubsan_type_info_for_type (tree type)
334 gcc_assert (TYPE_SIZE (type) && tree_fits_uhwi_p (TYPE_SIZE (type)));
335 if (TREE_CODE (type) == REAL_TYPE)
336 return tree_to_uhwi (TYPE_SIZE (type));
337 else if (INTEGRAL_TYPE_P (type))
339 int prec = exact_log2 (tree_to_uhwi (TYPE_SIZE (type)));
340 gcc_assert (prec != -1);
341 return (prec << 1) | !TYPE_UNSIGNED (type);
343 else
344 return 0;
347 /* Helper routine that returns ADDR_EXPR of a VAR_DECL of a type
348 descriptor. It first looks into the hash table; if not found,
349 create the VAR_DECL, put it into the hash table and return the
350 ADDR_EXPR of it. TYPE describes a particular type. PSTYLE is
351 an enum controlling how we want to print the type. */
353 tree
354 ubsan_type_descriptor (tree type, enum ubsan_print_style pstyle)
356 /* See through any typedefs. */
357 type = TYPE_MAIN_VARIANT (type);
359 tree decl = decl_for_type_lookup (type);
360 /* It is possible that some of the earlier created DECLs were found
361 unused, in that case they weren't emitted and varpool_node::get
362 returns NULL node on them. But now we really need them. Thus,
363 renew them here. */
364 if (decl != NULL_TREE && varpool_node::get (decl))
365 return build_fold_addr_expr (decl);
367 tree dtype = ubsan_get_type_descriptor_type ();
368 tree type2 = type;
369 const char *tname = NULL;
370 pretty_printer pretty_name;
371 unsigned char deref_depth = 0;
372 unsigned short tkind, tinfo;
374 /* Get the name of the type, or the name of the pointer type. */
375 if (pstyle == UBSAN_PRINT_POINTER)
377 gcc_assert (POINTER_TYPE_P (type));
378 type2 = TREE_TYPE (type);
380 /* Remove any '*' operators from TYPE. */
381 while (POINTER_TYPE_P (type2))
382 deref_depth++, type2 = TREE_TYPE (type2);
384 if (TREE_CODE (type2) == METHOD_TYPE)
385 type2 = TYPE_METHOD_BASETYPE (type2);
388 /* If an array, get its type. */
389 type2 = strip_array_types (type2);
391 if (pstyle == UBSAN_PRINT_ARRAY)
393 while (POINTER_TYPE_P (type2))
394 deref_depth++, type2 = TREE_TYPE (type2);
397 if (TYPE_NAME (type2) != NULL)
399 if (TREE_CODE (TYPE_NAME (type2)) == IDENTIFIER_NODE)
400 tname = IDENTIFIER_POINTER (TYPE_NAME (type2));
401 else if (DECL_NAME (TYPE_NAME (type2)) != NULL)
402 tname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type2)));
405 if (tname == NULL)
406 /* We weren't able to determine the type name. */
407 tname = "<unknown>";
409 if (pstyle == UBSAN_PRINT_POINTER)
411 pp_printf (&pretty_name, "'%s%s%s%s%s%s%s",
412 TYPE_VOLATILE (type2) ? "volatile " : "",
413 TYPE_READONLY (type2) ? "const " : "",
414 TYPE_RESTRICT (type2) ? "restrict " : "",
415 TYPE_ATOMIC (type2) ? "_Atomic " : "",
416 TREE_CODE (type2) == RECORD_TYPE
417 ? "struct "
418 : TREE_CODE (type2) == UNION_TYPE
419 ? "union " : "", tname,
420 deref_depth == 0 ? "" : " ");
421 while (deref_depth-- > 0)
422 pp_star (&pretty_name);
423 pp_quote (&pretty_name);
425 else if (pstyle == UBSAN_PRINT_ARRAY)
427 /* Pretty print the array dimensions. */
428 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
429 tree t = type;
430 pp_printf (&pretty_name, "'%s ", tname);
431 while (deref_depth-- > 0)
432 pp_star (&pretty_name);
433 while (TREE_CODE (t) == ARRAY_TYPE)
435 pp_left_bracket (&pretty_name);
436 tree dom = TYPE_DOMAIN (t);
437 if (dom && TREE_CODE (TYPE_MAX_VALUE (dom)) == INTEGER_CST)
439 if (tree_fits_uhwi_p (TYPE_MAX_VALUE (dom))
440 && tree_to_uhwi (TYPE_MAX_VALUE (dom)) + 1 != 0)
441 pp_printf (&pretty_name, HOST_WIDE_INT_PRINT_DEC,
442 tree_to_uhwi (TYPE_MAX_VALUE (dom)) + 1);
443 else
444 pp_wide_int (&pretty_name,
445 wi::add (wi::to_widest (TYPE_MAX_VALUE (dom)), 1),
446 TYPE_SIGN (TREE_TYPE (dom)));
448 else
449 /* ??? We can't determine the variable name; print VLA unspec. */
450 pp_star (&pretty_name);
451 pp_right_bracket (&pretty_name);
452 t = TREE_TYPE (t);
454 pp_quote (&pretty_name);
456 /* Save the tree with stripped types. */
457 type = t;
459 else
460 pp_printf (&pretty_name, "'%s'", tname);
462 switch (TREE_CODE (type))
464 case BOOLEAN_TYPE:
465 case ENUMERAL_TYPE:
466 case INTEGER_TYPE:
467 tkind = 0x0000;
468 break;
469 case REAL_TYPE:
470 /* FIXME: libubsan right now only supports float, double and
471 long double type formats. */
472 if (TYPE_MODE (type) == TYPE_MODE (float_type_node)
473 || TYPE_MODE (type) == TYPE_MODE (double_type_node)
474 || TYPE_MODE (type) == TYPE_MODE (long_double_type_node))
475 tkind = 0x0001;
476 else
477 tkind = 0xffff;
478 break;
479 default:
480 tkind = 0xffff;
481 break;
483 tinfo = get_ubsan_type_info_for_type (type);
485 /* Create a new VAR_DECL of type descriptor. */
486 const char *tmp = pp_formatted_text (&pretty_name);
487 size_t len = strlen (tmp) + 1;
488 tree str = build_string (len, tmp);
489 TREE_TYPE (str) = build_array_type_nelts (char_type_node, len);
490 TREE_READONLY (str) = 1;
491 TREE_STATIC (str) = 1;
493 char tmp_name[32];
494 static unsigned int type_var_id_num;
495 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_type", type_var_id_num++);
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 /* Firstly, create a pointer to type descriptor type. */
542 tree td_type = ubsan_get_type_descriptor_type ();
543 td_type = build_pointer_type (td_type);
545 /* Create the structure type. */
546 ret = make_node (RECORD_TYPE);
547 for (j = 0; j < loccnt; j++)
549 gcc_checking_assert (i < 2);
550 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
551 ubsan_get_source_location_type ());
552 DECL_CONTEXT (fields[i]) = ret;
553 if (i)
554 DECL_CHAIN (fields[i - 1]) = fields[i];
555 i++;
558 va_start (args, ploc);
559 for (t = va_arg (args, tree); t != NULL_TREE;
560 i++, t = va_arg (args, tree))
562 gcc_checking_assert (i < 4);
563 /* Save the tree arguments for later use. */
564 vec_safe_push (saved_args, t);
565 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
566 td_type);
567 DECL_CONTEXT (fields[i]) = ret;
568 if (i)
569 DECL_CHAIN (fields[i - 1]) = fields[i];
572 for (t = va_arg (args, tree); t != NULL_TREE;
573 i++, t = va_arg (args, tree))
575 gcc_checking_assert (i < 6);
576 /* Save the tree arguments for later use. */
577 vec_safe_push (saved_args, t);
578 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
579 TREE_TYPE (t));
580 DECL_CONTEXT (fields[i]) = ret;
581 if (i)
582 DECL_CHAIN (fields[i - 1]) = fields[i];
584 va_end (args);
586 tree type_decl = build_decl (input_location, TYPE_DECL,
587 get_identifier (name), ret);
588 DECL_IGNORED_P (type_decl) = 1;
589 DECL_ARTIFICIAL (type_decl) = 1;
590 TYPE_FIELDS (ret) = fields[0];
591 TYPE_NAME (ret) = type_decl;
592 TYPE_STUB_DECL (ret) = type_decl;
593 layout_type (ret);
595 /* Now, fill in the type. */
596 char tmp_name[32];
597 static unsigned int ubsan_var_id_num;
598 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_data", ubsan_var_id_num++);
599 tree var = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name),
600 ret);
601 TREE_STATIC (var) = 1;
602 TREE_PUBLIC (var) = 0;
603 DECL_ARTIFICIAL (var) = 1;
604 DECL_IGNORED_P (var) = 1;
605 DECL_EXTERNAL (var) = 0;
607 vec<constructor_elt, va_gc> *v;
608 vec_alloc (v, i);
609 tree ctor = build_constructor (ret, v);
611 /* If desirable, set the __ubsan_source_location element. */
612 for (j = 0; j < loccnt; j++)
614 location_t loc = LOCATION_LOCUS (ploc[j]);
615 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, ubsan_source_location (loc));
618 size_t nelts = vec_safe_length (saved_args);
619 for (i = 0; i < nelts; i++)
621 t = (*saved_args)[i];
622 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, t);
625 TREE_CONSTANT (ctor) = 1;
626 TREE_STATIC (ctor) = 1;
627 DECL_INITIAL (var) = ctor;
628 varpool_node::finalize_decl (var);
630 return var;
633 /* Instrument the __builtin_unreachable call. We just call the libubsan
634 routine instead. */
636 bool
637 ubsan_instrument_unreachable (gimple_stmt_iterator *gsi)
639 gimple g;
640 location_t loc = gimple_location (gsi_stmt (*gsi));
642 if (flag_sanitize_undefined_trap_on_error)
643 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
644 else
646 tree data = ubsan_create_data ("__ubsan_unreachable_data", 1, &loc,
647 NULL_TREE, NULL_TREE);
648 data = build_fold_addr_expr_loc (loc, data);
649 tree fn
650 = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE);
651 g = gimple_build_call (fn, 1, data);
653 gimple_set_location (g, loc);
654 gsi_replace (gsi, g, false);
655 return false;
658 /* Return true if T is a call to a libubsan routine. */
660 bool
661 is_ubsan_builtin_p (tree t)
663 return TREE_CODE (t) == FUNCTION_DECL
664 && DECL_BUILT_IN_CLASS (t) == BUILT_IN_NORMAL
665 && strncmp (IDENTIFIER_POINTER (DECL_NAME (t)),
666 "__builtin___ubsan_", 18) == 0;
669 /* Create a callgraph edge for statement STMT. */
671 static void
672 ubsan_create_edge (gimple stmt)
674 gcall *call_stmt = dyn_cast <gcall *> (stmt);
675 basic_block bb = gimple_bb (stmt);
676 int freq = compute_call_stmt_bb_frequency (current_function_decl, bb);
677 cgraph_node *node = cgraph_node::get (current_function_decl);
678 tree decl = gimple_call_fndecl (call_stmt);
679 if (decl)
680 node->create_edge (cgraph_node::get_create (decl), call_stmt, bb->count,
681 freq);
684 /* Expand the UBSAN_BOUNDS special builtin function. */
686 bool
687 ubsan_expand_bounds_ifn (gimple_stmt_iterator *gsi)
689 gimple stmt = gsi_stmt (*gsi);
690 location_t loc = gimple_location (stmt);
691 gcc_assert (gimple_call_num_args (stmt) == 3);
693 /* Pick up the arguments of the UBSAN_BOUNDS call. */
694 tree type = TREE_TYPE (TREE_TYPE (gimple_call_arg (stmt, 0)));
695 tree index = gimple_call_arg (stmt, 1);
696 tree orig_index_type = TREE_TYPE (index);
697 tree bound = gimple_call_arg (stmt, 2);
699 gimple_stmt_iterator gsi_orig = *gsi;
701 /* Create condition "if (index > bound)". */
702 basic_block then_bb, fallthru_bb;
703 gimple_stmt_iterator cond_insert_point
704 = create_cond_insert_point (gsi, false, false, true,
705 &then_bb, &fallthru_bb);
706 index = fold_convert (TREE_TYPE (bound), index);
707 index = force_gimple_operand_gsi (&cond_insert_point, index,
708 true, NULL_TREE,
709 false, GSI_NEW_STMT);
710 gimple g = gimple_build_cond (GT_EXPR, index, bound, NULL_TREE, NULL_TREE);
711 gimple_set_location (g, loc);
712 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
714 /* Generate __ubsan_handle_out_of_bounds call. */
715 *gsi = gsi_after_labels (then_bb);
716 if (flag_sanitize_undefined_trap_on_error)
717 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
718 else
720 tree data
721 = ubsan_create_data ("__ubsan_out_of_bounds_data", 1, &loc,
722 ubsan_type_descriptor (type, UBSAN_PRINT_ARRAY),
723 ubsan_type_descriptor (orig_index_type),
724 NULL_TREE, NULL_TREE);
725 data = build_fold_addr_expr_loc (loc, data);
726 enum built_in_function bcode
727 = (flag_sanitize_recover & SANITIZE_BOUNDS)
728 ? BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS
729 : BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS_ABORT;
730 tree fn = builtin_decl_explicit (bcode);
731 tree val = force_gimple_operand_gsi (gsi, ubsan_encode_value (index),
732 true, NULL_TREE, true,
733 GSI_SAME_STMT);
734 g = gimple_build_call (fn, 2, data, val);
736 gimple_set_location (g, loc);
737 gsi_insert_before (gsi, g, GSI_SAME_STMT);
739 /* Get rid of the UBSAN_BOUNDS call from the IR. */
740 unlink_stmt_vdef (stmt);
741 gsi_remove (&gsi_orig, true);
743 /* Point GSI to next logical statement. */
744 *gsi = gsi_start_bb (fallthru_bb);
745 return true;
748 /* Expand UBSAN_NULL internal call. The type is kept on the ckind
749 argument which is a constant, because the middle-end treats pointer
750 conversions as useless and therefore the type of the first argument
751 could be changed to any other pointer type. */
753 bool
754 ubsan_expand_null_ifn (gimple_stmt_iterator *gsip)
756 gimple_stmt_iterator gsi = *gsip;
757 gimple stmt = gsi_stmt (gsi);
758 location_t loc = gimple_location (stmt);
759 gcc_assert (gimple_call_num_args (stmt) == 3);
760 tree ptr = gimple_call_arg (stmt, 0);
761 tree ckind = gimple_call_arg (stmt, 1);
762 tree align = gimple_call_arg (stmt, 2);
763 tree check_align = NULL_TREE;
764 bool check_null;
766 basic_block cur_bb = gsi_bb (gsi);
768 gimple g;
769 if (!integer_zerop (align))
771 unsigned int ptralign = get_pointer_alignment (ptr) / BITS_PER_UNIT;
772 if (compare_tree_int (align, ptralign) == 1)
774 check_align = make_ssa_name (pointer_sized_int_node);
775 g = gimple_build_assign (check_align, NOP_EXPR, ptr);
776 gimple_set_location (g, loc);
777 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
780 check_null = (flag_sanitize & SANITIZE_NULL) != 0;
782 if (check_align == NULL_TREE && !check_null)
784 gsi_remove (gsip, true);
785 /* Unlink the UBSAN_NULLs vops before replacing it. */
786 unlink_stmt_vdef (stmt);
787 return true;
790 /* Split the original block holding the pointer dereference. */
791 edge e = split_block (cur_bb, stmt);
793 /* Get a hold on the 'condition block', the 'then block' and the
794 'else block'. */
795 basic_block cond_bb = e->src;
796 basic_block fallthru_bb = e->dest;
797 basic_block then_bb = create_empty_bb (cond_bb);
798 add_bb_to_loop (then_bb, cond_bb->loop_father);
799 loops_state_set (LOOPS_NEED_FIXUP);
801 /* Make an edge coming from the 'cond block' into the 'then block';
802 this edge is unlikely taken, so set up the probability accordingly. */
803 e = make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
804 e->probability = PROB_VERY_UNLIKELY;
806 /* Connect 'then block' with the 'else block'. This is needed
807 as the ubsan routines we call in the 'then block' are not noreturn.
808 The 'then block' only has one outcoming edge. */
809 make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);
811 /* Set up the fallthrough basic block. */
812 e = find_edge (cond_bb, fallthru_bb);
813 e->flags = EDGE_FALSE_VALUE;
814 e->count = cond_bb->count;
815 e->probability = REG_BR_PROB_BASE - PROB_VERY_UNLIKELY;
817 /* Update dominance info for the newly created then_bb; note that
818 fallthru_bb's dominance info has already been updated by
819 split_block. */
820 if (dom_info_available_p (CDI_DOMINATORS))
821 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
823 /* Put the ubsan builtin call into the newly created BB. */
824 if (flag_sanitize_undefined_trap_on_error)
825 g = gimple_build_call (builtin_decl_implicit (BUILT_IN_TRAP), 0);
826 else
828 enum built_in_function bcode
829 = (flag_sanitize_recover & ((check_align ? SANITIZE_ALIGNMENT : 0)
830 | (check_null ? SANITIZE_NULL : 0)))
831 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
832 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT;
833 tree fn = builtin_decl_implicit (bcode);
834 tree data
835 = ubsan_create_data ("__ubsan_null_data", 1, &loc,
836 ubsan_type_descriptor (TREE_TYPE (ckind),
837 UBSAN_PRINT_POINTER),
838 NULL_TREE,
839 align,
840 fold_convert (unsigned_char_type_node, ckind),
841 NULL_TREE);
842 data = build_fold_addr_expr_loc (loc, data);
843 g = gimple_build_call (fn, 2, data,
844 check_align ? check_align
845 : build_zero_cst (pointer_sized_int_node));
847 gimple_stmt_iterator gsi2 = gsi_start_bb (then_bb);
848 gimple_set_location (g, loc);
849 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
851 /* Unlink the UBSAN_NULLs vops before replacing it. */
852 unlink_stmt_vdef (stmt);
854 if (check_null)
856 g = gimple_build_cond (EQ_EXPR, ptr, build_int_cst (TREE_TYPE (ptr), 0),
857 NULL_TREE, NULL_TREE);
858 gimple_set_location (g, loc);
860 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
861 gsi_replace (&gsi, g, false);
862 stmt = g;
865 if (check_align)
867 if (check_null)
869 /* Split the block with the condition again. */
870 e = split_block (cond_bb, stmt);
871 basic_block cond1_bb = e->src;
872 basic_block cond2_bb = e->dest;
874 /* Make an edge coming from the 'cond1 block' into the 'then block';
875 this edge is unlikely taken, so set up the probability
876 accordingly. */
877 e = make_edge (cond1_bb, then_bb, EDGE_TRUE_VALUE);
878 e->probability = PROB_VERY_UNLIKELY;
880 /* Set up the fallthrough basic block. */
881 e = find_edge (cond1_bb, cond2_bb);
882 e->flags = EDGE_FALSE_VALUE;
883 e->count = cond1_bb->count;
884 e->probability = REG_BR_PROB_BASE - PROB_VERY_UNLIKELY;
886 /* Update dominance info. */
887 if (dom_info_available_p (CDI_DOMINATORS))
889 set_immediate_dominator (CDI_DOMINATORS, fallthru_bb, cond1_bb);
890 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond1_bb);
893 gsi2 = gsi_start_bb (cond2_bb);
896 tree mask = build_int_cst (pointer_sized_int_node,
897 tree_to_uhwi (align) - 1);
898 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
899 BIT_AND_EXPR, check_align, mask);
900 gimple_set_location (g, loc);
901 if (check_null)
902 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
903 else
904 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
906 g = gimple_build_cond (NE_EXPR, gimple_assign_lhs (g),
907 build_int_cst (pointer_sized_int_node, 0),
908 NULL_TREE, NULL_TREE);
909 gimple_set_location (g, loc);
910 if (check_null)
911 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
912 else
913 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
914 gsi_replace (&gsi, g, false);
916 return false;
919 #define OBJSZ_MAX_OFFSET (1024 * 16)
921 /* Expand UBSAN_OBJECT_SIZE internal call. */
923 bool
924 ubsan_expand_objsize_ifn (gimple_stmt_iterator *gsi)
926 gimple stmt = gsi_stmt (*gsi);
927 location_t loc = gimple_location (stmt);
928 gcc_assert (gimple_call_num_args (stmt) == 4);
930 tree ptr = gimple_call_arg (stmt, 0);
931 tree offset = gimple_call_arg (stmt, 1);
932 tree size = gimple_call_arg (stmt, 2);
933 tree ckind = gimple_call_arg (stmt, 3);
934 gimple_stmt_iterator gsi_orig = *gsi;
935 gimple g;
937 /* See if we can discard the check. */
938 if (TREE_CODE (size) != INTEGER_CST
939 || integer_all_onesp (size))
940 /* Yes, __builtin_object_size couldn't determine the
941 object size. */;
942 else if (TREE_CODE (offset) == INTEGER_CST
943 && wi::ges_p (wi::to_widest (offset), -OBJSZ_MAX_OFFSET)
944 && wi::les_p (wi::to_widest (offset), -1))
945 /* The offset is in range [-16K, -1]. */;
946 else
948 /* if (offset > objsize) */
949 basic_block then_bb, fallthru_bb;
950 gimple_stmt_iterator cond_insert_point
951 = create_cond_insert_point (gsi, false, false, true,
952 &then_bb, &fallthru_bb);
953 g = gimple_build_cond (GT_EXPR, offset, size, NULL_TREE, NULL_TREE);
954 gimple_set_location (g, loc);
955 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
957 /* If the offset is small enough, we don't need the second
958 run-time check. */
959 if (TREE_CODE (offset) == INTEGER_CST
960 && wi::ges_p (wi::to_widest (offset), 0)
961 && wi::les_p (wi::to_widest (offset), OBJSZ_MAX_OFFSET))
962 *gsi = gsi_after_labels (then_bb);
963 else
965 /* Don't issue run-time error if (ptr > ptr + offset). That
966 may happen when computing a POINTER_PLUS_EXPR. */
967 basic_block then2_bb, fallthru2_bb;
969 gimple_stmt_iterator gsi2 = gsi_after_labels (then_bb);
970 cond_insert_point = create_cond_insert_point (&gsi2, false, false,
971 true, &then2_bb,
972 &fallthru2_bb);
973 /* Convert the pointer to an integer type. */
974 tree p = make_ssa_name (pointer_sized_int_node);
975 g = gimple_build_assign (p, NOP_EXPR, ptr);
976 gimple_set_location (g, loc);
977 gsi_insert_before (&cond_insert_point, g, GSI_NEW_STMT);
978 p = gimple_assign_lhs (g);
979 /* Compute ptr + offset. */
980 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
981 PLUS_EXPR, p, offset);
982 gimple_set_location (g, loc);
983 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
984 /* Now build the conditional and put it into the IR. */
985 g = gimple_build_cond (LE_EXPR, p, gimple_assign_lhs (g),
986 NULL_TREE, NULL_TREE);
987 gimple_set_location (g, loc);
988 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
989 *gsi = gsi_after_labels (then2_bb);
992 /* Generate __ubsan_handle_type_mismatch call. */
993 if (flag_sanitize_undefined_trap_on_error)
994 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
995 else
997 tree data
998 = ubsan_create_data ("__ubsan_objsz_data", 1, &loc,
999 ubsan_type_descriptor (TREE_TYPE (ptr),
1000 UBSAN_PRINT_POINTER),
1001 NULL_TREE,
1002 build_zero_cst (pointer_sized_int_node),
1003 ckind,
1004 NULL_TREE);
1005 data = build_fold_addr_expr_loc (loc, data);
1006 enum built_in_function bcode
1007 = (flag_sanitize_recover & SANITIZE_OBJECT_SIZE)
1008 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
1009 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT;
1010 tree p = make_ssa_name (pointer_sized_int_node);
1011 g = gimple_build_assign (p, NOP_EXPR, ptr);
1012 gimple_set_location (g, loc);
1013 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1014 g = gimple_build_call (builtin_decl_explicit (bcode), 2, data, p);
1016 gimple_set_location (g, loc);
1017 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1019 /* Point GSI to next logical statement. */
1020 *gsi = gsi_start_bb (fallthru_bb);
1022 /* Get rid of the UBSAN_OBJECT_SIZE call from the IR. */
1023 unlink_stmt_vdef (stmt);
1024 gsi_remove (&gsi_orig, true);
1025 return true;
1028 /* Get rid of the UBSAN_OBJECT_SIZE call from the IR. */
1029 unlink_stmt_vdef (stmt);
1030 gsi_remove (gsi, true);
1031 return true;
1034 /* Cached __ubsan_vptr_type_cache decl. */
1035 static GTY(()) tree ubsan_vptr_type_cache_decl;
1037 /* Expand UBSAN_VPTR internal call. The type is kept on the ckind
1038 argument which is a constant, because the middle-end treats pointer
1039 conversions as useless and therefore the type of the first argument
1040 could be changed to any other pointer type. */
1042 bool
1043 ubsan_expand_vptr_ifn (gimple_stmt_iterator *gsip)
1045 gimple_stmt_iterator gsi = *gsip;
1046 gimple stmt = gsi_stmt (gsi);
1047 location_t loc = gimple_location (stmt);
1048 gcc_assert (gimple_call_num_args (stmt) == 5);
1049 tree op = gimple_call_arg (stmt, 0);
1050 tree vptr = gimple_call_arg (stmt, 1);
1051 tree str_hash = gimple_call_arg (stmt, 2);
1052 tree ti_decl_addr = gimple_call_arg (stmt, 3);
1053 tree ckind_tree = gimple_call_arg (stmt, 4);
1054 ubsan_null_ckind ckind = (ubsan_null_ckind) tree_to_uhwi (ckind_tree);
1055 tree type = TREE_TYPE (TREE_TYPE (ckind_tree));
1056 gimple g;
1057 basic_block fallthru_bb = NULL;
1059 if (ckind == UBSAN_DOWNCAST_POINTER)
1061 /* Guard everything with if (op != NULL) { ... }. */
1062 basic_block then_bb;
1063 gimple_stmt_iterator cond_insert_point
1064 = create_cond_insert_point (gsip, false, false, true,
1065 &then_bb, &fallthru_bb);
1066 g = gimple_build_cond (NE_EXPR, op, build_zero_cst (TREE_TYPE (op)),
1067 NULL_TREE, NULL_TREE);
1068 gimple_set_location (g, loc);
1069 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
1070 *gsip = gsi_after_labels (then_bb);
1071 gsi_remove (&gsi, false);
1072 gsi_insert_before (gsip, stmt, GSI_NEW_STMT);
1073 gsi = *gsip;
1076 tree htype = TREE_TYPE (str_hash);
1077 tree cst = wide_int_to_tree (htype,
1078 wi::uhwi (((uint64_t) 0x9ddfea08 << 32)
1079 | 0xeb382d69, 64));
1080 g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1081 vptr, str_hash);
1082 gimple_set_location (g, loc);
1083 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1084 g = gimple_build_assign (make_ssa_name (htype), MULT_EXPR,
1085 gimple_assign_lhs (g), cst);
1086 gimple_set_location (g, loc);
1087 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1088 tree t1 = gimple_assign_lhs (g);
1089 g = gimple_build_assign (make_ssa_name (htype), LSHIFT_EXPR,
1090 t1, build_int_cst (integer_type_node, 47));
1091 gimple_set_location (g, loc);
1092 tree t2 = gimple_assign_lhs (g);
1093 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1094 g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1095 vptr, t1);
1096 gimple_set_location (g, loc);
1097 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1098 g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1099 t2, gimple_assign_lhs (g));
1100 gimple_set_location (g, loc);
1101 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1102 g = gimple_build_assign (make_ssa_name (htype), MULT_EXPR,
1103 gimple_assign_lhs (g), cst);
1104 gimple_set_location (g, loc);
1105 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1106 tree t3 = gimple_assign_lhs (g);
1107 g = gimple_build_assign (make_ssa_name (htype), LSHIFT_EXPR,
1108 t3, build_int_cst (integer_type_node, 47));
1109 gimple_set_location (g, loc);
1110 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1111 g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1112 t3, gimple_assign_lhs (g));
1113 gimple_set_location (g, loc);
1114 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1115 g = gimple_build_assign (make_ssa_name (htype), MULT_EXPR,
1116 gimple_assign_lhs (g), cst);
1117 gimple_set_location (g, loc);
1118 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1119 if (!useless_type_conversion_p (pointer_sized_int_node, htype))
1121 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
1122 NOP_EXPR, gimple_assign_lhs (g));
1123 gimple_set_location (g, loc);
1124 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1126 tree hash = gimple_assign_lhs (g);
1128 if (ubsan_vptr_type_cache_decl == NULL_TREE)
1130 tree atype = build_array_type_nelts (pointer_sized_int_node, 128);
1131 tree array = build_decl (UNKNOWN_LOCATION, VAR_DECL,
1132 get_identifier ("__ubsan_vptr_type_cache"),
1133 atype);
1134 DECL_ARTIFICIAL (array) = 1;
1135 DECL_IGNORED_P (array) = 1;
1136 TREE_PUBLIC (array) = 1;
1137 TREE_STATIC (array) = 1;
1138 DECL_EXTERNAL (array) = 1;
1139 DECL_VISIBILITY (array) = VISIBILITY_DEFAULT;
1140 DECL_VISIBILITY_SPECIFIED (array) = 1;
1141 varpool_node::finalize_decl (array);
1142 ubsan_vptr_type_cache_decl = array;
1145 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
1146 BIT_AND_EXPR, hash,
1147 build_int_cst (pointer_sized_int_node, 127));
1148 gimple_set_location (g, loc);
1149 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1151 tree c = build4_loc (loc, ARRAY_REF, pointer_sized_int_node,
1152 ubsan_vptr_type_cache_decl, gimple_assign_lhs (g),
1153 NULL_TREE, NULL_TREE);
1154 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
1155 ARRAY_REF, c);
1156 gimple_set_location (g, loc);
1157 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1159 basic_block then_bb, fallthru2_bb;
1160 gimple_stmt_iterator cond_insert_point
1161 = create_cond_insert_point (gsip, false, false, true,
1162 &then_bb, &fallthru2_bb);
1163 g = gimple_build_cond (NE_EXPR, gimple_assign_lhs (g), hash,
1164 NULL_TREE, NULL_TREE);
1165 gimple_set_location (g, loc);
1166 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
1167 *gsip = gsi_after_labels (then_bb);
1168 if (fallthru_bb == NULL)
1169 fallthru_bb = fallthru2_bb;
1171 tree data
1172 = ubsan_create_data ("__ubsan_vptr_data", 1, &loc,
1173 ubsan_type_descriptor (type), NULL_TREE, ti_decl_addr,
1174 build_int_cst (unsigned_char_type_node, ckind),
1175 NULL_TREE);
1176 data = build_fold_addr_expr_loc (loc, data);
1177 enum built_in_function bcode
1178 = (flag_sanitize_recover & SANITIZE_VPTR)
1179 ? BUILT_IN_UBSAN_HANDLE_DYNAMIC_TYPE_CACHE_MISS
1180 : BUILT_IN_UBSAN_HANDLE_DYNAMIC_TYPE_CACHE_MISS_ABORT;
1182 g = gimple_build_call (builtin_decl_explicit (bcode), 3, data, op, hash);
1183 gimple_set_location (g, loc);
1184 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1186 /* Point GSI to next logical statement. */
1187 *gsip = gsi_start_bb (fallthru_bb);
1189 /* Get rid of the UBSAN_VPTR call from the IR. */
1190 unlink_stmt_vdef (stmt);
1191 gsi_remove (&gsi, true);
1192 return true;
1195 /* Instrument a memory reference. BASE is the base of MEM, IS_LHS says
1196 whether the pointer is on the left hand side of the assignment. */
1198 static void
1199 instrument_mem_ref (tree mem, tree base, gimple_stmt_iterator *iter,
1200 bool is_lhs)
1202 enum ubsan_null_ckind ikind = is_lhs ? UBSAN_STORE_OF : UBSAN_LOAD_OF;
1203 unsigned int align = 0;
1204 if (flag_sanitize & SANITIZE_ALIGNMENT)
1206 align = min_align_of_type (TREE_TYPE (base));
1207 if (align <= 1)
1208 align = 0;
1210 if (align == 0 && (flag_sanitize & SANITIZE_NULL) == 0)
1211 return;
1212 tree t = TREE_OPERAND (base, 0);
1213 if (!POINTER_TYPE_P (TREE_TYPE (t)))
1214 return;
1215 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (base)) && mem != base)
1216 ikind = UBSAN_MEMBER_ACCESS;
1217 tree kind = build_int_cst (build_pointer_type (TREE_TYPE (base)), ikind);
1218 tree alignt = build_int_cst (pointer_sized_int_node, align);
1219 gcall *g = gimple_build_call_internal (IFN_UBSAN_NULL, 3, t, kind, alignt);
1220 gimple_set_location (g, gimple_location (gsi_stmt (*iter)));
1221 gsi_insert_before (iter, g, GSI_SAME_STMT);
1224 /* Perform the pointer instrumentation. */
1226 static void
1227 instrument_null (gimple_stmt_iterator gsi, bool is_lhs)
1229 gimple stmt = gsi_stmt (gsi);
1230 tree t = is_lhs ? gimple_get_lhs (stmt) : gimple_assign_rhs1 (stmt);
1231 tree base = get_base_address (t);
1232 const enum tree_code code = TREE_CODE (base);
1233 if (code == MEM_REF
1234 && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
1235 instrument_mem_ref (t, base, &gsi, is_lhs);
1238 /* Build an ubsan builtin call for the signed-integer-overflow
1239 sanitization. CODE says what kind of builtin are we building,
1240 LOC is a location, LHSTYPE is the type of LHS, OP0 and OP1
1241 are operands of the binary operation. */
1243 tree
1244 ubsan_build_overflow_builtin (tree_code code, location_t loc, tree lhstype,
1245 tree op0, tree op1)
1247 if (flag_sanitize_undefined_trap_on_error)
1248 return build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
1250 tree data = ubsan_create_data ("__ubsan_overflow_data", 1, &loc,
1251 ubsan_type_descriptor (lhstype), NULL_TREE,
1252 NULL_TREE);
1253 enum built_in_function fn_code;
1255 switch (code)
1257 case PLUS_EXPR:
1258 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1259 ? BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW
1260 : BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW_ABORT;
1261 break;
1262 case MINUS_EXPR:
1263 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1264 ? BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW
1265 : BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW_ABORT;
1266 break;
1267 case MULT_EXPR:
1268 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1269 ? BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW
1270 : BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW_ABORT;
1271 break;
1272 case NEGATE_EXPR:
1273 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1274 ? BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW
1275 : BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW_ABORT;
1276 break;
1277 default:
1278 gcc_unreachable ();
1280 tree fn = builtin_decl_explicit (fn_code);
1281 return build_call_expr_loc (loc, fn, 2 + (code != NEGATE_EXPR),
1282 build_fold_addr_expr_loc (loc, data),
1283 ubsan_encode_value (op0, true),
1284 op1 ? ubsan_encode_value (op1, true)
1285 : NULL_TREE);
1288 /* Perform the signed integer instrumentation. GSI is the iterator
1289 pointing at statement we are trying to instrument. */
1291 static void
1292 instrument_si_overflow (gimple_stmt_iterator gsi)
1294 gimple stmt = gsi_stmt (gsi);
1295 tree_code code = gimple_assign_rhs_code (stmt);
1296 tree lhs = gimple_assign_lhs (stmt);
1297 tree lhstype = TREE_TYPE (lhs);
1298 tree a, b;
1299 gimple g;
1301 /* If this is not a signed operation, don't instrument anything here.
1302 Also punt on bit-fields. */
1303 if (!INTEGRAL_TYPE_P (lhstype)
1304 || TYPE_OVERFLOW_WRAPS (lhstype)
1305 || GET_MODE_BITSIZE (TYPE_MODE (lhstype)) != TYPE_PRECISION (lhstype))
1306 return;
1308 switch (code)
1310 case MINUS_EXPR:
1311 case PLUS_EXPR:
1312 case MULT_EXPR:
1313 /* Transform
1314 i = u {+,-,*} 5;
1315 into
1316 i = UBSAN_CHECK_{ADD,SUB,MUL} (u, 5); */
1317 a = gimple_assign_rhs1 (stmt);
1318 b = gimple_assign_rhs2 (stmt);
1319 g = gimple_build_call_internal (code == PLUS_EXPR
1320 ? IFN_UBSAN_CHECK_ADD
1321 : code == MINUS_EXPR
1322 ? IFN_UBSAN_CHECK_SUB
1323 : IFN_UBSAN_CHECK_MUL, 2, a, b);
1324 gimple_call_set_lhs (g, lhs);
1325 gsi_replace (&gsi, g, false);
1326 break;
1327 case NEGATE_EXPR:
1328 /* Represent i = -u;
1330 i = UBSAN_CHECK_SUB (0, u); */
1331 a = build_int_cst (lhstype, 0);
1332 b = gimple_assign_rhs1 (stmt);
1333 g = gimple_build_call_internal (IFN_UBSAN_CHECK_SUB, 2, a, b);
1334 gimple_call_set_lhs (g, lhs);
1335 gsi_replace (&gsi, g, false);
1336 break;
1337 case ABS_EXPR:
1338 /* Transform i = ABS_EXPR<u>;
1339 into
1340 _N = UBSAN_CHECK_SUB (0, u);
1341 i = ABS_EXPR<_N>; */
1342 a = build_int_cst (lhstype, 0);
1343 b = gimple_assign_rhs1 (stmt);
1344 g = gimple_build_call_internal (IFN_UBSAN_CHECK_SUB, 2, a, b);
1345 a = make_ssa_name (lhstype);
1346 gimple_call_set_lhs (g, a);
1347 gimple_set_location (g, gimple_location (stmt));
1348 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
1349 gimple_assign_set_rhs1 (stmt, a);
1350 update_stmt (stmt);
1351 break;
1352 default:
1353 break;
1357 /* Instrument loads from (non-bitfield) bool and C++ enum values
1358 to check if the memory value is outside of the range of the valid
1359 type values. */
1361 static void
1362 instrument_bool_enum_load (gimple_stmt_iterator *gsi)
1364 gimple stmt = gsi_stmt (*gsi);
1365 tree rhs = gimple_assign_rhs1 (stmt);
1366 tree type = TREE_TYPE (rhs);
1367 tree minv = NULL_TREE, maxv = NULL_TREE;
1369 if (TREE_CODE (type) == BOOLEAN_TYPE && (flag_sanitize & SANITIZE_BOOL))
1371 minv = boolean_false_node;
1372 maxv = boolean_true_node;
1374 else if (TREE_CODE (type) == ENUMERAL_TYPE
1375 && (flag_sanitize & SANITIZE_ENUM)
1376 && TREE_TYPE (type) != NULL_TREE
1377 && TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE
1378 && (TYPE_PRECISION (TREE_TYPE (type))
1379 < GET_MODE_PRECISION (TYPE_MODE (type))))
1381 minv = TYPE_MIN_VALUE (TREE_TYPE (type));
1382 maxv = TYPE_MAX_VALUE (TREE_TYPE (type));
1384 else
1385 return;
1387 int modebitsize = GET_MODE_BITSIZE (TYPE_MODE (type));
1388 HOST_WIDE_INT bitsize, bitpos;
1389 tree offset;
1390 machine_mode mode;
1391 int volatilep = 0, unsignedp = 0;
1392 tree base = get_inner_reference (rhs, &bitsize, &bitpos, &offset, &mode,
1393 &unsignedp, &volatilep, false);
1394 tree utype = build_nonstandard_integer_type (modebitsize, 1);
1396 if ((TREE_CODE (base) == VAR_DECL && DECL_HARD_REGISTER (base))
1397 || (bitpos % modebitsize) != 0
1398 || bitsize != modebitsize
1399 || GET_MODE_BITSIZE (TYPE_MODE (utype)) != modebitsize
1400 || TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME)
1401 return;
1403 bool ends_bb = stmt_ends_bb_p (stmt);
1404 location_t loc = gimple_location (stmt);
1405 tree lhs = gimple_assign_lhs (stmt);
1406 tree ptype = build_pointer_type (TREE_TYPE (rhs));
1407 tree atype = reference_alias_ptr_type (rhs);
1408 gimple g = gimple_build_assign (make_ssa_name (ptype),
1409 build_fold_addr_expr (rhs));
1410 gimple_set_location (g, loc);
1411 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1412 tree mem = build2 (MEM_REF, utype, gimple_assign_lhs (g),
1413 build_int_cst (atype, 0));
1414 tree urhs = make_ssa_name (utype);
1415 if (ends_bb)
1417 gimple_assign_set_lhs (stmt, urhs);
1418 g = gimple_build_assign (lhs, NOP_EXPR, urhs);
1419 gimple_set_location (g, loc);
1420 edge e = find_fallthru_edge (gimple_bb (stmt)->succs);
1421 gsi_insert_on_edge_immediate (e, g);
1422 gimple_assign_set_rhs_from_tree (gsi, mem);
1423 update_stmt (stmt);
1424 *gsi = gsi_for_stmt (g);
1425 g = stmt;
1427 else
1429 g = gimple_build_assign (urhs, mem);
1430 gimple_set_location (g, loc);
1431 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1433 minv = fold_convert (utype, minv);
1434 maxv = fold_convert (utype, maxv);
1435 if (!integer_zerop (minv))
1437 g = gimple_build_assign (make_ssa_name (utype), MINUS_EXPR, urhs, minv);
1438 gimple_set_location (g, loc);
1439 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1442 gimple_stmt_iterator gsi2 = *gsi;
1443 basic_block then_bb, fallthru_bb;
1444 *gsi = create_cond_insert_point (gsi, true, false, true,
1445 &then_bb, &fallthru_bb);
1446 g = gimple_build_cond (GT_EXPR, gimple_assign_lhs (g),
1447 int_const_binop (MINUS_EXPR, maxv, minv),
1448 NULL_TREE, NULL_TREE);
1449 gimple_set_location (g, loc);
1450 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1452 if (!ends_bb)
1454 gimple_assign_set_rhs_with_ops (&gsi2, NOP_EXPR, urhs);
1455 update_stmt (stmt);
1458 gsi2 = gsi_after_labels (then_bb);
1459 if (flag_sanitize_undefined_trap_on_error)
1460 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1461 else
1463 tree data = ubsan_create_data ("__ubsan_invalid_value_data", 1, &loc,
1464 ubsan_type_descriptor (type), NULL_TREE,
1465 NULL_TREE);
1466 data = build_fold_addr_expr_loc (loc, data);
1467 enum built_in_function bcode
1468 = (flag_sanitize_recover & (TREE_CODE (type) == BOOLEAN_TYPE
1469 ? SANITIZE_BOOL : SANITIZE_ENUM))
1470 ? BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE
1471 : BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE_ABORT;
1472 tree fn = builtin_decl_explicit (bcode);
1474 tree val = force_gimple_operand_gsi (&gsi2, ubsan_encode_value (urhs),
1475 true, NULL_TREE, true,
1476 GSI_SAME_STMT);
1477 g = gimple_build_call (fn, 2, data, val);
1479 gimple_set_location (g, loc);
1480 gsi_insert_before (&gsi2, g, GSI_SAME_STMT);
1481 ubsan_create_edge (g);
1482 *gsi = gsi_for_stmt (stmt);
1485 /* Instrument float point-to-integer conversion. TYPE is an integer type of
1486 destination, EXPR is floating-point expression. ARG is what to pass
1487 the libubsan call as value, often EXPR itself. */
1489 tree
1490 ubsan_instrument_float_cast (location_t loc, tree type, tree expr, tree arg)
1492 tree expr_type = TREE_TYPE (expr);
1493 tree t, tt, fn, min, max;
1494 machine_mode mode = TYPE_MODE (expr_type);
1495 int prec = TYPE_PRECISION (type);
1496 bool uns_p = TYPE_UNSIGNED (type);
1498 /* Float to integer conversion first truncates toward zero, so
1499 even signed char c = 127.875f; is not problematic.
1500 Therefore, we should complain only if EXPR is unordered or smaller
1501 or equal than TYPE_MIN_VALUE - 1.0 or greater or equal than
1502 TYPE_MAX_VALUE + 1.0. */
1503 if (REAL_MODE_FORMAT (mode)->b == 2)
1505 /* For maximum, TYPE_MAX_VALUE might not be representable
1506 in EXPR_TYPE, e.g. if TYPE is 64-bit long long and
1507 EXPR_TYPE is IEEE single float, but TYPE_MAX_VALUE + 1.0 is
1508 either representable or infinity. */
1509 REAL_VALUE_TYPE maxval = dconst1;
1510 SET_REAL_EXP (&maxval, REAL_EXP (&maxval) + prec - !uns_p);
1511 real_convert (&maxval, mode, &maxval);
1512 max = build_real (expr_type, maxval);
1514 /* For unsigned, assume -1.0 is always representable. */
1515 if (uns_p)
1516 min = build_minus_one_cst (expr_type);
1517 else
1519 /* TYPE_MIN_VALUE is generally representable (or -inf),
1520 but TYPE_MIN_VALUE - 1.0 might not be. */
1521 REAL_VALUE_TYPE minval = dconstm1, minval2;
1522 SET_REAL_EXP (&minval, REAL_EXP (&minval) + prec - 1);
1523 real_convert (&minval, mode, &minval);
1524 real_arithmetic (&minval2, MINUS_EXPR, &minval, &dconst1);
1525 real_convert (&minval2, mode, &minval2);
1526 if (real_compare (EQ_EXPR, &minval, &minval2)
1527 && !real_isinf (&minval))
1529 /* If TYPE_MIN_VALUE - 1.0 is not representable and
1530 rounds to TYPE_MIN_VALUE, we need to subtract
1531 more. As REAL_MODE_FORMAT (mode)->p is the number
1532 of base digits, we want to subtract a number that
1533 will be 1 << (REAL_MODE_FORMAT (mode)->p - 1)
1534 times smaller than minval. */
1535 minval2 = dconst1;
1536 gcc_assert (prec > REAL_MODE_FORMAT (mode)->p);
1537 SET_REAL_EXP (&minval2,
1538 REAL_EXP (&minval2) + prec - 1
1539 - REAL_MODE_FORMAT (mode)->p + 1);
1540 real_arithmetic (&minval2, MINUS_EXPR, &minval, &minval2);
1541 real_convert (&minval2, mode, &minval2);
1543 min = build_real (expr_type, minval2);
1546 else if (REAL_MODE_FORMAT (mode)->b == 10)
1548 /* For _Decimal128 up to 34 decimal digits, - sign,
1549 dot, e, exponent. */
1550 char buf[64];
1551 mpfr_t m;
1552 int p = REAL_MODE_FORMAT (mode)->p;
1553 REAL_VALUE_TYPE maxval, minval;
1555 /* Use mpfr_snprintf rounding to compute the smallest
1556 representable decimal number greater or equal than
1557 1 << (prec - !uns_p). */
1558 mpfr_init2 (m, prec + 2);
1559 mpfr_set_ui_2exp (m, 1, prec - !uns_p, GMP_RNDN);
1560 mpfr_snprintf (buf, sizeof buf, "%.*RUe", p - 1, m);
1561 decimal_real_from_string (&maxval, buf);
1562 max = build_real (expr_type, maxval);
1564 /* For unsigned, assume -1.0 is always representable. */
1565 if (uns_p)
1566 min = build_minus_one_cst (expr_type);
1567 else
1569 /* Use mpfr_snprintf rounding to compute the largest
1570 representable decimal number less or equal than
1571 (-1 << (prec - 1)) - 1. */
1572 mpfr_set_si_2exp (m, -1, prec - 1, GMP_RNDN);
1573 mpfr_sub_ui (m, m, 1, GMP_RNDN);
1574 mpfr_snprintf (buf, sizeof buf, "%.*RDe", p - 1, m);
1575 decimal_real_from_string (&minval, buf);
1576 min = build_real (expr_type, minval);
1578 mpfr_clear (m);
1580 else
1581 return NULL_TREE;
1583 t = fold_build2 (UNLE_EXPR, boolean_type_node, expr, min);
1584 tt = fold_build2 (UNGE_EXPR, boolean_type_node, expr, max);
1585 t = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t, tt);
1586 if (integer_zerop (t))
1587 return NULL_TREE;
1589 if (flag_sanitize_undefined_trap_on_error)
1590 fn = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
1591 else
1593 /* Create the __ubsan_handle_float_cast_overflow fn call. */
1594 tree data = ubsan_create_data ("__ubsan_float_cast_overflow_data", 0,
1595 NULL, ubsan_type_descriptor (expr_type),
1596 ubsan_type_descriptor (type), NULL_TREE,
1597 NULL_TREE);
1598 enum built_in_function bcode
1599 = (flag_sanitize_recover & SANITIZE_FLOAT_CAST)
1600 ? BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW
1601 : BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW_ABORT;
1602 fn = builtin_decl_explicit (bcode);
1603 fn = build_call_expr_loc (loc, fn, 2,
1604 build_fold_addr_expr_loc (loc, data),
1605 ubsan_encode_value (arg, false));
1608 return fold_build3 (COND_EXPR, void_type_node, t, fn, integer_zero_node);
1611 /* Instrument values passed to function arguments with nonnull attribute. */
1613 static void
1614 instrument_nonnull_arg (gimple_stmt_iterator *gsi)
1616 gimple stmt = gsi_stmt (*gsi);
1617 location_t loc[2];
1618 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
1619 while for nonnull sanitization it is clear. */
1620 int save_flag_delete_null_pointer_checks = flag_delete_null_pointer_checks;
1621 flag_delete_null_pointer_checks = 1;
1622 loc[0] = gimple_location (stmt);
1623 loc[1] = UNKNOWN_LOCATION;
1624 for (unsigned int i = 0; i < gimple_call_num_args (stmt); i++)
1626 tree arg = gimple_call_arg (stmt, i);
1627 if (POINTER_TYPE_P (TREE_TYPE (arg))
1628 && infer_nonnull_range (stmt, arg, false, true))
1630 gimple g;
1631 if (!is_gimple_val (arg))
1633 g = gimple_build_assign (make_ssa_name (TREE_TYPE (arg)), arg);
1634 gimple_set_location (g, loc[0]);
1635 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1636 arg = gimple_assign_lhs (g);
1639 basic_block then_bb, fallthru_bb;
1640 *gsi = create_cond_insert_point (gsi, true, false, true,
1641 &then_bb, &fallthru_bb);
1642 g = gimple_build_cond (EQ_EXPR, arg,
1643 build_zero_cst (TREE_TYPE (arg)),
1644 NULL_TREE, NULL_TREE);
1645 gimple_set_location (g, loc[0]);
1646 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1648 *gsi = gsi_after_labels (then_bb);
1649 if (flag_sanitize_undefined_trap_on_error)
1650 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1651 else
1653 tree data = ubsan_create_data ("__ubsan_nonnull_arg_data",
1654 2, loc, NULL_TREE,
1655 build_int_cst (integer_type_node,
1656 i + 1),
1657 NULL_TREE);
1658 data = build_fold_addr_expr_loc (loc[0], data);
1659 enum built_in_function bcode
1660 = (flag_sanitize_recover & SANITIZE_NONNULL_ATTRIBUTE)
1661 ? BUILT_IN_UBSAN_HANDLE_NONNULL_ARG
1662 : BUILT_IN_UBSAN_HANDLE_NONNULL_ARG_ABORT;
1663 tree fn = builtin_decl_explicit (bcode);
1665 g = gimple_build_call (fn, 1, data);
1667 gimple_set_location (g, loc[0]);
1668 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1669 ubsan_create_edge (g);
1671 *gsi = gsi_for_stmt (stmt);
1673 flag_delete_null_pointer_checks = save_flag_delete_null_pointer_checks;
1676 /* Instrument returns in functions with returns_nonnull attribute. */
1678 static void
1679 instrument_nonnull_return (gimple_stmt_iterator *gsi)
1681 greturn *stmt = as_a <greturn *> (gsi_stmt (*gsi));
1682 location_t loc[2];
1683 tree arg = gimple_return_retval (stmt);
1684 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
1685 while for nonnull return sanitization it is clear. */
1686 int save_flag_delete_null_pointer_checks = flag_delete_null_pointer_checks;
1687 flag_delete_null_pointer_checks = 1;
1688 loc[0] = gimple_location (stmt);
1689 loc[1] = UNKNOWN_LOCATION;
1690 if (arg
1691 && POINTER_TYPE_P (TREE_TYPE (arg))
1692 && is_gimple_val (arg)
1693 && infer_nonnull_range (stmt, arg, false, true))
1695 basic_block then_bb, fallthru_bb;
1696 *gsi = create_cond_insert_point (gsi, true, false, true,
1697 &then_bb, &fallthru_bb);
1698 gimple g = gimple_build_cond (EQ_EXPR, arg,
1699 build_zero_cst (TREE_TYPE (arg)),
1700 NULL_TREE, NULL_TREE);
1701 gimple_set_location (g, loc[0]);
1702 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1704 *gsi = gsi_after_labels (then_bb);
1705 if (flag_sanitize_undefined_trap_on_error)
1706 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1707 else
1709 tree data = ubsan_create_data ("__ubsan_nonnull_return_data",
1710 2, loc, NULL_TREE, NULL_TREE);
1711 data = build_fold_addr_expr_loc (loc[0], data);
1712 enum built_in_function bcode
1713 = (flag_sanitize_recover & SANITIZE_RETURNS_NONNULL_ATTRIBUTE)
1714 ? BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN
1715 : BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_ABORT;
1716 tree fn = builtin_decl_explicit (bcode);
1718 g = gimple_build_call (fn, 1, data);
1720 gimple_set_location (g, loc[0]);
1721 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1722 ubsan_create_edge (g);
1723 *gsi = gsi_for_stmt (stmt);
1725 flag_delete_null_pointer_checks = save_flag_delete_null_pointer_checks;
1728 /* Instrument memory references. Here we check whether the pointer
1729 points to an out-of-bounds location. */
1731 static void
1732 instrument_object_size (gimple_stmt_iterator *gsi, bool is_lhs)
1734 gimple stmt = gsi_stmt (*gsi);
1735 location_t loc = gimple_location (stmt);
1736 tree t = is_lhs ? gimple_get_lhs (stmt) : gimple_assign_rhs1 (stmt);
1737 tree type;
1738 tree index = NULL_TREE;
1739 HOST_WIDE_INT size_in_bytes;
1741 type = TREE_TYPE (t);
1742 if (VOID_TYPE_P (type))
1743 return;
1745 switch (TREE_CODE (t))
1747 case COMPONENT_REF:
1748 if (TREE_CODE (t) == COMPONENT_REF
1749 && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1)) != NULL_TREE)
1751 tree repr = DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1));
1752 t = build3 (COMPONENT_REF, TREE_TYPE (repr), TREE_OPERAND (t, 0),
1753 repr, NULL_TREE);
1755 break;
1756 case ARRAY_REF:
1757 index = TREE_OPERAND (t, 1);
1758 break;
1759 case INDIRECT_REF:
1760 case MEM_REF:
1761 case VAR_DECL:
1762 case PARM_DECL:
1763 case RESULT_DECL:
1764 break;
1765 default:
1766 return;
1769 size_in_bytes = int_size_in_bytes (type);
1770 if (size_in_bytes <= 0)
1771 return;
1773 HOST_WIDE_INT bitsize, bitpos;
1774 tree offset;
1775 machine_mode mode;
1776 int volatilep = 0, unsignedp = 0;
1777 tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset, &mode,
1778 &unsignedp, &volatilep, false);
1780 if (bitpos % BITS_PER_UNIT != 0
1781 || bitsize != size_in_bytes * BITS_PER_UNIT)
1782 return;
1784 bool decl_p = DECL_P (inner);
1785 tree base;
1786 if (decl_p)
1787 base = inner;
1788 else if (TREE_CODE (inner) == MEM_REF)
1789 base = TREE_OPERAND (inner, 0);
1790 else
1791 return;
1792 tree ptr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (t)), t);
1794 while (TREE_CODE (base) == SSA_NAME)
1796 gimple def_stmt = SSA_NAME_DEF_STMT (base);
1797 if (gimple_assign_ssa_name_copy_p (def_stmt)
1798 || (gimple_assign_cast_p (def_stmt)
1799 && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (def_stmt))))
1800 || (is_gimple_assign (def_stmt)
1801 && gimple_assign_rhs_code (def_stmt) == POINTER_PLUS_EXPR))
1803 tree rhs1 = gimple_assign_rhs1 (def_stmt);
1804 if (TREE_CODE (rhs1) == SSA_NAME
1805 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs1))
1806 break;
1807 else
1808 base = rhs1;
1810 else
1811 break;
1814 if (!POINTER_TYPE_P (TREE_TYPE (base)) && !DECL_P (base))
1815 return;
1817 tree sizet;
1818 tree base_addr = base;
1819 gimple bos_stmt = NULL;
1820 if (decl_p)
1821 base_addr = build1 (ADDR_EXPR,
1822 build_pointer_type (TREE_TYPE (base)), base);
1823 unsigned HOST_WIDE_INT size = compute_builtin_object_size (base_addr, 0);
1824 if (size != (unsigned HOST_WIDE_INT) -1)
1825 sizet = build_int_cst (sizetype, size);
1826 else if (optimize)
1828 if (LOCATION_LOCUS (loc) == UNKNOWN_LOCATION)
1829 loc = input_location;
1830 /* Generate __builtin_object_size call. */
1831 sizet = builtin_decl_explicit (BUILT_IN_OBJECT_SIZE);
1832 sizet = build_call_expr_loc (loc, sizet, 2, base_addr,
1833 integer_zero_node);
1834 sizet = force_gimple_operand_gsi (gsi, sizet, false, NULL_TREE, true,
1835 GSI_SAME_STMT);
1836 /* If the call above didn't end up being an integer constant, go one
1837 statement back and get the __builtin_object_size stmt. Save it,
1838 we might need it later. */
1839 if (SSA_VAR_P (sizet))
1841 gsi_prev (gsi);
1842 bos_stmt = gsi_stmt (*gsi);
1844 /* Move on to where we were. */
1845 gsi_next (gsi);
1848 else
1849 return;
1851 /* Generate UBSAN_OBJECT_SIZE (ptr, ptr+sizeof(*ptr)-base, objsize, ckind)
1852 call. */
1853 /* ptr + sizeof (*ptr) - base */
1854 t = fold_build2 (MINUS_EXPR, sizetype,
1855 fold_convert (pointer_sized_int_node, ptr),
1856 fold_convert (pointer_sized_int_node, base_addr));
1857 t = fold_build2 (PLUS_EXPR, sizetype, t, TYPE_SIZE_UNIT (type));
1859 /* Perhaps we can omit the check. */
1860 if (TREE_CODE (t) == INTEGER_CST
1861 && TREE_CODE (sizet) == INTEGER_CST
1862 && tree_int_cst_le (t, sizet))
1863 return;
1865 if (index != NULL_TREE
1866 && TREE_CODE (index) == SSA_NAME
1867 && TREE_CODE (sizet) == INTEGER_CST)
1869 gimple def = SSA_NAME_DEF_STMT (index);
1870 if (is_gimple_assign (def)
1871 && gimple_assign_rhs_code (def) == BIT_AND_EXPR
1872 && TREE_CODE (gimple_assign_rhs2 (def)) == INTEGER_CST)
1874 tree cst = gimple_assign_rhs2 (def);
1875 tree sz = fold_build2 (EXACT_DIV_EXPR, sizetype, sizet,
1876 TYPE_SIZE_UNIT (type));
1877 if (tree_int_cst_sgn (cst) >= 0
1878 && tree_int_cst_lt (cst, sz))
1879 return;
1883 if (bos_stmt && gimple_call_builtin_p (bos_stmt, BUILT_IN_OBJECT_SIZE))
1884 ubsan_create_edge (bos_stmt);
1886 /* We have to emit the check. */
1887 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE, true,
1888 GSI_SAME_STMT);
1889 ptr = force_gimple_operand_gsi (gsi, ptr, true, NULL_TREE, true,
1890 GSI_SAME_STMT);
1891 tree ckind = build_int_cst (unsigned_char_type_node,
1892 is_lhs ? UBSAN_STORE_OF : UBSAN_LOAD_OF);
1893 gimple g = gimple_build_call_internal (IFN_UBSAN_OBJECT_SIZE, 4,
1894 ptr, t, sizet, ckind);
1895 gimple_set_location (g, loc);
1896 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1899 /* True if we want to play UBSan games in the current function. */
1901 bool
1902 do_ubsan_in_current_function ()
1904 return (current_function_decl != NULL_TREE
1905 && !lookup_attribute ("no_sanitize_undefined",
1906 DECL_ATTRIBUTES (current_function_decl)));
1909 namespace {
1911 const pass_data pass_data_ubsan =
1913 GIMPLE_PASS, /* type */
1914 "ubsan", /* name */
1915 OPTGROUP_NONE, /* optinfo_flags */
1916 TV_TREE_UBSAN, /* tv_id */
1917 ( PROP_cfg | PROP_ssa ), /* properties_required */
1918 0, /* properties_provided */
1919 0, /* properties_destroyed */
1920 0, /* todo_flags_start */
1921 TODO_update_ssa, /* todo_flags_finish */
1924 class pass_ubsan : public gimple_opt_pass
1926 public:
1927 pass_ubsan (gcc::context *ctxt)
1928 : gimple_opt_pass (pass_data_ubsan, ctxt)
1931 /* opt_pass methods: */
1932 virtual bool gate (function *)
1934 return flag_sanitize & (SANITIZE_NULL | SANITIZE_SI_OVERFLOW
1935 | SANITIZE_BOOL | SANITIZE_ENUM
1936 | SANITIZE_ALIGNMENT
1937 | SANITIZE_NONNULL_ATTRIBUTE
1938 | SANITIZE_RETURNS_NONNULL_ATTRIBUTE
1939 | SANITIZE_OBJECT_SIZE)
1940 && do_ubsan_in_current_function ();
1943 virtual unsigned int execute (function *);
1945 }; // class pass_ubsan
1947 unsigned int
1948 pass_ubsan::execute (function *fun)
1950 basic_block bb;
1951 gimple_stmt_iterator gsi;
1953 initialize_sanitizer_builtins ();
1955 FOR_EACH_BB_FN (bb, fun)
1957 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
1959 gimple stmt = gsi_stmt (gsi);
1960 if (is_gimple_debug (stmt) || gimple_clobber_p (stmt))
1962 gsi_next (&gsi);
1963 continue;
1966 if ((flag_sanitize & SANITIZE_SI_OVERFLOW)
1967 && is_gimple_assign (stmt))
1968 instrument_si_overflow (gsi);
1970 if (flag_sanitize & (SANITIZE_NULL | SANITIZE_ALIGNMENT))
1972 if (gimple_store_p (stmt))
1973 instrument_null (gsi, true);
1974 if (gimple_assign_load_p (stmt))
1975 instrument_null (gsi, false);
1978 if (flag_sanitize & (SANITIZE_BOOL | SANITIZE_ENUM)
1979 && gimple_assign_load_p (stmt))
1981 instrument_bool_enum_load (&gsi);
1982 bb = gimple_bb (stmt);
1985 if ((flag_sanitize & SANITIZE_NONNULL_ATTRIBUTE)
1986 && is_gimple_call (stmt)
1987 && !gimple_call_internal_p (stmt))
1989 instrument_nonnull_arg (&gsi);
1990 bb = gimple_bb (stmt);
1993 if ((flag_sanitize & SANITIZE_RETURNS_NONNULL_ATTRIBUTE)
1994 && gimple_code (stmt) == GIMPLE_RETURN)
1996 instrument_nonnull_return (&gsi);
1997 bb = gimple_bb (stmt);
2000 if (flag_sanitize & SANITIZE_OBJECT_SIZE)
2002 if (gimple_store_p (stmt))
2003 instrument_object_size (&gsi, true);
2004 if (gimple_assign_load_p (stmt))
2005 instrument_object_size (&gsi, false);
2008 gsi_next (&gsi);
2011 return 0;
2014 } // anon namespace
2016 gimple_opt_pass *
2017 make_pass_ubsan (gcc::context *ctxt)
2019 return new pass_ubsan (ctxt);
2022 #include "gt-ubsan.h"