PR c++/68475
[official-gcc.git] / gcc / ubsan.c
blobd3fbfd177e6896443f9f6d20e0087727bf24e4f9
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 gcc_assert (TYPE_SIZE (type) && tree_fits_uhwi_p (TYPE_SIZE (type)));
306 if (TREE_CODE (type) == REAL_TYPE)
307 return tree_to_uhwi (TYPE_SIZE (type));
308 else if (INTEGRAL_TYPE_P (type))
310 int prec = exact_log2 (tree_to_uhwi (TYPE_SIZE (type)));
311 gcc_assert (prec != -1);
312 return (prec << 1) | !TYPE_UNSIGNED (type);
314 else
315 return 0;
318 /* Helper routine that returns ADDR_EXPR of a VAR_DECL of a type
319 descriptor. It first looks into the hash table; if not found,
320 create the VAR_DECL, put it into the hash table and return the
321 ADDR_EXPR of it. TYPE describes a particular type. PSTYLE is
322 an enum controlling how we want to print the type. */
324 tree
325 ubsan_type_descriptor (tree type, enum ubsan_print_style pstyle)
327 /* See through any typedefs. */
328 type = TYPE_MAIN_VARIANT (type);
330 tree decl = decl_for_type_lookup (type);
331 /* It is possible that some of the earlier created DECLs were found
332 unused, in that case they weren't emitted and varpool_node::get
333 returns NULL node on them. But now we really need them. Thus,
334 renew them here. */
335 if (decl != NULL_TREE && varpool_node::get (decl))
336 return build_fold_addr_expr (decl);
338 tree dtype = ubsan_get_type_descriptor_type ();
339 tree type2 = type;
340 const char *tname = NULL;
341 pretty_printer pretty_name;
342 unsigned char deref_depth = 0;
343 unsigned short tkind, tinfo;
345 /* Get the name of the type, or the name of the pointer type. */
346 if (pstyle == UBSAN_PRINT_POINTER)
348 gcc_assert (POINTER_TYPE_P (type));
349 type2 = TREE_TYPE (type);
351 /* Remove any '*' operators from TYPE. */
352 while (POINTER_TYPE_P (type2))
353 deref_depth++, type2 = TREE_TYPE (type2);
355 if (TREE_CODE (type2) == METHOD_TYPE)
356 type2 = TYPE_METHOD_BASETYPE (type2);
359 /* If an array, get its type. */
360 type2 = strip_array_types (type2);
362 if (pstyle == UBSAN_PRINT_ARRAY)
364 while (POINTER_TYPE_P (type2))
365 deref_depth++, type2 = TREE_TYPE (type2);
368 if (TYPE_NAME (type2) != NULL)
370 if (TREE_CODE (TYPE_NAME (type2)) == IDENTIFIER_NODE)
371 tname = IDENTIFIER_POINTER (TYPE_NAME (type2));
372 else if (DECL_NAME (TYPE_NAME (type2)) != NULL)
373 tname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type2)));
376 if (tname == NULL)
377 /* We weren't able to determine the type name. */
378 tname = "<unknown>";
380 if (pstyle == UBSAN_PRINT_POINTER)
382 pp_printf (&pretty_name, "'%s%s%s%s%s%s%s",
383 TYPE_VOLATILE (type2) ? "volatile " : "",
384 TYPE_READONLY (type2) ? "const " : "",
385 TYPE_RESTRICT (type2) ? "restrict " : "",
386 TYPE_ATOMIC (type2) ? "_Atomic " : "",
387 TREE_CODE (type2) == RECORD_TYPE
388 ? "struct "
389 : TREE_CODE (type2) == UNION_TYPE
390 ? "union " : "", tname,
391 deref_depth == 0 ? "" : " ");
392 while (deref_depth-- > 0)
393 pp_star (&pretty_name);
394 pp_quote (&pretty_name);
396 else if (pstyle == UBSAN_PRINT_ARRAY)
398 /* Pretty print the array dimensions. */
399 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
400 tree t = type;
401 pp_printf (&pretty_name, "'%s ", tname);
402 while (deref_depth-- > 0)
403 pp_star (&pretty_name);
404 while (TREE_CODE (t) == ARRAY_TYPE)
406 pp_left_bracket (&pretty_name);
407 tree dom = TYPE_DOMAIN (t);
408 if (dom && TREE_CODE (TYPE_MAX_VALUE (dom)) == INTEGER_CST)
410 if (tree_fits_uhwi_p (TYPE_MAX_VALUE (dom))
411 && tree_to_uhwi (TYPE_MAX_VALUE (dom)) + 1 != 0)
412 pp_printf (&pretty_name, HOST_WIDE_INT_PRINT_DEC,
413 tree_to_uhwi (TYPE_MAX_VALUE (dom)) + 1);
414 else
415 pp_wide_int (&pretty_name,
416 wi::add (wi::to_widest (TYPE_MAX_VALUE (dom)), 1),
417 TYPE_SIGN (TREE_TYPE (dom)));
419 else
420 /* ??? We can't determine the variable name; print VLA unspec. */
421 pp_star (&pretty_name);
422 pp_right_bracket (&pretty_name);
423 t = TREE_TYPE (t);
425 pp_quote (&pretty_name);
427 /* Save the tree with stripped types. */
428 type = t;
430 else
431 pp_printf (&pretty_name, "'%s'", tname);
433 switch (TREE_CODE (type))
435 case BOOLEAN_TYPE:
436 case ENUMERAL_TYPE:
437 case INTEGER_TYPE:
438 tkind = 0x0000;
439 break;
440 case REAL_TYPE:
441 /* FIXME: libubsan right now only supports float, double and
442 long double type formats. */
443 if (TYPE_MODE (type) == TYPE_MODE (float_type_node)
444 || TYPE_MODE (type) == TYPE_MODE (double_type_node)
445 || TYPE_MODE (type) == TYPE_MODE (long_double_type_node))
446 tkind = 0x0001;
447 else
448 tkind = 0xffff;
449 break;
450 default:
451 tkind = 0xffff;
452 break;
454 tinfo = get_ubsan_type_info_for_type (type);
456 /* Create a new VAR_DECL of type descriptor. */
457 const char *tmp = pp_formatted_text (&pretty_name);
458 size_t len = strlen (tmp) + 1;
459 tree str = build_string (len, tmp);
460 TREE_TYPE (str) = build_array_type_nelts (char_type_node, len);
461 TREE_READONLY (str) = 1;
462 TREE_STATIC (str) = 1;
464 char tmp_name[32];
465 static unsigned int type_var_id_num;
466 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_type", type_var_id_num++);
467 decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name),
468 dtype);
469 TREE_STATIC (decl) = 1;
470 TREE_PUBLIC (decl) = 0;
471 DECL_ARTIFICIAL (decl) = 1;
472 DECL_IGNORED_P (decl) = 1;
473 DECL_EXTERNAL (decl) = 0;
474 DECL_SIZE (decl)
475 = size_binop (PLUS_EXPR, DECL_SIZE (decl), TYPE_SIZE (TREE_TYPE (str)));
476 DECL_SIZE_UNIT (decl)
477 = size_binop (PLUS_EXPR, DECL_SIZE_UNIT (decl),
478 TYPE_SIZE_UNIT (TREE_TYPE (str)));
480 tree ctor = build_constructor_va (dtype, 3, NULL_TREE,
481 build_int_cst (short_unsigned_type_node,
482 tkind), NULL_TREE,
483 build_int_cst (short_unsigned_type_node,
484 tinfo), NULL_TREE, str);
485 TREE_CONSTANT (ctor) = 1;
486 TREE_STATIC (ctor) = 1;
487 DECL_INITIAL (decl) = ctor;
488 varpool_node::finalize_decl (decl);
490 /* Save the VAR_DECL into the hash table. */
491 decl_for_type_insert (type, decl);
493 return build_fold_addr_expr (decl);
496 /* Create a structure for the ubsan library. NAME is a name of the new
497 structure. LOCCNT is number of locations, PLOC points to array of
498 locations. The arguments in ... are of __ubsan_type_descriptor type
499 and there are at most two of them, followed by NULL_TREE, followed
500 by optional extra arguments and another NULL_TREE. */
502 tree
503 ubsan_create_data (const char *name, int loccnt, const location_t *ploc, ...)
505 va_list args;
506 tree ret, t;
507 tree fields[6];
508 vec<tree, va_gc> *saved_args = NULL;
509 size_t i = 0;
510 int j;
512 /* Firstly, create a pointer to type descriptor type. */
513 tree td_type = ubsan_get_type_descriptor_type ();
514 td_type = build_pointer_type (td_type);
516 /* Create the structure type. */
517 ret = make_node (RECORD_TYPE);
518 for (j = 0; j < loccnt; j++)
520 gcc_checking_assert (i < 2);
521 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
522 ubsan_get_source_location_type ());
523 DECL_CONTEXT (fields[i]) = ret;
524 if (i)
525 DECL_CHAIN (fields[i - 1]) = fields[i];
526 i++;
529 va_start (args, ploc);
530 for (t = va_arg (args, tree); t != NULL_TREE;
531 i++, t = va_arg (args, tree))
533 gcc_checking_assert (i < 4);
534 /* Save the tree arguments for later use. */
535 vec_safe_push (saved_args, t);
536 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
537 td_type);
538 DECL_CONTEXT (fields[i]) = ret;
539 if (i)
540 DECL_CHAIN (fields[i - 1]) = fields[i];
543 for (t = va_arg (args, tree); t != NULL_TREE;
544 i++, t = va_arg (args, tree))
546 gcc_checking_assert (i < 6);
547 /* Save the tree arguments for later use. */
548 vec_safe_push (saved_args, t);
549 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
550 TREE_TYPE (t));
551 DECL_CONTEXT (fields[i]) = ret;
552 if (i)
553 DECL_CHAIN (fields[i - 1]) = fields[i];
555 va_end (args);
557 tree type_decl = build_decl (input_location, TYPE_DECL,
558 get_identifier (name), ret);
559 DECL_IGNORED_P (type_decl) = 1;
560 DECL_ARTIFICIAL (type_decl) = 1;
561 TYPE_FIELDS (ret) = fields[0];
562 TYPE_NAME (ret) = type_decl;
563 TYPE_STUB_DECL (ret) = type_decl;
564 layout_type (ret);
566 /* Now, fill in the type. */
567 char tmp_name[32];
568 static unsigned int ubsan_var_id_num;
569 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_data", ubsan_var_id_num++);
570 tree var = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name),
571 ret);
572 TREE_STATIC (var) = 1;
573 TREE_PUBLIC (var) = 0;
574 DECL_ARTIFICIAL (var) = 1;
575 DECL_IGNORED_P (var) = 1;
576 DECL_EXTERNAL (var) = 0;
578 vec<constructor_elt, va_gc> *v;
579 vec_alloc (v, i);
580 tree ctor = build_constructor (ret, v);
582 /* If desirable, set the __ubsan_source_location element. */
583 for (j = 0; j < loccnt; j++)
585 location_t loc = LOCATION_LOCUS (ploc[j]);
586 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, ubsan_source_location (loc));
589 size_t nelts = vec_safe_length (saved_args);
590 for (i = 0; i < nelts; i++)
592 t = (*saved_args)[i];
593 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, t);
596 TREE_CONSTANT (ctor) = 1;
597 TREE_STATIC (ctor) = 1;
598 DECL_INITIAL (var) = ctor;
599 varpool_node::finalize_decl (var);
601 return var;
604 /* Instrument the __builtin_unreachable call. We just call the libubsan
605 routine instead. */
607 bool
608 ubsan_instrument_unreachable (gimple_stmt_iterator *gsi)
610 gimple *g;
611 location_t loc = gimple_location (gsi_stmt (*gsi));
613 if (flag_sanitize_undefined_trap_on_error)
614 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
615 else
617 tree data = ubsan_create_data ("__ubsan_unreachable_data", 1, &loc,
618 NULL_TREE, NULL_TREE);
619 data = build_fold_addr_expr_loc (loc, data);
620 tree fn
621 = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE);
622 g = gimple_build_call (fn, 1, data);
624 gimple_set_location (g, loc);
625 gsi_replace (gsi, g, false);
626 return false;
629 /* Return true if T is a call to a libubsan routine. */
631 bool
632 is_ubsan_builtin_p (tree t)
634 return TREE_CODE (t) == FUNCTION_DECL
635 && DECL_BUILT_IN_CLASS (t) == BUILT_IN_NORMAL
636 && strncmp (IDENTIFIER_POINTER (DECL_NAME (t)),
637 "__builtin___ubsan_", 18) == 0;
640 /* Create a callgraph edge for statement STMT. */
642 static void
643 ubsan_create_edge (gimple *stmt)
645 gcall *call_stmt = dyn_cast <gcall *> (stmt);
646 basic_block bb = gimple_bb (stmt);
647 int freq = compute_call_stmt_bb_frequency (current_function_decl, bb);
648 cgraph_node *node = cgraph_node::get (current_function_decl);
649 tree decl = gimple_call_fndecl (call_stmt);
650 if (decl)
651 node->create_edge (cgraph_node::get_create (decl), call_stmt, bb->count,
652 freq);
655 /* Expand the UBSAN_BOUNDS special builtin function. */
657 bool
658 ubsan_expand_bounds_ifn (gimple_stmt_iterator *gsi)
660 gimple *stmt = gsi_stmt (*gsi);
661 location_t loc = gimple_location (stmt);
662 gcc_assert (gimple_call_num_args (stmt) == 3);
664 /* Pick up the arguments of the UBSAN_BOUNDS call. */
665 tree type = TREE_TYPE (TREE_TYPE (gimple_call_arg (stmt, 0)));
666 tree index = gimple_call_arg (stmt, 1);
667 tree orig_index_type = TREE_TYPE (index);
668 tree bound = gimple_call_arg (stmt, 2);
670 gimple_stmt_iterator gsi_orig = *gsi;
672 /* Create condition "if (index > bound)". */
673 basic_block then_bb, fallthru_bb;
674 gimple_stmt_iterator cond_insert_point
675 = create_cond_insert_point (gsi, false, false, true,
676 &then_bb, &fallthru_bb);
677 index = fold_convert (TREE_TYPE (bound), index);
678 index = force_gimple_operand_gsi (&cond_insert_point, index,
679 true, NULL_TREE,
680 false, GSI_NEW_STMT);
681 gimple *g = gimple_build_cond (GT_EXPR, index, bound, NULL_TREE, NULL_TREE);
682 gimple_set_location (g, loc);
683 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
685 /* Generate __ubsan_handle_out_of_bounds call. */
686 *gsi = gsi_after_labels (then_bb);
687 if (flag_sanitize_undefined_trap_on_error)
688 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
689 else
691 tree data
692 = ubsan_create_data ("__ubsan_out_of_bounds_data", 1, &loc,
693 ubsan_type_descriptor (type, UBSAN_PRINT_ARRAY),
694 ubsan_type_descriptor (orig_index_type),
695 NULL_TREE, NULL_TREE);
696 data = build_fold_addr_expr_loc (loc, data);
697 enum built_in_function bcode
698 = (flag_sanitize_recover & SANITIZE_BOUNDS)
699 ? BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS
700 : BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS_ABORT;
701 tree fn = builtin_decl_explicit (bcode);
702 tree val = force_gimple_operand_gsi (gsi, ubsan_encode_value (index),
703 true, NULL_TREE, true,
704 GSI_SAME_STMT);
705 g = gimple_build_call (fn, 2, data, val);
707 gimple_set_location (g, loc);
708 gsi_insert_before (gsi, g, GSI_SAME_STMT);
710 /* Get rid of the UBSAN_BOUNDS call from the IR. */
711 unlink_stmt_vdef (stmt);
712 gsi_remove (&gsi_orig, true);
714 /* Point GSI to next logical statement. */
715 *gsi = gsi_start_bb (fallthru_bb);
716 return true;
719 /* Expand UBSAN_NULL internal call. The type is kept on the ckind
720 argument which is a constant, because the middle-end treats pointer
721 conversions as useless and therefore the type of the first argument
722 could be changed to any other pointer type. */
724 bool
725 ubsan_expand_null_ifn (gimple_stmt_iterator *gsip)
727 gimple_stmt_iterator gsi = *gsip;
728 gimple *stmt = gsi_stmt (gsi);
729 location_t loc = gimple_location (stmt);
730 gcc_assert (gimple_call_num_args (stmt) == 3);
731 tree ptr = gimple_call_arg (stmt, 0);
732 tree ckind = gimple_call_arg (stmt, 1);
733 tree align = gimple_call_arg (stmt, 2);
734 tree check_align = NULL_TREE;
735 bool check_null;
737 basic_block cur_bb = gsi_bb (gsi);
739 gimple *g;
740 if (!integer_zerop (align))
742 unsigned int ptralign = get_pointer_alignment (ptr) / BITS_PER_UNIT;
743 if (compare_tree_int (align, ptralign) == 1)
745 check_align = make_ssa_name (pointer_sized_int_node);
746 g = gimple_build_assign (check_align, NOP_EXPR, ptr);
747 gimple_set_location (g, loc);
748 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
751 check_null = (flag_sanitize & SANITIZE_NULL) != 0;
753 if (check_align == NULL_TREE && !check_null)
755 gsi_remove (gsip, true);
756 /* Unlink the UBSAN_NULLs vops before replacing it. */
757 unlink_stmt_vdef (stmt);
758 return true;
761 /* Split the original block holding the pointer dereference. */
762 edge e = split_block (cur_bb, stmt);
764 /* Get a hold on the 'condition block', the 'then block' and the
765 'else block'. */
766 basic_block cond_bb = e->src;
767 basic_block fallthru_bb = e->dest;
768 basic_block then_bb = create_empty_bb (cond_bb);
769 add_bb_to_loop (then_bb, cond_bb->loop_father);
770 loops_state_set (LOOPS_NEED_FIXUP);
772 /* Make an edge coming from the 'cond block' into the 'then block';
773 this edge is unlikely taken, so set up the probability accordingly. */
774 e = make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
775 e->probability = PROB_VERY_UNLIKELY;
777 /* Connect 'then block' with the 'else block'. This is needed
778 as the ubsan routines we call in the 'then block' are not noreturn.
779 The 'then block' only has one outcoming edge. */
780 make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);
782 /* Set up the fallthrough basic block. */
783 e = find_edge (cond_bb, fallthru_bb);
784 e->flags = EDGE_FALSE_VALUE;
785 e->count = cond_bb->count;
786 e->probability = REG_BR_PROB_BASE - PROB_VERY_UNLIKELY;
788 /* Update dominance info for the newly created then_bb; note that
789 fallthru_bb's dominance info has already been updated by
790 split_block. */
791 if (dom_info_available_p (CDI_DOMINATORS))
792 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
794 /* Put the ubsan builtin call into the newly created BB. */
795 if (flag_sanitize_undefined_trap_on_error)
796 g = gimple_build_call (builtin_decl_implicit (BUILT_IN_TRAP), 0);
797 else
799 enum built_in_function bcode
800 = (flag_sanitize_recover & ((check_align ? SANITIZE_ALIGNMENT : 0)
801 | (check_null ? SANITIZE_NULL : 0)))
802 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
803 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT;
804 tree fn = builtin_decl_implicit (bcode);
805 tree data
806 = ubsan_create_data ("__ubsan_null_data", 1, &loc,
807 ubsan_type_descriptor (TREE_TYPE (ckind),
808 UBSAN_PRINT_POINTER),
809 NULL_TREE,
810 align,
811 fold_convert (unsigned_char_type_node, ckind),
812 NULL_TREE);
813 data = build_fold_addr_expr_loc (loc, data);
814 g = gimple_build_call (fn, 2, data,
815 check_align ? check_align
816 : build_zero_cst (pointer_sized_int_node));
818 gimple_stmt_iterator gsi2 = gsi_start_bb (then_bb);
819 gimple_set_location (g, loc);
820 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
822 /* Unlink the UBSAN_NULLs vops before replacing it. */
823 unlink_stmt_vdef (stmt);
825 if (check_null)
827 g = gimple_build_cond (EQ_EXPR, ptr, build_int_cst (TREE_TYPE (ptr), 0),
828 NULL_TREE, NULL_TREE);
829 gimple_set_location (g, loc);
831 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
832 gsi_replace (&gsi, g, false);
833 stmt = g;
836 if (check_align)
838 if (check_null)
840 /* Split the block with the condition again. */
841 e = split_block (cond_bb, stmt);
842 basic_block cond1_bb = e->src;
843 basic_block cond2_bb = e->dest;
845 /* Make an edge coming from the 'cond1 block' into the 'then block';
846 this edge is unlikely taken, so set up the probability
847 accordingly. */
848 e = make_edge (cond1_bb, then_bb, EDGE_TRUE_VALUE);
849 e->probability = PROB_VERY_UNLIKELY;
851 /* Set up the fallthrough basic block. */
852 e = find_edge (cond1_bb, cond2_bb);
853 e->flags = EDGE_FALSE_VALUE;
854 e->count = cond1_bb->count;
855 e->probability = REG_BR_PROB_BASE - PROB_VERY_UNLIKELY;
857 /* Update dominance info. */
858 if (dom_info_available_p (CDI_DOMINATORS))
860 set_immediate_dominator (CDI_DOMINATORS, fallthru_bb, cond1_bb);
861 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond1_bb);
864 gsi2 = gsi_start_bb (cond2_bb);
867 tree mask = build_int_cst (pointer_sized_int_node,
868 tree_to_uhwi (align) - 1);
869 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
870 BIT_AND_EXPR, check_align, mask);
871 gimple_set_location (g, loc);
872 if (check_null)
873 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
874 else
875 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
877 g = gimple_build_cond (NE_EXPR, gimple_assign_lhs (g),
878 build_int_cst (pointer_sized_int_node, 0),
879 NULL_TREE, NULL_TREE);
880 gimple_set_location (g, loc);
881 if (check_null)
882 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
883 else
884 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
885 gsi_replace (&gsi, g, false);
887 return false;
890 #define OBJSZ_MAX_OFFSET (1024 * 16)
892 /* Expand UBSAN_OBJECT_SIZE internal call. */
894 bool
895 ubsan_expand_objsize_ifn (gimple_stmt_iterator *gsi)
897 gimple *stmt = gsi_stmt (*gsi);
898 location_t loc = gimple_location (stmt);
899 gcc_assert (gimple_call_num_args (stmt) == 4);
901 tree ptr = gimple_call_arg (stmt, 0);
902 tree offset = gimple_call_arg (stmt, 1);
903 tree size = gimple_call_arg (stmt, 2);
904 tree ckind = gimple_call_arg (stmt, 3);
905 gimple_stmt_iterator gsi_orig = *gsi;
906 gimple *g;
908 /* See if we can discard the check. */
909 if (TREE_CODE (size) != INTEGER_CST
910 || integer_all_onesp (size))
911 /* Yes, __builtin_object_size couldn't determine the
912 object size. */;
913 else if (TREE_CODE (offset) == INTEGER_CST
914 && wi::ges_p (wi::to_widest (offset), -OBJSZ_MAX_OFFSET)
915 && wi::les_p (wi::to_widest (offset), -1))
916 /* The offset is in range [-16K, -1]. */;
917 else
919 /* if (offset > objsize) */
920 basic_block then_bb, fallthru_bb;
921 gimple_stmt_iterator cond_insert_point
922 = create_cond_insert_point (gsi, false, false, true,
923 &then_bb, &fallthru_bb);
924 g = gimple_build_cond (GT_EXPR, offset, size, NULL_TREE, NULL_TREE);
925 gimple_set_location (g, loc);
926 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
928 /* If the offset is small enough, we don't need the second
929 run-time check. */
930 if (TREE_CODE (offset) == INTEGER_CST
931 && wi::ges_p (wi::to_widest (offset), 0)
932 && wi::les_p (wi::to_widest (offset), OBJSZ_MAX_OFFSET))
933 *gsi = gsi_after_labels (then_bb);
934 else
936 /* Don't issue run-time error if (ptr > ptr + offset). That
937 may happen when computing a POINTER_PLUS_EXPR. */
938 basic_block then2_bb, fallthru2_bb;
940 gimple_stmt_iterator gsi2 = gsi_after_labels (then_bb);
941 cond_insert_point = create_cond_insert_point (&gsi2, false, false,
942 true, &then2_bb,
943 &fallthru2_bb);
944 /* Convert the pointer to an integer type. */
945 tree p = make_ssa_name (pointer_sized_int_node);
946 g = gimple_build_assign (p, NOP_EXPR, ptr);
947 gimple_set_location (g, loc);
948 gsi_insert_before (&cond_insert_point, g, GSI_NEW_STMT);
949 p = gimple_assign_lhs (g);
950 /* Compute ptr + offset. */
951 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
952 PLUS_EXPR, p, offset);
953 gimple_set_location (g, loc);
954 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
955 /* Now build the conditional and put it into the IR. */
956 g = gimple_build_cond (LE_EXPR, p, gimple_assign_lhs (g),
957 NULL_TREE, NULL_TREE);
958 gimple_set_location (g, loc);
959 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
960 *gsi = gsi_after_labels (then2_bb);
963 /* Generate __ubsan_handle_type_mismatch call. */
964 if (flag_sanitize_undefined_trap_on_error)
965 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
966 else
968 tree data
969 = ubsan_create_data ("__ubsan_objsz_data", 1, &loc,
970 ubsan_type_descriptor (TREE_TYPE (ptr),
971 UBSAN_PRINT_POINTER),
972 NULL_TREE,
973 build_zero_cst (pointer_sized_int_node),
974 ckind,
975 NULL_TREE);
976 data = build_fold_addr_expr_loc (loc, data);
977 enum built_in_function bcode
978 = (flag_sanitize_recover & SANITIZE_OBJECT_SIZE)
979 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
980 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT;
981 tree p = make_ssa_name (pointer_sized_int_node);
982 g = gimple_build_assign (p, NOP_EXPR, ptr);
983 gimple_set_location (g, loc);
984 gsi_insert_before (gsi, g, GSI_SAME_STMT);
985 g = gimple_build_call (builtin_decl_explicit (bcode), 2, data, p);
987 gimple_set_location (g, loc);
988 gsi_insert_before (gsi, g, GSI_SAME_STMT);
990 /* Point GSI to next logical statement. */
991 *gsi = gsi_start_bb (fallthru_bb);
993 /* Get rid of the UBSAN_OBJECT_SIZE call from the IR. */
994 unlink_stmt_vdef (stmt);
995 gsi_remove (&gsi_orig, true);
996 return true;
999 /* Get rid of the UBSAN_OBJECT_SIZE call from the IR. */
1000 unlink_stmt_vdef (stmt);
1001 gsi_remove (gsi, true);
1002 return true;
1005 /* Cached __ubsan_vptr_type_cache decl. */
1006 static GTY(()) tree ubsan_vptr_type_cache_decl;
1008 /* Expand UBSAN_VPTR internal call. The type is kept on the ckind
1009 argument which is a constant, because the middle-end treats pointer
1010 conversions as useless and therefore the type of the first argument
1011 could be changed to any other pointer type. */
1013 bool
1014 ubsan_expand_vptr_ifn (gimple_stmt_iterator *gsip)
1016 gimple_stmt_iterator gsi = *gsip;
1017 gimple *stmt = gsi_stmt (gsi);
1018 location_t loc = gimple_location (stmt);
1019 gcc_assert (gimple_call_num_args (stmt) == 5);
1020 tree op = gimple_call_arg (stmt, 0);
1021 tree vptr = gimple_call_arg (stmt, 1);
1022 tree str_hash = gimple_call_arg (stmt, 2);
1023 tree ti_decl_addr = gimple_call_arg (stmt, 3);
1024 tree ckind_tree = gimple_call_arg (stmt, 4);
1025 ubsan_null_ckind ckind = (ubsan_null_ckind) tree_to_uhwi (ckind_tree);
1026 tree type = TREE_TYPE (TREE_TYPE (ckind_tree));
1027 gimple *g;
1028 basic_block fallthru_bb = NULL;
1030 if (ckind == UBSAN_DOWNCAST_POINTER)
1032 /* Guard everything with if (op != NULL) { ... }. */
1033 basic_block then_bb;
1034 gimple_stmt_iterator cond_insert_point
1035 = create_cond_insert_point (gsip, false, false, true,
1036 &then_bb, &fallthru_bb);
1037 g = gimple_build_cond (NE_EXPR, op, build_zero_cst (TREE_TYPE (op)),
1038 NULL_TREE, NULL_TREE);
1039 gimple_set_location (g, loc);
1040 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
1041 *gsip = gsi_after_labels (then_bb);
1042 gsi_remove (&gsi, false);
1043 gsi_insert_before (gsip, stmt, GSI_NEW_STMT);
1044 gsi = *gsip;
1047 tree htype = TREE_TYPE (str_hash);
1048 tree cst = wide_int_to_tree (htype,
1049 wi::uhwi (((uint64_t) 0x9ddfea08 << 32)
1050 | 0xeb382d69, 64));
1051 g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1052 vptr, str_hash);
1053 gimple_set_location (g, loc);
1054 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1055 g = gimple_build_assign (make_ssa_name (htype), MULT_EXPR,
1056 gimple_assign_lhs (g), cst);
1057 gimple_set_location (g, loc);
1058 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1059 tree t1 = gimple_assign_lhs (g);
1060 g = gimple_build_assign (make_ssa_name (htype), LSHIFT_EXPR,
1061 t1, build_int_cst (integer_type_node, 47));
1062 gimple_set_location (g, loc);
1063 tree t2 = gimple_assign_lhs (g);
1064 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1065 g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1066 vptr, t1);
1067 gimple_set_location (g, loc);
1068 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1069 g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1070 t2, gimple_assign_lhs (g));
1071 gimple_set_location (g, loc);
1072 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1073 g = gimple_build_assign (make_ssa_name (htype), MULT_EXPR,
1074 gimple_assign_lhs (g), cst);
1075 gimple_set_location (g, loc);
1076 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1077 tree t3 = gimple_assign_lhs (g);
1078 g = gimple_build_assign (make_ssa_name (htype), LSHIFT_EXPR,
1079 t3, build_int_cst (integer_type_node, 47));
1080 gimple_set_location (g, loc);
1081 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1082 g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1083 t3, gimple_assign_lhs (g));
1084 gimple_set_location (g, loc);
1085 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1086 g = gimple_build_assign (make_ssa_name (htype), MULT_EXPR,
1087 gimple_assign_lhs (g), cst);
1088 gimple_set_location (g, loc);
1089 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1090 if (!useless_type_conversion_p (pointer_sized_int_node, htype))
1092 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
1093 NOP_EXPR, gimple_assign_lhs (g));
1094 gimple_set_location (g, loc);
1095 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1097 tree hash = gimple_assign_lhs (g);
1099 if (ubsan_vptr_type_cache_decl == NULL_TREE)
1101 tree atype = build_array_type_nelts (pointer_sized_int_node, 128);
1102 tree array = build_decl (UNKNOWN_LOCATION, VAR_DECL,
1103 get_identifier ("__ubsan_vptr_type_cache"),
1104 atype);
1105 DECL_ARTIFICIAL (array) = 1;
1106 DECL_IGNORED_P (array) = 1;
1107 TREE_PUBLIC (array) = 1;
1108 TREE_STATIC (array) = 1;
1109 DECL_EXTERNAL (array) = 1;
1110 DECL_VISIBILITY (array) = VISIBILITY_DEFAULT;
1111 DECL_VISIBILITY_SPECIFIED (array) = 1;
1112 varpool_node::finalize_decl (array);
1113 ubsan_vptr_type_cache_decl = array;
1116 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
1117 BIT_AND_EXPR, hash,
1118 build_int_cst (pointer_sized_int_node, 127));
1119 gimple_set_location (g, loc);
1120 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1122 tree c = build4_loc (loc, ARRAY_REF, pointer_sized_int_node,
1123 ubsan_vptr_type_cache_decl, gimple_assign_lhs (g),
1124 NULL_TREE, NULL_TREE);
1125 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
1126 ARRAY_REF, c);
1127 gimple_set_location (g, loc);
1128 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1130 basic_block then_bb, fallthru2_bb;
1131 gimple_stmt_iterator cond_insert_point
1132 = create_cond_insert_point (gsip, false, false, true,
1133 &then_bb, &fallthru2_bb);
1134 g = gimple_build_cond (NE_EXPR, gimple_assign_lhs (g), hash,
1135 NULL_TREE, NULL_TREE);
1136 gimple_set_location (g, loc);
1137 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
1138 *gsip = gsi_after_labels (then_bb);
1139 if (fallthru_bb == NULL)
1140 fallthru_bb = fallthru2_bb;
1142 tree data
1143 = ubsan_create_data ("__ubsan_vptr_data", 1, &loc,
1144 ubsan_type_descriptor (type), NULL_TREE, ti_decl_addr,
1145 build_int_cst (unsigned_char_type_node, ckind),
1146 NULL_TREE);
1147 data = build_fold_addr_expr_loc (loc, data);
1148 enum built_in_function bcode
1149 = (flag_sanitize_recover & SANITIZE_VPTR)
1150 ? BUILT_IN_UBSAN_HANDLE_DYNAMIC_TYPE_CACHE_MISS
1151 : BUILT_IN_UBSAN_HANDLE_DYNAMIC_TYPE_CACHE_MISS_ABORT;
1153 g = gimple_build_call (builtin_decl_explicit (bcode), 3, data, op, hash);
1154 gimple_set_location (g, loc);
1155 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1157 /* Point GSI to next logical statement. */
1158 *gsip = gsi_start_bb (fallthru_bb);
1160 /* Get rid of the UBSAN_VPTR call from the IR. */
1161 unlink_stmt_vdef (stmt);
1162 gsi_remove (&gsi, true);
1163 return true;
1166 /* Instrument a memory reference. BASE is the base of MEM, IS_LHS says
1167 whether the pointer is on the left hand side of the assignment. */
1169 static void
1170 instrument_mem_ref (tree mem, tree base, gimple_stmt_iterator *iter,
1171 bool is_lhs)
1173 enum ubsan_null_ckind ikind = is_lhs ? UBSAN_STORE_OF : UBSAN_LOAD_OF;
1174 unsigned int align = 0;
1175 if (flag_sanitize & SANITIZE_ALIGNMENT)
1177 align = min_align_of_type (TREE_TYPE (base));
1178 if (align <= 1)
1179 align = 0;
1181 if (align == 0 && (flag_sanitize & SANITIZE_NULL) == 0)
1182 return;
1183 tree t = TREE_OPERAND (base, 0);
1184 if (!POINTER_TYPE_P (TREE_TYPE (t)))
1185 return;
1186 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (base)) && mem != base)
1187 ikind = UBSAN_MEMBER_ACCESS;
1188 tree kind = build_int_cst (build_pointer_type (TREE_TYPE (base)), ikind);
1189 tree alignt = build_int_cst (pointer_sized_int_node, align);
1190 gcall *g = gimple_build_call_internal (IFN_UBSAN_NULL, 3, t, kind, alignt);
1191 gimple_set_location (g, gimple_location (gsi_stmt (*iter)));
1192 gsi_insert_before (iter, g, GSI_SAME_STMT);
1195 /* Perform the pointer instrumentation. */
1197 static void
1198 instrument_null (gimple_stmt_iterator gsi, bool is_lhs)
1200 gimple *stmt = gsi_stmt (gsi);
1201 tree t = is_lhs ? gimple_get_lhs (stmt) : gimple_assign_rhs1 (stmt);
1202 tree base = get_base_address (t);
1203 const enum tree_code code = TREE_CODE (base);
1204 if (code == MEM_REF
1205 && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
1206 instrument_mem_ref (t, base, &gsi, is_lhs);
1209 /* Build an ubsan builtin call for the signed-integer-overflow
1210 sanitization. CODE says what kind of builtin are we building,
1211 LOC is a location, LHSTYPE is the type of LHS, OP0 and OP1
1212 are operands of the binary operation. */
1214 tree
1215 ubsan_build_overflow_builtin (tree_code code, location_t loc, tree lhstype,
1216 tree op0, tree op1)
1218 if (flag_sanitize_undefined_trap_on_error)
1219 return build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
1221 tree data = ubsan_create_data ("__ubsan_overflow_data", 1, &loc,
1222 ubsan_type_descriptor (lhstype), NULL_TREE,
1223 NULL_TREE);
1224 enum built_in_function fn_code;
1226 switch (code)
1228 case PLUS_EXPR:
1229 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1230 ? BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW
1231 : BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW_ABORT;
1232 break;
1233 case MINUS_EXPR:
1234 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1235 ? BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW
1236 : BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW_ABORT;
1237 break;
1238 case MULT_EXPR:
1239 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1240 ? BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW
1241 : BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW_ABORT;
1242 break;
1243 case NEGATE_EXPR:
1244 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1245 ? BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW
1246 : BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW_ABORT;
1247 break;
1248 default:
1249 gcc_unreachable ();
1251 tree fn = builtin_decl_explicit (fn_code);
1252 return build_call_expr_loc (loc, fn, 2 + (code != NEGATE_EXPR),
1253 build_fold_addr_expr_loc (loc, data),
1254 ubsan_encode_value (op0, true),
1255 op1 ? ubsan_encode_value (op1, true)
1256 : NULL_TREE);
1259 /* Perform the signed integer instrumentation. GSI is the iterator
1260 pointing at statement we are trying to instrument. */
1262 static void
1263 instrument_si_overflow (gimple_stmt_iterator gsi)
1265 gimple *stmt = gsi_stmt (gsi);
1266 tree_code code = gimple_assign_rhs_code (stmt);
1267 tree lhs = gimple_assign_lhs (stmt);
1268 tree lhstype = TREE_TYPE (lhs);
1269 tree a, b;
1270 gimple *g;
1272 /* If this is not a signed operation, don't instrument anything here.
1273 Also punt on bit-fields. */
1274 if (!INTEGRAL_TYPE_P (lhstype)
1275 || TYPE_OVERFLOW_WRAPS (lhstype)
1276 || GET_MODE_BITSIZE (TYPE_MODE (lhstype)) != TYPE_PRECISION (lhstype))
1277 return;
1279 switch (code)
1281 case MINUS_EXPR:
1282 case PLUS_EXPR:
1283 case MULT_EXPR:
1284 /* Transform
1285 i = u {+,-,*} 5;
1286 into
1287 i = UBSAN_CHECK_{ADD,SUB,MUL} (u, 5); */
1288 a = gimple_assign_rhs1 (stmt);
1289 b = gimple_assign_rhs2 (stmt);
1290 g = gimple_build_call_internal (code == PLUS_EXPR
1291 ? IFN_UBSAN_CHECK_ADD
1292 : code == MINUS_EXPR
1293 ? IFN_UBSAN_CHECK_SUB
1294 : IFN_UBSAN_CHECK_MUL, 2, a, b);
1295 gimple_call_set_lhs (g, lhs);
1296 gsi_replace (&gsi, g, false);
1297 break;
1298 case NEGATE_EXPR:
1299 /* Represent i = -u;
1301 i = UBSAN_CHECK_SUB (0, u); */
1302 a = build_int_cst (lhstype, 0);
1303 b = gimple_assign_rhs1 (stmt);
1304 g = gimple_build_call_internal (IFN_UBSAN_CHECK_SUB, 2, a, b);
1305 gimple_call_set_lhs (g, lhs);
1306 gsi_replace (&gsi, g, false);
1307 break;
1308 case ABS_EXPR:
1309 /* Transform i = ABS_EXPR<u>;
1310 into
1311 _N = UBSAN_CHECK_SUB (0, u);
1312 i = ABS_EXPR<_N>; */
1313 a = build_int_cst (lhstype, 0);
1314 b = gimple_assign_rhs1 (stmt);
1315 g = gimple_build_call_internal (IFN_UBSAN_CHECK_SUB, 2, a, b);
1316 a = make_ssa_name (lhstype);
1317 gimple_call_set_lhs (g, a);
1318 gimple_set_location (g, gimple_location (stmt));
1319 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
1320 gimple_assign_set_rhs1 (stmt, a);
1321 update_stmt (stmt);
1322 break;
1323 default:
1324 break;
1328 /* Instrument loads from (non-bitfield) bool and C++ enum values
1329 to check if the memory value is outside of the range of the valid
1330 type values. */
1332 static void
1333 instrument_bool_enum_load (gimple_stmt_iterator *gsi)
1335 gimple *stmt = gsi_stmt (*gsi);
1336 tree rhs = gimple_assign_rhs1 (stmt);
1337 tree type = TREE_TYPE (rhs);
1338 tree minv = NULL_TREE, maxv = NULL_TREE;
1340 if (TREE_CODE (type) == BOOLEAN_TYPE && (flag_sanitize & SANITIZE_BOOL))
1342 minv = boolean_false_node;
1343 maxv = boolean_true_node;
1345 else if (TREE_CODE (type) == ENUMERAL_TYPE
1346 && (flag_sanitize & SANITIZE_ENUM)
1347 && TREE_TYPE (type) != NULL_TREE
1348 && TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE
1349 && (TYPE_PRECISION (TREE_TYPE (type))
1350 < GET_MODE_PRECISION (TYPE_MODE (type))))
1352 minv = TYPE_MIN_VALUE (TREE_TYPE (type));
1353 maxv = TYPE_MAX_VALUE (TREE_TYPE (type));
1355 else
1356 return;
1358 int modebitsize = GET_MODE_BITSIZE (TYPE_MODE (type));
1359 HOST_WIDE_INT bitsize, bitpos;
1360 tree offset;
1361 machine_mode mode;
1362 int volatilep = 0, reversep, unsignedp = 0;
1363 tree base = get_inner_reference (rhs, &bitsize, &bitpos, &offset, &mode,
1364 &unsignedp, &reversep, &volatilep, false);
1365 tree utype = build_nonstandard_integer_type (modebitsize, 1);
1367 if ((TREE_CODE (base) == VAR_DECL && DECL_HARD_REGISTER (base))
1368 || (bitpos % modebitsize) != 0
1369 || bitsize != modebitsize
1370 || GET_MODE_BITSIZE (TYPE_MODE (utype)) != modebitsize
1371 || TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME)
1372 return;
1374 bool ends_bb = stmt_ends_bb_p (stmt);
1375 location_t loc = gimple_location (stmt);
1376 tree lhs = gimple_assign_lhs (stmt);
1377 tree ptype = build_pointer_type (TREE_TYPE (rhs));
1378 tree atype = reference_alias_ptr_type (rhs);
1379 gimple *g = gimple_build_assign (make_ssa_name (ptype),
1380 build_fold_addr_expr (rhs));
1381 gimple_set_location (g, loc);
1382 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1383 tree mem = build2 (MEM_REF, utype, gimple_assign_lhs (g),
1384 build_int_cst (atype, 0));
1385 tree urhs = make_ssa_name (utype);
1386 if (ends_bb)
1388 gimple_assign_set_lhs (stmt, urhs);
1389 g = gimple_build_assign (lhs, NOP_EXPR, urhs);
1390 gimple_set_location (g, loc);
1391 edge e = find_fallthru_edge (gimple_bb (stmt)->succs);
1392 gsi_insert_on_edge_immediate (e, g);
1393 gimple_assign_set_rhs_from_tree (gsi, mem);
1394 update_stmt (stmt);
1395 *gsi = gsi_for_stmt (g);
1396 g = stmt;
1398 else
1400 g = gimple_build_assign (urhs, mem);
1401 gimple_set_location (g, loc);
1402 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1404 minv = fold_convert (utype, minv);
1405 maxv = fold_convert (utype, maxv);
1406 if (!integer_zerop (minv))
1408 g = gimple_build_assign (make_ssa_name (utype), MINUS_EXPR, urhs, minv);
1409 gimple_set_location (g, loc);
1410 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1413 gimple_stmt_iterator gsi2 = *gsi;
1414 basic_block then_bb, fallthru_bb;
1415 *gsi = create_cond_insert_point (gsi, true, false, true,
1416 &then_bb, &fallthru_bb);
1417 g = gimple_build_cond (GT_EXPR, gimple_assign_lhs (g),
1418 int_const_binop (MINUS_EXPR, maxv, minv),
1419 NULL_TREE, NULL_TREE);
1420 gimple_set_location (g, loc);
1421 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1423 if (!ends_bb)
1425 gimple_assign_set_rhs_with_ops (&gsi2, NOP_EXPR, urhs);
1426 update_stmt (stmt);
1429 gsi2 = gsi_after_labels (then_bb);
1430 if (flag_sanitize_undefined_trap_on_error)
1431 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1432 else
1434 tree data = ubsan_create_data ("__ubsan_invalid_value_data", 1, &loc,
1435 ubsan_type_descriptor (type), NULL_TREE,
1436 NULL_TREE);
1437 data = build_fold_addr_expr_loc (loc, data);
1438 enum built_in_function bcode
1439 = (flag_sanitize_recover & (TREE_CODE (type) == BOOLEAN_TYPE
1440 ? SANITIZE_BOOL : SANITIZE_ENUM))
1441 ? BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE
1442 : BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE_ABORT;
1443 tree fn = builtin_decl_explicit (bcode);
1445 tree val = force_gimple_operand_gsi (&gsi2, ubsan_encode_value (urhs),
1446 true, NULL_TREE, true,
1447 GSI_SAME_STMT);
1448 g = gimple_build_call (fn, 2, data, val);
1450 gimple_set_location (g, loc);
1451 gsi_insert_before (&gsi2, g, GSI_SAME_STMT);
1452 ubsan_create_edge (g);
1453 *gsi = gsi_for_stmt (stmt);
1456 /* Determine if we can propagate given LOCATION to ubsan_data descriptor to use
1457 new style handlers. Libubsan uses heuristics to destinguish between old and
1458 new styles and relies on these properties for filename:
1460 a) Location's filename must not be NULL.
1461 b) Location's filename must not be equal to "".
1462 c) Location's filename must not be equal to "\1".
1463 d) First two bytes of filename must not contain '\xff' symbol. */
1465 static bool
1466 ubsan_use_new_style_p (location_t loc)
1468 if (loc == UNKNOWN_LOCATION)
1469 return false;
1471 expanded_location xloc = expand_location (loc);
1472 if (xloc.file == NULL || strncmp (xloc.file, "\1", 2) == 0
1473 || xloc.file == '\0' || xloc.file[0] == '\xff'
1474 || xloc.file[1] == '\xff')
1475 return false;
1477 return true;
1480 /* Instrument float point-to-integer conversion. TYPE is an integer type of
1481 destination, EXPR is floating-point expression. */
1483 tree
1484 ubsan_instrument_float_cast (location_t loc, tree type, tree expr)
1486 tree expr_type = TREE_TYPE (expr);
1487 tree t, tt, fn, min, max;
1488 machine_mode mode = TYPE_MODE (expr_type);
1489 int prec = TYPE_PRECISION (type);
1490 bool uns_p = TYPE_UNSIGNED (type);
1491 if (loc == UNKNOWN_LOCATION)
1492 loc = input_location;
1494 /* Float to integer conversion first truncates toward zero, so
1495 even signed char c = 127.875f; is not problematic.
1496 Therefore, we should complain only if EXPR is unordered or smaller
1497 or equal than TYPE_MIN_VALUE - 1.0 or greater or equal than
1498 TYPE_MAX_VALUE + 1.0. */
1499 if (REAL_MODE_FORMAT (mode)->b == 2)
1501 /* For maximum, TYPE_MAX_VALUE might not be representable
1502 in EXPR_TYPE, e.g. if TYPE is 64-bit long long and
1503 EXPR_TYPE is IEEE single float, but TYPE_MAX_VALUE + 1.0 is
1504 either representable or infinity. */
1505 REAL_VALUE_TYPE maxval = dconst1;
1506 SET_REAL_EXP (&maxval, REAL_EXP (&maxval) + prec - !uns_p);
1507 real_convert (&maxval, mode, &maxval);
1508 max = build_real (expr_type, maxval);
1510 /* For unsigned, assume -1.0 is always representable. */
1511 if (uns_p)
1512 min = build_minus_one_cst (expr_type);
1513 else
1515 /* TYPE_MIN_VALUE is generally representable (or -inf),
1516 but TYPE_MIN_VALUE - 1.0 might not be. */
1517 REAL_VALUE_TYPE minval = dconstm1, minval2;
1518 SET_REAL_EXP (&minval, REAL_EXP (&minval) + prec - 1);
1519 real_convert (&minval, mode, &minval);
1520 real_arithmetic (&minval2, MINUS_EXPR, &minval, &dconst1);
1521 real_convert (&minval2, mode, &minval2);
1522 if (real_compare (EQ_EXPR, &minval, &minval2)
1523 && !real_isinf (&minval))
1525 /* If TYPE_MIN_VALUE - 1.0 is not representable and
1526 rounds to TYPE_MIN_VALUE, we need to subtract
1527 more. As REAL_MODE_FORMAT (mode)->p is the number
1528 of base digits, we want to subtract a number that
1529 will be 1 << (REAL_MODE_FORMAT (mode)->p - 1)
1530 times smaller than minval. */
1531 minval2 = dconst1;
1532 gcc_assert (prec > REAL_MODE_FORMAT (mode)->p);
1533 SET_REAL_EXP (&minval2,
1534 REAL_EXP (&minval2) + prec - 1
1535 - REAL_MODE_FORMAT (mode)->p + 1);
1536 real_arithmetic (&minval2, MINUS_EXPR, &minval, &minval2);
1537 real_convert (&minval2, mode, &minval2);
1539 min = build_real (expr_type, minval2);
1542 else if (REAL_MODE_FORMAT (mode)->b == 10)
1544 /* For _Decimal128 up to 34 decimal digits, - sign,
1545 dot, e, exponent. */
1546 char buf[64];
1547 mpfr_t m;
1548 int p = REAL_MODE_FORMAT (mode)->p;
1549 REAL_VALUE_TYPE maxval, minval;
1551 /* Use mpfr_snprintf rounding to compute the smallest
1552 representable decimal number greater or equal than
1553 1 << (prec - !uns_p). */
1554 mpfr_init2 (m, prec + 2);
1555 mpfr_set_ui_2exp (m, 1, prec - !uns_p, GMP_RNDN);
1556 mpfr_snprintf (buf, sizeof buf, "%.*RUe", p - 1, m);
1557 decimal_real_from_string (&maxval, buf);
1558 max = build_real (expr_type, maxval);
1560 /* For unsigned, assume -1.0 is always representable. */
1561 if (uns_p)
1562 min = build_minus_one_cst (expr_type);
1563 else
1565 /* Use mpfr_snprintf rounding to compute the largest
1566 representable decimal number less or equal than
1567 (-1 << (prec - 1)) - 1. */
1568 mpfr_set_si_2exp (m, -1, prec - 1, GMP_RNDN);
1569 mpfr_sub_ui (m, m, 1, GMP_RNDN);
1570 mpfr_snprintf (buf, sizeof buf, "%.*RDe", p - 1, m);
1571 decimal_real_from_string (&minval, buf);
1572 min = build_real (expr_type, minval);
1574 mpfr_clear (m);
1576 else
1577 return NULL_TREE;
1579 t = fold_build2 (UNLE_EXPR, boolean_type_node, expr, min);
1580 tt = fold_build2 (UNGE_EXPR, boolean_type_node, expr, max);
1581 t = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t, tt);
1582 if (integer_zerop (t))
1583 return NULL_TREE;
1585 if (flag_sanitize_undefined_trap_on_error)
1586 fn = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
1587 else
1589 location_t *loc_ptr = NULL;
1590 unsigned num_locations = 0;
1591 initialize_sanitizer_builtins ();
1592 /* Figure out if we can propagate location to ubsan_data and use new
1593 style handlers in libubsan. */
1594 if (ubsan_use_new_style_p (loc))
1596 loc_ptr = &loc;
1597 num_locations = 1;
1599 /* Create the __ubsan_handle_float_cast_overflow fn call. */
1600 tree data = ubsan_create_data ("__ubsan_float_cast_overflow_data",
1601 num_locations, loc_ptr,
1602 ubsan_type_descriptor (expr_type),
1603 ubsan_type_descriptor (type), NULL_TREE,
1604 NULL_TREE);
1605 enum built_in_function bcode
1606 = (flag_sanitize_recover & SANITIZE_FLOAT_CAST)
1607 ? BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW
1608 : BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW_ABORT;
1609 fn = builtin_decl_explicit (bcode);
1610 fn = build_call_expr_loc (loc, fn, 2,
1611 build_fold_addr_expr_loc (loc, data),
1612 ubsan_encode_value (expr, false));
1615 return fold_build3 (COND_EXPR, void_type_node, t, fn, integer_zero_node);
1618 /* Instrument values passed to function arguments with nonnull attribute. */
1620 static void
1621 instrument_nonnull_arg (gimple_stmt_iterator *gsi)
1623 gimple *stmt = gsi_stmt (*gsi);
1624 location_t loc[2];
1625 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
1626 while for nonnull sanitization it is clear. */
1627 int save_flag_delete_null_pointer_checks = flag_delete_null_pointer_checks;
1628 flag_delete_null_pointer_checks = 1;
1629 loc[0] = gimple_location (stmt);
1630 loc[1] = UNKNOWN_LOCATION;
1631 for (unsigned int i = 0; i < gimple_call_num_args (stmt); i++)
1633 tree arg = gimple_call_arg (stmt, i);
1634 if (POINTER_TYPE_P (TREE_TYPE (arg))
1635 && infer_nonnull_range_by_attribute (stmt, arg))
1637 gimple *g;
1638 if (!is_gimple_val (arg))
1640 g = gimple_build_assign (make_ssa_name (TREE_TYPE (arg)), arg);
1641 gimple_set_location (g, loc[0]);
1642 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1643 arg = gimple_assign_lhs (g);
1646 basic_block then_bb, fallthru_bb;
1647 *gsi = create_cond_insert_point (gsi, true, false, true,
1648 &then_bb, &fallthru_bb);
1649 g = gimple_build_cond (EQ_EXPR, arg,
1650 build_zero_cst (TREE_TYPE (arg)),
1651 NULL_TREE, NULL_TREE);
1652 gimple_set_location (g, loc[0]);
1653 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1655 *gsi = gsi_after_labels (then_bb);
1656 if (flag_sanitize_undefined_trap_on_error)
1657 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1658 else
1660 tree data = ubsan_create_data ("__ubsan_nonnull_arg_data",
1661 2, loc, NULL_TREE,
1662 build_int_cst (integer_type_node,
1663 i + 1),
1664 NULL_TREE);
1665 data = build_fold_addr_expr_loc (loc[0], data);
1666 enum built_in_function bcode
1667 = (flag_sanitize_recover & SANITIZE_NONNULL_ATTRIBUTE)
1668 ? BUILT_IN_UBSAN_HANDLE_NONNULL_ARG
1669 : BUILT_IN_UBSAN_HANDLE_NONNULL_ARG_ABORT;
1670 tree fn = builtin_decl_explicit (bcode);
1672 g = gimple_build_call (fn, 1, data);
1674 gimple_set_location (g, loc[0]);
1675 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1676 ubsan_create_edge (g);
1678 *gsi = gsi_for_stmt (stmt);
1680 flag_delete_null_pointer_checks = save_flag_delete_null_pointer_checks;
1683 /* Instrument returns in functions with returns_nonnull attribute. */
1685 static void
1686 instrument_nonnull_return (gimple_stmt_iterator *gsi)
1688 greturn *stmt = as_a <greturn *> (gsi_stmt (*gsi));
1689 location_t loc[2];
1690 tree arg = gimple_return_retval (stmt);
1691 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
1692 while for nonnull return sanitization it is clear. */
1693 int save_flag_delete_null_pointer_checks = flag_delete_null_pointer_checks;
1694 flag_delete_null_pointer_checks = 1;
1695 loc[0] = gimple_location (stmt);
1696 loc[1] = UNKNOWN_LOCATION;
1697 if (arg
1698 && POINTER_TYPE_P (TREE_TYPE (arg))
1699 && is_gimple_val (arg)
1700 && infer_nonnull_range_by_attribute (stmt, arg))
1702 basic_block then_bb, fallthru_bb;
1703 *gsi = create_cond_insert_point (gsi, true, false, true,
1704 &then_bb, &fallthru_bb);
1705 gimple *g = gimple_build_cond (EQ_EXPR, arg,
1706 build_zero_cst (TREE_TYPE (arg)),
1707 NULL_TREE, NULL_TREE);
1708 gimple_set_location (g, loc[0]);
1709 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1711 *gsi = gsi_after_labels (then_bb);
1712 if (flag_sanitize_undefined_trap_on_error)
1713 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1714 else
1716 tree data = ubsan_create_data ("__ubsan_nonnull_return_data",
1717 2, loc, NULL_TREE, NULL_TREE);
1718 data = build_fold_addr_expr_loc (loc[0], data);
1719 enum built_in_function bcode
1720 = (flag_sanitize_recover & SANITIZE_RETURNS_NONNULL_ATTRIBUTE)
1721 ? BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN
1722 : BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_ABORT;
1723 tree fn = builtin_decl_explicit (bcode);
1725 g = gimple_build_call (fn, 1, data);
1727 gimple_set_location (g, loc[0]);
1728 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1729 ubsan_create_edge (g);
1730 *gsi = gsi_for_stmt (stmt);
1732 flag_delete_null_pointer_checks = save_flag_delete_null_pointer_checks;
1735 /* Instrument memory references. Here we check whether the pointer
1736 points to an out-of-bounds location. */
1738 static void
1739 instrument_object_size (gimple_stmt_iterator *gsi, bool is_lhs)
1741 gimple *stmt = gsi_stmt (*gsi);
1742 location_t loc = gimple_location (stmt);
1743 tree t = is_lhs ? gimple_get_lhs (stmt) : gimple_assign_rhs1 (stmt);
1744 tree type;
1745 tree index = NULL_TREE;
1746 HOST_WIDE_INT size_in_bytes;
1748 type = TREE_TYPE (t);
1749 if (VOID_TYPE_P (type))
1750 return;
1752 switch (TREE_CODE (t))
1754 case COMPONENT_REF:
1755 if (TREE_CODE (t) == COMPONENT_REF
1756 && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1)) != NULL_TREE)
1758 tree repr = DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1));
1759 t = build3 (COMPONENT_REF, TREE_TYPE (repr), TREE_OPERAND (t, 0),
1760 repr, NULL_TREE);
1762 break;
1763 case ARRAY_REF:
1764 index = TREE_OPERAND (t, 1);
1765 break;
1766 case INDIRECT_REF:
1767 case MEM_REF:
1768 case VAR_DECL:
1769 case PARM_DECL:
1770 case RESULT_DECL:
1771 break;
1772 default:
1773 return;
1776 size_in_bytes = int_size_in_bytes (type);
1777 if (size_in_bytes <= 0)
1778 return;
1780 HOST_WIDE_INT bitsize, bitpos;
1781 tree offset;
1782 machine_mode mode;
1783 int volatilep = 0, reversep, unsignedp = 0;
1784 tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset, &mode,
1785 &unsignedp, &reversep, &volatilep, false);
1787 if (bitpos % BITS_PER_UNIT != 0
1788 || bitsize != size_in_bytes * BITS_PER_UNIT)
1789 return;
1791 bool decl_p = DECL_P (inner);
1792 tree base;
1793 if (decl_p)
1794 base = inner;
1795 else if (TREE_CODE (inner) == MEM_REF)
1796 base = TREE_OPERAND (inner, 0);
1797 else
1798 return;
1799 tree ptr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (t)), t);
1801 while (TREE_CODE (base) == SSA_NAME)
1803 gimple *def_stmt = SSA_NAME_DEF_STMT (base);
1804 if (gimple_assign_ssa_name_copy_p (def_stmt)
1805 || (gimple_assign_cast_p (def_stmt)
1806 && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (def_stmt))))
1807 || (is_gimple_assign (def_stmt)
1808 && gimple_assign_rhs_code (def_stmt) == POINTER_PLUS_EXPR))
1810 tree rhs1 = gimple_assign_rhs1 (def_stmt);
1811 if (TREE_CODE (rhs1) == SSA_NAME
1812 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs1))
1813 break;
1814 else
1815 base = rhs1;
1817 else
1818 break;
1821 if (!POINTER_TYPE_P (TREE_TYPE (base)) && !DECL_P (base))
1822 return;
1824 tree sizet;
1825 tree base_addr = base;
1826 gimple *bos_stmt = NULL;
1827 if (decl_p)
1828 base_addr = build1 (ADDR_EXPR,
1829 build_pointer_type (TREE_TYPE (base)), base);
1830 unsigned HOST_WIDE_INT size = compute_builtin_object_size (base_addr, 0);
1831 if (size != (unsigned HOST_WIDE_INT) -1)
1832 sizet = build_int_cst (sizetype, size);
1833 else if (optimize)
1835 if (LOCATION_LOCUS (loc) == UNKNOWN_LOCATION)
1836 loc = input_location;
1837 /* Generate __builtin_object_size call. */
1838 sizet = builtin_decl_explicit (BUILT_IN_OBJECT_SIZE);
1839 sizet = build_call_expr_loc (loc, sizet, 2, base_addr,
1840 integer_zero_node);
1841 sizet = force_gimple_operand_gsi (gsi, sizet, false, NULL_TREE, true,
1842 GSI_SAME_STMT);
1843 /* If the call above didn't end up being an integer constant, go one
1844 statement back and get the __builtin_object_size stmt. Save it,
1845 we might need it later. */
1846 if (SSA_VAR_P (sizet))
1848 gsi_prev (gsi);
1849 bos_stmt = gsi_stmt (*gsi);
1851 /* Move on to where we were. */
1852 gsi_next (gsi);
1855 else
1856 return;
1858 /* Generate UBSAN_OBJECT_SIZE (ptr, ptr+sizeof(*ptr)-base, objsize, ckind)
1859 call. */
1860 /* ptr + sizeof (*ptr) - base */
1861 t = fold_build2 (MINUS_EXPR, sizetype,
1862 fold_convert (pointer_sized_int_node, ptr),
1863 fold_convert (pointer_sized_int_node, base_addr));
1864 t = fold_build2 (PLUS_EXPR, sizetype, t, TYPE_SIZE_UNIT (type));
1866 /* Perhaps we can omit the check. */
1867 if (TREE_CODE (t) == INTEGER_CST
1868 && TREE_CODE (sizet) == INTEGER_CST
1869 && tree_int_cst_le (t, sizet))
1870 return;
1872 if (index != NULL_TREE
1873 && TREE_CODE (index) == SSA_NAME
1874 && TREE_CODE (sizet) == INTEGER_CST)
1876 gimple *def = SSA_NAME_DEF_STMT (index);
1877 if (is_gimple_assign (def)
1878 && gimple_assign_rhs_code (def) == BIT_AND_EXPR
1879 && TREE_CODE (gimple_assign_rhs2 (def)) == INTEGER_CST)
1881 tree cst = gimple_assign_rhs2 (def);
1882 tree sz = fold_build2 (EXACT_DIV_EXPR, sizetype, sizet,
1883 TYPE_SIZE_UNIT (type));
1884 if (tree_int_cst_sgn (cst) >= 0
1885 && tree_int_cst_lt (cst, sz))
1886 return;
1890 if (bos_stmt && gimple_call_builtin_p (bos_stmt, BUILT_IN_OBJECT_SIZE))
1891 ubsan_create_edge (bos_stmt);
1893 /* We have to emit the check. */
1894 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE, true,
1895 GSI_SAME_STMT);
1896 ptr = force_gimple_operand_gsi (gsi, ptr, true, NULL_TREE, true,
1897 GSI_SAME_STMT);
1898 tree ckind = build_int_cst (unsigned_char_type_node,
1899 is_lhs ? UBSAN_STORE_OF : UBSAN_LOAD_OF);
1900 gimple *g = gimple_build_call_internal (IFN_UBSAN_OBJECT_SIZE, 4,
1901 ptr, t, sizet, ckind);
1902 gimple_set_location (g, loc);
1903 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1906 /* True if we want to play UBSan games in the current function. */
1908 bool
1909 do_ubsan_in_current_function ()
1911 return (current_function_decl != NULL_TREE
1912 && !lookup_attribute ("no_sanitize_undefined",
1913 DECL_ATTRIBUTES (current_function_decl)));
1916 namespace {
1918 const pass_data pass_data_ubsan =
1920 GIMPLE_PASS, /* type */
1921 "ubsan", /* name */
1922 OPTGROUP_NONE, /* optinfo_flags */
1923 TV_TREE_UBSAN, /* tv_id */
1924 ( PROP_cfg | PROP_ssa ), /* properties_required */
1925 0, /* properties_provided */
1926 0, /* properties_destroyed */
1927 0, /* todo_flags_start */
1928 TODO_update_ssa, /* todo_flags_finish */
1931 class pass_ubsan : public gimple_opt_pass
1933 public:
1934 pass_ubsan (gcc::context *ctxt)
1935 : gimple_opt_pass (pass_data_ubsan, ctxt)
1938 /* opt_pass methods: */
1939 virtual bool gate (function *)
1941 return flag_sanitize & (SANITIZE_NULL | SANITIZE_SI_OVERFLOW
1942 | SANITIZE_BOOL | SANITIZE_ENUM
1943 | SANITIZE_ALIGNMENT
1944 | SANITIZE_NONNULL_ATTRIBUTE
1945 | SANITIZE_RETURNS_NONNULL_ATTRIBUTE
1946 | SANITIZE_OBJECT_SIZE)
1947 && do_ubsan_in_current_function ();
1950 virtual unsigned int execute (function *);
1952 }; // class pass_ubsan
1954 unsigned int
1955 pass_ubsan::execute (function *fun)
1957 basic_block bb;
1958 gimple_stmt_iterator gsi;
1960 initialize_sanitizer_builtins ();
1962 FOR_EACH_BB_FN (bb, fun)
1964 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
1966 gimple *stmt = gsi_stmt (gsi);
1967 if (is_gimple_debug (stmt) || gimple_clobber_p (stmt))
1969 gsi_next (&gsi);
1970 continue;
1973 if ((flag_sanitize & SANITIZE_SI_OVERFLOW)
1974 && is_gimple_assign (stmt))
1975 instrument_si_overflow (gsi);
1977 if (flag_sanitize & (SANITIZE_NULL | SANITIZE_ALIGNMENT))
1979 if (gimple_store_p (stmt))
1980 instrument_null (gsi, true);
1981 if (gimple_assign_load_p (stmt))
1982 instrument_null (gsi, false);
1985 if (flag_sanitize & (SANITIZE_BOOL | SANITIZE_ENUM)
1986 && gimple_assign_load_p (stmt))
1988 instrument_bool_enum_load (&gsi);
1989 bb = gimple_bb (stmt);
1992 if ((flag_sanitize & SANITIZE_NONNULL_ATTRIBUTE)
1993 && is_gimple_call (stmt)
1994 && !gimple_call_internal_p (stmt))
1996 instrument_nonnull_arg (&gsi);
1997 bb = gimple_bb (stmt);
2000 if ((flag_sanitize & SANITIZE_RETURNS_NONNULL_ATTRIBUTE)
2001 && gimple_code (stmt) == GIMPLE_RETURN)
2003 instrument_nonnull_return (&gsi);
2004 bb = gimple_bb (stmt);
2007 if (flag_sanitize & SANITIZE_OBJECT_SIZE)
2009 if (gimple_store_p (stmt))
2010 instrument_object_size (&gsi, true);
2011 if (gimple_assign_load_p (stmt))
2012 instrument_object_size (&gsi, false);
2015 gsi_next (&gsi);
2018 return 0;
2021 } // anon namespace
2023 gimple_opt_pass *
2024 make_pass_ubsan (gcc::context *ctxt)
2026 return new pass_ubsan (ctxt);
2029 #include "gt-ubsan.h"