Remove assert in get_def_bb_for_const
[official-gcc.git] / gcc / ubsan.c
blobc5543f821d8bcf761889d7b75606f29de1da0c79
1 /* UndefinedBehaviorSanitizer, undefined behavior detector.
2 Copyright (C) 2013-2016 Free Software Foundation, Inc.
3 Contributed by Marek Polacek <polacek@redhat.com>
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "backend.h"
25 #include "rtl.h"
26 #include "c-family/c-common.h"
27 #include "gimple.h"
28 #include "cfghooks.h"
29 #include "tree-pass.h"
30 #include "tm_p.h"
31 #include "ssa.h"
32 #include "cgraph.h"
33 #include "tree-pretty-print.h"
34 #include "stor-layout.h"
35 #include "cfganal.h"
36 #include "gimple-iterator.h"
37 #include "output.h"
38 #include "cfgloop.h"
39 #include "ubsan.h"
40 #include "expr.h"
41 #include "asan.h"
42 #include "gimplify-me.h"
43 #include "dfp.h"
44 #include "builtins.h"
45 #include "tree-object-size.h"
46 #include "tree-cfg.h"
48 /* Map from a tree to a VAR_DECL tree. */
50 struct GTY((for_user)) tree_type_map {
51 struct tree_map_base type;
52 tree decl;
55 struct tree_type_map_cache_hasher : ggc_cache_ptr_hash<tree_type_map>
57 static inline hashval_t
58 hash (tree_type_map *t)
60 return TYPE_UID (t->type.from);
63 static inline bool
64 equal (tree_type_map *a, tree_type_map *b)
66 return a->type.from == b->type.from;
69 static int
70 keep_cache_entry (tree_type_map *&m)
72 return ggc_marked_p (m->type.from);
76 static GTY ((cache))
77 hash_table<tree_type_map_cache_hasher> *decl_tree_for_type;
79 /* Lookup a VAR_DECL for TYPE, and return it if we find one. */
81 static tree
82 decl_for_type_lookup (tree type)
84 /* If the hash table is not initialized yet, create it now. */
85 if (decl_tree_for_type == NULL)
87 decl_tree_for_type
88 = hash_table<tree_type_map_cache_hasher>::create_ggc (10);
89 /* That also means we don't have to bother with the lookup. */
90 return NULL_TREE;
93 struct tree_type_map *h, in;
94 in.type.from = type;
96 h = decl_tree_for_type->find_with_hash (&in, TYPE_UID (type));
97 return h ? h->decl : NULL_TREE;
100 /* Insert a mapping TYPE->DECL in the VAR_DECL for type hashtable. */
102 static void
103 decl_for_type_insert (tree type, tree decl)
105 struct tree_type_map *h;
107 h = ggc_alloc<tree_type_map> ();
108 h->type.from = type;
109 h->decl = decl;
110 *decl_tree_for_type->find_slot_with_hash (h, TYPE_UID (type), INSERT) = h;
113 /* Helper routine, which encodes a value in the pointer_sized_int_node.
114 Arguments with precision <= POINTER_SIZE are passed directly,
115 the rest is passed by reference. T is a value we are to encode.
116 IN_EXPAND_P is true if this function is called during expansion. */
118 tree
119 ubsan_encode_value (tree t, bool in_expand_p)
121 tree type = TREE_TYPE (t);
122 const unsigned int bitsize = GET_MODE_BITSIZE (TYPE_MODE (type));
123 if (bitsize <= POINTER_SIZE)
124 switch (TREE_CODE (type))
126 case BOOLEAN_TYPE:
127 case ENUMERAL_TYPE:
128 case INTEGER_TYPE:
129 return fold_build1 (NOP_EXPR, pointer_sized_int_node, t);
130 case REAL_TYPE:
132 tree itype = build_nonstandard_integer_type (bitsize, true);
133 t = fold_build1 (VIEW_CONVERT_EXPR, itype, t);
134 return fold_convert (pointer_sized_int_node, t);
136 default:
137 gcc_unreachable ();
139 else
141 if (!DECL_P (t) || !TREE_ADDRESSABLE (t))
143 /* The reason for this is that we don't want to pessimize
144 code by making vars unnecessarily addressable. */
145 tree var = create_tmp_var (type);
146 tree tem = build2 (MODIFY_EXPR, void_type_node, var, t);
147 if (in_expand_p)
149 rtx mem
150 = assign_stack_temp_for_type (TYPE_MODE (type),
151 GET_MODE_SIZE (TYPE_MODE (type)),
152 type);
153 SET_DECL_RTL (var, mem);
154 expand_assignment (var, t, false);
155 return build_fold_addr_expr (var);
157 t = build_fold_addr_expr (var);
158 return build2 (COMPOUND_EXPR, TREE_TYPE (t), tem, t);
160 else
161 return build_fold_addr_expr (t);
165 /* Cached ubsan_get_type_descriptor_type () return value. */
166 static GTY(()) tree ubsan_type_descriptor_type;
168 /* Build
169 struct __ubsan_type_descriptor
171 unsigned short __typekind;
172 unsigned short __typeinfo;
173 char __typename[];
175 type. */
177 static tree
178 ubsan_get_type_descriptor_type (void)
180 static const char *field_names[3]
181 = { "__typekind", "__typeinfo", "__typename" };
182 tree fields[3], ret;
184 if (ubsan_type_descriptor_type)
185 return ubsan_type_descriptor_type;
187 tree itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
188 tree flex_arr_type = build_array_type (char_type_node, itype);
190 ret = make_node (RECORD_TYPE);
191 for (int i = 0; i < 3; i++)
193 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
194 get_identifier (field_names[i]),
195 (i == 2) ? flex_arr_type
196 : short_unsigned_type_node);
197 DECL_CONTEXT (fields[i]) = ret;
198 if (i)
199 DECL_CHAIN (fields[i - 1]) = fields[i];
201 tree type_decl = build_decl (input_location, TYPE_DECL,
202 get_identifier ("__ubsan_type_descriptor"),
203 ret);
204 DECL_IGNORED_P (type_decl) = 1;
205 DECL_ARTIFICIAL (type_decl) = 1;
206 TYPE_FIELDS (ret) = fields[0];
207 TYPE_NAME (ret) = type_decl;
208 TYPE_STUB_DECL (ret) = type_decl;
209 layout_type (ret);
210 ubsan_type_descriptor_type = ret;
211 return ret;
214 /* Cached ubsan_get_source_location_type () return value. */
215 static GTY(()) tree ubsan_source_location_type;
217 /* Build
218 struct __ubsan_source_location
220 const char *__filename;
221 unsigned int __line;
222 unsigned int __column;
224 type. */
226 tree
227 ubsan_get_source_location_type (void)
229 static const char *field_names[3]
230 = { "__filename", "__line", "__column" };
231 tree fields[3], ret;
232 if (ubsan_source_location_type)
233 return ubsan_source_location_type;
235 tree const_char_type = build_qualified_type (char_type_node,
236 TYPE_QUAL_CONST);
238 ret = make_node (RECORD_TYPE);
239 for (int i = 0; i < 3; i++)
241 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
242 get_identifier (field_names[i]),
243 (i == 0) ? build_pointer_type (const_char_type)
244 : unsigned_type_node);
245 DECL_CONTEXT (fields[i]) = ret;
246 if (i)
247 DECL_CHAIN (fields[i - 1]) = fields[i];
249 tree type_decl = build_decl (input_location, TYPE_DECL,
250 get_identifier ("__ubsan_source_location"),
251 ret);
252 DECL_IGNORED_P (type_decl) = 1;
253 DECL_ARTIFICIAL (type_decl) = 1;
254 TYPE_FIELDS (ret) = fields[0];
255 TYPE_NAME (ret) = type_decl;
256 TYPE_STUB_DECL (ret) = type_decl;
257 layout_type (ret);
258 ubsan_source_location_type = ret;
259 return ret;
262 /* Helper routine that returns a CONSTRUCTOR of __ubsan_source_location
263 type with its fields filled from a location_t LOC. */
265 static tree
266 ubsan_source_location (location_t loc)
268 expanded_location xloc;
269 tree type = ubsan_get_source_location_type ();
271 xloc = expand_location (loc);
272 tree str;
273 if (xloc.file == NULL)
275 str = build_int_cst (ptr_type_node, 0);
276 xloc.line = 0;
277 xloc.column = 0;
279 else
281 /* Fill in the values from LOC. */
282 size_t len = strlen (xloc.file) + 1;
283 str = build_string (len, xloc.file);
284 TREE_TYPE (str) = build_array_type_nelts (char_type_node, len);
285 TREE_READONLY (str) = 1;
286 TREE_STATIC (str) = 1;
287 str = build_fold_addr_expr (str);
289 tree ctor = build_constructor_va (type, 3, NULL_TREE, str, NULL_TREE,
290 build_int_cst (unsigned_type_node,
291 xloc.line), NULL_TREE,
292 build_int_cst (unsigned_type_node,
293 xloc.column));
294 TREE_CONSTANT (ctor) = 1;
295 TREE_STATIC (ctor) = 1;
297 return ctor;
300 /* This routine returns a magic number for TYPE. */
302 static unsigned short
303 get_ubsan_type_info_for_type (tree type)
305 if (TREE_CODE (type) == REAL_TYPE)
306 return tree_to_uhwi (TYPE_SIZE (type));
307 else if (INTEGRAL_TYPE_P (type))
309 int prec = exact_log2 (tree_to_uhwi (TYPE_SIZE (type)));
310 gcc_assert (prec != -1);
311 return (prec << 1) | !TYPE_UNSIGNED (type);
313 else
314 return 0;
317 /* Helper routine that returns ADDR_EXPR of a VAR_DECL of a type
318 descriptor. It first looks into the hash table; if not found,
319 create the VAR_DECL, put it into the hash table and return the
320 ADDR_EXPR of it. TYPE describes a particular type. PSTYLE is
321 an enum controlling how we want to print the type. */
323 tree
324 ubsan_type_descriptor (tree type, enum ubsan_print_style pstyle)
326 /* See through any typedefs. */
327 type = TYPE_MAIN_VARIANT (type);
329 tree decl = decl_for_type_lookup (type);
330 /* It is possible that some of the earlier created DECLs were found
331 unused, in that case they weren't emitted and varpool_node::get
332 returns NULL node on them. But now we really need them. Thus,
333 renew them here. */
334 if (decl != NULL_TREE && varpool_node::get (decl))
335 return build_fold_addr_expr (decl);
337 tree dtype = ubsan_get_type_descriptor_type ();
338 tree type2 = type;
339 const char *tname = NULL;
340 pretty_printer pretty_name;
341 unsigned char deref_depth = 0;
342 unsigned short tkind, tinfo;
344 /* Get the name of the type, or the name of the pointer type. */
345 if (pstyle == UBSAN_PRINT_POINTER)
347 gcc_assert (POINTER_TYPE_P (type));
348 type2 = TREE_TYPE (type);
350 /* Remove any '*' operators from TYPE. */
351 while (POINTER_TYPE_P (type2))
352 deref_depth++, type2 = TREE_TYPE (type2);
354 if (TREE_CODE (type2) == METHOD_TYPE)
355 type2 = TYPE_METHOD_BASETYPE (type2);
358 /* If an array, get its type. */
359 type2 = strip_array_types (type2);
361 if (pstyle == UBSAN_PRINT_ARRAY)
363 while (POINTER_TYPE_P (type2))
364 deref_depth++, type2 = TREE_TYPE (type2);
367 if (TYPE_NAME (type2) != NULL)
369 if (TREE_CODE (TYPE_NAME (type2)) == IDENTIFIER_NODE)
370 tname = IDENTIFIER_POINTER (TYPE_NAME (type2));
371 else if (DECL_NAME (TYPE_NAME (type2)) != NULL)
372 tname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type2)));
375 if (tname == NULL)
376 /* We weren't able to determine the type name. */
377 tname = "<unknown>";
379 if (pstyle == UBSAN_PRINT_POINTER)
381 pp_printf (&pretty_name, "'%s%s%s%s%s%s%s",
382 TYPE_VOLATILE (type2) ? "volatile " : "",
383 TYPE_READONLY (type2) ? "const " : "",
384 TYPE_RESTRICT (type2) ? "restrict " : "",
385 TYPE_ATOMIC (type2) ? "_Atomic " : "",
386 TREE_CODE (type2) == RECORD_TYPE
387 ? "struct "
388 : TREE_CODE (type2) == UNION_TYPE
389 ? "union " : "", tname,
390 deref_depth == 0 ? "" : " ");
391 while (deref_depth-- > 0)
392 pp_star (&pretty_name);
393 pp_quote (&pretty_name);
395 else if (pstyle == UBSAN_PRINT_ARRAY)
397 /* Pretty print the array dimensions. */
398 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
399 tree t = type;
400 pp_printf (&pretty_name, "'%s ", tname);
401 while (deref_depth-- > 0)
402 pp_star (&pretty_name);
403 while (TREE_CODE (t) == ARRAY_TYPE)
405 pp_left_bracket (&pretty_name);
406 tree dom = TYPE_DOMAIN (t);
407 if (dom && TREE_CODE (TYPE_MAX_VALUE (dom)) == INTEGER_CST)
409 if (tree_fits_uhwi_p (TYPE_MAX_VALUE (dom))
410 && tree_to_uhwi (TYPE_MAX_VALUE (dom)) + 1 != 0)
411 pp_printf (&pretty_name, HOST_WIDE_INT_PRINT_DEC,
412 tree_to_uhwi (TYPE_MAX_VALUE (dom)) + 1);
413 else
414 pp_wide_int (&pretty_name,
415 wi::add (wi::to_widest (TYPE_MAX_VALUE (dom)), 1),
416 TYPE_SIGN (TREE_TYPE (dom)));
418 else
419 /* ??? We can't determine the variable name; print VLA unspec. */
420 pp_star (&pretty_name);
421 pp_right_bracket (&pretty_name);
422 t = TREE_TYPE (t);
424 pp_quote (&pretty_name);
426 /* Save the tree with stripped types. */
427 type = t;
429 else
430 pp_printf (&pretty_name, "'%s'", tname);
432 switch (TREE_CODE (type))
434 case BOOLEAN_TYPE:
435 case ENUMERAL_TYPE:
436 case INTEGER_TYPE:
437 tkind = 0x0000;
438 break;
439 case REAL_TYPE:
440 /* FIXME: libubsan right now only supports float, double and
441 long double type formats. */
442 if (TYPE_MODE (type) == TYPE_MODE (float_type_node)
443 || TYPE_MODE (type) == TYPE_MODE (double_type_node)
444 || TYPE_MODE (type) == TYPE_MODE (long_double_type_node))
445 tkind = 0x0001;
446 else
447 tkind = 0xffff;
448 break;
449 default:
450 tkind = 0xffff;
451 break;
453 tinfo = get_ubsan_type_info_for_type (type);
455 /* Create a new VAR_DECL of type descriptor. */
456 const char *tmp = pp_formatted_text (&pretty_name);
457 size_t len = strlen (tmp) + 1;
458 tree str = build_string (len, tmp);
459 TREE_TYPE (str) = build_array_type_nelts (char_type_node, len);
460 TREE_READONLY (str) = 1;
461 TREE_STATIC (str) = 1;
463 char tmp_name[32];
464 static unsigned int type_var_id_num;
465 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_type", type_var_id_num++);
466 decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name),
467 dtype);
468 TREE_STATIC (decl) = 1;
469 TREE_PUBLIC (decl) = 0;
470 DECL_ARTIFICIAL (decl) = 1;
471 DECL_IGNORED_P (decl) = 1;
472 DECL_EXTERNAL (decl) = 0;
473 DECL_SIZE (decl)
474 = size_binop (PLUS_EXPR, DECL_SIZE (decl), TYPE_SIZE (TREE_TYPE (str)));
475 DECL_SIZE_UNIT (decl)
476 = size_binop (PLUS_EXPR, DECL_SIZE_UNIT (decl),
477 TYPE_SIZE_UNIT (TREE_TYPE (str)));
479 tree ctor = build_constructor_va (dtype, 3, NULL_TREE,
480 build_int_cst (short_unsigned_type_node,
481 tkind), NULL_TREE,
482 build_int_cst (short_unsigned_type_node,
483 tinfo), NULL_TREE, str);
484 TREE_CONSTANT (ctor) = 1;
485 TREE_STATIC (ctor) = 1;
486 DECL_INITIAL (decl) = ctor;
487 varpool_node::finalize_decl (decl);
489 /* Save the VAR_DECL into the hash table. */
490 decl_for_type_insert (type, decl);
492 return build_fold_addr_expr (decl);
495 /* Create a structure for the ubsan library. NAME is a name of the new
496 structure. LOCCNT is number of locations, PLOC points to array of
497 locations. The arguments in ... are of __ubsan_type_descriptor type
498 and there are at most two of them, followed by NULL_TREE, followed
499 by optional extra arguments and another NULL_TREE. */
501 tree
502 ubsan_create_data (const char *name, int loccnt, const location_t *ploc, ...)
504 va_list args;
505 tree ret, t;
506 tree fields[6];
507 vec<tree, va_gc> *saved_args = NULL;
508 size_t i = 0;
509 int j;
511 /* Firstly, create a pointer to type descriptor type. */
512 tree td_type = ubsan_get_type_descriptor_type ();
513 td_type = build_pointer_type (td_type);
515 /* Create the structure type. */
516 ret = make_node (RECORD_TYPE);
517 for (j = 0; j < loccnt; j++)
519 gcc_checking_assert (i < 2);
520 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
521 ubsan_get_source_location_type ());
522 DECL_CONTEXT (fields[i]) = ret;
523 if (i)
524 DECL_CHAIN (fields[i - 1]) = fields[i];
525 i++;
528 va_start (args, ploc);
529 for (t = va_arg (args, tree); t != NULL_TREE;
530 i++, t = va_arg (args, tree))
532 gcc_checking_assert (i < 4);
533 /* Save the tree arguments for later use. */
534 vec_safe_push (saved_args, t);
535 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
536 td_type);
537 DECL_CONTEXT (fields[i]) = ret;
538 if (i)
539 DECL_CHAIN (fields[i - 1]) = fields[i];
542 for (t = va_arg (args, tree); t != NULL_TREE;
543 i++, t = va_arg (args, tree))
545 gcc_checking_assert (i < 6);
546 /* Save the tree arguments for later use. */
547 vec_safe_push (saved_args, t);
548 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
549 TREE_TYPE (t));
550 DECL_CONTEXT (fields[i]) = ret;
551 if (i)
552 DECL_CHAIN (fields[i - 1]) = fields[i];
554 va_end (args);
556 tree type_decl = build_decl (input_location, TYPE_DECL,
557 get_identifier (name), ret);
558 DECL_IGNORED_P (type_decl) = 1;
559 DECL_ARTIFICIAL (type_decl) = 1;
560 TYPE_FIELDS (ret) = fields[0];
561 TYPE_NAME (ret) = type_decl;
562 TYPE_STUB_DECL (ret) = type_decl;
563 layout_type (ret);
565 /* Now, fill in the type. */
566 char tmp_name[32];
567 static unsigned int ubsan_var_id_num;
568 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_data", ubsan_var_id_num++);
569 tree var = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name),
570 ret);
571 TREE_STATIC (var) = 1;
572 TREE_PUBLIC (var) = 0;
573 DECL_ARTIFICIAL (var) = 1;
574 DECL_IGNORED_P (var) = 1;
575 DECL_EXTERNAL (var) = 0;
577 vec<constructor_elt, va_gc> *v;
578 vec_alloc (v, i);
579 tree ctor = build_constructor (ret, v);
581 /* If desirable, set the __ubsan_source_location element. */
582 for (j = 0; j < loccnt; j++)
584 location_t loc = LOCATION_LOCUS (ploc[j]);
585 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, ubsan_source_location (loc));
588 size_t nelts = vec_safe_length (saved_args);
589 for (i = 0; i < nelts; i++)
591 t = (*saved_args)[i];
592 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, t);
595 TREE_CONSTANT (ctor) = 1;
596 TREE_STATIC (ctor) = 1;
597 DECL_INITIAL (var) = ctor;
598 varpool_node::finalize_decl (var);
600 return var;
603 /* Instrument the __builtin_unreachable call. We just call the libubsan
604 routine instead. */
606 bool
607 ubsan_instrument_unreachable (gimple_stmt_iterator *gsi)
609 gimple *g;
610 location_t loc = gimple_location (gsi_stmt (*gsi));
612 if (flag_sanitize_undefined_trap_on_error)
613 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
614 else
616 tree data = ubsan_create_data ("__ubsan_unreachable_data", 1, &loc,
617 NULL_TREE, NULL_TREE);
618 data = build_fold_addr_expr_loc (loc, data);
619 tree fn
620 = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE);
621 g = gimple_build_call (fn, 1, data);
623 gimple_set_location (g, loc);
624 gsi_replace (gsi, g, false);
625 return false;
628 /* Return true if T is a call to a libubsan routine. */
630 bool
631 is_ubsan_builtin_p (tree t)
633 return TREE_CODE (t) == FUNCTION_DECL
634 && DECL_BUILT_IN_CLASS (t) == BUILT_IN_NORMAL
635 && strncmp (IDENTIFIER_POINTER (DECL_NAME (t)),
636 "__builtin___ubsan_", 18) == 0;
639 /* Create a callgraph edge for statement STMT. */
641 static void
642 ubsan_create_edge (gimple *stmt)
644 gcall *call_stmt = dyn_cast <gcall *> (stmt);
645 basic_block bb = gimple_bb (stmt);
646 int freq = compute_call_stmt_bb_frequency (current_function_decl, bb);
647 cgraph_node *node = cgraph_node::get (current_function_decl);
648 tree decl = gimple_call_fndecl (call_stmt);
649 if (decl)
650 node->create_edge (cgraph_node::get_create (decl), call_stmt, bb->count,
651 freq);
654 /* Expand the UBSAN_BOUNDS special builtin function. */
656 bool
657 ubsan_expand_bounds_ifn (gimple_stmt_iterator *gsi)
659 gimple *stmt = gsi_stmt (*gsi);
660 location_t loc = gimple_location (stmt);
661 gcc_assert (gimple_call_num_args (stmt) == 3);
663 /* Pick up the arguments of the UBSAN_BOUNDS call. */
664 tree type = TREE_TYPE (TREE_TYPE (gimple_call_arg (stmt, 0)));
665 tree index = gimple_call_arg (stmt, 1);
666 tree orig_index_type = TREE_TYPE (index);
667 tree bound = gimple_call_arg (stmt, 2);
669 gimple_stmt_iterator gsi_orig = *gsi;
671 /* Create condition "if (index > bound)". */
672 basic_block then_bb, fallthru_bb;
673 gimple_stmt_iterator cond_insert_point
674 = create_cond_insert_point (gsi, false, false, true,
675 &then_bb, &fallthru_bb);
676 index = fold_convert (TREE_TYPE (bound), index);
677 index = force_gimple_operand_gsi (&cond_insert_point, index,
678 true, NULL_TREE,
679 false, GSI_NEW_STMT);
680 gimple *g = gimple_build_cond (GT_EXPR, index, bound, NULL_TREE, NULL_TREE);
681 gimple_set_location (g, loc);
682 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
684 /* Generate __ubsan_handle_out_of_bounds call. */
685 *gsi = gsi_after_labels (then_bb);
686 if (flag_sanitize_undefined_trap_on_error)
687 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
688 else
690 tree data
691 = ubsan_create_data ("__ubsan_out_of_bounds_data", 1, &loc,
692 ubsan_type_descriptor (type, UBSAN_PRINT_ARRAY),
693 ubsan_type_descriptor (orig_index_type),
694 NULL_TREE, NULL_TREE);
695 data = build_fold_addr_expr_loc (loc, data);
696 enum built_in_function bcode
697 = (flag_sanitize_recover & SANITIZE_BOUNDS)
698 ? BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS
699 : BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS_ABORT;
700 tree fn = builtin_decl_explicit (bcode);
701 tree val = force_gimple_operand_gsi (gsi, ubsan_encode_value (index),
702 true, NULL_TREE, true,
703 GSI_SAME_STMT);
704 g = gimple_build_call (fn, 2, data, val);
706 gimple_set_location (g, loc);
707 gsi_insert_before (gsi, g, GSI_SAME_STMT);
709 /* Get rid of the UBSAN_BOUNDS call from the IR. */
710 unlink_stmt_vdef (stmt);
711 gsi_remove (&gsi_orig, true);
713 /* Point GSI to next logical statement. */
714 *gsi = gsi_start_bb (fallthru_bb);
715 return true;
718 /* Expand UBSAN_NULL internal call. The type is kept on the ckind
719 argument which is a constant, because the middle-end treats pointer
720 conversions as useless and therefore the type of the first argument
721 could be changed to any other pointer type. */
723 bool
724 ubsan_expand_null_ifn (gimple_stmt_iterator *gsip)
726 gimple_stmt_iterator gsi = *gsip;
727 gimple *stmt = gsi_stmt (gsi);
728 location_t loc = gimple_location (stmt);
729 gcc_assert (gimple_call_num_args (stmt) == 3);
730 tree ptr = gimple_call_arg (stmt, 0);
731 tree ckind = gimple_call_arg (stmt, 1);
732 tree align = gimple_call_arg (stmt, 2);
733 tree check_align = NULL_TREE;
734 bool check_null;
736 basic_block cur_bb = gsi_bb (gsi);
738 gimple *g;
739 if (!integer_zerop (align))
741 unsigned int ptralign = get_pointer_alignment (ptr) / BITS_PER_UNIT;
742 if (compare_tree_int (align, ptralign) == 1)
744 check_align = make_ssa_name (pointer_sized_int_node);
745 g = gimple_build_assign (check_align, NOP_EXPR, ptr);
746 gimple_set_location (g, loc);
747 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
750 check_null = (flag_sanitize & SANITIZE_NULL) != 0;
752 if (check_align == NULL_TREE && !check_null)
754 gsi_remove (gsip, true);
755 /* Unlink the UBSAN_NULLs vops before replacing it. */
756 unlink_stmt_vdef (stmt);
757 return true;
760 /* Split the original block holding the pointer dereference. */
761 edge e = split_block (cur_bb, stmt);
763 /* Get a hold on the 'condition block', the 'then block' and the
764 'else block'. */
765 basic_block cond_bb = e->src;
766 basic_block fallthru_bb = e->dest;
767 basic_block then_bb = create_empty_bb (cond_bb);
768 add_bb_to_loop (then_bb, cond_bb->loop_father);
769 loops_state_set (LOOPS_NEED_FIXUP);
771 /* Make an edge coming from the 'cond block' into the 'then block';
772 this edge is unlikely taken, so set up the probability accordingly. */
773 e = make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
774 e->probability = PROB_VERY_UNLIKELY;
776 /* Connect 'then block' with the 'else block'. This is needed
777 as the ubsan routines we call in the 'then block' are not noreturn.
778 The 'then block' only has one outcoming edge. */
779 make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);
781 /* Set up the fallthrough basic block. */
782 e = find_edge (cond_bb, fallthru_bb);
783 e->flags = EDGE_FALSE_VALUE;
784 e->count = cond_bb->count;
785 e->probability = REG_BR_PROB_BASE - PROB_VERY_UNLIKELY;
787 /* Update dominance info for the newly created then_bb; note that
788 fallthru_bb's dominance info has already been updated by
789 split_block. */
790 if (dom_info_available_p (CDI_DOMINATORS))
791 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
793 /* Put the ubsan builtin call into the newly created BB. */
794 if (flag_sanitize_undefined_trap_on_error)
795 g = gimple_build_call (builtin_decl_implicit (BUILT_IN_TRAP), 0);
796 else
798 enum built_in_function bcode
799 = (flag_sanitize_recover & ((check_align ? SANITIZE_ALIGNMENT : 0)
800 | (check_null ? SANITIZE_NULL : 0)))
801 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
802 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT;
803 tree fn = builtin_decl_implicit (bcode);
804 tree data
805 = ubsan_create_data ("__ubsan_null_data", 1, &loc,
806 ubsan_type_descriptor (TREE_TYPE (ckind),
807 UBSAN_PRINT_POINTER),
808 NULL_TREE,
809 align,
810 fold_convert (unsigned_char_type_node, ckind),
811 NULL_TREE);
812 data = build_fold_addr_expr_loc (loc, data);
813 g = gimple_build_call (fn, 2, data,
814 check_align ? check_align
815 : build_zero_cst (pointer_sized_int_node));
817 gimple_stmt_iterator gsi2 = gsi_start_bb (then_bb);
818 gimple_set_location (g, loc);
819 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
821 /* Unlink the UBSAN_NULLs vops before replacing it. */
822 unlink_stmt_vdef (stmt);
824 if (check_null)
826 g = gimple_build_cond (EQ_EXPR, ptr, build_int_cst (TREE_TYPE (ptr), 0),
827 NULL_TREE, NULL_TREE);
828 gimple_set_location (g, loc);
830 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
831 gsi_replace (&gsi, g, false);
832 stmt = g;
835 if (check_align)
837 if (check_null)
839 /* Split the block with the condition again. */
840 e = split_block (cond_bb, stmt);
841 basic_block cond1_bb = e->src;
842 basic_block cond2_bb = e->dest;
844 /* Make an edge coming from the 'cond1 block' into the 'then block';
845 this edge is unlikely taken, so set up the probability
846 accordingly. */
847 e = make_edge (cond1_bb, then_bb, EDGE_TRUE_VALUE);
848 e->probability = PROB_VERY_UNLIKELY;
850 /* Set up the fallthrough basic block. */
851 e = find_edge (cond1_bb, cond2_bb);
852 e->flags = EDGE_FALSE_VALUE;
853 e->count = cond1_bb->count;
854 e->probability = REG_BR_PROB_BASE - PROB_VERY_UNLIKELY;
856 /* Update dominance info. */
857 if (dom_info_available_p (CDI_DOMINATORS))
859 set_immediate_dominator (CDI_DOMINATORS, fallthru_bb, cond1_bb);
860 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond1_bb);
863 gsi2 = gsi_start_bb (cond2_bb);
866 tree mask = build_int_cst (pointer_sized_int_node,
867 tree_to_uhwi (align) - 1);
868 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
869 BIT_AND_EXPR, check_align, mask);
870 gimple_set_location (g, loc);
871 if (check_null)
872 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
873 else
874 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
876 g = gimple_build_cond (NE_EXPR, gimple_assign_lhs (g),
877 build_int_cst (pointer_sized_int_node, 0),
878 NULL_TREE, NULL_TREE);
879 gimple_set_location (g, loc);
880 if (check_null)
881 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
882 else
883 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
884 gsi_replace (&gsi, g, false);
886 return false;
889 #define OBJSZ_MAX_OFFSET (1024 * 16)
891 /* Expand UBSAN_OBJECT_SIZE internal call. */
893 bool
894 ubsan_expand_objsize_ifn (gimple_stmt_iterator *gsi)
896 gimple *stmt = gsi_stmt (*gsi);
897 location_t loc = gimple_location (stmt);
898 gcc_assert (gimple_call_num_args (stmt) == 4);
900 tree ptr = gimple_call_arg (stmt, 0);
901 tree offset = gimple_call_arg (stmt, 1);
902 tree size = gimple_call_arg (stmt, 2);
903 tree ckind = gimple_call_arg (stmt, 3);
904 gimple_stmt_iterator gsi_orig = *gsi;
905 gimple *g;
907 /* See if we can discard the check. */
908 if (TREE_CODE (size) != INTEGER_CST
909 || integer_all_onesp (size))
910 /* Yes, __builtin_object_size couldn't determine the
911 object size. */;
912 else if (TREE_CODE (offset) == INTEGER_CST
913 && wi::to_widest (offset) >= -OBJSZ_MAX_OFFSET
914 && wi::to_widest (offset) <= -1)
915 /* The offset is in range [-16K, -1]. */;
916 else
918 /* if (offset > objsize) */
919 basic_block then_bb, fallthru_bb;
920 gimple_stmt_iterator cond_insert_point
921 = create_cond_insert_point (gsi, false, false, true,
922 &then_bb, &fallthru_bb);
923 g = gimple_build_cond (GT_EXPR, offset, size, NULL_TREE, NULL_TREE);
924 gimple_set_location (g, loc);
925 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
927 /* If the offset is small enough, we don't need the second
928 run-time check. */
929 if (TREE_CODE (offset) == INTEGER_CST
930 && wi::to_widest (offset) >= 0
931 && wi::to_widest (offset) <= OBJSZ_MAX_OFFSET)
932 *gsi = gsi_after_labels (then_bb);
933 else
935 /* Don't issue run-time error if (ptr > ptr + offset). That
936 may happen when computing a POINTER_PLUS_EXPR. */
937 basic_block then2_bb, fallthru2_bb;
939 gimple_stmt_iterator gsi2 = gsi_after_labels (then_bb);
940 cond_insert_point = create_cond_insert_point (&gsi2, false, false,
941 true, &then2_bb,
942 &fallthru2_bb);
943 /* Convert the pointer to an integer type. */
944 tree p = make_ssa_name (pointer_sized_int_node);
945 g = gimple_build_assign (p, NOP_EXPR, ptr);
946 gimple_set_location (g, loc);
947 gsi_insert_before (&cond_insert_point, g, GSI_NEW_STMT);
948 p = gimple_assign_lhs (g);
949 /* Compute ptr + offset. */
950 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
951 PLUS_EXPR, p, offset);
952 gimple_set_location (g, loc);
953 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
954 /* Now build the conditional and put it into the IR. */
955 g = gimple_build_cond (LE_EXPR, p, gimple_assign_lhs (g),
956 NULL_TREE, NULL_TREE);
957 gimple_set_location (g, loc);
958 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
959 *gsi = gsi_after_labels (then2_bb);
962 /* Generate __ubsan_handle_type_mismatch call. */
963 if (flag_sanitize_undefined_trap_on_error)
964 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
965 else
967 tree data
968 = ubsan_create_data ("__ubsan_objsz_data", 1, &loc,
969 ubsan_type_descriptor (TREE_TYPE (ptr),
970 UBSAN_PRINT_POINTER),
971 NULL_TREE,
972 build_zero_cst (pointer_sized_int_node),
973 ckind,
974 NULL_TREE);
975 data = build_fold_addr_expr_loc (loc, data);
976 enum built_in_function bcode
977 = (flag_sanitize_recover & SANITIZE_OBJECT_SIZE)
978 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
979 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT;
980 tree p = make_ssa_name (pointer_sized_int_node);
981 g = gimple_build_assign (p, NOP_EXPR, ptr);
982 gimple_set_location (g, loc);
983 gsi_insert_before (gsi, g, GSI_SAME_STMT);
984 g = gimple_build_call (builtin_decl_explicit (bcode), 2, data, p);
986 gimple_set_location (g, loc);
987 gsi_insert_before (gsi, g, GSI_SAME_STMT);
989 /* Point GSI to next logical statement. */
990 *gsi = gsi_start_bb (fallthru_bb);
992 /* Get rid of the UBSAN_OBJECT_SIZE call from the IR. */
993 unlink_stmt_vdef (stmt);
994 gsi_remove (&gsi_orig, true);
995 return true;
998 /* Get rid of the UBSAN_OBJECT_SIZE call from the IR. */
999 unlink_stmt_vdef (stmt);
1000 gsi_remove (gsi, true);
1001 return true;
1004 /* Cached __ubsan_vptr_type_cache decl. */
1005 static GTY(()) tree ubsan_vptr_type_cache_decl;
1007 /* Expand UBSAN_VPTR internal call. The type is kept on the ckind
1008 argument which is a constant, because the middle-end treats pointer
1009 conversions as useless and therefore the type of the first argument
1010 could be changed to any other pointer type. */
1012 bool
1013 ubsan_expand_vptr_ifn (gimple_stmt_iterator *gsip)
1015 gimple_stmt_iterator gsi = *gsip;
1016 gimple *stmt = gsi_stmt (gsi);
1017 location_t loc = gimple_location (stmt);
1018 gcc_assert (gimple_call_num_args (stmt) == 5);
1019 tree op = gimple_call_arg (stmt, 0);
1020 tree vptr = gimple_call_arg (stmt, 1);
1021 tree str_hash = gimple_call_arg (stmt, 2);
1022 tree ti_decl_addr = gimple_call_arg (stmt, 3);
1023 tree ckind_tree = gimple_call_arg (stmt, 4);
1024 ubsan_null_ckind ckind = (ubsan_null_ckind) tree_to_uhwi (ckind_tree);
1025 tree type = TREE_TYPE (TREE_TYPE (ckind_tree));
1026 gimple *g;
1027 basic_block fallthru_bb = NULL;
1029 if (ckind == UBSAN_DOWNCAST_POINTER)
1031 /* Guard everything with if (op != NULL) { ... }. */
1032 basic_block then_bb;
1033 gimple_stmt_iterator cond_insert_point
1034 = create_cond_insert_point (gsip, false, false, true,
1035 &then_bb, &fallthru_bb);
1036 g = gimple_build_cond (NE_EXPR, op, build_zero_cst (TREE_TYPE (op)),
1037 NULL_TREE, NULL_TREE);
1038 gimple_set_location (g, loc);
1039 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
1040 *gsip = gsi_after_labels (then_bb);
1041 gsi_remove (&gsi, false);
1042 gsi_insert_before (gsip, stmt, GSI_NEW_STMT);
1043 gsi = *gsip;
1046 tree htype = TREE_TYPE (str_hash);
1047 tree cst = wide_int_to_tree (htype,
1048 wi::uhwi (((uint64_t) 0x9ddfea08 << 32)
1049 | 0xeb382d69, 64));
1050 g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1051 vptr, str_hash);
1052 gimple_set_location (g, loc);
1053 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1054 g = gimple_build_assign (make_ssa_name (htype), MULT_EXPR,
1055 gimple_assign_lhs (g), cst);
1056 gimple_set_location (g, loc);
1057 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1058 tree t1 = gimple_assign_lhs (g);
1059 g = gimple_build_assign (make_ssa_name (htype), LSHIFT_EXPR,
1060 t1, build_int_cst (integer_type_node, 47));
1061 gimple_set_location (g, loc);
1062 tree t2 = gimple_assign_lhs (g);
1063 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1064 g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1065 vptr, t1);
1066 gimple_set_location (g, loc);
1067 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1068 g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1069 t2, gimple_assign_lhs (g));
1070 gimple_set_location (g, loc);
1071 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1072 g = gimple_build_assign (make_ssa_name (htype), MULT_EXPR,
1073 gimple_assign_lhs (g), cst);
1074 gimple_set_location (g, loc);
1075 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1076 tree t3 = gimple_assign_lhs (g);
1077 g = gimple_build_assign (make_ssa_name (htype), LSHIFT_EXPR,
1078 t3, build_int_cst (integer_type_node, 47));
1079 gimple_set_location (g, loc);
1080 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1081 g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1082 t3, gimple_assign_lhs (g));
1083 gimple_set_location (g, loc);
1084 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1085 g = gimple_build_assign (make_ssa_name (htype), MULT_EXPR,
1086 gimple_assign_lhs (g), cst);
1087 gimple_set_location (g, loc);
1088 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1089 if (!useless_type_conversion_p (pointer_sized_int_node, htype))
1091 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
1092 NOP_EXPR, gimple_assign_lhs (g));
1093 gimple_set_location (g, loc);
1094 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1096 tree hash = gimple_assign_lhs (g);
1098 if (ubsan_vptr_type_cache_decl == NULL_TREE)
1100 tree atype = build_array_type_nelts (pointer_sized_int_node, 128);
1101 tree array = build_decl (UNKNOWN_LOCATION, VAR_DECL,
1102 get_identifier ("__ubsan_vptr_type_cache"),
1103 atype);
1104 DECL_ARTIFICIAL (array) = 1;
1105 DECL_IGNORED_P (array) = 1;
1106 TREE_PUBLIC (array) = 1;
1107 TREE_STATIC (array) = 1;
1108 DECL_EXTERNAL (array) = 1;
1109 DECL_VISIBILITY (array) = VISIBILITY_DEFAULT;
1110 DECL_VISIBILITY_SPECIFIED (array) = 1;
1111 varpool_node::finalize_decl (array);
1112 ubsan_vptr_type_cache_decl = array;
1115 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
1116 BIT_AND_EXPR, hash,
1117 build_int_cst (pointer_sized_int_node, 127));
1118 gimple_set_location (g, loc);
1119 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1121 tree c = build4_loc (loc, ARRAY_REF, pointer_sized_int_node,
1122 ubsan_vptr_type_cache_decl, gimple_assign_lhs (g),
1123 NULL_TREE, NULL_TREE);
1124 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
1125 ARRAY_REF, c);
1126 gimple_set_location (g, loc);
1127 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1129 basic_block then_bb, fallthru2_bb;
1130 gimple_stmt_iterator cond_insert_point
1131 = create_cond_insert_point (gsip, false, false, true,
1132 &then_bb, &fallthru2_bb);
1133 g = gimple_build_cond (NE_EXPR, gimple_assign_lhs (g), hash,
1134 NULL_TREE, NULL_TREE);
1135 gimple_set_location (g, loc);
1136 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
1137 *gsip = gsi_after_labels (then_bb);
1138 if (fallthru_bb == NULL)
1139 fallthru_bb = fallthru2_bb;
1141 tree data
1142 = ubsan_create_data ("__ubsan_vptr_data", 1, &loc,
1143 ubsan_type_descriptor (type), NULL_TREE, ti_decl_addr,
1144 build_int_cst (unsigned_char_type_node, ckind),
1145 NULL_TREE);
1146 data = build_fold_addr_expr_loc (loc, data);
1147 enum built_in_function bcode
1148 = (flag_sanitize_recover & SANITIZE_VPTR)
1149 ? BUILT_IN_UBSAN_HANDLE_DYNAMIC_TYPE_CACHE_MISS
1150 : BUILT_IN_UBSAN_HANDLE_DYNAMIC_TYPE_CACHE_MISS_ABORT;
1152 g = gimple_build_call (builtin_decl_explicit (bcode), 3, data, op, hash);
1153 gimple_set_location (g, loc);
1154 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1156 /* Point GSI to next logical statement. */
1157 *gsip = gsi_start_bb (fallthru_bb);
1159 /* Get rid of the UBSAN_VPTR call from the IR. */
1160 unlink_stmt_vdef (stmt);
1161 gsi_remove (&gsi, true);
1162 return true;
1165 /* Instrument a memory reference. BASE is the base of MEM, IS_LHS says
1166 whether the pointer is on the left hand side of the assignment. */
1168 static void
1169 instrument_mem_ref (tree mem, tree base, gimple_stmt_iterator *iter,
1170 bool is_lhs)
1172 enum ubsan_null_ckind ikind = is_lhs ? UBSAN_STORE_OF : UBSAN_LOAD_OF;
1173 unsigned int align = 0;
1174 if (flag_sanitize & SANITIZE_ALIGNMENT)
1176 align = min_align_of_type (TREE_TYPE (base));
1177 if (align <= 1)
1178 align = 0;
1180 if (align == 0 && (flag_sanitize & SANITIZE_NULL) == 0)
1181 return;
1182 tree t = TREE_OPERAND (base, 0);
1183 if (!POINTER_TYPE_P (TREE_TYPE (t)))
1184 return;
1185 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (base)) && mem != base)
1186 ikind = UBSAN_MEMBER_ACCESS;
1187 tree kind = build_int_cst (build_pointer_type (TREE_TYPE (base)), ikind);
1188 tree alignt = build_int_cst (pointer_sized_int_node, align);
1189 gcall *g = gimple_build_call_internal (IFN_UBSAN_NULL, 3, t, kind, alignt);
1190 gimple_set_location (g, gimple_location (gsi_stmt (*iter)));
1191 gsi_insert_before (iter, g, GSI_SAME_STMT);
1194 /* Perform the pointer instrumentation. */
1196 static void
1197 instrument_null (gimple_stmt_iterator gsi, bool is_lhs)
1199 gimple *stmt = gsi_stmt (gsi);
1200 tree t = is_lhs ? gimple_get_lhs (stmt) : gimple_assign_rhs1 (stmt);
1201 tree base = get_base_address (t);
1202 const enum tree_code code = TREE_CODE (base);
1203 if (code == MEM_REF
1204 && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
1205 instrument_mem_ref (t, base, &gsi, is_lhs);
1208 /* Build an ubsan builtin call for the signed-integer-overflow
1209 sanitization. CODE says what kind of builtin are we building,
1210 LOC is a location, LHSTYPE is the type of LHS, OP0 and OP1
1211 are operands of the binary operation. */
1213 tree
1214 ubsan_build_overflow_builtin (tree_code code, location_t loc, tree lhstype,
1215 tree op0, tree op1)
1217 if (flag_sanitize_undefined_trap_on_error)
1218 return build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
1220 tree data = ubsan_create_data ("__ubsan_overflow_data", 1, &loc,
1221 ubsan_type_descriptor (lhstype), NULL_TREE,
1222 NULL_TREE);
1223 enum built_in_function fn_code;
1225 switch (code)
1227 case PLUS_EXPR:
1228 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1229 ? BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW
1230 : BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW_ABORT;
1231 break;
1232 case MINUS_EXPR:
1233 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1234 ? BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW
1235 : BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW_ABORT;
1236 break;
1237 case MULT_EXPR:
1238 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1239 ? BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW
1240 : BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW_ABORT;
1241 break;
1242 case NEGATE_EXPR:
1243 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1244 ? BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW
1245 : BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW_ABORT;
1246 break;
1247 default:
1248 gcc_unreachable ();
1250 tree fn = builtin_decl_explicit (fn_code);
1251 return build_call_expr_loc (loc, fn, 2 + (code != NEGATE_EXPR),
1252 build_fold_addr_expr_loc (loc, data),
1253 ubsan_encode_value (op0, true),
1254 op1 ? ubsan_encode_value (op1, true)
1255 : NULL_TREE);
1258 /* Perform the signed integer instrumentation. GSI is the iterator
1259 pointing at statement we are trying to instrument. */
1261 static void
1262 instrument_si_overflow (gimple_stmt_iterator gsi)
1264 gimple *stmt = gsi_stmt (gsi);
1265 tree_code code = gimple_assign_rhs_code (stmt);
1266 tree lhs = gimple_assign_lhs (stmt);
1267 tree lhstype = TREE_TYPE (lhs);
1268 tree a, b;
1269 gimple *g;
1271 /* If this is not a signed operation, don't instrument anything here.
1272 Also punt on bit-fields. */
1273 if (!INTEGRAL_TYPE_P (lhstype)
1274 || TYPE_OVERFLOW_WRAPS (lhstype)
1275 || GET_MODE_BITSIZE (TYPE_MODE (lhstype)) != TYPE_PRECISION (lhstype))
1276 return;
1278 switch (code)
1280 case MINUS_EXPR:
1281 case PLUS_EXPR:
1282 case MULT_EXPR:
1283 /* Transform
1284 i = u {+,-,*} 5;
1285 into
1286 i = UBSAN_CHECK_{ADD,SUB,MUL} (u, 5); */
1287 a = gimple_assign_rhs1 (stmt);
1288 b = gimple_assign_rhs2 (stmt);
1289 g = gimple_build_call_internal (code == PLUS_EXPR
1290 ? IFN_UBSAN_CHECK_ADD
1291 : code == MINUS_EXPR
1292 ? IFN_UBSAN_CHECK_SUB
1293 : IFN_UBSAN_CHECK_MUL, 2, a, b);
1294 gimple_call_set_lhs (g, lhs);
1295 gsi_replace (&gsi, g, false);
1296 break;
1297 case NEGATE_EXPR:
1298 /* Represent i = -u;
1300 i = UBSAN_CHECK_SUB (0, u); */
1301 a = build_int_cst (lhstype, 0);
1302 b = gimple_assign_rhs1 (stmt);
1303 g = gimple_build_call_internal (IFN_UBSAN_CHECK_SUB, 2, a, b);
1304 gimple_call_set_lhs (g, lhs);
1305 gsi_replace (&gsi, g, false);
1306 break;
1307 case ABS_EXPR:
1308 /* Transform i = ABS_EXPR<u>;
1309 into
1310 _N = UBSAN_CHECK_SUB (0, u);
1311 i = ABS_EXPR<_N>; */
1312 a = build_int_cst (lhstype, 0);
1313 b = gimple_assign_rhs1 (stmt);
1314 g = gimple_build_call_internal (IFN_UBSAN_CHECK_SUB, 2, a, b);
1315 a = make_ssa_name (lhstype);
1316 gimple_call_set_lhs (g, a);
1317 gimple_set_location (g, gimple_location (stmt));
1318 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
1319 gimple_assign_set_rhs1 (stmt, a);
1320 update_stmt (stmt);
1321 break;
1322 default:
1323 break;
1327 /* Instrument loads from (non-bitfield) bool and C++ enum values
1328 to check if the memory value is outside of the range of the valid
1329 type values. */
1331 static void
1332 instrument_bool_enum_load (gimple_stmt_iterator *gsi)
1334 gimple *stmt = gsi_stmt (*gsi);
1335 tree rhs = gimple_assign_rhs1 (stmt);
1336 tree type = TREE_TYPE (rhs);
1337 tree minv = NULL_TREE, maxv = NULL_TREE;
1339 if (TREE_CODE (type) == BOOLEAN_TYPE && (flag_sanitize & SANITIZE_BOOL))
1341 minv = boolean_false_node;
1342 maxv = boolean_true_node;
1344 else if (TREE_CODE (type) == ENUMERAL_TYPE
1345 && (flag_sanitize & SANITIZE_ENUM)
1346 && TREE_TYPE (type) != NULL_TREE
1347 && TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE
1348 && (TYPE_PRECISION (TREE_TYPE (type))
1349 < GET_MODE_PRECISION (TYPE_MODE (type))))
1351 minv = TYPE_MIN_VALUE (TREE_TYPE (type));
1352 maxv = TYPE_MAX_VALUE (TREE_TYPE (type));
1354 else
1355 return;
1357 int modebitsize = GET_MODE_BITSIZE (TYPE_MODE (type));
1358 HOST_WIDE_INT bitsize, bitpos;
1359 tree offset;
1360 machine_mode mode;
1361 int volatilep = 0, reversep, unsignedp = 0;
1362 tree base = get_inner_reference (rhs, &bitsize, &bitpos, &offset, &mode,
1363 &unsignedp, &reversep, &volatilep, false);
1364 tree utype = build_nonstandard_integer_type (modebitsize, 1);
1366 if ((TREE_CODE (base) == VAR_DECL && DECL_HARD_REGISTER (base))
1367 || (bitpos % modebitsize) != 0
1368 || bitsize != modebitsize
1369 || GET_MODE_BITSIZE (TYPE_MODE (utype)) != modebitsize
1370 || TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME)
1371 return;
1373 bool ends_bb = stmt_ends_bb_p (stmt);
1374 location_t loc = gimple_location (stmt);
1375 tree lhs = gimple_assign_lhs (stmt);
1376 tree ptype = build_pointer_type (TREE_TYPE (rhs));
1377 tree atype = reference_alias_ptr_type (rhs);
1378 gimple *g = gimple_build_assign (make_ssa_name (ptype),
1379 build_fold_addr_expr (rhs));
1380 gimple_set_location (g, loc);
1381 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1382 tree mem = build2 (MEM_REF, utype, gimple_assign_lhs (g),
1383 build_int_cst (atype, 0));
1384 tree urhs = make_ssa_name (utype);
1385 if (ends_bb)
1387 gimple_assign_set_lhs (stmt, urhs);
1388 g = gimple_build_assign (lhs, NOP_EXPR, urhs);
1389 gimple_set_location (g, loc);
1390 edge e = find_fallthru_edge (gimple_bb (stmt)->succs);
1391 gsi_insert_on_edge_immediate (e, g);
1392 gimple_assign_set_rhs_from_tree (gsi, mem);
1393 update_stmt (stmt);
1394 *gsi = gsi_for_stmt (g);
1395 g = stmt;
1397 else
1399 g = gimple_build_assign (urhs, mem);
1400 gimple_set_location (g, loc);
1401 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1403 minv = fold_convert (utype, minv);
1404 maxv = fold_convert (utype, maxv);
1405 if (!integer_zerop (minv))
1407 g = gimple_build_assign (make_ssa_name (utype), MINUS_EXPR, urhs, minv);
1408 gimple_set_location (g, loc);
1409 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1412 gimple_stmt_iterator gsi2 = *gsi;
1413 basic_block then_bb, fallthru_bb;
1414 *gsi = create_cond_insert_point (gsi, true, false, true,
1415 &then_bb, &fallthru_bb);
1416 g = gimple_build_cond (GT_EXPR, gimple_assign_lhs (g),
1417 int_const_binop (MINUS_EXPR, maxv, minv),
1418 NULL_TREE, NULL_TREE);
1419 gimple_set_location (g, loc);
1420 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1422 if (!ends_bb)
1424 gimple_assign_set_rhs_with_ops (&gsi2, NOP_EXPR, urhs);
1425 update_stmt (stmt);
1428 gsi2 = gsi_after_labels (then_bb);
1429 if (flag_sanitize_undefined_trap_on_error)
1430 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1431 else
1433 tree data = ubsan_create_data ("__ubsan_invalid_value_data", 1, &loc,
1434 ubsan_type_descriptor (type), NULL_TREE,
1435 NULL_TREE);
1436 data = build_fold_addr_expr_loc (loc, data);
1437 enum built_in_function bcode
1438 = (flag_sanitize_recover & (TREE_CODE (type) == BOOLEAN_TYPE
1439 ? SANITIZE_BOOL : SANITIZE_ENUM))
1440 ? BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE
1441 : BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE_ABORT;
1442 tree fn = builtin_decl_explicit (bcode);
1444 tree val = force_gimple_operand_gsi (&gsi2, ubsan_encode_value (urhs),
1445 true, NULL_TREE, true,
1446 GSI_SAME_STMT);
1447 g = gimple_build_call (fn, 2, data, val);
1449 gimple_set_location (g, loc);
1450 gsi_insert_before (&gsi2, g, GSI_SAME_STMT);
1451 ubsan_create_edge (g);
1452 *gsi = gsi_for_stmt (stmt);
1455 /* Determine if we can propagate given LOCATION to ubsan_data descriptor to use
1456 new style handlers. Libubsan uses heuristics to destinguish between old and
1457 new styles and relies on these properties for filename:
1459 a) Location's filename must not be NULL.
1460 b) Location's filename must not be equal to "".
1461 c) Location's filename must not be equal to "\1".
1462 d) First two bytes of filename must not contain '\xff' symbol. */
1464 static bool
1465 ubsan_use_new_style_p (location_t loc)
1467 if (loc == UNKNOWN_LOCATION)
1468 return false;
1470 expanded_location xloc = expand_location (loc);
1471 if (xloc.file == NULL || strncmp (xloc.file, "\1", 2) == 0
1472 || xloc.file == '\0' || xloc.file[0] == '\xff'
1473 || xloc.file[1] == '\xff')
1474 return false;
1476 return true;
1479 /* Instrument float point-to-integer conversion. TYPE is an integer type of
1480 destination, EXPR is floating-point expression. */
1482 tree
1483 ubsan_instrument_float_cast (location_t loc, tree type, tree expr)
1485 tree expr_type = TREE_TYPE (expr);
1486 tree t, tt, fn, min, max;
1487 machine_mode mode = TYPE_MODE (expr_type);
1488 int prec = TYPE_PRECISION (type);
1489 bool uns_p = TYPE_UNSIGNED (type);
1490 if (loc == UNKNOWN_LOCATION)
1491 loc = input_location;
1493 /* Float to integer conversion first truncates toward zero, so
1494 even signed char c = 127.875f; is not problematic.
1495 Therefore, we should complain only if EXPR is unordered or smaller
1496 or equal than TYPE_MIN_VALUE - 1.0 or greater or equal than
1497 TYPE_MAX_VALUE + 1.0. */
1498 if (REAL_MODE_FORMAT (mode)->b == 2)
1500 /* For maximum, TYPE_MAX_VALUE might not be representable
1501 in EXPR_TYPE, e.g. if TYPE is 64-bit long long and
1502 EXPR_TYPE is IEEE single float, but TYPE_MAX_VALUE + 1.0 is
1503 either representable or infinity. */
1504 REAL_VALUE_TYPE maxval = dconst1;
1505 SET_REAL_EXP (&maxval, REAL_EXP (&maxval) + prec - !uns_p);
1506 real_convert (&maxval, mode, &maxval);
1507 max = build_real (expr_type, maxval);
1509 /* For unsigned, assume -1.0 is always representable. */
1510 if (uns_p)
1511 min = build_minus_one_cst (expr_type);
1512 else
1514 /* TYPE_MIN_VALUE is generally representable (or -inf),
1515 but TYPE_MIN_VALUE - 1.0 might not be. */
1516 REAL_VALUE_TYPE minval = dconstm1, minval2;
1517 SET_REAL_EXP (&minval, REAL_EXP (&minval) + prec - 1);
1518 real_convert (&minval, mode, &minval);
1519 real_arithmetic (&minval2, MINUS_EXPR, &minval, &dconst1);
1520 real_convert (&minval2, mode, &minval2);
1521 if (real_compare (EQ_EXPR, &minval, &minval2)
1522 && !real_isinf (&minval))
1524 /* If TYPE_MIN_VALUE - 1.0 is not representable and
1525 rounds to TYPE_MIN_VALUE, we need to subtract
1526 more. As REAL_MODE_FORMAT (mode)->p is the number
1527 of base digits, we want to subtract a number that
1528 will be 1 << (REAL_MODE_FORMAT (mode)->p - 1)
1529 times smaller than minval. */
1530 minval2 = dconst1;
1531 gcc_assert (prec > REAL_MODE_FORMAT (mode)->p);
1532 SET_REAL_EXP (&minval2,
1533 REAL_EXP (&minval2) + prec - 1
1534 - REAL_MODE_FORMAT (mode)->p + 1);
1535 real_arithmetic (&minval2, MINUS_EXPR, &minval, &minval2);
1536 real_convert (&minval2, mode, &minval2);
1538 min = build_real (expr_type, minval2);
1541 else if (REAL_MODE_FORMAT (mode)->b == 10)
1543 /* For _Decimal128 up to 34 decimal digits, - sign,
1544 dot, e, exponent. */
1545 char buf[64];
1546 mpfr_t m;
1547 int p = REAL_MODE_FORMAT (mode)->p;
1548 REAL_VALUE_TYPE maxval, minval;
1550 /* Use mpfr_snprintf rounding to compute the smallest
1551 representable decimal number greater or equal than
1552 1 << (prec - !uns_p). */
1553 mpfr_init2 (m, prec + 2);
1554 mpfr_set_ui_2exp (m, 1, prec - !uns_p, GMP_RNDN);
1555 mpfr_snprintf (buf, sizeof buf, "%.*RUe", p - 1, m);
1556 decimal_real_from_string (&maxval, buf);
1557 max = build_real (expr_type, maxval);
1559 /* For unsigned, assume -1.0 is always representable. */
1560 if (uns_p)
1561 min = build_minus_one_cst (expr_type);
1562 else
1564 /* Use mpfr_snprintf rounding to compute the largest
1565 representable decimal number less or equal than
1566 (-1 << (prec - 1)) - 1. */
1567 mpfr_set_si_2exp (m, -1, prec - 1, GMP_RNDN);
1568 mpfr_sub_ui (m, m, 1, GMP_RNDN);
1569 mpfr_snprintf (buf, sizeof buf, "%.*RDe", p - 1, m);
1570 decimal_real_from_string (&minval, buf);
1571 min = build_real (expr_type, minval);
1573 mpfr_clear (m);
1575 else
1576 return NULL_TREE;
1578 t = fold_build2 (UNLE_EXPR, boolean_type_node, expr, min);
1579 tt = fold_build2 (UNGE_EXPR, boolean_type_node, expr, max);
1580 t = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t, tt);
1581 if (integer_zerop (t))
1582 return NULL_TREE;
1584 if (flag_sanitize_undefined_trap_on_error)
1585 fn = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
1586 else
1588 location_t *loc_ptr = NULL;
1589 unsigned num_locations = 0;
1590 initialize_sanitizer_builtins ();
1591 /* Figure out if we can propagate location to ubsan_data and use new
1592 style handlers in libubsan. */
1593 if (ubsan_use_new_style_p (loc))
1595 loc_ptr = &loc;
1596 num_locations = 1;
1598 /* Create the __ubsan_handle_float_cast_overflow fn call. */
1599 tree data = ubsan_create_data ("__ubsan_float_cast_overflow_data",
1600 num_locations, loc_ptr,
1601 ubsan_type_descriptor (expr_type),
1602 ubsan_type_descriptor (type), NULL_TREE,
1603 NULL_TREE);
1604 enum built_in_function bcode
1605 = (flag_sanitize_recover & SANITIZE_FLOAT_CAST)
1606 ? BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW
1607 : BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW_ABORT;
1608 fn = builtin_decl_explicit (bcode);
1609 fn = build_call_expr_loc (loc, fn, 2,
1610 build_fold_addr_expr_loc (loc, data),
1611 ubsan_encode_value (expr, false));
1614 return fold_build3 (COND_EXPR, void_type_node, t, fn, integer_zero_node);
1617 /* Instrument values passed to function arguments with nonnull attribute. */
1619 static void
1620 instrument_nonnull_arg (gimple_stmt_iterator *gsi)
1622 gimple *stmt = gsi_stmt (*gsi);
1623 location_t loc[2];
1624 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
1625 while for nonnull sanitization it is clear. */
1626 int save_flag_delete_null_pointer_checks = flag_delete_null_pointer_checks;
1627 flag_delete_null_pointer_checks = 1;
1628 loc[0] = gimple_location (stmt);
1629 loc[1] = UNKNOWN_LOCATION;
1630 for (unsigned int i = 0; i < gimple_call_num_args (stmt); i++)
1632 tree arg = gimple_call_arg (stmt, i);
1633 if (POINTER_TYPE_P (TREE_TYPE (arg))
1634 && infer_nonnull_range_by_attribute (stmt, arg))
1636 gimple *g;
1637 if (!is_gimple_val (arg))
1639 g = gimple_build_assign (make_ssa_name (TREE_TYPE (arg)), arg);
1640 gimple_set_location (g, loc[0]);
1641 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1642 arg = gimple_assign_lhs (g);
1645 basic_block then_bb, fallthru_bb;
1646 *gsi = create_cond_insert_point (gsi, true, false, true,
1647 &then_bb, &fallthru_bb);
1648 g = gimple_build_cond (EQ_EXPR, arg,
1649 build_zero_cst (TREE_TYPE (arg)),
1650 NULL_TREE, NULL_TREE);
1651 gimple_set_location (g, loc[0]);
1652 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1654 *gsi = gsi_after_labels (then_bb);
1655 if (flag_sanitize_undefined_trap_on_error)
1656 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1657 else
1659 tree data = ubsan_create_data ("__ubsan_nonnull_arg_data",
1660 2, loc, NULL_TREE,
1661 build_int_cst (integer_type_node,
1662 i + 1),
1663 NULL_TREE);
1664 data = build_fold_addr_expr_loc (loc[0], data);
1665 enum built_in_function bcode
1666 = (flag_sanitize_recover & SANITIZE_NONNULL_ATTRIBUTE)
1667 ? BUILT_IN_UBSAN_HANDLE_NONNULL_ARG
1668 : BUILT_IN_UBSAN_HANDLE_NONNULL_ARG_ABORT;
1669 tree fn = builtin_decl_explicit (bcode);
1671 g = gimple_build_call (fn, 1, data);
1673 gimple_set_location (g, loc[0]);
1674 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1675 ubsan_create_edge (g);
1677 *gsi = gsi_for_stmt (stmt);
1679 flag_delete_null_pointer_checks = save_flag_delete_null_pointer_checks;
1682 /* Instrument returns in functions with returns_nonnull attribute. */
1684 static void
1685 instrument_nonnull_return (gimple_stmt_iterator *gsi)
1687 greturn *stmt = as_a <greturn *> (gsi_stmt (*gsi));
1688 location_t loc[2];
1689 tree arg = gimple_return_retval (stmt);
1690 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
1691 while for nonnull return sanitization it is clear. */
1692 int save_flag_delete_null_pointer_checks = flag_delete_null_pointer_checks;
1693 flag_delete_null_pointer_checks = 1;
1694 loc[0] = gimple_location (stmt);
1695 loc[1] = UNKNOWN_LOCATION;
1696 if (arg
1697 && POINTER_TYPE_P (TREE_TYPE (arg))
1698 && is_gimple_val (arg)
1699 && infer_nonnull_range_by_attribute (stmt, arg))
1701 basic_block then_bb, fallthru_bb;
1702 *gsi = create_cond_insert_point (gsi, true, false, true,
1703 &then_bb, &fallthru_bb);
1704 gimple *g = gimple_build_cond (EQ_EXPR, arg,
1705 build_zero_cst (TREE_TYPE (arg)),
1706 NULL_TREE, NULL_TREE);
1707 gimple_set_location (g, loc[0]);
1708 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1710 *gsi = gsi_after_labels (then_bb);
1711 if (flag_sanitize_undefined_trap_on_error)
1712 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1713 else
1715 tree data = ubsan_create_data ("__ubsan_nonnull_return_data",
1716 2, loc, NULL_TREE, NULL_TREE);
1717 data = build_fold_addr_expr_loc (loc[0], data);
1718 enum built_in_function bcode
1719 = (flag_sanitize_recover & SANITIZE_RETURNS_NONNULL_ATTRIBUTE)
1720 ? BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN
1721 : BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_ABORT;
1722 tree fn = builtin_decl_explicit (bcode);
1724 g = gimple_build_call (fn, 1, data);
1726 gimple_set_location (g, loc[0]);
1727 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1728 ubsan_create_edge (g);
1729 *gsi = gsi_for_stmt (stmt);
1731 flag_delete_null_pointer_checks = save_flag_delete_null_pointer_checks;
1734 /* Instrument memory references. Here we check whether the pointer
1735 points to an out-of-bounds location. */
1737 static void
1738 instrument_object_size (gimple_stmt_iterator *gsi, bool is_lhs)
1740 gimple *stmt = gsi_stmt (*gsi);
1741 location_t loc = gimple_location (stmt);
1742 tree t = is_lhs ? gimple_get_lhs (stmt) : gimple_assign_rhs1 (stmt);
1743 tree type;
1744 tree index = NULL_TREE;
1745 HOST_WIDE_INT size_in_bytes;
1747 type = TREE_TYPE (t);
1748 if (VOID_TYPE_P (type))
1749 return;
1751 switch (TREE_CODE (t))
1753 case COMPONENT_REF:
1754 if (TREE_CODE (t) == COMPONENT_REF
1755 && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1)) != NULL_TREE)
1757 tree repr = DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1));
1758 t = build3 (COMPONENT_REF, TREE_TYPE (repr), TREE_OPERAND (t, 0),
1759 repr, NULL_TREE);
1761 break;
1762 case ARRAY_REF:
1763 index = TREE_OPERAND (t, 1);
1764 break;
1765 case INDIRECT_REF:
1766 case MEM_REF:
1767 case VAR_DECL:
1768 case PARM_DECL:
1769 case RESULT_DECL:
1770 break;
1771 default:
1772 return;
1775 size_in_bytes = int_size_in_bytes (type);
1776 if (size_in_bytes <= 0)
1777 return;
1779 HOST_WIDE_INT bitsize, bitpos;
1780 tree offset;
1781 machine_mode mode;
1782 int volatilep = 0, reversep, unsignedp = 0;
1783 tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset, &mode,
1784 &unsignedp, &reversep, &volatilep, false);
1786 if (bitpos % BITS_PER_UNIT != 0
1787 || bitsize != size_in_bytes * BITS_PER_UNIT)
1788 return;
1790 bool decl_p = DECL_P (inner);
1791 tree base;
1792 if (decl_p)
1793 base = inner;
1794 else if (TREE_CODE (inner) == MEM_REF)
1795 base = TREE_OPERAND (inner, 0);
1796 else
1797 return;
1798 tree ptr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (t)), t);
1800 while (TREE_CODE (base) == SSA_NAME)
1802 gimple *def_stmt = SSA_NAME_DEF_STMT (base);
1803 if (gimple_assign_ssa_name_copy_p (def_stmt)
1804 || (gimple_assign_cast_p (def_stmt)
1805 && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (def_stmt))))
1806 || (is_gimple_assign (def_stmt)
1807 && gimple_assign_rhs_code (def_stmt) == POINTER_PLUS_EXPR))
1809 tree rhs1 = gimple_assign_rhs1 (def_stmt);
1810 if (TREE_CODE (rhs1) == SSA_NAME
1811 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs1))
1812 break;
1813 else
1814 base = rhs1;
1816 else
1817 break;
1820 if (!POINTER_TYPE_P (TREE_TYPE (base)) && !DECL_P (base))
1821 return;
1823 tree sizet;
1824 tree base_addr = base;
1825 gimple *bos_stmt = NULL;
1826 if (decl_p)
1827 base_addr = build1 (ADDR_EXPR,
1828 build_pointer_type (TREE_TYPE (base)), base);
1829 unsigned HOST_WIDE_INT size = compute_builtin_object_size (base_addr, 0);
1830 if (size != (unsigned HOST_WIDE_INT) -1)
1831 sizet = build_int_cst (sizetype, size);
1832 else if (optimize)
1834 if (LOCATION_LOCUS (loc) == UNKNOWN_LOCATION)
1835 loc = input_location;
1836 /* Generate __builtin_object_size call. */
1837 sizet = builtin_decl_explicit (BUILT_IN_OBJECT_SIZE);
1838 sizet = build_call_expr_loc (loc, sizet, 2, base_addr,
1839 integer_zero_node);
1840 sizet = force_gimple_operand_gsi (gsi, sizet, false, NULL_TREE, true,
1841 GSI_SAME_STMT);
1842 /* If the call above didn't end up being an integer constant, go one
1843 statement back and get the __builtin_object_size stmt. Save it,
1844 we might need it later. */
1845 if (SSA_VAR_P (sizet))
1847 gsi_prev (gsi);
1848 bos_stmt = gsi_stmt (*gsi);
1850 /* Move on to where we were. */
1851 gsi_next (gsi);
1854 else
1855 return;
1857 /* Generate UBSAN_OBJECT_SIZE (ptr, ptr+sizeof(*ptr)-base, objsize, ckind)
1858 call. */
1859 /* ptr + sizeof (*ptr) - base */
1860 t = fold_build2 (MINUS_EXPR, sizetype,
1861 fold_convert (pointer_sized_int_node, ptr),
1862 fold_convert (pointer_sized_int_node, base_addr));
1863 t = fold_build2 (PLUS_EXPR, sizetype, t, TYPE_SIZE_UNIT (type));
1865 /* Perhaps we can omit the check. */
1866 if (TREE_CODE (t) == INTEGER_CST
1867 && TREE_CODE (sizet) == INTEGER_CST
1868 && tree_int_cst_le (t, sizet))
1869 return;
1871 if (index != NULL_TREE
1872 && TREE_CODE (index) == SSA_NAME
1873 && TREE_CODE (sizet) == INTEGER_CST)
1875 gimple *def = SSA_NAME_DEF_STMT (index);
1876 if (is_gimple_assign (def)
1877 && gimple_assign_rhs_code (def) == BIT_AND_EXPR
1878 && TREE_CODE (gimple_assign_rhs2 (def)) == INTEGER_CST)
1880 tree cst = gimple_assign_rhs2 (def);
1881 tree sz = fold_build2 (EXACT_DIV_EXPR, sizetype, sizet,
1882 TYPE_SIZE_UNIT (type));
1883 if (tree_int_cst_sgn (cst) >= 0
1884 && tree_int_cst_lt (cst, sz))
1885 return;
1889 if (bos_stmt && gimple_call_builtin_p (bos_stmt, BUILT_IN_OBJECT_SIZE))
1890 ubsan_create_edge (bos_stmt);
1892 /* We have to emit the check. */
1893 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE, true,
1894 GSI_SAME_STMT);
1895 ptr = force_gimple_operand_gsi (gsi, ptr, true, NULL_TREE, true,
1896 GSI_SAME_STMT);
1897 tree ckind = build_int_cst (unsigned_char_type_node,
1898 is_lhs ? UBSAN_STORE_OF : UBSAN_LOAD_OF);
1899 gimple *g = gimple_build_call_internal (IFN_UBSAN_OBJECT_SIZE, 4,
1900 ptr, t, sizet, ckind);
1901 gimple_set_location (g, loc);
1902 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1905 /* True if we want to play UBSan games in the current function. */
1907 bool
1908 do_ubsan_in_current_function ()
1910 return (current_function_decl != NULL_TREE
1911 && !lookup_attribute ("no_sanitize_undefined",
1912 DECL_ATTRIBUTES (current_function_decl)));
1915 namespace {
1917 const pass_data pass_data_ubsan =
1919 GIMPLE_PASS, /* type */
1920 "ubsan", /* name */
1921 OPTGROUP_NONE, /* optinfo_flags */
1922 TV_TREE_UBSAN, /* tv_id */
1923 ( PROP_cfg | PROP_ssa ), /* properties_required */
1924 0, /* properties_provided */
1925 0, /* properties_destroyed */
1926 0, /* todo_flags_start */
1927 TODO_update_ssa, /* todo_flags_finish */
1930 class pass_ubsan : public gimple_opt_pass
1932 public:
1933 pass_ubsan (gcc::context *ctxt)
1934 : gimple_opt_pass (pass_data_ubsan, ctxt)
1937 /* opt_pass methods: */
1938 virtual bool gate (function *)
1940 return flag_sanitize & (SANITIZE_NULL | SANITIZE_SI_OVERFLOW
1941 | SANITIZE_BOOL | SANITIZE_ENUM
1942 | SANITIZE_ALIGNMENT
1943 | SANITIZE_NONNULL_ATTRIBUTE
1944 | SANITIZE_RETURNS_NONNULL_ATTRIBUTE
1945 | SANITIZE_OBJECT_SIZE)
1946 && do_ubsan_in_current_function ();
1949 virtual unsigned int execute (function *);
1951 }; // class pass_ubsan
1953 unsigned int
1954 pass_ubsan::execute (function *fun)
1956 basic_block bb;
1957 gimple_stmt_iterator gsi;
1959 initialize_sanitizer_builtins ();
1961 FOR_EACH_BB_FN (bb, fun)
1963 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
1965 gimple *stmt = gsi_stmt (gsi);
1966 if (is_gimple_debug (stmt) || gimple_clobber_p (stmt))
1968 gsi_next (&gsi);
1969 continue;
1972 if ((flag_sanitize & SANITIZE_SI_OVERFLOW)
1973 && is_gimple_assign (stmt))
1974 instrument_si_overflow (gsi);
1976 if (flag_sanitize & (SANITIZE_NULL | SANITIZE_ALIGNMENT))
1978 if (gimple_store_p (stmt))
1979 instrument_null (gsi, true);
1980 if (gimple_assign_load_p (stmt))
1981 instrument_null (gsi, false);
1984 if (flag_sanitize & (SANITIZE_BOOL | SANITIZE_ENUM)
1985 && gimple_assign_load_p (stmt))
1987 instrument_bool_enum_load (&gsi);
1988 bb = gimple_bb (stmt);
1991 if ((flag_sanitize & SANITIZE_NONNULL_ATTRIBUTE)
1992 && is_gimple_call (stmt)
1993 && !gimple_call_internal_p (stmt))
1995 instrument_nonnull_arg (&gsi);
1996 bb = gimple_bb (stmt);
1999 if ((flag_sanitize & SANITIZE_RETURNS_NONNULL_ATTRIBUTE)
2000 && gimple_code (stmt) == GIMPLE_RETURN)
2002 instrument_nonnull_return (&gsi);
2003 bb = gimple_bb (stmt);
2006 if (flag_sanitize & SANITIZE_OBJECT_SIZE)
2008 if (gimple_store_p (stmt))
2009 instrument_object_size (&gsi, true);
2010 if (gimple_assign_load_p (stmt))
2011 instrument_object_size (&gsi, false);
2014 gsi_next (&gsi);
2017 return 0;
2020 } // anon namespace
2022 gimple_opt_pass *
2023 make_pass_ubsan (gcc::context *ctxt)
2025 return new pass_ubsan (ctxt);
2028 #include "gt-ubsan.h"