Fix bootstrap/PR63632
[official-gcc.git] / gcc / ubsan.c
blobf143fcef6bf0e34d645b50fbd68d5cc66bcfeca2
1 /* UndefinedBehaviorSanitizer, undefined behavior detector.
2 Copyright (C) 2013-2014 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 "tree.h"
25 #include "stor-layout.h"
26 #include "stringpool.h"
27 #include "cgraph.h"
28 #include "tree-pass.h"
29 #include "tree-ssa-alias.h"
30 #include "tree-pretty-print.h"
31 #include "internal-fn.h"
32 #include "gimple-expr.h"
33 #include "gimple.h"
34 #include "gimple-iterator.h"
35 #include "gimple-ssa.h"
36 #include "gimple-walk.h"
37 #include "hashtab.h"
38 #include "output.h"
39 #include "tm_p.h"
40 #include "toplev.h"
41 #include "cfgloop.h"
42 #include "ubsan.h"
43 #include "c-family/c-common.h"
44 #include "rtl.h"
45 #include "expr.h"
46 #include "tree-ssanames.h"
47 #include "asan.h"
48 #include "gimplify-me.h"
49 #include "intl.h"
50 #include "realmpfr.h"
51 #include "dfp.h"
52 #include "builtins.h"
53 #include "tree-object-size.h"
55 /* Map from a tree to a VAR_DECL tree. */
57 struct GTY(()) tree_type_map {
58 struct tree_map_base type;
59 tree decl;
62 #define tree_type_map_eq tree_map_base_eq
63 #define tree_type_map_marked_p tree_map_base_marked_p
65 /* Hash from a tree in a tree_type_map. */
67 unsigned int
68 tree_type_map_hash (const void *item)
70 return TYPE_UID (((const struct tree_type_map *)item)->type.from);
73 static GTY ((if_marked ("tree_type_map_marked_p"), param_is (struct tree_type_map)))
74 htab_t decl_tree_for_type;
76 /* Lookup a VAR_DECL for TYPE, and return it if we find one. */
78 static tree
79 decl_for_type_lookup (tree type)
81 /* If the hash table is not initialized yet, create it now. */
82 if (decl_tree_for_type == NULL)
84 decl_tree_for_type = htab_create_ggc (10, tree_type_map_hash,
85 tree_type_map_eq, 0);
86 /* That also means we don't have to bother with the lookup. */
87 return NULL_TREE;
90 struct tree_type_map *h, in;
91 in.type.from = type;
93 h = (struct tree_type_map *)
94 htab_find_with_hash (decl_tree_for_type, &in, TYPE_UID (type));
95 return h ? h->decl : NULL_TREE;
98 /* Insert a mapping TYPE->DECL in the VAR_DECL for type hashtable. */
100 static void
101 decl_for_type_insert (tree type, tree decl)
103 struct tree_type_map *h;
104 void **slot;
106 h = ggc_alloc<tree_type_map> ();
107 h->type.from = type;
108 h->decl = decl;
109 slot = htab_find_slot_with_hash (decl_tree_for_type, h, TYPE_UID (type),
110 INSERT);
111 *(struct tree_type_map **) slot = h;
114 /* Helper routine, which encodes a value in the pointer_sized_int_node.
115 Arguments with precision <= POINTER_SIZE are passed directly,
116 the rest is passed by reference. T is a value we are to encode.
117 IN_EXPAND_P is true if this function is called during expansion. */
119 tree
120 ubsan_encode_value (tree t, bool in_expand_p)
122 tree type = TREE_TYPE (t);
123 const unsigned int bitsize = GET_MODE_BITSIZE (TYPE_MODE (type));
124 if (bitsize <= POINTER_SIZE)
125 switch (TREE_CODE (type))
127 case BOOLEAN_TYPE:
128 case ENUMERAL_TYPE:
129 case INTEGER_TYPE:
130 return fold_build1 (NOP_EXPR, pointer_sized_int_node, t);
131 case REAL_TYPE:
133 tree itype = build_nonstandard_integer_type (bitsize, true);
134 t = fold_build1 (VIEW_CONVERT_EXPR, itype, t);
135 return fold_convert (pointer_sized_int_node, t);
137 default:
138 gcc_unreachable ();
140 else
142 if (!DECL_P (t) || !TREE_ADDRESSABLE (t))
144 /* The reason for this is that we don't want to pessimize
145 code by making vars unnecessarily addressable. */
146 tree var = create_tmp_var (type, NULL);
147 tree tem = build2 (MODIFY_EXPR, void_type_node, var, t);
148 if (in_expand_p)
150 rtx mem
151 = assign_stack_temp_for_type (TYPE_MODE (type),
152 GET_MODE_SIZE (TYPE_MODE (type)),
153 type);
154 SET_DECL_RTL (var, mem);
155 expand_assignment (var, t, false);
156 return build_fold_addr_expr (var);
158 t = build_fold_addr_expr (var);
159 return build2 (COMPOUND_EXPR, TREE_TYPE (t), tem, t);
161 else
162 return build_fold_addr_expr (t);
166 /* Build
167 struct __ubsan_type_descriptor
169 unsigned short __typekind;
170 unsigned short __typeinfo;
171 char __typename[];
173 type. */
175 static tree
176 ubsan_type_descriptor_type (void)
178 static const char *field_names[3]
179 = { "__typekind", "__typeinfo", "__typename" };
180 tree fields[3], ret;
181 tree itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
182 tree flex_arr_type = build_array_type (char_type_node, itype);
184 ret = make_node (RECORD_TYPE);
185 for (int i = 0; i < 3; i++)
187 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
188 get_identifier (field_names[i]),
189 (i == 2) ? flex_arr_type
190 : short_unsigned_type_node);
191 DECL_CONTEXT (fields[i]) = ret;
192 if (i)
193 DECL_CHAIN (fields[i - 1]) = fields[i];
195 TYPE_FIELDS (ret) = fields[0];
196 TYPE_NAME (ret) = get_identifier ("__ubsan_type_descriptor");
197 layout_type (ret);
198 return ret;
201 /* Cached ubsan_get_source_location_type () return value. */
202 static GTY(()) tree ubsan_source_location_type;
204 /* Build
205 struct __ubsan_source_location
207 const char *__filename;
208 unsigned int __line;
209 unsigned int __column;
211 type. */
213 tree
214 ubsan_get_source_location_type (void)
216 static const char *field_names[3]
217 = { "__filename", "__line", "__column" };
218 tree fields[3], ret;
219 if (ubsan_source_location_type)
220 return ubsan_source_location_type;
222 tree const_char_type = build_qualified_type (char_type_node,
223 TYPE_QUAL_CONST);
225 ret = make_node (RECORD_TYPE);
226 for (int i = 0; i < 3; i++)
228 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
229 get_identifier (field_names[i]),
230 (i == 0) ? build_pointer_type (const_char_type)
231 : unsigned_type_node);
232 DECL_CONTEXT (fields[i]) = ret;
233 if (i)
234 DECL_CHAIN (fields[i - 1]) = fields[i];
236 TYPE_FIELDS (ret) = fields[0];
237 TYPE_NAME (ret) = get_identifier ("__ubsan_source_location");
238 layout_type (ret);
239 ubsan_source_location_type = ret;
240 return ret;
243 /* Helper routine that returns a CONSTRUCTOR of __ubsan_source_location
244 type with its fields filled from a location_t LOC. */
246 static tree
247 ubsan_source_location (location_t loc)
249 expanded_location xloc;
250 tree type = ubsan_get_source_location_type ();
252 xloc = expand_location (loc);
253 tree str;
254 if (xloc.file == NULL)
256 str = build_int_cst (ptr_type_node, 0);
257 xloc.line = 0;
258 xloc.column = 0;
260 else
262 /* Fill in the values from LOC. */
263 size_t len = strlen (xloc.file);
264 str = build_string (len + 1, xloc.file);
265 TREE_TYPE (str) = build_array_type (char_type_node,
266 build_index_type (size_int (len)));
267 TREE_READONLY (str) = 1;
268 TREE_STATIC (str) = 1;
269 str = build_fold_addr_expr (str);
271 tree ctor = build_constructor_va (type, 3, NULL_TREE, str, NULL_TREE,
272 build_int_cst (unsigned_type_node,
273 xloc.line), NULL_TREE,
274 build_int_cst (unsigned_type_node,
275 xloc.column));
276 TREE_CONSTANT (ctor) = 1;
277 TREE_STATIC (ctor) = 1;
279 return ctor;
282 /* This routine returns a magic number for TYPE. */
284 static unsigned short
285 get_ubsan_type_info_for_type (tree type)
287 gcc_assert (TYPE_SIZE (type) && tree_fits_uhwi_p (TYPE_SIZE (type)));
288 if (TREE_CODE (type) == REAL_TYPE)
289 return tree_to_uhwi (TYPE_SIZE (type));
290 else if (INTEGRAL_TYPE_P (type))
292 int prec = exact_log2 (tree_to_uhwi (TYPE_SIZE (type)));
293 gcc_assert (prec != -1);
294 return (prec << 1) | !TYPE_UNSIGNED (type);
296 else
297 return 0;
300 /* Helper routine that returns ADDR_EXPR of a VAR_DECL of a type
301 descriptor. It first looks into the hash table; if not found,
302 create the VAR_DECL, put it into the hash table and return the
303 ADDR_EXPR of it. TYPE describes a particular type. PSTYLE is
304 an enum controlling how we want to print the type. */
306 tree
307 ubsan_type_descriptor (tree type, enum ubsan_print_style pstyle)
309 /* See through any typedefs. */
310 type = TYPE_MAIN_VARIANT (type);
312 tree decl = decl_for_type_lookup (type);
313 /* It is possible that some of the earlier created DECLs were found
314 unused, in that case they weren't emitted and varpool_node::get
315 returns NULL node on them. But now we really need them. Thus,
316 renew them here. */
317 if (decl != NULL_TREE && varpool_node::get (decl))
318 return build_fold_addr_expr (decl);
320 tree dtype = ubsan_type_descriptor_type ();
321 tree type2 = type;
322 const char *tname = NULL;
323 char *pretty_name;
324 unsigned char deref_depth = 0;
325 unsigned short tkind, tinfo;
327 /* Get the name of the type, or the name of the pointer type. */
328 if (pstyle == UBSAN_PRINT_POINTER)
330 gcc_assert (POINTER_TYPE_P (type));
331 type2 = TREE_TYPE (type);
333 /* Remove any '*' operators from TYPE. */
334 while (POINTER_TYPE_P (type2))
335 deref_depth++, type2 = TREE_TYPE (type2);
337 if (TREE_CODE (type2) == METHOD_TYPE)
338 type2 = TYPE_METHOD_BASETYPE (type2);
341 /* If an array, get its type. */
342 type2 = strip_array_types (type2);
344 if (pstyle == UBSAN_PRINT_ARRAY)
346 while (POINTER_TYPE_P (type2))
347 deref_depth++, type2 = TREE_TYPE (type2);
350 if (TYPE_NAME (type2) != NULL)
352 if (TREE_CODE (TYPE_NAME (type2)) == IDENTIFIER_NODE)
353 tname = IDENTIFIER_POINTER (TYPE_NAME (type2));
354 else if (DECL_NAME (TYPE_NAME (type2)) != NULL)
355 tname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type2)));
358 if (tname == NULL)
359 /* We weren't able to determine the type name. */
360 tname = "<unknown>";
362 /* Decorate the type name with '', '*', "struct", or "union". */
363 pretty_name = (char *) alloca (strlen (tname) + 16 + deref_depth);
364 if (pstyle == UBSAN_PRINT_POINTER)
366 int pos = sprintf (pretty_name, "'%s%s%s%s%s%s%s",
367 TYPE_VOLATILE (type2) ? "volatile " : "",
368 TYPE_READONLY (type2) ? "const " : "",
369 TYPE_RESTRICT (type2) ? "restrict " : "",
370 TYPE_ATOMIC (type2) ? "_Atomic " : "",
371 TREE_CODE (type2) == RECORD_TYPE
372 ? "struct "
373 : TREE_CODE (type2) == UNION_TYPE
374 ? "union " : "", tname,
375 deref_depth == 0 ? "" : " ");
376 while (deref_depth-- > 0)
377 pretty_name[pos++] = '*';
378 pretty_name[pos++] = '\'';
379 pretty_name[pos] = '\0';
381 else if (pstyle == UBSAN_PRINT_ARRAY)
383 /* Pretty print the array dimensions. */
384 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
385 tree t = type;
386 int pos = sprintf (pretty_name, "'%s ", tname);
387 while (deref_depth-- > 0)
388 pretty_name[pos++] = '*';
389 while (TREE_CODE (t) == ARRAY_TYPE)
391 pretty_name[pos++] = '[';
392 tree dom = TYPE_DOMAIN (t);
393 if (dom && TREE_CODE (TYPE_MAX_VALUE (dom)) == INTEGER_CST)
394 pos += sprintf (&pretty_name[pos], HOST_WIDE_INT_PRINT_DEC,
395 tree_to_uhwi (TYPE_MAX_VALUE (dom)) + 1);
396 else
397 /* ??? We can't determine the variable name; print VLA unspec. */
398 pretty_name[pos++] = '*';
399 pretty_name[pos++] = ']';
400 t = TREE_TYPE (t);
402 pretty_name[pos++] = '\'';
403 pretty_name[pos] = '\0';
405 /* Save the tree with stripped types. */
406 type = t;
408 else
409 sprintf (pretty_name, "'%s'", tname);
411 switch (TREE_CODE (type))
413 case BOOLEAN_TYPE:
414 case ENUMERAL_TYPE:
415 case INTEGER_TYPE:
416 tkind = 0x0000;
417 break;
418 case REAL_TYPE:
419 /* FIXME: libubsan right now only supports float, double and
420 long double type formats. */
421 if (TYPE_MODE (type) == TYPE_MODE (float_type_node)
422 || TYPE_MODE (type) == TYPE_MODE (double_type_node)
423 || TYPE_MODE (type) == TYPE_MODE (long_double_type_node))
424 tkind = 0x0001;
425 else
426 tkind = 0xffff;
427 break;
428 default:
429 tkind = 0xffff;
430 break;
432 tinfo = get_ubsan_type_info_for_type (type);
434 /* Create a new VAR_DECL of type descriptor. */
435 char tmp_name[32];
436 static unsigned int type_var_id_num;
437 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_type", type_var_id_num++);
438 decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name),
439 dtype);
440 TREE_STATIC (decl) = 1;
441 TREE_PUBLIC (decl) = 0;
442 DECL_ARTIFICIAL (decl) = 1;
443 DECL_IGNORED_P (decl) = 1;
444 DECL_EXTERNAL (decl) = 0;
446 size_t len = strlen (pretty_name);
447 tree str = build_string (len + 1, pretty_name);
448 TREE_TYPE (str) = build_array_type (char_type_node,
449 build_index_type (size_int (len)));
450 TREE_READONLY (str) = 1;
451 TREE_STATIC (str) = 1;
452 tree ctor = build_constructor_va (dtype, 3, NULL_TREE,
453 build_int_cst (short_unsigned_type_node,
454 tkind), NULL_TREE,
455 build_int_cst (short_unsigned_type_node,
456 tinfo), NULL_TREE, str);
457 TREE_CONSTANT (ctor) = 1;
458 TREE_STATIC (ctor) = 1;
459 DECL_INITIAL (decl) = ctor;
460 varpool_node::finalize_decl (decl);
462 /* Save the VAR_DECL into the hash table. */
463 decl_for_type_insert (type, decl);
465 return build_fold_addr_expr (decl);
468 /* Create a structure for the ubsan library. NAME is a name of the new
469 structure. LOCCNT is number of locations, PLOC points to array of
470 locations. The arguments in ... are of __ubsan_type_descriptor type
471 and there are at most two of them, followed by NULL_TREE, followed
472 by optional extra arguments and another NULL_TREE. */
474 tree
475 ubsan_create_data (const char *name, int loccnt, const location_t *ploc, ...)
477 va_list args;
478 tree ret, t;
479 tree fields[6];
480 vec<tree, va_gc> *saved_args = NULL;
481 size_t i = 0;
482 int j;
484 /* Firstly, create a pointer to type descriptor type. */
485 tree td_type = ubsan_type_descriptor_type ();
486 TYPE_READONLY (td_type) = 1;
487 td_type = build_pointer_type (td_type);
489 /* Create the structure type. */
490 ret = make_node (RECORD_TYPE);
491 for (j = 0; j < loccnt; j++)
493 gcc_checking_assert (i < 2);
494 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
495 ubsan_get_source_location_type ());
496 DECL_CONTEXT (fields[i]) = ret;
497 if (i)
498 DECL_CHAIN (fields[i - 1]) = fields[i];
499 i++;
502 va_start (args, ploc);
503 for (t = va_arg (args, tree); t != NULL_TREE;
504 i++, t = va_arg (args, tree))
506 gcc_checking_assert (i < 4);
507 /* Save the tree arguments for later use. */
508 vec_safe_push (saved_args, t);
509 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
510 td_type);
511 DECL_CONTEXT (fields[i]) = ret;
512 if (i)
513 DECL_CHAIN (fields[i - 1]) = fields[i];
516 for (t = va_arg (args, tree); t != NULL_TREE;
517 i++, t = va_arg (args, tree))
519 gcc_checking_assert (i < 6);
520 /* Save the tree arguments for later use. */
521 vec_safe_push (saved_args, t);
522 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
523 TREE_TYPE (t));
524 DECL_CONTEXT (fields[i]) = ret;
525 if (i)
526 DECL_CHAIN (fields[i - 1]) = fields[i];
528 va_end (args);
530 TYPE_FIELDS (ret) = fields[0];
531 TYPE_NAME (ret) = get_identifier (name);
532 layout_type (ret);
534 /* Now, fill in the type. */
535 char tmp_name[32];
536 static unsigned int ubsan_var_id_num;
537 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_data", ubsan_var_id_num++);
538 tree var = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name),
539 ret);
540 TREE_STATIC (var) = 1;
541 TREE_PUBLIC (var) = 0;
542 DECL_ARTIFICIAL (var) = 1;
543 DECL_IGNORED_P (var) = 1;
544 DECL_EXTERNAL (var) = 0;
546 vec<constructor_elt, va_gc> *v;
547 vec_alloc (v, i);
548 tree ctor = build_constructor (ret, v);
550 /* If desirable, set the __ubsan_source_location element. */
551 for (j = 0; j < loccnt; j++)
553 location_t loc = LOCATION_LOCUS (ploc[j]);
554 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, ubsan_source_location (loc));
557 size_t nelts = vec_safe_length (saved_args);
558 for (i = 0; i < nelts; i++)
560 t = (*saved_args)[i];
561 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, t);
564 TREE_CONSTANT (ctor) = 1;
565 TREE_STATIC (ctor) = 1;
566 DECL_INITIAL (var) = ctor;
567 varpool_node::finalize_decl (var);
569 return var;
572 /* Instrument the __builtin_unreachable call. We just call the libubsan
573 routine instead. */
575 tree
576 ubsan_instrument_unreachable (location_t loc)
578 if (flag_sanitize_undefined_trap_on_error)
579 return build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
581 initialize_sanitizer_builtins ();
582 tree data = ubsan_create_data ("__ubsan_unreachable_data", 1, &loc, NULL_TREE,
583 NULL_TREE);
584 tree t = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE);
585 return build_call_expr_loc (loc, t, 1, build_fold_addr_expr_loc (loc, data));
588 /* Return true if T is a call to a libubsan routine. */
590 bool
591 is_ubsan_builtin_p (tree t)
593 return TREE_CODE (t) == FUNCTION_DECL
594 && strncmp (IDENTIFIER_POINTER (DECL_NAME (t)),
595 "__builtin___ubsan_", 18) == 0;
598 /* Expand the UBSAN_BOUNDS special builtin function. */
600 bool
601 ubsan_expand_bounds_ifn (gimple_stmt_iterator *gsi)
603 gimple stmt = gsi_stmt (*gsi);
604 location_t loc = gimple_location (stmt);
605 gcc_assert (gimple_call_num_args (stmt) == 3);
607 /* Pick up the arguments of the UBSAN_BOUNDS call. */
608 tree type = TREE_TYPE (TREE_TYPE (gimple_call_arg (stmt, 0)));
609 tree index = gimple_call_arg (stmt, 1);
610 tree orig_index_type = TREE_TYPE (index);
611 tree bound = gimple_call_arg (stmt, 2);
613 gimple_stmt_iterator gsi_orig = *gsi;
615 /* Create condition "if (index > bound)". */
616 basic_block then_bb, fallthru_bb;
617 gimple_stmt_iterator cond_insert_point
618 = create_cond_insert_point (gsi, false, false, true,
619 &then_bb, &fallthru_bb);
620 index = fold_convert (TREE_TYPE (bound), index);
621 index = force_gimple_operand_gsi (&cond_insert_point, index,
622 true, NULL_TREE,
623 false, GSI_NEW_STMT);
624 gimple g = gimple_build_cond (GT_EXPR, index, bound, NULL_TREE, NULL_TREE);
625 gimple_set_location (g, loc);
626 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
628 /* Generate __ubsan_handle_out_of_bounds call. */
629 *gsi = gsi_after_labels (then_bb);
630 if (flag_sanitize_undefined_trap_on_error)
631 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
632 else
634 tree data
635 = ubsan_create_data ("__ubsan_out_of_bounds_data", 1, &loc,
636 ubsan_type_descriptor (type, UBSAN_PRINT_ARRAY),
637 ubsan_type_descriptor (orig_index_type),
638 NULL_TREE, NULL_TREE);
639 data = build_fold_addr_expr_loc (loc, data);
640 enum built_in_function bcode
641 = (flag_sanitize_recover & SANITIZE_BOUNDS)
642 ? BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS
643 : BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS_ABORT;
644 tree fn = builtin_decl_explicit (bcode);
645 tree val = force_gimple_operand_gsi (gsi, ubsan_encode_value (index),
646 true, NULL_TREE, true,
647 GSI_SAME_STMT);
648 g = gimple_build_call (fn, 2, data, val);
650 gimple_set_location (g, loc);
651 gsi_insert_before (gsi, g, GSI_SAME_STMT);
653 /* Get rid of the UBSAN_BOUNDS call from the IR. */
654 unlink_stmt_vdef (stmt);
655 gsi_remove (&gsi_orig, true);
657 /* Point GSI to next logical statement. */
658 *gsi = gsi_start_bb (fallthru_bb);
659 return true;
662 /* Expand UBSAN_NULL internal call. The type is kept on the ckind
663 argument which is a constant, because the middle-end treats pointer
664 conversions as useless and therefore the type of the first argument
665 could be changed to any other pointer type. */
667 bool
668 ubsan_expand_null_ifn (gimple_stmt_iterator *gsip)
670 gimple_stmt_iterator gsi = *gsip;
671 gimple stmt = gsi_stmt (gsi);
672 location_t loc = gimple_location (stmt);
673 gcc_assert (gimple_call_num_args (stmt) == 3);
674 tree ptr = gimple_call_arg (stmt, 0);
675 tree ckind = gimple_call_arg (stmt, 1);
676 tree align = gimple_call_arg (stmt, 2);
677 tree check_align = NULL_TREE;
678 bool check_null;
680 basic_block cur_bb = gsi_bb (gsi);
682 gimple g;
683 if (!integer_zerop (align))
685 unsigned int ptralign = get_pointer_alignment (ptr) / BITS_PER_UNIT;
686 if (compare_tree_int (align, ptralign) == 1)
688 check_align = make_ssa_name (pointer_sized_int_node, NULL);
689 g = gimple_build_assign_with_ops (NOP_EXPR, check_align,
690 ptr, NULL_TREE);
691 gimple_set_location (g, loc);
692 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
695 check_null = (flag_sanitize & SANITIZE_NULL) != 0;
697 if (check_align == NULL_TREE && !check_null)
699 gsi_remove (gsip, true);
700 /* Unlink the UBSAN_NULLs vops before replacing it. */
701 unlink_stmt_vdef (stmt);
702 return true;
705 /* Split the original block holding the pointer dereference. */
706 edge e = split_block (cur_bb, stmt);
708 /* Get a hold on the 'condition block', the 'then block' and the
709 'else block'. */
710 basic_block cond_bb = e->src;
711 basic_block fallthru_bb = e->dest;
712 basic_block then_bb = create_empty_bb (cond_bb);
713 add_bb_to_loop (then_bb, cond_bb->loop_father);
714 loops_state_set (LOOPS_NEED_FIXUP);
716 /* Make an edge coming from the 'cond block' into the 'then block';
717 this edge is unlikely taken, so set up the probability accordingly. */
718 e = make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
719 e->probability = PROB_VERY_UNLIKELY;
721 /* Connect 'then block' with the 'else block'. This is needed
722 as the ubsan routines we call in the 'then block' are not noreturn.
723 The 'then block' only has one outcoming edge. */
724 make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);
726 /* Set up the fallthrough basic block. */
727 e = find_edge (cond_bb, fallthru_bb);
728 e->flags = EDGE_FALSE_VALUE;
729 e->count = cond_bb->count;
730 e->probability = REG_BR_PROB_BASE - PROB_VERY_UNLIKELY;
732 /* Update dominance info for the newly created then_bb; note that
733 fallthru_bb's dominance info has already been updated by
734 split_block. */
735 if (dom_info_available_p (CDI_DOMINATORS))
736 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
738 /* Put the ubsan builtin call into the newly created BB. */
739 if (flag_sanitize_undefined_trap_on_error)
740 g = gimple_build_call (builtin_decl_implicit (BUILT_IN_TRAP), 0);
741 else
743 enum built_in_function bcode
744 = (flag_sanitize_recover & ((check_align ? SANITIZE_ALIGNMENT : 0)
745 | (check_null ? SANITIZE_NULL : 0)))
746 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
747 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT;
748 tree fn = builtin_decl_implicit (bcode);
749 tree data
750 = ubsan_create_data ("__ubsan_null_data", 1, &loc,
751 ubsan_type_descriptor (TREE_TYPE (ckind),
752 UBSAN_PRINT_POINTER),
753 NULL_TREE,
754 align,
755 fold_convert (unsigned_char_type_node, ckind),
756 NULL_TREE);
757 data = build_fold_addr_expr_loc (loc, data);
758 g = gimple_build_call (fn, 2, data,
759 check_align ? check_align
760 : build_zero_cst (pointer_sized_int_node));
762 gimple_stmt_iterator gsi2 = gsi_start_bb (then_bb);
763 gimple_set_location (g, loc);
764 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
766 /* Unlink the UBSAN_NULLs vops before replacing it. */
767 unlink_stmt_vdef (stmt);
769 if (check_null)
771 g = gimple_build_cond (EQ_EXPR, ptr, build_int_cst (TREE_TYPE (ptr), 0),
772 NULL_TREE, NULL_TREE);
773 gimple_set_location (g, loc);
775 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
776 gsi_replace (&gsi, g, false);
779 if (check_align)
781 if (check_null)
783 /* Split the block with the condition again. */
784 e = split_block (cond_bb, stmt);
785 basic_block cond1_bb = e->src;
786 basic_block cond2_bb = e->dest;
788 /* Make an edge coming from the 'cond1 block' into the 'then block';
789 this edge is unlikely taken, so set up the probability
790 accordingly. */
791 e = make_edge (cond1_bb, then_bb, EDGE_TRUE_VALUE);
792 e->probability = PROB_VERY_UNLIKELY;
794 /* Set up the fallthrough basic block. */
795 e = find_edge (cond1_bb, cond2_bb);
796 e->flags = EDGE_FALSE_VALUE;
797 e->count = cond1_bb->count;
798 e->probability = REG_BR_PROB_BASE - PROB_VERY_UNLIKELY;
800 /* Update dominance info. */
801 if (dom_info_available_p (CDI_DOMINATORS))
803 set_immediate_dominator (CDI_DOMINATORS, fallthru_bb, cond1_bb);
804 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond1_bb);
807 gsi2 = gsi_start_bb (cond2_bb);
810 tree mask = build_int_cst (pointer_sized_int_node,
811 tree_to_uhwi (align) - 1);
812 g = gimple_build_assign_with_ops (BIT_AND_EXPR,
813 make_ssa_name (pointer_sized_int_node,
814 NULL),
815 check_align, mask);
816 gimple_set_location (g, loc);
817 if (check_null)
818 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
819 else
820 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
822 g = gimple_build_cond (NE_EXPR, gimple_assign_lhs (g),
823 build_int_cst (pointer_sized_int_node, 0),
824 NULL_TREE, NULL_TREE);
825 gimple_set_location (g, loc);
826 if (check_null)
827 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
828 else
829 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
830 gsi_replace (&gsi, g, false);
832 return false;
835 /* Expand UBSAN_OBJECT_SIZE internal call. */
837 bool
838 ubsan_expand_objsize_ifn (gimple_stmt_iterator *gsi)
840 gimple stmt = gsi_stmt (*gsi);
841 location_t loc = gimple_location (stmt);
842 gcc_assert (gimple_call_num_args (stmt) == 4);
844 tree ptr = gimple_call_arg (stmt, 0);
845 tree offset = gimple_call_arg (stmt, 1);
846 tree size = gimple_call_arg (stmt, 2);
847 tree ckind = gimple_call_arg (stmt, 3);
848 gimple_stmt_iterator gsi_orig = *gsi;
849 gimple g;
851 /* See if we can discard the check. */
852 if (TREE_CODE (size) != INTEGER_CST
853 || integer_all_onesp (size))
854 /* Yes, __builtin_object_size couldn't determine the
855 object size. */;
856 else
858 /* if (offset > objsize) */
859 basic_block then_bb, fallthru_bb;
860 gimple_stmt_iterator cond_insert_point
861 = create_cond_insert_point (gsi, false, false, true,
862 &then_bb, &fallthru_bb);
863 g = gimple_build_cond (GT_EXPR, offset, size, NULL_TREE, NULL_TREE);
864 gimple_set_location (g, loc);
865 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
867 /* Generate __ubsan_handle_type_mismatch call. */
868 *gsi = gsi_after_labels (then_bb);
869 if (flag_sanitize_undefined_trap_on_error)
870 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
871 else
873 tree data
874 = ubsan_create_data ("__ubsan_objsz_data", 1, &loc,
875 ubsan_type_descriptor (TREE_TYPE (ptr),
876 UBSAN_PRINT_POINTER),
877 NULL_TREE,
878 build_zero_cst (pointer_sized_int_node),
879 ckind,
880 NULL_TREE);
881 data = build_fold_addr_expr_loc (loc, data);
882 enum built_in_function bcode
883 = (flag_sanitize_recover & SANITIZE_OBJECT_SIZE)
884 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
885 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT;
886 tree p = make_ssa_name (pointer_sized_int_node, NULL);
887 g = gimple_build_assign_with_ops (NOP_EXPR, p, ptr, NULL_TREE);
888 gimple_set_location (g, loc);
889 gsi_insert_before (gsi, g, GSI_SAME_STMT);
890 g = gimple_build_call (builtin_decl_explicit (bcode), 2, data, p);
892 gimple_set_location (g, loc);
893 gsi_insert_before (gsi, g, GSI_SAME_STMT);
895 /* Point GSI to next logical statement. */
896 *gsi = gsi_start_bb (fallthru_bb);
899 /* Get rid of the UBSAN_OBJECT_SIZE call from the IR. */
900 unlink_stmt_vdef (stmt);
901 gsi_remove (&gsi_orig, true);
902 return gsi_end_p (*gsi);
905 /* Instrument a memory reference. BASE is the base of MEM, IS_LHS says
906 whether the pointer is on the left hand side of the assignment. */
908 static void
909 instrument_mem_ref (tree mem, tree base, gimple_stmt_iterator *iter,
910 bool is_lhs)
912 enum ubsan_null_ckind ikind = is_lhs ? UBSAN_STORE_OF : UBSAN_LOAD_OF;
913 unsigned int align = 0;
914 if (flag_sanitize & SANITIZE_ALIGNMENT)
916 align = min_align_of_type (TREE_TYPE (base));
917 if (align <= 1)
918 align = 0;
920 if (align == 0 && (flag_sanitize & SANITIZE_NULL) == 0)
921 return;
922 tree t = TREE_OPERAND (base, 0);
923 if (!POINTER_TYPE_P (TREE_TYPE (t)))
924 return;
925 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (TREE_TYPE (t))) && mem != base)
926 ikind = UBSAN_MEMBER_ACCESS;
927 tree kind = build_int_cst (TREE_TYPE (t), ikind);
928 tree alignt = build_int_cst (pointer_sized_int_node, align);
929 gimple g = gimple_build_call_internal (IFN_UBSAN_NULL, 3, t, kind, alignt);
930 gimple_set_location (g, gimple_location (gsi_stmt (*iter)));
931 gsi_insert_before (iter, g, GSI_SAME_STMT);
934 /* Perform the pointer instrumentation. */
936 static void
937 instrument_null (gimple_stmt_iterator gsi, bool is_lhs)
939 gimple stmt = gsi_stmt (gsi);
940 tree t = is_lhs ? gimple_get_lhs (stmt) : gimple_assign_rhs1 (stmt);
941 tree base = get_base_address (t);
942 const enum tree_code code = TREE_CODE (base);
943 if (code == MEM_REF
944 && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
945 instrument_mem_ref (t, base, &gsi, is_lhs);
948 /* Build an ubsan builtin call for the signed-integer-overflow
949 sanitization. CODE says what kind of builtin are we building,
950 LOC is a location, LHSTYPE is the type of LHS, OP0 and OP1
951 are operands of the binary operation. */
953 tree
954 ubsan_build_overflow_builtin (tree_code code, location_t loc, tree lhstype,
955 tree op0, tree op1)
957 if (flag_sanitize_undefined_trap_on_error)
958 return build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
960 tree data = ubsan_create_data ("__ubsan_overflow_data", 1, &loc,
961 ubsan_type_descriptor (lhstype), NULL_TREE,
962 NULL_TREE);
963 enum built_in_function fn_code;
965 switch (code)
967 case PLUS_EXPR:
968 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
969 ? BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW
970 : BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW_ABORT;
971 break;
972 case MINUS_EXPR:
973 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
974 ? BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW
975 : BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW_ABORT;
976 break;
977 case MULT_EXPR:
978 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
979 ? BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW
980 : BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW_ABORT;
981 break;
982 case NEGATE_EXPR:
983 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
984 ? BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW
985 : BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW_ABORT;
986 break;
987 default:
988 gcc_unreachable ();
990 tree fn = builtin_decl_explicit (fn_code);
991 return build_call_expr_loc (loc, fn, 2 + (code != NEGATE_EXPR),
992 build_fold_addr_expr_loc (loc, data),
993 ubsan_encode_value (op0, true),
994 op1 ? ubsan_encode_value (op1, true)
995 : NULL_TREE);
998 /* Perform the signed integer instrumentation. GSI is the iterator
999 pointing at statement we are trying to instrument. */
1001 static void
1002 instrument_si_overflow (gimple_stmt_iterator gsi)
1004 gimple stmt = gsi_stmt (gsi);
1005 tree_code code = gimple_assign_rhs_code (stmt);
1006 tree lhs = gimple_assign_lhs (stmt);
1007 tree lhstype = TREE_TYPE (lhs);
1008 tree a, b;
1009 gimple g;
1011 /* If this is not a signed operation, don't instrument anything here.
1012 Also punt on bit-fields. */
1013 if (!INTEGRAL_TYPE_P (lhstype)
1014 || TYPE_OVERFLOW_WRAPS (lhstype)
1015 || GET_MODE_BITSIZE (TYPE_MODE (lhstype)) != TYPE_PRECISION (lhstype))
1016 return;
1018 switch (code)
1020 case MINUS_EXPR:
1021 case PLUS_EXPR:
1022 case MULT_EXPR:
1023 /* Transform
1024 i = u {+,-,*} 5;
1025 into
1026 i = UBSAN_CHECK_{ADD,SUB,MUL} (u, 5); */
1027 a = gimple_assign_rhs1 (stmt);
1028 b = gimple_assign_rhs2 (stmt);
1029 g = gimple_build_call_internal (code == PLUS_EXPR
1030 ? IFN_UBSAN_CHECK_ADD
1031 : code == MINUS_EXPR
1032 ? IFN_UBSAN_CHECK_SUB
1033 : IFN_UBSAN_CHECK_MUL, 2, a, b);
1034 gimple_call_set_lhs (g, lhs);
1035 gsi_replace (&gsi, g, false);
1036 break;
1037 case NEGATE_EXPR:
1038 /* Represent i = -u;
1040 i = UBSAN_CHECK_SUB (0, u); */
1041 a = build_int_cst (lhstype, 0);
1042 b = gimple_assign_rhs1 (stmt);
1043 g = gimple_build_call_internal (IFN_UBSAN_CHECK_SUB, 2, a, b);
1044 gimple_call_set_lhs (g, lhs);
1045 gsi_replace (&gsi, g, false);
1046 break;
1047 case ABS_EXPR:
1048 /* Transform i = ABS_EXPR<u>;
1049 into
1050 _N = UBSAN_CHECK_SUB (0, u);
1051 i = ABS_EXPR<_N>; */
1052 a = build_int_cst (lhstype, 0);
1053 b = gimple_assign_rhs1 (stmt);
1054 g = gimple_build_call_internal (IFN_UBSAN_CHECK_SUB, 2, a, b);
1055 a = make_ssa_name (lhstype, NULL);
1056 gimple_call_set_lhs (g, a);
1057 gimple_set_location (g, gimple_location (stmt));
1058 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
1059 gimple_assign_set_rhs1 (stmt, a);
1060 update_stmt (stmt);
1061 break;
1062 default:
1063 break;
1067 /* Instrument loads from (non-bitfield) bool and C++ enum values
1068 to check if the memory value is outside of the range of the valid
1069 type values. */
1071 static void
1072 instrument_bool_enum_load (gimple_stmt_iterator *gsi)
1074 gimple stmt = gsi_stmt (*gsi);
1075 tree rhs = gimple_assign_rhs1 (stmt);
1076 tree type = TREE_TYPE (rhs);
1077 tree minv = NULL_TREE, maxv = NULL_TREE;
1079 if (TREE_CODE (type) == BOOLEAN_TYPE && (flag_sanitize & SANITIZE_BOOL))
1081 minv = boolean_false_node;
1082 maxv = boolean_true_node;
1084 else if (TREE_CODE (type) == ENUMERAL_TYPE
1085 && (flag_sanitize & SANITIZE_ENUM)
1086 && TREE_TYPE (type) != NULL_TREE
1087 && TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE
1088 && (TYPE_PRECISION (TREE_TYPE (type))
1089 < GET_MODE_PRECISION (TYPE_MODE (type))))
1091 minv = TYPE_MIN_VALUE (TREE_TYPE (type));
1092 maxv = TYPE_MAX_VALUE (TREE_TYPE (type));
1094 else
1095 return;
1097 int modebitsize = GET_MODE_BITSIZE (TYPE_MODE (type));
1098 HOST_WIDE_INT bitsize, bitpos;
1099 tree offset;
1100 enum machine_mode mode;
1101 int volatilep = 0, unsignedp = 0;
1102 tree base = get_inner_reference (rhs, &bitsize, &bitpos, &offset, &mode,
1103 &unsignedp, &volatilep, false);
1104 tree utype = build_nonstandard_integer_type (modebitsize, 1);
1106 if ((TREE_CODE (base) == VAR_DECL && DECL_HARD_REGISTER (base))
1107 || (bitpos % modebitsize) != 0
1108 || bitsize != modebitsize
1109 || GET_MODE_BITSIZE (TYPE_MODE (utype)) != modebitsize
1110 || TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME)
1111 return;
1113 location_t loc = gimple_location (stmt);
1114 tree ptype = build_pointer_type (TREE_TYPE (rhs));
1115 tree atype = reference_alias_ptr_type (rhs);
1116 gimple g = gimple_build_assign (make_ssa_name (ptype, NULL),
1117 build_fold_addr_expr (rhs));
1118 gimple_set_location (g, loc);
1119 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1120 tree mem = build2 (MEM_REF, utype, gimple_assign_lhs (g),
1121 build_int_cst (atype, 0));
1122 tree urhs = make_ssa_name (utype, NULL);
1123 g = gimple_build_assign (urhs, mem);
1124 gimple_set_location (g, loc);
1125 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1126 minv = fold_convert (utype, minv);
1127 maxv = fold_convert (utype, maxv);
1128 if (!integer_zerop (minv))
1130 g = gimple_build_assign_with_ops (MINUS_EXPR,
1131 make_ssa_name (utype, NULL),
1132 urhs, minv);
1133 gimple_set_location (g, loc);
1134 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1137 gimple_stmt_iterator gsi2 = *gsi;
1138 basic_block then_bb, fallthru_bb;
1139 *gsi = create_cond_insert_point (gsi, true, false, true,
1140 &then_bb, &fallthru_bb);
1141 g = gimple_build_cond (GT_EXPR, gimple_assign_lhs (g),
1142 int_const_binop (MINUS_EXPR, maxv, minv),
1143 NULL_TREE, NULL_TREE);
1144 gimple_set_location (g, loc);
1145 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1147 gimple_assign_set_rhs_with_ops (&gsi2, NOP_EXPR, urhs, NULL_TREE);
1148 update_stmt (stmt);
1150 gsi2 = gsi_after_labels (then_bb);
1151 if (flag_sanitize_undefined_trap_on_error)
1152 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1153 else
1155 tree data = ubsan_create_data ("__ubsan_invalid_value_data", 1, &loc,
1156 ubsan_type_descriptor (type), NULL_TREE,
1157 NULL_TREE);
1158 data = build_fold_addr_expr_loc (loc, data);
1159 enum built_in_function bcode
1160 = (flag_sanitize_recover & (TREE_CODE (type) == BOOLEAN_TYPE
1161 ? SANITIZE_BOOL : SANITIZE_ENUM))
1162 ? BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE
1163 : BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE_ABORT;
1164 tree fn = builtin_decl_explicit (bcode);
1166 tree val = force_gimple_operand_gsi (&gsi2, ubsan_encode_value (urhs),
1167 true, NULL_TREE, true,
1168 GSI_SAME_STMT);
1169 g = gimple_build_call (fn, 2, data, val);
1171 gimple_set_location (g, loc);
1172 gsi_insert_before (&gsi2, g, GSI_SAME_STMT);
1173 *gsi = gsi_for_stmt (stmt);
1176 /* Instrument float point-to-integer conversion. TYPE is an integer type of
1177 destination, EXPR is floating-point expression. */
1179 tree
1180 ubsan_instrument_float_cast (location_t loc, tree type, tree expr)
1182 tree expr_type = TREE_TYPE (expr);
1183 tree t, tt, fn, min, max;
1184 enum machine_mode mode = TYPE_MODE (expr_type);
1185 int prec = TYPE_PRECISION (type);
1186 bool uns_p = TYPE_UNSIGNED (type);
1188 /* Float to integer conversion first truncates toward zero, so
1189 even signed char c = 127.875f; is not problematic.
1190 Therefore, we should complain only if EXPR is unordered or smaller
1191 or equal than TYPE_MIN_VALUE - 1.0 or greater or equal than
1192 TYPE_MAX_VALUE + 1.0. */
1193 if (REAL_MODE_FORMAT (mode)->b == 2)
1195 /* For maximum, TYPE_MAX_VALUE might not be representable
1196 in EXPR_TYPE, e.g. if TYPE is 64-bit long long and
1197 EXPR_TYPE is IEEE single float, but TYPE_MAX_VALUE + 1.0 is
1198 either representable or infinity. */
1199 REAL_VALUE_TYPE maxval = dconst1;
1200 SET_REAL_EXP (&maxval, REAL_EXP (&maxval) + prec - !uns_p);
1201 real_convert (&maxval, mode, &maxval);
1202 max = build_real (expr_type, maxval);
1204 /* For unsigned, assume -1.0 is always representable. */
1205 if (uns_p)
1206 min = build_minus_one_cst (expr_type);
1207 else
1209 /* TYPE_MIN_VALUE is generally representable (or -inf),
1210 but TYPE_MIN_VALUE - 1.0 might not be. */
1211 REAL_VALUE_TYPE minval = dconstm1, minval2;
1212 SET_REAL_EXP (&minval, REAL_EXP (&minval) + prec - 1);
1213 real_convert (&minval, mode, &minval);
1214 real_arithmetic (&minval2, MINUS_EXPR, &minval, &dconst1);
1215 real_convert (&minval2, mode, &minval2);
1216 if (real_compare (EQ_EXPR, &minval, &minval2)
1217 && !real_isinf (&minval))
1219 /* If TYPE_MIN_VALUE - 1.0 is not representable and
1220 rounds to TYPE_MIN_VALUE, we need to subtract
1221 more. As REAL_MODE_FORMAT (mode)->p is the number
1222 of base digits, we want to subtract a number that
1223 will be 1 << (REAL_MODE_FORMAT (mode)->p - 1)
1224 times smaller than minval. */
1225 minval2 = dconst1;
1226 gcc_assert (prec > REAL_MODE_FORMAT (mode)->p);
1227 SET_REAL_EXP (&minval2,
1228 REAL_EXP (&minval2) + prec - 1
1229 - REAL_MODE_FORMAT (mode)->p + 1);
1230 real_arithmetic (&minval2, MINUS_EXPR, &minval, &minval2);
1231 real_convert (&minval2, mode, &minval2);
1233 min = build_real (expr_type, minval2);
1236 else if (REAL_MODE_FORMAT (mode)->b == 10)
1238 /* For _Decimal128 up to 34 decimal digits, - sign,
1239 dot, e, exponent. */
1240 char buf[64];
1241 mpfr_t m;
1242 int p = REAL_MODE_FORMAT (mode)->p;
1243 REAL_VALUE_TYPE maxval, minval;
1245 /* Use mpfr_snprintf rounding to compute the smallest
1246 representable decimal number greater or equal than
1247 1 << (prec - !uns_p). */
1248 mpfr_init2 (m, prec + 2);
1249 mpfr_set_ui_2exp (m, 1, prec - !uns_p, GMP_RNDN);
1250 mpfr_snprintf (buf, sizeof buf, "%.*RUe", p - 1, m);
1251 decimal_real_from_string (&maxval, buf);
1252 max = build_real (expr_type, maxval);
1254 /* For unsigned, assume -1.0 is always representable. */
1255 if (uns_p)
1256 min = build_minus_one_cst (expr_type);
1257 else
1259 /* Use mpfr_snprintf rounding to compute the largest
1260 representable decimal number less or equal than
1261 (-1 << (prec - 1)) - 1. */
1262 mpfr_set_si_2exp (m, -1, prec - 1, GMP_RNDN);
1263 mpfr_sub_ui (m, m, 1, GMP_RNDN);
1264 mpfr_snprintf (buf, sizeof buf, "%.*RDe", p - 1, m);
1265 decimal_real_from_string (&minval, buf);
1266 min = build_real (expr_type, minval);
1268 mpfr_clear (m);
1270 else
1271 return NULL_TREE;
1273 if (flag_sanitize_undefined_trap_on_error)
1274 fn = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
1275 else
1277 /* Create the __ubsan_handle_float_cast_overflow fn call. */
1278 tree data = ubsan_create_data ("__ubsan_float_cast_overflow_data", 0,
1279 NULL, ubsan_type_descriptor (expr_type),
1280 ubsan_type_descriptor (type), NULL_TREE,
1281 NULL_TREE);
1282 enum built_in_function bcode
1283 = (flag_sanitize_recover & SANITIZE_FLOAT_CAST)
1284 ? BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW
1285 : BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW_ABORT;
1286 fn = builtin_decl_explicit (bcode);
1287 fn = build_call_expr_loc (loc, fn, 2,
1288 build_fold_addr_expr_loc (loc, data),
1289 ubsan_encode_value (expr, false));
1292 t = fold_build2 (UNLE_EXPR, boolean_type_node, expr, min);
1293 tt = fold_build2 (UNGE_EXPR, boolean_type_node, expr, max);
1294 return fold_build3 (COND_EXPR, void_type_node,
1295 fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t, tt),
1296 fn, integer_zero_node);
1299 /* Instrument values passed to function arguments with nonnull attribute. */
1301 static void
1302 instrument_nonnull_arg (gimple_stmt_iterator *gsi)
1304 gimple stmt = gsi_stmt (*gsi);
1305 location_t loc[2];
1306 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
1307 while for nonnull sanitization it is clear. */
1308 int save_flag_delete_null_pointer_checks = flag_delete_null_pointer_checks;
1309 flag_delete_null_pointer_checks = 1;
1310 loc[0] = gimple_location (stmt);
1311 loc[1] = UNKNOWN_LOCATION;
1312 for (unsigned int i = 0; i < gimple_call_num_args (stmt); i++)
1314 tree arg = gimple_call_arg (stmt, i);
1315 if (POINTER_TYPE_P (TREE_TYPE (arg))
1316 && infer_nonnull_range (stmt, arg, false, true))
1318 gimple g;
1319 if (!is_gimple_val (arg))
1321 g = gimple_build_assign (make_ssa_name (TREE_TYPE (arg), NULL),
1322 arg);
1323 gimple_set_location (g, loc[0]);
1324 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1325 arg = gimple_assign_lhs (g);
1328 basic_block then_bb, fallthru_bb;
1329 *gsi = create_cond_insert_point (gsi, true, false, true,
1330 &then_bb, &fallthru_bb);
1331 g = gimple_build_cond (EQ_EXPR, arg,
1332 build_zero_cst (TREE_TYPE (arg)),
1333 NULL_TREE, NULL_TREE);
1334 gimple_set_location (g, loc[0]);
1335 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1337 *gsi = gsi_after_labels (then_bb);
1338 if (flag_sanitize_undefined_trap_on_error)
1339 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1340 else
1342 tree data = ubsan_create_data ("__ubsan_nonnull_arg_data",
1343 2, loc, NULL_TREE,
1344 build_int_cst (integer_type_node,
1345 i + 1),
1346 NULL_TREE);
1347 data = build_fold_addr_expr_loc (loc[0], data);
1348 enum built_in_function bcode
1349 = (flag_sanitize_recover & SANITIZE_NONNULL_ATTRIBUTE)
1350 ? BUILT_IN_UBSAN_HANDLE_NONNULL_ARG
1351 : BUILT_IN_UBSAN_HANDLE_NONNULL_ARG_ABORT;
1352 tree fn = builtin_decl_explicit (bcode);
1354 g = gimple_build_call (fn, 1, data);
1356 gimple_set_location (g, loc[0]);
1357 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1359 *gsi = gsi_for_stmt (stmt);
1361 flag_delete_null_pointer_checks = save_flag_delete_null_pointer_checks;
1364 /* Instrument returns in functions with returns_nonnull attribute. */
1366 static void
1367 instrument_nonnull_return (gimple_stmt_iterator *gsi)
1369 gimple stmt = gsi_stmt (*gsi);
1370 location_t loc[2];
1371 tree arg = gimple_return_retval (stmt);
1372 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
1373 while for nonnull return sanitization it is clear. */
1374 int save_flag_delete_null_pointer_checks = flag_delete_null_pointer_checks;
1375 flag_delete_null_pointer_checks = 1;
1376 loc[0] = gimple_location (stmt);
1377 loc[1] = UNKNOWN_LOCATION;
1378 if (arg
1379 && POINTER_TYPE_P (TREE_TYPE (arg))
1380 && is_gimple_val (arg)
1381 && infer_nonnull_range (stmt, arg, false, true))
1383 basic_block then_bb, fallthru_bb;
1384 *gsi = create_cond_insert_point (gsi, true, false, true,
1385 &then_bb, &fallthru_bb);
1386 gimple g = gimple_build_cond (EQ_EXPR, arg,
1387 build_zero_cst (TREE_TYPE (arg)),
1388 NULL_TREE, NULL_TREE);
1389 gimple_set_location (g, loc[0]);
1390 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1392 *gsi = gsi_after_labels (then_bb);
1393 if (flag_sanitize_undefined_trap_on_error)
1394 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1395 else
1397 tree data = ubsan_create_data ("__ubsan_nonnull_return_data",
1398 2, loc, NULL_TREE, NULL_TREE);
1399 data = build_fold_addr_expr_loc (loc[0], data);
1400 enum built_in_function bcode
1401 = (flag_sanitize_recover & SANITIZE_RETURNS_NONNULL_ATTRIBUTE)
1402 ? BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN
1403 : BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_ABORT;
1404 tree fn = builtin_decl_explicit (bcode);
1406 g = gimple_build_call (fn, 1, data);
1408 gimple_set_location (g, loc[0]);
1409 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1410 *gsi = gsi_for_stmt (stmt);
1412 flag_delete_null_pointer_checks = save_flag_delete_null_pointer_checks;
1415 /* Instrument memory references. Here we check whether the pointer
1416 points to an out-of-bounds location. */
1418 static void
1419 instrument_object_size (gimple_stmt_iterator *gsi, bool is_lhs)
1421 gimple stmt = gsi_stmt (*gsi);
1422 location_t loc = gimple_location (stmt);
1423 tree t = is_lhs ? gimple_get_lhs (stmt) : gimple_assign_rhs1 (stmt);
1424 tree type;
1425 HOST_WIDE_INT size_in_bytes;
1427 type = TREE_TYPE (t);
1428 if (VOID_TYPE_P (type))
1429 return;
1431 switch (TREE_CODE (t))
1433 case COMPONENT_REF:
1434 if (TREE_CODE (t) == COMPONENT_REF
1435 && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1)) != NULL_TREE)
1437 tree repr = DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1));
1438 t = build3 (COMPONENT_REF, TREE_TYPE (repr), TREE_OPERAND (t, 0),
1439 repr, NULL_TREE);
1441 break;
1442 case ARRAY_REF:
1443 case INDIRECT_REF:
1444 case MEM_REF:
1445 case VAR_DECL:
1446 case PARM_DECL:
1447 case RESULT_DECL:
1448 break;
1449 default:
1450 return;
1453 size_in_bytes = int_size_in_bytes (type);
1454 if (size_in_bytes <= 0)
1455 return;
1457 HOST_WIDE_INT bitsize, bitpos;
1458 tree offset;
1459 enum machine_mode mode;
1460 int volatilep = 0, unsignedp = 0;
1461 tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset, &mode,
1462 &unsignedp, &volatilep, false);
1464 if (bitpos % BITS_PER_UNIT != 0
1465 || bitsize != size_in_bytes * BITS_PER_UNIT)
1466 return;
1468 bool decl_p = DECL_P (inner);
1469 tree base = decl_p ? inner : TREE_OPERAND (inner, 0);
1470 tree ptr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (t)), t);
1472 while (TREE_CODE (base) == SSA_NAME)
1474 gimple def_stmt = SSA_NAME_DEF_STMT (base);
1475 if (gimple_assign_ssa_name_copy_p (def_stmt)
1476 || (gimple_assign_cast_p (def_stmt)
1477 && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (def_stmt))))
1478 || (is_gimple_assign (def_stmt)
1479 && gimple_assign_rhs_code (def_stmt) == POINTER_PLUS_EXPR))
1480 base = gimple_assign_rhs1 (def_stmt);
1481 else
1482 break;
1485 if (!POINTER_TYPE_P (TREE_TYPE (base)) && !DECL_P (base))
1486 return;
1488 tree sizet;
1489 tree base_addr = base;
1490 if (decl_p)
1491 base_addr = build1 (ADDR_EXPR,
1492 build_pointer_type (TREE_TYPE (base)), base);
1493 unsigned HOST_WIDE_INT size = compute_builtin_object_size (base_addr, 0);
1494 if (size != (unsigned HOST_WIDE_INT) -1)
1495 sizet = build_int_cst (sizetype, size);
1496 else if (optimize)
1498 if (LOCATION_LOCUS (loc) == UNKNOWN_LOCATION)
1499 loc = input_location;
1500 /* Generate __builtin_object_size call. */
1501 sizet = builtin_decl_explicit (BUILT_IN_OBJECT_SIZE);
1502 sizet = build_call_expr_loc (loc, sizet, 2, base_addr,
1503 integer_zero_node);
1504 sizet = force_gimple_operand_gsi (gsi, sizet, false, NULL_TREE, true,
1505 GSI_SAME_STMT);
1507 else
1508 return;
1510 /* Generate UBSAN_OBJECT_SIZE (ptr, ptr+sizeof(*ptr)-base, objsize, ckind)
1511 call. */
1512 /* ptr + sizeof (*ptr) - base */
1513 t = fold_build2 (MINUS_EXPR, sizetype,
1514 fold_convert (pointer_sized_int_node, ptr),
1515 fold_convert (pointer_sized_int_node, base_addr));
1516 t = fold_build2 (PLUS_EXPR, sizetype, t, TYPE_SIZE_UNIT (type));
1518 /* Perhaps we can omit the check. */
1519 if (TREE_CODE (t) == INTEGER_CST
1520 && TREE_CODE (sizet) == INTEGER_CST
1521 && tree_int_cst_le (t, sizet))
1522 return;
1524 /* Nope. Emit the check. */
1525 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE, true,
1526 GSI_SAME_STMT);
1527 ptr = force_gimple_operand_gsi (gsi, ptr, true, NULL_TREE, true,
1528 GSI_SAME_STMT);
1529 tree ckind = build_int_cst (unsigned_char_type_node,
1530 is_lhs ? UBSAN_STORE_OF : UBSAN_LOAD_OF);
1531 gimple g = gimple_build_call_internal (IFN_UBSAN_OBJECT_SIZE, 4,
1532 ptr, t, sizet, ckind);
1533 gimple_set_location (g, loc);
1534 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1537 namespace {
1539 const pass_data pass_data_ubsan =
1541 GIMPLE_PASS, /* type */
1542 "ubsan", /* name */
1543 OPTGROUP_NONE, /* optinfo_flags */
1544 TV_TREE_UBSAN, /* tv_id */
1545 ( PROP_cfg | PROP_ssa ), /* properties_required */
1546 0, /* properties_provided */
1547 0, /* properties_destroyed */
1548 0, /* todo_flags_start */
1549 TODO_update_ssa, /* todo_flags_finish */
1552 class pass_ubsan : public gimple_opt_pass
1554 public:
1555 pass_ubsan (gcc::context *ctxt)
1556 : gimple_opt_pass (pass_data_ubsan, ctxt)
1559 /* opt_pass methods: */
1560 virtual bool gate (function *)
1562 return flag_sanitize & (SANITIZE_NULL | SANITIZE_SI_OVERFLOW
1563 | SANITIZE_BOOL | SANITIZE_ENUM
1564 | SANITIZE_ALIGNMENT
1565 | SANITIZE_NONNULL_ATTRIBUTE
1566 | SANITIZE_RETURNS_NONNULL_ATTRIBUTE
1567 | SANITIZE_OBJECT_SIZE)
1568 && current_function_decl != NULL_TREE
1569 && !lookup_attribute ("no_sanitize_undefined",
1570 DECL_ATTRIBUTES (current_function_decl));
1573 virtual unsigned int execute (function *);
1575 }; // class pass_ubsan
1577 unsigned int
1578 pass_ubsan::execute (function *fun)
1580 basic_block bb;
1581 gimple_stmt_iterator gsi;
1583 initialize_sanitizer_builtins ();
1585 FOR_EACH_BB_FN (bb, fun)
1587 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
1589 gimple stmt = gsi_stmt (gsi);
1590 if (is_gimple_debug (stmt) || gimple_clobber_p (stmt))
1592 gsi_next (&gsi);
1593 continue;
1596 if ((flag_sanitize & SANITIZE_SI_OVERFLOW)
1597 && is_gimple_assign (stmt))
1598 instrument_si_overflow (gsi);
1600 if (flag_sanitize & (SANITIZE_NULL | SANITIZE_ALIGNMENT))
1602 if (gimple_store_p (stmt))
1603 instrument_null (gsi, true);
1604 if (gimple_assign_load_p (stmt))
1605 instrument_null (gsi, false);
1608 if (flag_sanitize & (SANITIZE_BOOL | SANITIZE_ENUM)
1609 && gimple_assign_load_p (stmt))
1611 instrument_bool_enum_load (&gsi);
1612 bb = gimple_bb (stmt);
1615 if ((flag_sanitize & SANITIZE_NONNULL_ATTRIBUTE)
1616 && is_gimple_call (stmt)
1617 && !gimple_call_internal_p (stmt))
1619 instrument_nonnull_arg (&gsi);
1620 bb = gimple_bb (stmt);
1623 if ((flag_sanitize & SANITIZE_RETURNS_NONNULL_ATTRIBUTE)
1624 && gimple_code (stmt) == GIMPLE_RETURN)
1626 instrument_nonnull_return (&gsi);
1627 bb = gimple_bb (stmt);
1630 if (flag_sanitize & SANITIZE_OBJECT_SIZE)
1632 if (gimple_store_p (stmt))
1633 instrument_object_size (&gsi, true);
1634 if (gimple_assign_load_p (stmt))
1635 instrument_object_size (&gsi, false);
1638 gsi_next (&gsi);
1641 return 0;
1644 } // anon namespace
1646 gimple_opt_pass *
1647 make_pass_ubsan (gcc::context *ctxt)
1649 return new pass_ubsan (ctxt);
1652 #include "gt-ubsan.h"