gcc/
[official-gcc.git] / gcc / ubsan.c
blob5bf53276d7dc0a11888d184868832cfcd019861f
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 "hash-set.h"
25 #include "machmode.h"
26 #include "vec.h"
27 #include "double-int.h"
28 #include "input.h"
29 #include "alias.h"
30 #include "symtab.h"
31 #include "options.h"
32 #include "wide-int.h"
33 #include "inchash.h"
34 #include "tree.h"
35 #include "fold-const.h"
36 #include "stor-layout.h"
37 #include "stringpool.h"
38 #include "predict.h"
39 #include "dominance.h"
40 #include "cfg.h"
41 #include "cfganal.h"
42 #include "basic-block.h"
43 #include "hash-map.h"
44 #include "is-a.h"
45 #include "plugin-api.h"
46 #include "tm.h"
47 #include "hard-reg-set.h"
48 #include "function.h"
49 #include "ipa-ref.h"
50 #include "cgraph.h"
51 #include "tree-pass.h"
52 #include "tree-ssa-alias.h"
53 #include "tree-pretty-print.h"
54 #include "internal-fn.h"
55 #include "gimple-expr.h"
56 #include "gimple.h"
57 #include "gimple-iterator.h"
58 #include "gimple-ssa.h"
59 #include "gimple-walk.h"
60 #include "output.h"
61 #include "tm_p.h"
62 #include "toplev.h"
63 #include "cfgloop.h"
64 #include "ubsan.h"
65 #include "c-family/c-common.h"
66 #include "rtl.h"
67 #include "hashtab.h"
68 #include "flags.h"
69 #include "statistics.h"
70 #include "real.h"
71 #include "fixed-value.h"
72 #include "insn-config.h"
73 #include "expmed.h"
74 #include "dojump.h"
75 #include "explow.h"
76 #include "calls.h"
77 #include "emit-rtl.h"
78 #include "varasm.h"
79 #include "stmt.h"
80 #include "expr.h"
81 #include "tree-ssanames.h"
82 #include "asan.h"
83 #include "gimplify-me.h"
84 #include "intl.h"
85 #include "realmpfr.h"
86 #include "dfp.h"
87 #include "builtins.h"
88 #include "tree-object-size.h"
89 #include "tree-eh.h"
91 /* Map from a tree to a VAR_DECL tree. */
93 struct GTY((for_user)) tree_type_map {
94 struct tree_map_base type;
95 tree decl;
98 struct tree_type_map_cache_hasher : ggc_cache_hasher<tree_type_map *>
100 static inline hashval_t
101 hash (tree_type_map *t)
103 return TYPE_UID (t->type.from);
106 static inline bool
107 equal (tree_type_map *a, tree_type_map *b)
109 return a->type.from == b->type.from;
112 static void
113 handle_cache_entry (tree_type_map *&m)
115 extern void gt_ggc_mx (tree_type_map *&);
116 if (m == HTAB_EMPTY_ENTRY || m == HTAB_DELETED_ENTRY)
117 return;
118 else if (ggc_marked_p (m->type.from))
119 gt_ggc_mx (m);
120 else
121 m = static_cast<tree_type_map *> (HTAB_DELETED_ENTRY);
125 static GTY ((cache))
126 hash_table<tree_type_map_cache_hasher> *decl_tree_for_type;
128 /* Lookup a VAR_DECL for TYPE, and return it if we find one. */
130 static tree
131 decl_for_type_lookup (tree type)
133 /* If the hash table is not initialized yet, create it now. */
134 if (decl_tree_for_type == NULL)
136 decl_tree_for_type
137 = hash_table<tree_type_map_cache_hasher>::create_ggc (10);
138 /* That also means we don't have to bother with the lookup. */
139 return NULL_TREE;
142 struct tree_type_map *h, in;
143 in.type.from = type;
145 h = decl_tree_for_type->find_with_hash (&in, TYPE_UID (type));
146 return h ? h->decl : NULL_TREE;
149 /* Insert a mapping TYPE->DECL in the VAR_DECL for type hashtable. */
151 static void
152 decl_for_type_insert (tree type, tree decl)
154 struct tree_type_map *h;
156 h = ggc_alloc<tree_type_map> ();
157 h->type.from = type;
158 h->decl = decl;
159 *decl_tree_for_type->find_slot_with_hash (h, TYPE_UID (type), INSERT) = h;
162 /* Helper routine, which encodes a value in the pointer_sized_int_node.
163 Arguments with precision <= POINTER_SIZE are passed directly,
164 the rest is passed by reference. T is a value we are to encode.
165 IN_EXPAND_P is true if this function is called during expansion. */
167 tree
168 ubsan_encode_value (tree t, bool in_expand_p)
170 tree type = TREE_TYPE (t);
171 const unsigned int bitsize = GET_MODE_BITSIZE (TYPE_MODE (type));
172 if (bitsize <= POINTER_SIZE)
173 switch (TREE_CODE (type))
175 case BOOLEAN_TYPE:
176 case ENUMERAL_TYPE:
177 case INTEGER_TYPE:
178 return fold_build1 (NOP_EXPR, pointer_sized_int_node, t);
179 case REAL_TYPE:
181 tree itype = build_nonstandard_integer_type (bitsize, true);
182 t = fold_build1 (VIEW_CONVERT_EXPR, itype, t);
183 return fold_convert (pointer_sized_int_node, t);
185 default:
186 gcc_unreachable ();
188 else
190 if (!DECL_P (t) || !TREE_ADDRESSABLE (t))
192 /* The reason for this is that we don't want to pessimize
193 code by making vars unnecessarily addressable. */
194 tree var = create_tmp_var (type);
195 tree tem = build2 (MODIFY_EXPR, void_type_node, var, t);
196 if (in_expand_p)
198 rtx mem
199 = assign_stack_temp_for_type (TYPE_MODE (type),
200 GET_MODE_SIZE (TYPE_MODE (type)),
201 type);
202 SET_DECL_RTL (var, mem);
203 expand_assignment (var, t, false);
204 return build_fold_addr_expr (var);
206 t = build_fold_addr_expr (var);
207 return build2 (COMPOUND_EXPR, TREE_TYPE (t), tem, t);
209 else
210 return build_fold_addr_expr (t);
214 /* Cached ubsan_get_type_descriptor_type () return value. */
215 static GTY(()) tree ubsan_type_descriptor_type;
217 /* Build
218 struct __ubsan_type_descriptor
220 unsigned short __typekind;
221 unsigned short __typeinfo;
222 char __typename[];
224 type. */
226 static tree
227 ubsan_get_type_descriptor_type (void)
229 static const char *field_names[3]
230 = { "__typekind", "__typeinfo", "__typename" };
231 tree fields[3], ret;
233 if (ubsan_type_descriptor_type)
234 return ubsan_type_descriptor_type;
236 tree itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
237 tree flex_arr_type = build_array_type (char_type_node, itype);
239 ret = make_node (RECORD_TYPE);
240 for (int i = 0; i < 3; i++)
242 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
243 get_identifier (field_names[i]),
244 (i == 2) ? flex_arr_type
245 : short_unsigned_type_node);
246 DECL_CONTEXT (fields[i]) = ret;
247 if (i)
248 DECL_CHAIN (fields[i - 1]) = fields[i];
250 tree type_decl = build_decl (input_location, TYPE_DECL,
251 get_identifier ("__ubsan_type_descriptor"),
252 ret);
253 DECL_IGNORED_P (type_decl) = 1;
254 DECL_ARTIFICIAL (type_decl) = 1;
255 TYPE_FIELDS (ret) = fields[0];
256 TYPE_NAME (ret) = type_decl;
257 TYPE_STUB_DECL (ret) = type_decl;
258 layout_type (ret);
259 ubsan_type_descriptor_type = ret;
260 return ret;
263 /* Cached ubsan_get_source_location_type () return value. */
264 static GTY(()) tree ubsan_source_location_type;
266 /* Build
267 struct __ubsan_source_location
269 const char *__filename;
270 unsigned int __line;
271 unsigned int __column;
273 type. */
275 tree
276 ubsan_get_source_location_type (void)
278 static const char *field_names[3]
279 = { "__filename", "__line", "__column" };
280 tree fields[3], ret;
281 if (ubsan_source_location_type)
282 return ubsan_source_location_type;
284 tree const_char_type = build_qualified_type (char_type_node,
285 TYPE_QUAL_CONST);
287 ret = make_node (RECORD_TYPE);
288 for (int i = 0; i < 3; i++)
290 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
291 get_identifier (field_names[i]),
292 (i == 0) ? build_pointer_type (const_char_type)
293 : unsigned_type_node);
294 DECL_CONTEXT (fields[i]) = ret;
295 if (i)
296 DECL_CHAIN (fields[i - 1]) = fields[i];
298 tree type_decl = build_decl (input_location, TYPE_DECL,
299 get_identifier ("__ubsan_source_location"),
300 ret);
301 DECL_IGNORED_P (type_decl) = 1;
302 DECL_ARTIFICIAL (type_decl) = 1;
303 TYPE_FIELDS (ret) = fields[0];
304 TYPE_NAME (ret) = type_decl;
305 TYPE_STUB_DECL (ret) = type_decl;
306 layout_type (ret);
307 ubsan_source_location_type = ret;
308 return ret;
311 /* Helper routine that returns a CONSTRUCTOR of __ubsan_source_location
312 type with its fields filled from a location_t LOC. */
314 static tree
315 ubsan_source_location (location_t loc)
317 expanded_location xloc;
318 tree type = ubsan_get_source_location_type ();
320 xloc = expand_location (loc);
321 tree str;
322 if (xloc.file == NULL)
324 str = build_int_cst (ptr_type_node, 0);
325 xloc.line = 0;
326 xloc.column = 0;
328 else
330 /* Fill in the values from LOC. */
331 size_t len = strlen (xloc.file);
332 str = build_string (len + 1, xloc.file);
333 TREE_TYPE (str) = build_array_type (char_type_node,
334 build_index_type (size_int (len)));
335 TREE_READONLY (str) = 1;
336 TREE_STATIC (str) = 1;
337 str = build_fold_addr_expr (str);
339 tree ctor = build_constructor_va (type, 3, NULL_TREE, str, NULL_TREE,
340 build_int_cst (unsigned_type_node,
341 xloc.line), NULL_TREE,
342 build_int_cst (unsigned_type_node,
343 xloc.column));
344 TREE_CONSTANT (ctor) = 1;
345 TREE_STATIC (ctor) = 1;
347 return ctor;
350 /* This routine returns a magic number for TYPE. */
352 static unsigned short
353 get_ubsan_type_info_for_type (tree type)
355 gcc_assert (TYPE_SIZE (type) && tree_fits_uhwi_p (TYPE_SIZE (type)));
356 if (TREE_CODE (type) == REAL_TYPE)
357 return tree_to_uhwi (TYPE_SIZE (type));
358 else if (INTEGRAL_TYPE_P (type))
360 int prec = exact_log2 (tree_to_uhwi (TYPE_SIZE (type)));
361 gcc_assert (prec != -1);
362 return (prec << 1) | !TYPE_UNSIGNED (type);
364 else
365 return 0;
368 /* Helper routine that returns ADDR_EXPR of a VAR_DECL of a type
369 descriptor. It first looks into the hash table; if not found,
370 create the VAR_DECL, put it into the hash table and return the
371 ADDR_EXPR of it. TYPE describes a particular type. PSTYLE is
372 an enum controlling how we want to print the type. */
374 tree
375 ubsan_type_descriptor (tree type, enum ubsan_print_style pstyle)
377 /* See through any typedefs. */
378 type = TYPE_MAIN_VARIANT (type);
380 tree decl = decl_for_type_lookup (type);
381 /* It is possible that some of the earlier created DECLs were found
382 unused, in that case they weren't emitted and varpool_node::get
383 returns NULL node on them. But now we really need them. Thus,
384 renew them here. */
385 if (decl != NULL_TREE && varpool_node::get (decl))
386 return build_fold_addr_expr (decl);
388 tree dtype = ubsan_get_type_descriptor_type ();
389 tree type2 = type;
390 const char *tname = NULL;
391 char *pretty_name;
392 unsigned char deref_depth = 0;
393 unsigned short tkind, tinfo;
395 /* Get the name of the type, or the name of the pointer type. */
396 if (pstyle == UBSAN_PRINT_POINTER)
398 gcc_assert (POINTER_TYPE_P (type));
399 type2 = TREE_TYPE (type);
401 /* Remove any '*' operators from TYPE. */
402 while (POINTER_TYPE_P (type2))
403 deref_depth++, type2 = TREE_TYPE (type2);
405 if (TREE_CODE (type2) == METHOD_TYPE)
406 type2 = TYPE_METHOD_BASETYPE (type2);
409 /* If an array, get its type. */
410 type2 = strip_array_types (type2);
412 if (pstyle == UBSAN_PRINT_ARRAY)
414 while (POINTER_TYPE_P (type2))
415 deref_depth++, type2 = TREE_TYPE (type2);
418 if (TYPE_NAME (type2) != NULL)
420 if (TREE_CODE (TYPE_NAME (type2)) == IDENTIFIER_NODE)
421 tname = IDENTIFIER_POINTER (TYPE_NAME (type2));
422 else if (DECL_NAME (TYPE_NAME (type2)) != NULL)
423 tname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type2)));
426 if (tname == NULL)
427 /* We weren't able to determine the type name. */
428 tname = "<unknown>";
430 /* Decorate the type name with '', '*', "struct", or "union". */
431 pretty_name = (char *) alloca (strlen (tname) + 16 + deref_depth);
432 if (pstyle == UBSAN_PRINT_POINTER)
434 int pos = sprintf (pretty_name, "'%s%s%s%s%s%s%s",
435 TYPE_VOLATILE (type2) ? "volatile " : "",
436 TYPE_READONLY (type2) ? "const " : "",
437 TYPE_RESTRICT (type2) ? "restrict " : "",
438 TYPE_ATOMIC (type2) ? "_Atomic " : "",
439 TREE_CODE (type2) == RECORD_TYPE
440 ? "struct "
441 : TREE_CODE (type2) == UNION_TYPE
442 ? "union " : "", tname,
443 deref_depth == 0 ? "" : " ");
444 while (deref_depth-- > 0)
445 pretty_name[pos++] = '*';
446 pretty_name[pos++] = '\'';
447 pretty_name[pos] = '\0';
449 else if (pstyle == UBSAN_PRINT_ARRAY)
451 /* Pretty print the array dimensions. */
452 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
453 tree t = type;
454 int pos = sprintf (pretty_name, "'%s ", tname);
455 while (deref_depth-- > 0)
456 pretty_name[pos++] = '*';
457 while (TREE_CODE (t) == ARRAY_TYPE)
459 pretty_name[pos++] = '[';
460 tree dom = TYPE_DOMAIN (t);
461 if (dom && TREE_CODE (TYPE_MAX_VALUE (dom)) == INTEGER_CST)
462 pos += sprintf (&pretty_name[pos], HOST_WIDE_INT_PRINT_DEC,
463 tree_to_uhwi (TYPE_MAX_VALUE (dom)) + 1);
464 else
465 /* ??? We can't determine the variable name; print VLA unspec. */
466 pretty_name[pos++] = '*';
467 pretty_name[pos++] = ']';
468 t = TREE_TYPE (t);
470 pretty_name[pos++] = '\'';
471 pretty_name[pos] = '\0';
473 /* Save the tree with stripped types. */
474 type = t;
476 else
477 sprintf (pretty_name, "'%s'", tname);
479 switch (TREE_CODE (type))
481 case BOOLEAN_TYPE:
482 case ENUMERAL_TYPE:
483 case INTEGER_TYPE:
484 tkind = 0x0000;
485 break;
486 case REAL_TYPE:
487 /* FIXME: libubsan right now only supports float, double and
488 long double type formats. */
489 if (TYPE_MODE (type) == TYPE_MODE (float_type_node)
490 || TYPE_MODE (type) == TYPE_MODE (double_type_node)
491 || TYPE_MODE (type) == TYPE_MODE (long_double_type_node))
492 tkind = 0x0001;
493 else
494 tkind = 0xffff;
495 break;
496 default:
497 tkind = 0xffff;
498 break;
500 tinfo = get_ubsan_type_info_for_type (type);
502 /* Create a new VAR_DECL of type descriptor. */
503 char tmp_name[32];
504 static unsigned int type_var_id_num;
505 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_type", type_var_id_num++);
506 decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name),
507 dtype);
508 TREE_STATIC (decl) = 1;
509 TREE_PUBLIC (decl) = 0;
510 DECL_ARTIFICIAL (decl) = 1;
511 DECL_IGNORED_P (decl) = 1;
512 DECL_EXTERNAL (decl) = 0;
514 size_t len = strlen (pretty_name);
515 tree str = build_string (len + 1, pretty_name);
516 TREE_TYPE (str) = build_array_type (char_type_node,
517 build_index_type (size_int (len)));
518 TREE_READONLY (str) = 1;
519 TREE_STATIC (str) = 1;
520 tree ctor = build_constructor_va (dtype, 3, NULL_TREE,
521 build_int_cst (short_unsigned_type_node,
522 tkind), NULL_TREE,
523 build_int_cst (short_unsigned_type_node,
524 tinfo), NULL_TREE, str);
525 TREE_CONSTANT (ctor) = 1;
526 TREE_STATIC (ctor) = 1;
527 DECL_INITIAL (decl) = ctor;
528 varpool_node::finalize_decl (decl);
530 /* Save the VAR_DECL into the hash table. */
531 decl_for_type_insert (type, decl);
533 return build_fold_addr_expr (decl);
536 /* Create a structure for the ubsan library. NAME is a name of the new
537 structure. LOCCNT is number of locations, PLOC points to array of
538 locations. The arguments in ... are of __ubsan_type_descriptor type
539 and there are at most two of them, followed by NULL_TREE, followed
540 by optional extra arguments and another NULL_TREE. */
542 tree
543 ubsan_create_data (const char *name, int loccnt, const location_t *ploc, ...)
545 va_list args;
546 tree ret, t;
547 tree fields[6];
548 vec<tree, va_gc> *saved_args = NULL;
549 size_t i = 0;
550 int j;
552 /* Firstly, create a pointer to type descriptor type. */
553 tree td_type = ubsan_get_type_descriptor_type ();
554 td_type = build_pointer_type (td_type);
556 /* Create the structure type. */
557 ret = make_node (RECORD_TYPE);
558 for (j = 0; j < loccnt; j++)
560 gcc_checking_assert (i < 2);
561 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
562 ubsan_get_source_location_type ());
563 DECL_CONTEXT (fields[i]) = ret;
564 if (i)
565 DECL_CHAIN (fields[i - 1]) = fields[i];
566 i++;
569 va_start (args, ploc);
570 for (t = va_arg (args, tree); t != NULL_TREE;
571 i++, t = va_arg (args, tree))
573 gcc_checking_assert (i < 4);
574 /* Save the tree arguments for later use. */
575 vec_safe_push (saved_args, t);
576 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
577 td_type);
578 DECL_CONTEXT (fields[i]) = ret;
579 if (i)
580 DECL_CHAIN (fields[i - 1]) = fields[i];
583 for (t = va_arg (args, tree); t != NULL_TREE;
584 i++, t = va_arg (args, tree))
586 gcc_checking_assert (i < 6);
587 /* Save the tree arguments for later use. */
588 vec_safe_push (saved_args, t);
589 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
590 TREE_TYPE (t));
591 DECL_CONTEXT (fields[i]) = ret;
592 if (i)
593 DECL_CHAIN (fields[i - 1]) = fields[i];
595 va_end (args);
597 tree type_decl = build_decl (input_location, TYPE_DECL,
598 get_identifier (name), ret);
599 DECL_IGNORED_P (type_decl) = 1;
600 DECL_ARTIFICIAL (type_decl) = 1;
601 TYPE_FIELDS (ret) = fields[0];
602 TYPE_NAME (ret) = type_decl;
603 TYPE_STUB_DECL (ret) = type_decl;
604 layout_type (ret);
606 /* Now, fill in the type. */
607 char tmp_name[32];
608 static unsigned int ubsan_var_id_num;
609 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_data", ubsan_var_id_num++);
610 tree var = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name),
611 ret);
612 TREE_STATIC (var) = 1;
613 TREE_PUBLIC (var) = 0;
614 DECL_ARTIFICIAL (var) = 1;
615 DECL_IGNORED_P (var) = 1;
616 DECL_EXTERNAL (var) = 0;
618 vec<constructor_elt, va_gc> *v;
619 vec_alloc (v, i);
620 tree ctor = build_constructor (ret, v);
622 /* If desirable, set the __ubsan_source_location element. */
623 for (j = 0; j < loccnt; j++)
625 location_t loc = LOCATION_LOCUS (ploc[j]);
626 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, ubsan_source_location (loc));
629 size_t nelts = vec_safe_length (saved_args);
630 for (i = 0; i < nelts; i++)
632 t = (*saved_args)[i];
633 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, t);
636 TREE_CONSTANT (ctor) = 1;
637 TREE_STATIC (ctor) = 1;
638 DECL_INITIAL (var) = ctor;
639 varpool_node::finalize_decl (var);
641 return var;
644 /* Instrument the __builtin_unreachable call. We just call the libubsan
645 routine instead. */
647 bool
648 ubsan_instrument_unreachable (gimple_stmt_iterator *gsi)
650 gimple g;
651 location_t loc = gimple_location (gsi_stmt (*gsi));
653 if (flag_sanitize_undefined_trap_on_error)
654 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
655 else
657 tree data = ubsan_create_data ("__ubsan_unreachable_data", 1, &loc,
658 NULL_TREE, NULL_TREE);
659 data = build_fold_addr_expr_loc (loc, data);
660 tree fn
661 = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE);
662 g = gimple_build_call (fn, 1, data);
664 gimple_set_location (g, loc);
665 gsi_replace (gsi, g, false);
666 return false;
669 /* Return true if T is a call to a libubsan routine. */
671 bool
672 is_ubsan_builtin_p (tree t)
674 return TREE_CODE (t) == FUNCTION_DECL
675 && DECL_BUILT_IN_CLASS (t) == BUILT_IN_NORMAL
676 && strncmp (IDENTIFIER_POINTER (DECL_NAME (t)),
677 "__builtin___ubsan_", 18) == 0;
680 /* Expand the UBSAN_BOUNDS special builtin function. */
682 bool
683 ubsan_expand_bounds_ifn (gimple_stmt_iterator *gsi)
685 gimple stmt = gsi_stmt (*gsi);
686 location_t loc = gimple_location (stmt);
687 gcc_assert (gimple_call_num_args (stmt) == 3);
689 /* Pick up the arguments of the UBSAN_BOUNDS call. */
690 tree type = TREE_TYPE (TREE_TYPE (gimple_call_arg (stmt, 0)));
691 tree index = gimple_call_arg (stmt, 1);
692 tree orig_index_type = TREE_TYPE (index);
693 tree bound = gimple_call_arg (stmt, 2);
695 gimple_stmt_iterator gsi_orig = *gsi;
697 /* Create condition "if (index > bound)". */
698 basic_block then_bb, fallthru_bb;
699 gimple_stmt_iterator cond_insert_point
700 = create_cond_insert_point (gsi, false, false, true,
701 &then_bb, &fallthru_bb);
702 index = fold_convert (TREE_TYPE (bound), index);
703 index = force_gimple_operand_gsi (&cond_insert_point, index,
704 true, NULL_TREE,
705 false, GSI_NEW_STMT);
706 gimple g = gimple_build_cond (GT_EXPR, index, bound, NULL_TREE, NULL_TREE);
707 gimple_set_location (g, loc);
708 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
710 /* Generate __ubsan_handle_out_of_bounds call. */
711 *gsi = gsi_after_labels (then_bb);
712 if (flag_sanitize_undefined_trap_on_error)
713 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
714 else
716 tree data
717 = ubsan_create_data ("__ubsan_out_of_bounds_data", 1, &loc,
718 ubsan_type_descriptor (type, UBSAN_PRINT_ARRAY),
719 ubsan_type_descriptor (orig_index_type),
720 NULL_TREE, NULL_TREE);
721 data = build_fold_addr_expr_loc (loc, data);
722 enum built_in_function bcode
723 = (flag_sanitize_recover & SANITIZE_BOUNDS)
724 ? BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS
725 : BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS_ABORT;
726 tree fn = builtin_decl_explicit (bcode);
727 tree val = force_gimple_operand_gsi (gsi, ubsan_encode_value (index),
728 true, NULL_TREE, true,
729 GSI_SAME_STMT);
730 g = gimple_build_call (fn, 2, data, val);
732 gimple_set_location (g, loc);
733 gsi_insert_before (gsi, g, GSI_SAME_STMT);
735 /* Get rid of the UBSAN_BOUNDS call from the IR. */
736 unlink_stmt_vdef (stmt);
737 gsi_remove (&gsi_orig, true);
739 /* Point GSI to next logical statement. */
740 *gsi = gsi_start_bb (fallthru_bb);
741 return true;
744 /* Expand UBSAN_NULL internal call. The type is kept on the ckind
745 argument which is a constant, because the middle-end treats pointer
746 conversions as useless and therefore the type of the first argument
747 could be changed to any other pointer type. */
749 bool
750 ubsan_expand_null_ifn (gimple_stmt_iterator *gsip)
752 gimple_stmt_iterator gsi = *gsip;
753 gimple stmt = gsi_stmt (gsi);
754 location_t loc = gimple_location (stmt);
755 gcc_assert (gimple_call_num_args (stmt) == 3);
756 tree ptr = gimple_call_arg (stmt, 0);
757 tree ckind = gimple_call_arg (stmt, 1);
758 tree align = gimple_call_arg (stmt, 2);
759 tree check_align = NULL_TREE;
760 bool check_null;
762 basic_block cur_bb = gsi_bb (gsi);
764 gimple g;
765 if (!integer_zerop (align))
767 unsigned int ptralign = get_pointer_alignment (ptr) / BITS_PER_UNIT;
768 if (compare_tree_int (align, ptralign) == 1)
770 check_align = make_ssa_name (pointer_sized_int_node);
771 g = gimple_build_assign (check_align, NOP_EXPR, ptr);
772 gimple_set_location (g, loc);
773 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
776 check_null = (flag_sanitize & SANITIZE_NULL) != 0;
778 if (check_align == NULL_TREE && !check_null)
780 gsi_remove (gsip, true);
781 /* Unlink the UBSAN_NULLs vops before replacing it. */
782 unlink_stmt_vdef (stmt);
783 return true;
786 /* Split the original block holding the pointer dereference. */
787 edge e = split_block (cur_bb, stmt);
789 /* Get a hold on the 'condition block', the 'then block' and the
790 'else block'. */
791 basic_block cond_bb = e->src;
792 basic_block fallthru_bb = e->dest;
793 basic_block then_bb = create_empty_bb (cond_bb);
794 add_bb_to_loop (then_bb, cond_bb->loop_father);
795 loops_state_set (LOOPS_NEED_FIXUP);
797 /* Make an edge coming from the 'cond block' into the 'then block';
798 this edge is unlikely taken, so set up the probability accordingly. */
799 e = make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
800 e->probability = PROB_VERY_UNLIKELY;
802 /* Connect 'then block' with the 'else block'. This is needed
803 as the ubsan routines we call in the 'then block' are not noreturn.
804 The 'then block' only has one outcoming edge. */
805 make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);
807 /* Set up the fallthrough basic block. */
808 e = find_edge (cond_bb, fallthru_bb);
809 e->flags = EDGE_FALSE_VALUE;
810 e->count = cond_bb->count;
811 e->probability = REG_BR_PROB_BASE - PROB_VERY_UNLIKELY;
813 /* Update dominance info for the newly created then_bb; note that
814 fallthru_bb's dominance info has already been updated by
815 split_block. */
816 if (dom_info_available_p (CDI_DOMINATORS))
817 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
819 /* Put the ubsan builtin call into the newly created BB. */
820 if (flag_sanitize_undefined_trap_on_error)
821 g = gimple_build_call (builtin_decl_implicit (BUILT_IN_TRAP), 0);
822 else
824 enum built_in_function bcode
825 = (flag_sanitize_recover & ((check_align ? SANITIZE_ALIGNMENT : 0)
826 | (check_null ? SANITIZE_NULL : 0)))
827 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
828 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT;
829 tree fn = builtin_decl_implicit (bcode);
830 tree data
831 = ubsan_create_data ("__ubsan_null_data", 1, &loc,
832 ubsan_type_descriptor (TREE_TYPE (ckind),
833 UBSAN_PRINT_POINTER),
834 NULL_TREE,
835 align,
836 fold_convert (unsigned_char_type_node, ckind),
837 NULL_TREE);
838 data = build_fold_addr_expr_loc (loc, data);
839 g = gimple_build_call (fn, 2, data,
840 check_align ? check_align
841 : build_zero_cst (pointer_sized_int_node));
843 gimple_stmt_iterator gsi2 = gsi_start_bb (then_bb);
844 gimple_set_location (g, loc);
845 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
847 /* Unlink the UBSAN_NULLs vops before replacing it. */
848 unlink_stmt_vdef (stmt);
850 if (check_null)
852 g = gimple_build_cond (EQ_EXPR, ptr, build_int_cst (TREE_TYPE (ptr), 0),
853 NULL_TREE, NULL_TREE);
854 gimple_set_location (g, loc);
856 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
857 gsi_replace (&gsi, g, false);
860 if (check_align)
862 if (check_null)
864 /* Split the block with the condition again. */
865 e = split_block (cond_bb, stmt);
866 basic_block cond1_bb = e->src;
867 basic_block cond2_bb = e->dest;
869 /* Make an edge coming from the 'cond1 block' into the 'then block';
870 this edge is unlikely taken, so set up the probability
871 accordingly. */
872 e = make_edge (cond1_bb, then_bb, EDGE_TRUE_VALUE);
873 e->probability = PROB_VERY_UNLIKELY;
875 /* Set up the fallthrough basic block. */
876 e = find_edge (cond1_bb, cond2_bb);
877 e->flags = EDGE_FALSE_VALUE;
878 e->count = cond1_bb->count;
879 e->probability = REG_BR_PROB_BASE - PROB_VERY_UNLIKELY;
881 /* Update dominance info. */
882 if (dom_info_available_p (CDI_DOMINATORS))
884 set_immediate_dominator (CDI_DOMINATORS, fallthru_bb, cond1_bb);
885 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond1_bb);
888 gsi2 = gsi_start_bb (cond2_bb);
891 tree mask = build_int_cst (pointer_sized_int_node,
892 tree_to_uhwi (align) - 1);
893 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
894 BIT_AND_EXPR, check_align, mask);
895 gimple_set_location (g, loc);
896 if (check_null)
897 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
898 else
899 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
901 g = gimple_build_cond (NE_EXPR, gimple_assign_lhs (g),
902 build_int_cst (pointer_sized_int_node, 0),
903 NULL_TREE, NULL_TREE);
904 gimple_set_location (g, loc);
905 if (check_null)
906 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
907 else
908 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
909 gsi_replace (&gsi, g, false);
911 return false;
914 /* Expand UBSAN_OBJECT_SIZE internal call. */
916 bool
917 ubsan_expand_objsize_ifn (gimple_stmt_iterator *gsi)
919 gimple stmt = gsi_stmt (*gsi);
920 location_t loc = gimple_location (stmt);
921 gcc_assert (gimple_call_num_args (stmt) == 4);
923 tree ptr = gimple_call_arg (stmt, 0);
924 tree offset = gimple_call_arg (stmt, 1);
925 tree size = gimple_call_arg (stmt, 2);
926 tree ckind = gimple_call_arg (stmt, 3);
927 gimple_stmt_iterator gsi_orig = *gsi;
928 gimple g;
930 /* See if we can discard the check. */
931 if (TREE_CODE (size) != INTEGER_CST
932 || integer_all_onesp (size))
933 /* Yes, __builtin_object_size couldn't determine the
934 object size. */;
935 else
937 /* if (offset > objsize) */
938 basic_block then_bb, fallthru_bb;
939 gimple_stmt_iterator cond_insert_point
940 = create_cond_insert_point (gsi, false, false, true,
941 &then_bb, &fallthru_bb);
942 g = gimple_build_cond (GT_EXPR, offset, size, NULL_TREE, NULL_TREE);
943 gimple_set_location (g, loc);
944 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
946 /* Generate __ubsan_handle_type_mismatch call. */
947 *gsi = gsi_after_labels (then_bb);
948 if (flag_sanitize_undefined_trap_on_error)
949 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
950 else
952 tree data
953 = ubsan_create_data ("__ubsan_objsz_data", 1, &loc,
954 ubsan_type_descriptor (TREE_TYPE (ptr),
955 UBSAN_PRINT_POINTER),
956 NULL_TREE,
957 build_zero_cst (pointer_sized_int_node),
958 ckind,
959 NULL_TREE);
960 data = build_fold_addr_expr_loc (loc, data);
961 enum built_in_function bcode
962 = (flag_sanitize_recover & SANITIZE_OBJECT_SIZE)
963 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
964 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT;
965 tree p = make_ssa_name (pointer_sized_int_node);
966 g = gimple_build_assign (p, NOP_EXPR, ptr);
967 gimple_set_location (g, loc);
968 gsi_insert_before (gsi, g, GSI_SAME_STMT);
969 g = gimple_build_call (builtin_decl_explicit (bcode), 2, data, p);
971 gimple_set_location (g, loc);
972 gsi_insert_before (gsi, g, GSI_SAME_STMT);
974 /* Point GSI to next logical statement. */
975 *gsi = gsi_start_bb (fallthru_bb);
978 /* Get rid of the UBSAN_OBJECT_SIZE call from the IR. */
979 unlink_stmt_vdef (stmt);
980 gsi_remove (&gsi_orig, true);
981 return gsi_end_p (*gsi);
984 /* Cached __ubsan_vptr_type_cache decl. */
985 static GTY(()) tree ubsan_vptr_type_cache_decl;
987 /* Expand UBSAN_VPTR internal call. The type is kept on the ckind
988 argument which is a constant, because the middle-end treats pointer
989 conversions as useless and therefore the type of the first argument
990 could be changed to any other pointer type. */
992 bool
993 ubsan_expand_vptr_ifn (gimple_stmt_iterator *gsip)
995 gimple_stmt_iterator gsi = *gsip;
996 gimple stmt = gsi_stmt (gsi);
997 location_t loc = gimple_location (stmt);
998 gcc_assert (gimple_call_num_args (stmt) == 5);
999 tree op = gimple_call_arg (stmt, 0);
1000 tree vptr = gimple_call_arg (stmt, 1);
1001 tree str_hash = gimple_call_arg (stmt, 2);
1002 tree ti_decl_addr = gimple_call_arg (stmt, 3);
1003 tree ckind_tree = gimple_call_arg (stmt, 4);
1004 ubsan_null_ckind ckind = (ubsan_null_ckind) tree_to_uhwi (ckind_tree);
1005 tree type = TREE_TYPE (TREE_TYPE (ckind_tree));
1006 gimple g;
1007 basic_block fallthru_bb = NULL;
1009 if (ckind == UBSAN_DOWNCAST_POINTER)
1011 /* Guard everything with if (op != NULL) { ... }. */
1012 basic_block then_bb;
1013 gimple_stmt_iterator cond_insert_point
1014 = create_cond_insert_point (gsip, false, false, true,
1015 &then_bb, &fallthru_bb);
1016 g = gimple_build_cond (NE_EXPR, op, build_zero_cst (TREE_TYPE (op)),
1017 NULL_TREE, NULL_TREE);
1018 gimple_set_location (g, loc);
1019 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
1020 *gsip = gsi_after_labels (then_bb);
1021 gsi_remove (&gsi, false);
1022 gsi_insert_before (gsip, stmt, GSI_NEW_STMT);
1023 gsi = *gsip;
1026 tree htype = TREE_TYPE (str_hash);
1027 tree cst = wide_int_to_tree (htype,
1028 wi::uhwi (((uint64_t) 0x9ddfea08 << 32)
1029 | 0xeb382d69, 64));
1030 g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1031 vptr, str_hash);
1032 gimple_set_location (g, loc);
1033 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1034 g = gimple_build_assign (make_ssa_name (htype), MULT_EXPR,
1035 gimple_assign_lhs (g), cst);
1036 gimple_set_location (g, loc);
1037 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1038 tree t1 = gimple_assign_lhs (g);
1039 g = gimple_build_assign (make_ssa_name (htype), LSHIFT_EXPR,
1040 t1, build_int_cst (integer_type_node, 47));
1041 gimple_set_location (g, loc);
1042 tree t2 = gimple_assign_lhs (g);
1043 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1044 g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1045 vptr, t1);
1046 gimple_set_location (g, loc);
1047 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1048 g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1049 t2, gimple_assign_lhs (g));
1050 gimple_set_location (g, loc);
1051 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1052 g = gimple_build_assign (make_ssa_name (htype), MULT_EXPR,
1053 gimple_assign_lhs (g), cst);
1054 gimple_set_location (g, loc);
1055 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1056 tree t3 = gimple_assign_lhs (g);
1057 g = gimple_build_assign (make_ssa_name (htype), LSHIFT_EXPR,
1058 t3, build_int_cst (integer_type_node, 47));
1059 gimple_set_location (g, loc);
1060 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1061 g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1062 t3, gimple_assign_lhs (g));
1063 gimple_set_location (g, loc);
1064 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1065 g = gimple_build_assign (make_ssa_name (htype), MULT_EXPR,
1066 gimple_assign_lhs (g), cst);
1067 gimple_set_location (g, loc);
1068 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1069 if (!useless_type_conversion_p (pointer_sized_int_node, htype))
1071 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
1072 NOP_EXPR, gimple_assign_lhs (g));
1073 gimple_set_location (g, loc);
1074 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1076 tree hash = gimple_assign_lhs (g);
1078 if (ubsan_vptr_type_cache_decl == NULL_TREE)
1080 tree atype = build_array_type_nelts (pointer_sized_int_node, 128);
1081 tree array = build_decl (UNKNOWN_LOCATION, VAR_DECL,
1082 get_identifier ("__ubsan_vptr_type_cache"),
1083 atype);
1084 DECL_ARTIFICIAL (array) = 1;
1085 DECL_IGNORED_P (array) = 1;
1086 TREE_PUBLIC (array) = 1;
1087 TREE_STATIC (array) = 1;
1088 DECL_EXTERNAL (array) = 1;
1089 DECL_VISIBILITY (array) = VISIBILITY_DEFAULT;
1090 DECL_VISIBILITY_SPECIFIED (array) = 1;
1091 varpool_node::finalize_decl (array);
1092 ubsan_vptr_type_cache_decl = array;
1095 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
1096 BIT_AND_EXPR, hash,
1097 build_int_cst (pointer_sized_int_node, 127));
1098 gimple_set_location (g, loc);
1099 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1101 tree c = build4_loc (loc, ARRAY_REF, pointer_sized_int_node,
1102 ubsan_vptr_type_cache_decl, gimple_assign_lhs (g),
1103 NULL_TREE, NULL_TREE);
1104 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
1105 ARRAY_REF, c);
1106 gimple_set_location (g, loc);
1107 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1109 basic_block then_bb, fallthru2_bb;
1110 gimple_stmt_iterator cond_insert_point
1111 = create_cond_insert_point (gsip, false, false, true,
1112 &then_bb, &fallthru2_bb);
1113 g = gimple_build_cond (NE_EXPR, gimple_assign_lhs (g), hash,
1114 NULL_TREE, NULL_TREE);
1115 gimple_set_location (g, loc);
1116 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
1117 *gsip = gsi_after_labels (then_bb);
1118 if (fallthru_bb == NULL)
1119 fallthru_bb = fallthru2_bb;
1121 tree data
1122 = ubsan_create_data ("__ubsan_vptr_data", 1, &loc,
1123 ubsan_type_descriptor (type), NULL_TREE, ti_decl_addr,
1124 build_int_cst (unsigned_char_type_node, ckind),
1125 NULL_TREE);
1126 data = build_fold_addr_expr_loc (loc, data);
1127 enum built_in_function bcode
1128 = (flag_sanitize_recover & SANITIZE_VPTR)
1129 ? BUILT_IN_UBSAN_HANDLE_DYNAMIC_TYPE_CACHE_MISS
1130 : BUILT_IN_UBSAN_HANDLE_DYNAMIC_TYPE_CACHE_MISS_ABORT;
1132 g = gimple_build_call (builtin_decl_explicit (bcode), 3, data, op, hash);
1133 gimple_set_location (g, loc);
1134 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1136 /* Point GSI to next logical statement. */
1137 *gsip = gsi_start_bb (fallthru_bb);
1139 /* Get rid of the UBSAN_VPTR call from the IR. */
1140 unlink_stmt_vdef (stmt);
1141 gsi_remove (&gsi, true);
1142 return gsi_end_p (*gsip);
1145 /* Instrument a memory reference. BASE is the base of MEM, IS_LHS says
1146 whether the pointer is on the left hand side of the assignment. */
1148 static void
1149 instrument_mem_ref (tree mem, tree base, gimple_stmt_iterator *iter,
1150 bool is_lhs)
1152 enum ubsan_null_ckind ikind = is_lhs ? UBSAN_STORE_OF : UBSAN_LOAD_OF;
1153 unsigned int align = 0;
1154 if (flag_sanitize & SANITIZE_ALIGNMENT)
1156 align = min_align_of_type (TREE_TYPE (base));
1157 if (align <= 1)
1158 align = 0;
1160 if (align == 0 && (flag_sanitize & SANITIZE_NULL) == 0)
1161 return;
1162 tree t = TREE_OPERAND (base, 0);
1163 if (!POINTER_TYPE_P (TREE_TYPE (t)))
1164 return;
1165 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (TREE_TYPE (t))) && mem != base)
1166 ikind = UBSAN_MEMBER_ACCESS;
1167 tree kind = build_int_cst (TREE_TYPE (t), ikind);
1168 tree alignt = build_int_cst (pointer_sized_int_node, align);
1169 gcall *g = gimple_build_call_internal (IFN_UBSAN_NULL, 3, t, kind, alignt);
1170 gimple_set_location (g, gimple_location (gsi_stmt (*iter)));
1171 gsi_insert_before (iter, g, GSI_SAME_STMT);
1174 /* Perform the pointer instrumentation. */
1176 static void
1177 instrument_null (gimple_stmt_iterator gsi, bool is_lhs)
1179 gimple stmt = gsi_stmt (gsi);
1180 tree t = is_lhs ? gimple_get_lhs (stmt) : gimple_assign_rhs1 (stmt);
1181 tree base = get_base_address (t);
1182 const enum tree_code code = TREE_CODE (base);
1183 if (code == MEM_REF
1184 && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
1185 instrument_mem_ref (t, base, &gsi, is_lhs);
1188 /* Build an ubsan builtin call for the signed-integer-overflow
1189 sanitization. CODE says what kind of builtin are we building,
1190 LOC is a location, LHSTYPE is the type of LHS, OP0 and OP1
1191 are operands of the binary operation. */
1193 tree
1194 ubsan_build_overflow_builtin (tree_code code, location_t loc, tree lhstype,
1195 tree op0, tree op1)
1197 if (flag_sanitize_undefined_trap_on_error)
1198 return build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
1200 tree data = ubsan_create_data ("__ubsan_overflow_data", 1, &loc,
1201 ubsan_type_descriptor (lhstype), NULL_TREE,
1202 NULL_TREE);
1203 enum built_in_function fn_code;
1205 switch (code)
1207 case PLUS_EXPR:
1208 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1209 ? BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW
1210 : BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW_ABORT;
1211 break;
1212 case MINUS_EXPR:
1213 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1214 ? BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW
1215 : BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW_ABORT;
1216 break;
1217 case MULT_EXPR:
1218 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1219 ? BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW
1220 : BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW_ABORT;
1221 break;
1222 case NEGATE_EXPR:
1223 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1224 ? BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW
1225 : BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW_ABORT;
1226 break;
1227 default:
1228 gcc_unreachable ();
1230 tree fn = builtin_decl_explicit (fn_code);
1231 return build_call_expr_loc (loc, fn, 2 + (code != NEGATE_EXPR),
1232 build_fold_addr_expr_loc (loc, data),
1233 ubsan_encode_value (op0, true),
1234 op1 ? ubsan_encode_value (op1, true)
1235 : NULL_TREE);
1238 /* Perform the signed integer instrumentation. GSI is the iterator
1239 pointing at statement we are trying to instrument. */
1241 static void
1242 instrument_si_overflow (gimple_stmt_iterator gsi)
1244 gimple stmt = gsi_stmt (gsi);
1245 tree_code code = gimple_assign_rhs_code (stmt);
1246 tree lhs = gimple_assign_lhs (stmt);
1247 tree lhstype = TREE_TYPE (lhs);
1248 tree a, b;
1249 gimple g;
1251 /* If this is not a signed operation, don't instrument anything here.
1252 Also punt on bit-fields. */
1253 if (!INTEGRAL_TYPE_P (lhstype)
1254 || TYPE_OVERFLOW_WRAPS (lhstype)
1255 || GET_MODE_BITSIZE (TYPE_MODE (lhstype)) != TYPE_PRECISION (lhstype))
1256 return;
1258 switch (code)
1260 case MINUS_EXPR:
1261 case PLUS_EXPR:
1262 case MULT_EXPR:
1263 /* Transform
1264 i = u {+,-,*} 5;
1265 into
1266 i = UBSAN_CHECK_{ADD,SUB,MUL} (u, 5); */
1267 a = gimple_assign_rhs1 (stmt);
1268 b = gimple_assign_rhs2 (stmt);
1269 g = gimple_build_call_internal (code == PLUS_EXPR
1270 ? IFN_UBSAN_CHECK_ADD
1271 : code == MINUS_EXPR
1272 ? IFN_UBSAN_CHECK_SUB
1273 : IFN_UBSAN_CHECK_MUL, 2, a, b);
1274 gimple_call_set_lhs (g, lhs);
1275 gsi_replace (&gsi, g, false);
1276 break;
1277 case NEGATE_EXPR:
1278 /* Represent i = -u;
1280 i = UBSAN_CHECK_SUB (0, u); */
1281 a = build_int_cst (lhstype, 0);
1282 b = gimple_assign_rhs1 (stmt);
1283 g = gimple_build_call_internal (IFN_UBSAN_CHECK_SUB, 2, a, b);
1284 gimple_call_set_lhs (g, lhs);
1285 gsi_replace (&gsi, g, false);
1286 break;
1287 case ABS_EXPR:
1288 /* Transform i = ABS_EXPR<u>;
1289 into
1290 _N = UBSAN_CHECK_SUB (0, u);
1291 i = ABS_EXPR<_N>; */
1292 a = build_int_cst (lhstype, 0);
1293 b = gimple_assign_rhs1 (stmt);
1294 g = gimple_build_call_internal (IFN_UBSAN_CHECK_SUB, 2, a, b);
1295 a = make_ssa_name (lhstype);
1296 gimple_call_set_lhs (g, a);
1297 gimple_set_location (g, gimple_location (stmt));
1298 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
1299 gimple_assign_set_rhs1 (stmt, a);
1300 update_stmt (stmt);
1301 break;
1302 default:
1303 break;
1307 /* Instrument loads from (non-bitfield) bool and C++ enum values
1308 to check if the memory value is outside of the range of the valid
1309 type values. */
1311 static void
1312 instrument_bool_enum_load (gimple_stmt_iterator *gsi)
1314 gimple stmt = gsi_stmt (*gsi);
1315 tree rhs = gimple_assign_rhs1 (stmt);
1316 tree type = TREE_TYPE (rhs);
1317 tree minv = NULL_TREE, maxv = NULL_TREE;
1319 if (TREE_CODE (type) == BOOLEAN_TYPE && (flag_sanitize & SANITIZE_BOOL))
1321 minv = boolean_false_node;
1322 maxv = boolean_true_node;
1324 else if (TREE_CODE (type) == ENUMERAL_TYPE
1325 && (flag_sanitize & SANITIZE_ENUM)
1326 && TREE_TYPE (type) != NULL_TREE
1327 && TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE
1328 && (TYPE_PRECISION (TREE_TYPE (type))
1329 < GET_MODE_PRECISION (TYPE_MODE (type))))
1331 minv = TYPE_MIN_VALUE (TREE_TYPE (type));
1332 maxv = TYPE_MAX_VALUE (TREE_TYPE (type));
1334 else
1335 return;
1337 int modebitsize = GET_MODE_BITSIZE (TYPE_MODE (type));
1338 HOST_WIDE_INT bitsize, bitpos;
1339 tree offset;
1340 machine_mode mode;
1341 int volatilep = 0, unsignedp = 0;
1342 tree base = get_inner_reference (rhs, &bitsize, &bitpos, &offset, &mode,
1343 &unsignedp, &volatilep, false);
1344 tree utype = build_nonstandard_integer_type (modebitsize, 1);
1346 if ((TREE_CODE (base) == VAR_DECL && DECL_HARD_REGISTER (base))
1347 || (bitpos % modebitsize) != 0
1348 || bitsize != modebitsize
1349 || GET_MODE_BITSIZE (TYPE_MODE (utype)) != modebitsize
1350 || TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME)
1351 return;
1353 bool can_throw = stmt_could_throw_p (stmt);
1354 location_t loc = gimple_location (stmt);
1355 tree lhs = gimple_assign_lhs (stmt);
1356 tree ptype = build_pointer_type (TREE_TYPE (rhs));
1357 tree atype = reference_alias_ptr_type (rhs);
1358 gimple g = gimple_build_assign (make_ssa_name (ptype),
1359 build_fold_addr_expr (rhs));
1360 gimple_set_location (g, loc);
1361 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1362 tree mem = build2 (MEM_REF, utype, gimple_assign_lhs (g),
1363 build_int_cst (atype, 0));
1364 tree urhs = make_ssa_name (utype);
1365 if (can_throw)
1367 gimple_assign_set_lhs (stmt, urhs);
1368 g = gimple_build_assign (lhs, NOP_EXPR, urhs);
1369 gimple_set_location (g, loc);
1370 edge e = find_fallthru_edge (gimple_bb (stmt)->succs);
1371 gsi_insert_on_edge_immediate (e, g);
1372 gimple_assign_set_rhs_from_tree (gsi, mem);
1373 update_stmt (stmt);
1374 *gsi = gsi_for_stmt (g);
1375 g = stmt;
1377 else
1379 g = gimple_build_assign (urhs, mem);
1380 gimple_set_location (g, loc);
1381 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1383 minv = fold_convert (utype, minv);
1384 maxv = fold_convert (utype, maxv);
1385 if (!integer_zerop (minv))
1387 g = gimple_build_assign (make_ssa_name (utype), MINUS_EXPR, urhs, minv);
1388 gimple_set_location (g, loc);
1389 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1392 gimple_stmt_iterator gsi2 = *gsi;
1393 basic_block then_bb, fallthru_bb;
1394 *gsi = create_cond_insert_point (gsi, true, false, true,
1395 &then_bb, &fallthru_bb);
1396 g = gimple_build_cond (GT_EXPR, gimple_assign_lhs (g),
1397 int_const_binop (MINUS_EXPR, maxv, minv),
1398 NULL_TREE, NULL_TREE);
1399 gimple_set_location (g, loc);
1400 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1402 if (!can_throw)
1404 gimple_assign_set_rhs_with_ops (&gsi2, NOP_EXPR, urhs);
1405 update_stmt (stmt);
1408 gsi2 = gsi_after_labels (then_bb);
1409 if (flag_sanitize_undefined_trap_on_error)
1410 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1411 else
1413 tree data = ubsan_create_data ("__ubsan_invalid_value_data", 1, &loc,
1414 ubsan_type_descriptor (type), NULL_TREE,
1415 NULL_TREE);
1416 data = build_fold_addr_expr_loc (loc, data);
1417 enum built_in_function bcode
1418 = (flag_sanitize_recover & (TREE_CODE (type) == BOOLEAN_TYPE
1419 ? SANITIZE_BOOL : SANITIZE_ENUM))
1420 ? BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE
1421 : BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE_ABORT;
1422 tree fn = builtin_decl_explicit (bcode);
1424 tree val = force_gimple_operand_gsi (&gsi2, ubsan_encode_value (urhs),
1425 true, NULL_TREE, true,
1426 GSI_SAME_STMT);
1427 g = gimple_build_call (fn, 2, data, val);
1429 gimple_set_location (g, loc);
1430 gsi_insert_before (&gsi2, g, GSI_SAME_STMT);
1431 *gsi = gsi_for_stmt (stmt);
1434 /* Instrument float point-to-integer conversion. TYPE is an integer type of
1435 destination, EXPR is floating-point expression. ARG is what to pass
1436 the libubsan call as value, often EXPR itself. */
1438 tree
1439 ubsan_instrument_float_cast (location_t loc, tree type, tree expr, tree arg)
1441 tree expr_type = TREE_TYPE (expr);
1442 tree t, tt, fn, min, max;
1443 machine_mode mode = TYPE_MODE (expr_type);
1444 int prec = TYPE_PRECISION (type);
1445 bool uns_p = TYPE_UNSIGNED (type);
1447 /* Float to integer conversion first truncates toward zero, so
1448 even signed char c = 127.875f; is not problematic.
1449 Therefore, we should complain only if EXPR is unordered or smaller
1450 or equal than TYPE_MIN_VALUE - 1.0 or greater or equal than
1451 TYPE_MAX_VALUE + 1.0. */
1452 if (REAL_MODE_FORMAT (mode)->b == 2)
1454 /* For maximum, TYPE_MAX_VALUE might not be representable
1455 in EXPR_TYPE, e.g. if TYPE is 64-bit long long and
1456 EXPR_TYPE is IEEE single float, but TYPE_MAX_VALUE + 1.0 is
1457 either representable or infinity. */
1458 REAL_VALUE_TYPE maxval = dconst1;
1459 SET_REAL_EXP (&maxval, REAL_EXP (&maxval) + prec - !uns_p);
1460 real_convert (&maxval, mode, &maxval);
1461 max = build_real (expr_type, maxval);
1463 /* For unsigned, assume -1.0 is always representable. */
1464 if (uns_p)
1465 min = build_minus_one_cst (expr_type);
1466 else
1468 /* TYPE_MIN_VALUE is generally representable (or -inf),
1469 but TYPE_MIN_VALUE - 1.0 might not be. */
1470 REAL_VALUE_TYPE minval = dconstm1, minval2;
1471 SET_REAL_EXP (&minval, REAL_EXP (&minval) + prec - 1);
1472 real_convert (&minval, mode, &minval);
1473 real_arithmetic (&minval2, MINUS_EXPR, &minval, &dconst1);
1474 real_convert (&minval2, mode, &minval2);
1475 if (real_compare (EQ_EXPR, &minval, &minval2)
1476 && !real_isinf (&minval))
1478 /* If TYPE_MIN_VALUE - 1.0 is not representable and
1479 rounds to TYPE_MIN_VALUE, we need to subtract
1480 more. As REAL_MODE_FORMAT (mode)->p is the number
1481 of base digits, we want to subtract a number that
1482 will be 1 << (REAL_MODE_FORMAT (mode)->p - 1)
1483 times smaller than minval. */
1484 minval2 = dconst1;
1485 gcc_assert (prec > REAL_MODE_FORMAT (mode)->p);
1486 SET_REAL_EXP (&minval2,
1487 REAL_EXP (&minval2) + prec - 1
1488 - REAL_MODE_FORMAT (mode)->p + 1);
1489 real_arithmetic (&minval2, MINUS_EXPR, &minval, &minval2);
1490 real_convert (&minval2, mode, &minval2);
1492 min = build_real (expr_type, minval2);
1495 else if (REAL_MODE_FORMAT (mode)->b == 10)
1497 /* For _Decimal128 up to 34 decimal digits, - sign,
1498 dot, e, exponent. */
1499 char buf[64];
1500 mpfr_t m;
1501 int p = REAL_MODE_FORMAT (mode)->p;
1502 REAL_VALUE_TYPE maxval, minval;
1504 /* Use mpfr_snprintf rounding to compute the smallest
1505 representable decimal number greater or equal than
1506 1 << (prec - !uns_p). */
1507 mpfr_init2 (m, prec + 2);
1508 mpfr_set_ui_2exp (m, 1, prec - !uns_p, GMP_RNDN);
1509 mpfr_snprintf (buf, sizeof buf, "%.*RUe", p - 1, m);
1510 decimal_real_from_string (&maxval, buf);
1511 max = build_real (expr_type, maxval);
1513 /* For unsigned, assume -1.0 is always representable. */
1514 if (uns_p)
1515 min = build_minus_one_cst (expr_type);
1516 else
1518 /* Use mpfr_snprintf rounding to compute the largest
1519 representable decimal number less or equal than
1520 (-1 << (prec - 1)) - 1. */
1521 mpfr_set_si_2exp (m, -1, prec - 1, GMP_RNDN);
1522 mpfr_sub_ui (m, m, 1, GMP_RNDN);
1523 mpfr_snprintf (buf, sizeof buf, "%.*RDe", p - 1, m);
1524 decimal_real_from_string (&minval, buf);
1525 min = build_real (expr_type, minval);
1527 mpfr_clear (m);
1529 else
1530 return NULL_TREE;
1532 t = fold_build2 (UNLE_EXPR, boolean_type_node, expr, min);
1533 tt = fold_build2 (UNGE_EXPR, boolean_type_node, expr, max);
1534 t = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t, tt);
1535 if (integer_zerop (t))
1536 return NULL_TREE;
1538 if (flag_sanitize_undefined_trap_on_error)
1539 fn = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
1540 else
1542 /* Create the __ubsan_handle_float_cast_overflow fn call. */
1543 tree data = ubsan_create_data ("__ubsan_float_cast_overflow_data", 0,
1544 NULL, ubsan_type_descriptor (expr_type),
1545 ubsan_type_descriptor (type), NULL_TREE,
1546 NULL_TREE);
1547 enum built_in_function bcode
1548 = (flag_sanitize_recover & SANITIZE_FLOAT_CAST)
1549 ? BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW
1550 : BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW_ABORT;
1551 fn = builtin_decl_explicit (bcode);
1552 fn = build_call_expr_loc (loc, fn, 2,
1553 build_fold_addr_expr_loc (loc, data),
1554 ubsan_encode_value (arg, false));
1557 return fold_build3 (COND_EXPR, void_type_node, t, fn, integer_zero_node);
1560 /* Instrument values passed to function arguments with nonnull attribute. */
1562 static void
1563 instrument_nonnull_arg (gimple_stmt_iterator *gsi)
1565 gimple stmt = gsi_stmt (*gsi);
1566 location_t loc[2];
1567 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
1568 while for nonnull sanitization it is clear. */
1569 int save_flag_delete_null_pointer_checks = flag_delete_null_pointer_checks;
1570 flag_delete_null_pointer_checks = 1;
1571 loc[0] = gimple_location (stmt);
1572 loc[1] = UNKNOWN_LOCATION;
1573 for (unsigned int i = 0; i < gimple_call_num_args (stmt); i++)
1575 tree arg = gimple_call_arg (stmt, i);
1576 if (POINTER_TYPE_P (TREE_TYPE (arg))
1577 && infer_nonnull_range (stmt, arg, false, true))
1579 gimple g;
1580 if (!is_gimple_val (arg))
1582 g = gimple_build_assign (make_ssa_name (TREE_TYPE (arg)), arg);
1583 gimple_set_location (g, loc[0]);
1584 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1585 arg = gimple_assign_lhs (g);
1588 basic_block then_bb, fallthru_bb;
1589 *gsi = create_cond_insert_point (gsi, true, false, true,
1590 &then_bb, &fallthru_bb);
1591 g = gimple_build_cond (EQ_EXPR, arg,
1592 build_zero_cst (TREE_TYPE (arg)),
1593 NULL_TREE, NULL_TREE);
1594 gimple_set_location (g, loc[0]);
1595 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1597 *gsi = gsi_after_labels (then_bb);
1598 if (flag_sanitize_undefined_trap_on_error)
1599 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1600 else
1602 tree data = ubsan_create_data ("__ubsan_nonnull_arg_data",
1603 2, loc, NULL_TREE,
1604 build_int_cst (integer_type_node,
1605 i + 1),
1606 NULL_TREE);
1607 data = build_fold_addr_expr_loc (loc[0], data);
1608 enum built_in_function bcode
1609 = (flag_sanitize_recover & SANITIZE_NONNULL_ATTRIBUTE)
1610 ? BUILT_IN_UBSAN_HANDLE_NONNULL_ARG
1611 : BUILT_IN_UBSAN_HANDLE_NONNULL_ARG_ABORT;
1612 tree fn = builtin_decl_explicit (bcode);
1614 g = gimple_build_call (fn, 1, data);
1616 gimple_set_location (g, loc[0]);
1617 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1619 *gsi = gsi_for_stmt (stmt);
1621 flag_delete_null_pointer_checks = save_flag_delete_null_pointer_checks;
1624 /* Instrument returns in functions with returns_nonnull attribute. */
1626 static void
1627 instrument_nonnull_return (gimple_stmt_iterator *gsi)
1629 greturn *stmt = as_a <greturn *> (gsi_stmt (*gsi));
1630 location_t loc[2];
1631 tree arg = gimple_return_retval (stmt);
1632 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
1633 while for nonnull return sanitization it is clear. */
1634 int save_flag_delete_null_pointer_checks = flag_delete_null_pointer_checks;
1635 flag_delete_null_pointer_checks = 1;
1636 loc[0] = gimple_location (stmt);
1637 loc[1] = UNKNOWN_LOCATION;
1638 if (arg
1639 && POINTER_TYPE_P (TREE_TYPE (arg))
1640 && is_gimple_val (arg)
1641 && infer_nonnull_range (stmt, arg, false, true))
1643 basic_block then_bb, fallthru_bb;
1644 *gsi = create_cond_insert_point (gsi, true, false, true,
1645 &then_bb, &fallthru_bb);
1646 gimple g = gimple_build_cond (EQ_EXPR, arg,
1647 build_zero_cst (TREE_TYPE (arg)),
1648 NULL_TREE, NULL_TREE);
1649 gimple_set_location (g, loc[0]);
1650 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1652 *gsi = gsi_after_labels (then_bb);
1653 if (flag_sanitize_undefined_trap_on_error)
1654 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1655 else
1657 tree data = ubsan_create_data ("__ubsan_nonnull_return_data",
1658 2, loc, NULL_TREE, NULL_TREE);
1659 data = build_fold_addr_expr_loc (loc[0], data);
1660 enum built_in_function bcode
1661 = (flag_sanitize_recover & SANITIZE_RETURNS_NONNULL_ATTRIBUTE)
1662 ? BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN
1663 : BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_ABORT;
1664 tree fn = builtin_decl_explicit (bcode);
1666 g = gimple_build_call (fn, 1, data);
1668 gimple_set_location (g, loc[0]);
1669 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1670 *gsi = gsi_for_stmt (stmt);
1672 flag_delete_null_pointer_checks = save_flag_delete_null_pointer_checks;
1675 /* Instrument memory references. Here we check whether the pointer
1676 points to an out-of-bounds location. */
1678 static void
1679 instrument_object_size (gimple_stmt_iterator *gsi, bool is_lhs)
1681 gimple stmt = gsi_stmt (*gsi);
1682 location_t loc = gimple_location (stmt);
1683 tree t = is_lhs ? gimple_get_lhs (stmt) : gimple_assign_rhs1 (stmt);
1684 tree type;
1685 tree index = NULL_TREE;
1686 HOST_WIDE_INT size_in_bytes;
1688 type = TREE_TYPE (t);
1689 if (VOID_TYPE_P (type))
1690 return;
1692 switch (TREE_CODE (t))
1694 case COMPONENT_REF:
1695 if (TREE_CODE (t) == COMPONENT_REF
1696 && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1)) != NULL_TREE)
1698 tree repr = DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1));
1699 t = build3 (COMPONENT_REF, TREE_TYPE (repr), TREE_OPERAND (t, 0),
1700 repr, NULL_TREE);
1702 break;
1703 case ARRAY_REF:
1704 index = TREE_OPERAND (t, 1);
1705 break;
1706 case INDIRECT_REF:
1707 case MEM_REF:
1708 case VAR_DECL:
1709 case PARM_DECL:
1710 case RESULT_DECL:
1711 break;
1712 default:
1713 return;
1716 size_in_bytes = int_size_in_bytes (type);
1717 if (size_in_bytes <= 0)
1718 return;
1720 HOST_WIDE_INT bitsize, bitpos;
1721 tree offset;
1722 machine_mode mode;
1723 int volatilep = 0, unsignedp = 0;
1724 tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset, &mode,
1725 &unsignedp, &volatilep, false);
1727 if (bitpos % BITS_PER_UNIT != 0
1728 || bitsize != size_in_bytes * BITS_PER_UNIT)
1729 return;
1731 bool decl_p = DECL_P (inner);
1732 tree base;
1733 if (decl_p)
1734 base = inner;
1735 else if (TREE_CODE (inner) == MEM_REF)
1736 base = TREE_OPERAND (inner, 0);
1737 else
1738 return;
1739 tree ptr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (t)), t);
1741 while (TREE_CODE (base) == SSA_NAME)
1743 gimple def_stmt = SSA_NAME_DEF_STMT (base);
1744 if (gimple_assign_ssa_name_copy_p (def_stmt)
1745 || (gimple_assign_cast_p (def_stmt)
1746 && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (def_stmt))))
1747 || (is_gimple_assign (def_stmt)
1748 && gimple_assign_rhs_code (def_stmt) == POINTER_PLUS_EXPR))
1750 tree rhs1 = gimple_assign_rhs1 (def_stmt);
1751 if (TREE_CODE (rhs1) == SSA_NAME
1752 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs1))
1753 break;
1754 else
1755 base = rhs1;
1757 else
1758 break;
1761 if (!POINTER_TYPE_P (TREE_TYPE (base)) && !DECL_P (base))
1762 return;
1764 tree sizet;
1765 tree base_addr = base;
1766 if (decl_p)
1767 base_addr = build1 (ADDR_EXPR,
1768 build_pointer_type (TREE_TYPE (base)), base);
1769 unsigned HOST_WIDE_INT size = compute_builtin_object_size (base_addr, 0);
1770 if (size != (unsigned HOST_WIDE_INT) -1)
1771 sizet = build_int_cst (sizetype, size);
1772 else if (optimize)
1774 if (LOCATION_LOCUS (loc) == UNKNOWN_LOCATION)
1775 loc = input_location;
1776 /* Generate __builtin_object_size call. */
1777 sizet = builtin_decl_explicit (BUILT_IN_OBJECT_SIZE);
1778 sizet = build_call_expr_loc (loc, sizet, 2, base_addr,
1779 integer_zero_node);
1780 sizet = force_gimple_operand_gsi (gsi, sizet, false, NULL_TREE, true,
1781 GSI_SAME_STMT);
1783 else
1784 return;
1786 /* Generate UBSAN_OBJECT_SIZE (ptr, ptr+sizeof(*ptr)-base, objsize, ckind)
1787 call. */
1788 /* ptr + sizeof (*ptr) - base */
1789 t = fold_build2 (MINUS_EXPR, sizetype,
1790 fold_convert (pointer_sized_int_node, ptr),
1791 fold_convert (pointer_sized_int_node, base_addr));
1792 t = fold_build2 (PLUS_EXPR, sizetype, t, TYPE_SIZE_UNIT (type));
1794 /* Perhaps we can omit the check. */
1795 if (TREE_CODE (t) == INTEGER_CST
1796 && TREE_CODE (sizet) == INTEGER_CST
1797 && tree_int_cst_le (t, sizet))
1798 return;
1800 if (index != NULL_TREE
1801 && TREE_CODE (index) == SSA_NAME
1802 && TREE_CODE (sizet) == INTEGER_CST)
1804 gimple def = SSA_NAME_DEF_STMT (index);
1805 if (is_gimple_assign (def)
1806 && gimple_assign_rhs_code (def) == BIT_AND_EXPR
1807 && TREE_CODE (gimple_assign_rhs2 (def)) == INTEGER_CST)
1809 tree cst = gimple_assign_rhs2 (def);
1810 tree sz = fold_build2 (EXACT_DIV_EXPR, sizetype, sizet,
1811 TYPE_SIZE_UNIT (type));
1812 if (tree_int_cst_sgn (cst) >= 0
1813 && tree_int_cst_lt (cst, sz))
1814 return;
1818 /* Nope. Emit the check. */
1819 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE, true,
1820 GSI_SAME_STMT);
1821 ptr = force_gimple_operand_gsi (gsi, ptr, true, NULL_TREE, true,
1822 GSI_SAME_STMT);
1823 tree ckind = build_int_cst (unsigned_char_type_node,
1824 is_lhs ? UBSAN_STORE_OF : UBSAN_LOAD_OF);
1825 gimple g = gimple_build_call_internal (IFN_UBSAN_OBJECT_SIZE, 4,
1826 ptr, t, sizet, ckind);
1827 gimple_set_location (g, loc);
1828 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1831 /* True if we want to play UBSan games in the current function. */
1833 bool
1834 do_ubsan_in_current_function ()
1836 return (current_function_decl != NULL_TREE
1837 && !lookup_attribute ("no_sanitize_undefined",
1838 DECL_ATTRIBUTES (current_function_decl)));
1841 namespace {
1843 const pass_data pass_data_ubsan =
1845 GIMPLE_PASS, /* type */
1846 "ubsan", /* name */
1847 OPTGROUP_NONE, /* optinfo_flags */
1848 TV_TREE_UBSAN, /* tv_id */
1849 ( PROP_cfg | PROP_ssa ), /* properties_required */
1850 0, /* properties_provided */
1851 0, /* properties_destroyed */
1852 0, /* todo_flags_start */
1853 TODO_update_ssa, /* todo_flags_finish */
1856 class pass_ubsan : public gimple_opt_pass
1858 public:
1859 pass_ubsan (gcc::context *ctxt)
1860 : gimple_opt_pass (pass_data_ubsan, ctxt)
1863 /* opt_pass methods: */
1864 virtual bool gate (function *)
1866 return flag_sanitize & (SANITIZE_NULL | SANITIZE_SI_OVERFLOW
1867 | SANITIZE_BOOL | SANITIZE_ENUM
1868 | SANITIZE_ALIGNMENT
1869 | SANITIZE_NONNULL_ATTRIBUTE
1870 | SANITIZE_RETURNS_NONNULL_ATTRIBUTE
1871 | SANITIZE_OBJECT_SIZE)
1872 && do_ubsan_in_current_function ();
1875 virtual unsigned int execute (function *);
1877 }; // class pass_ubsan
1879 unsigned int
1880 pass_ubsan::execute (function *fun)
1882 basic_block bb;
1883 gimple_stmt_iterator gsi;
1885 initialize_sanitizer_builtins ();
1887 FOR_EACH_BB_FN (bb, fun)
1889 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
1891 gimple stmt = gsi_stmt (gsi);
1892 if (is_gimple_debug (stmt) || gimple_clobber_p (stmt))
1894 gsi_next (&gsi);
1895 continue;
1898 if ((flag_sanitize & SANITIZE_SI_OVERFLOW)
1899 && is_gimple_assign (stmt))
1900 instrument_si_overflow (gsi);
1902 if (flag_sanitize & (SANITIZE_NULL | SANITIZE_ALIGNMENT))
1904 if (gimple_store_p (stmt))
1905 instrument_null (gsi, true);
1906 if (gimple_assign_load_p (stmt))
1907 instrument_null (gsi, false);
1910 if (flag_sanitize & (SANITIZE_BOOL | SANITIZE_ENUM)
1911 && gimple_assign_load_p (stmt))
1913 instrument_bool_enum_load (&gsi);
1914 bb = gimple_bb (stmt);
1917 if ((flag_sanitize & SANITIZE_NONNULL_ATTRIBUTE)
1918 && is_gimple_call (stmt)
1919 && !gimple_call_internal_p (stmt))
1921 instrument_nonnull_arg (&gsi);
1922 bb = gimple_bb (stmt);
1925 if ((flag_sanitize & SANITIZE_RETURNS_NONNULL_ATTRIBUTE)
1926 && gimple_code (stmt) == GIMPLE_RETURN)
1928 instrument_nonnull_return (&gsi);
1929 bb = gimple_bb (stmt);
1932 if (flag_sanitize & SANITIZE_OBJECT_SIZE)
1934 if (gimple_store_p (stmt))
1935 instrument_object_size (&gsi, true);
1936 if (gimple_assign_load_p (stmt))
1937 instrument_object_size (&gsi, false);
1940 gsi_next (&gsi);
1943 return 0;
1946 } // anon namespace
1948 gimple_opt_pass *
1949 make_pass_ubsan (gcc::context *ctxt)
1951 return new pass_ubsan (ctxt);
1954 #include "gt-ubsan.h"