PR rtl-optimization/57003
[official-gcc.git] / gcc / ubsan.c
blobc9a72ad47202e1c6e9b4539ac9cf49eb99175cd8
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"
54 /* Map from a tree to a VAR_DECL tree. */
56 struct GTY(()) tree_type_map {
57 struct tree_map_base type;
58 tree decl;
61 #define tree_type_map_eq tree_map_base_eq
62 #define tree_type_map_marked_p tree_map_base_marked_p
64 /* Hash from a tree in a tree_type_map. */
66 unsigned int
67 tree_type_map_hash (const void *item)
69 return TYPE_UID (((const struct tree_type_map *)item)->type.from);
72 static GTY ((if_marked ("tree_type_map_marked_p"), param_is (struct tree_type_map)))
73 htab_t decl_tree_for_type;
75 /* Lookup a VAR_DECL for TYPE, and return it if we find one. */
77 static tree
78 decl_for_type_lookup (tree type)
80 /* If the hash table is not initialized yet, create it now. */
81 if (decl_tree_for_type == NULL)
83 decl_tree_for_type = htab_create_ggc (10, tree_type_map_hash,
84 tree_type_map_eq, 0);
85 /* That also means we don't have to bother with the lookup. */
86 return NULL_TREE;
89 struct tree_type_map *h, in;
90 in.type.from = type;
92 h = (struct tree_type_map *)
93 htab_find_with_hash (decl_tree_for_type, &in, TYPE_UID (type));
94 return h ? h->decl : NULL_TREE;
97 /* Insert a mapping TYPE->DECL in the VAR_DECL for type hashtable. */
99 static void
100 decl_for_type_insert (tree type, tree decl)
102 struct tree_type_map *h;
103 void **slot;
105 h = ggc_alloc<tree_type_map> ();
106 h->type.from = type;
107 h->decl = decl;
108 slot = htab_find_slot_with_hash (decl_tree_for_type, h, TYPE_UID (type),
109 INSERT);
110 *(struct tree_type_map **) slot = 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, NULL);
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 /* Build
166 struct __ubsan_type_descriptor
168 unsigned short __typekind;
169 unsigned short __typeinfo;
170 char __typename[];
172 type. */
174 static tree
175 ubsan_type_descriptor_type (void)
177 static const char *field_names[3]
178 = { "__typekind", "__typeinfo", "__typename" };
179 tree fields[3], ret;
180 tree itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
181 tree flex_arr_type = build_array_type (char_type_node, itype);
183 ret = make_node (RECORD_TYPE);
184 for (int i = 0; i < 3; i++)
186 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
187 get_identifier (field_names[i]),
188 (i == 2) ? flex_arr_type
189 : short_unsigned_type_node);
190 DECL_CONTEXT (fields[i]) = ret;
191 if (i)
192 DECL_CHAIN (fields[i - 1]) = fields[i];
194 TYPE_FIELDS (ret) = fields[0];
195 TYPE_NAME (ret) = get_identifier ("__ubsan_type_descriptor");
196 layout_type (ret);
197 return ret;
200 /* Cached ubsan_get_source_location_type () return value. */
201 static GTY(()) tree ubsan_source_location_type;
203 /* Build
204 struct __ubsan_source_location
206 const char *__filename;
207 unsigned int __line;
208 unsigned int __column;
210 type. */
212 tree
213 ubsan_get_source_location_type (void)
215 static const char *field_names[3]
216 = { "__filename", "__line", "__column" };
217 tree fields[3], ret;
218 if (ubsan_source_location_type)
219 return ubsan_source_location_type;
221 tree const_char_type = build_qualified_type (char_type_node,
222 TYPE_QUAL_CONST);
224 ret = make_node (RECORD_TYPE);
225 for (int i = 0; i < 3; i++)
227 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
228 get_identifier (field_names[i]),
229 (i == 0) ? build_pointer_type (const_char_type)
230 : unsigned_type_node);
231 DECL_CONTEXT (fields[i]) = ret;
232 if (i)
233 DECL_CHAIN (fields[i - 1]) = fields[i];
235 TYPE_FIELDS (ret) = fields[0];
236 TYPE_NAME (ret) = get_identifier ("__ubsan_source_location");
237 layout_type (ret);
238 ubsan_source_location_type = ret;
239 return ret;
242 /* Helper routine that returns a CONSTRUCTOR of __ubsan_source_location
243 type with its fields filled from a location_t LOC. */
245 static tree
246 ubsan_source_location (location_t loc)
248 expanded_location xloc;
249 tree type = ubsan_get_source_location_type ();
251 xloc = expand_location (loc);
252 tree str;
253 if (xloc.file == NULL)
255 str = build_int_cst (ptr_type_node, 0);
256 xloc.line = 0;
257 xloc.column = 0;
259 else
261 /* Fill in the values from LOC. */
262 size_t len = strlen (xloc.file);
263 str = build_string (len + 1, xloc.file);
264 TREE_TYPE (str) = build_array_type (char_type_node,
265 build_index_type (size_int (len)));
266 TREE_READONLY (str) = 1;
267 TREE_STATIC (str) = 1;
268 str = build_fold_addr_expr (str);
270 tree ctor = build_constructor_va (type, 3, NULL_TREE, str, NULL_TREE,
271 build_int_cst (unsigned_type_node,
272 xloc.line), NULL_TREE,
273 build_int_cst (unsigned_type_node,
274 xloc.column));
275 TREE_CONSTANT (ctor) = 1;
276 TREE_STATIC (ctor) = 1;
278 return ctor;
281 /* This routine returns a magic number for TYPE. */
283 static unsigned short
284 get_ubsan_type_info_for_type (tree type)
286 gcc_assert (TYPE_SIZE (type) && tree_fits_uhwi_p (TYPE_SIZE (type)));
287 if (TREE_CODE (type) == REAL_TYPE)
288 return tree_to_uhwi (TYPE_SIZE (type));
289 else if (INTEGRAL_TYPE_P (type))
291 int prec = exact_log2 (tree_to_uhwi (TYPE_SIZE (type)));
292 gcc_assert (prec != -1);
293 return (prec << 1) | !TYPE_UNSIGNED (type);
295 else
296 return 0;
299 /* Helper routine that returns ADDR_EXPR of a VAR_DECL of a type
300 descriptor. It first looks into the hash table; if not found,
301 create the VAR_DECL, put it into the hash table and return the
302 ADDR_EXPR of it. TYPE describes a particular type. PSTYLE is
303 an enum controlling how we want to print the type. */
305 tree
306 ubsan_type_descriptor (tree type, enum ubsan_print_style pstyle)
308 /* See through any typedefs. */
309 type = TYPE_MAIN_VARIANT (type);
311 tree decl = decl_for_type_lookup (type);
312 /* It is possible that some of the earlier created DECLs were found
313 unused, in that case they weren't emitted and varpool_node::get
314 returns NULL node on them. But now we really need them. Thus,
315 renew them here. */
316 if (decl != NULL_TREE && varpool_node::get (decl))
317 return build_fold_addr_expr (decl);
319 tree dtype = ubsan_type_descriptor_type ();
320 tree type2 = type;
321 const char *tname = NULL;
322 char *pretty_name;
323 unsigned char deref_depth = 0;
324 unsigned short tkind, tinfo;
326 /* Get the name of the type, or the name of the pointer type. */
327 if (pstyle == UBSAN_PRINT_POINTER)
329 gcc_assert (POINTER_TYPE_P (type));
330 type2 = TREE_TYPE (type);
332 /* Remove any '*' operators from TYPE. */
333 while (POINTER_TYPE_P (type2))
334 deref_depth++, type2 = TREE_TYPE (type2);
336 if (TREE_CODE (type2) == METHOD_TYPE)
337 type2 = TYPE_METHOD_BASETYPE (type2);
340 /* If an array, get its type. */
341 type2 = strip_array_types (type2);
343 if (pstyle == UBSAN_PRINT_ARRAY)
345 while (POINTER_TYPE_P (type2))
346 deref_depth++, type2 = TREE_TYPE (type2);
349 if (TYPE_NAME (type2) != NULL)
351 if (TREE_CODE (TYPE_NAME (type2)) == IDENTIFIER_NODE)
352 tname = IDENTIFIER_POINTER (TYPE_NAME (type2));
353 else if (DECL_NAME (TYPE_NAME (type2)) != NULL)
354 tname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type2)));
357 if (tname == NULL)
358 /* We weren't able to determine the type name. */
359 tname = "<unknown>";
361 /* Decorate the type name with '', '*', "struct", or "union". */
362 pretty_name = (char *) alloca (strlen (tname) + 16 + deref_depth);
363 if (pstyle == UBSAN_PRINT_POINTER)
365 int pos = sprintf (pretty_name, "'%s%s%s%s%s%s%s",
366 TYPE_VOLATILE (type2) ? "volatile " : "",
367 TYPE_READONLY (type2) ? "const " : "",
368 TYPE_RESTRICT (type2) ? "restrict " : "",
369 TYPE_ATOMIC (type2) ? "_Atomic " : "",
370 TREE_CODE (type2) == RECORD_TYPE
371 ? "struct "
372 : TREE_CODE (type2) == UNION_TYPE
373 ? "union " : "", tname,
374 deref_depth == 0 ? "" : " ");
375 while (deref_depth-- > 0)
376 pretty_name[pos++] = '*';
377 pretty_name[pos++] = '\'';
378 pretty_name[pos] = '\0';
380 else if (pstyle == UBSAN_PRINT_ARRAY)
382 /* Pretty print the array dimensions. */
383 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
384 tree t = type;
385 int pos = sprintf (pretty_name, "'%s ", tname);
386 while (deref_depth-- > 0)
387 pretty_name[pos++] = '*';
388 while (TREE_CODE (t) == ARRAY_TYPE)
390 pretty_name[pos++] = '[';
391 tree dom = TYPE_DOMAIN (t);
392 if (dom && TREE_CODE (TYPE_MAX_VALUE (dom)) == INTEGER_CST)
393 pos += sprintf (&pretty_name[pos], HOST_WIDE_INT_PRINT_DEC,
394 tree_to_shwi (TYPE_MAX_VALUE (dom)) + 1);
395 else
396 /* ??? We can't determine the variable name; print VLA unspec. */
397 pretty_name[pos++] = '*';
398 pretty_name[pos++] = ']';
399 t = TREE_TYPE (t);
401 pretty_name[pos++] = '\'';
402 pretty_name[pos] = '\0';
404 /* Save the tree with stripped types. */
405 type = t;
407 else
408 sprintf (pretty_name, "'%s'", tname);
410 switch (TREE_CODE (type))
412 case BOOLEAN_TYPE:
413 case ENUMERAL_TYPE:
414 case INTEGER_TYPE:
415 tkind = 0x0000;
416 break;
417 case REAL_TYPE:
418 /* FIXME: libubsan right now only supports float, double and
419 long double type formats. */
420 if (TYPE_MODE (type) == TYPE_MODE (float_type_node)
421 || TYPE_MODE (type) == TYPE_MODE (double_type_node)
422 || TYPE_MODE (type) == TYPE_MODE (long_double_type_node))
423 tkind = 0x0001;
424 else
425 tkind = 0xffff;
426 break;
427 default:
428 tkind = 0xffff;
429 break;
431 tinfo = get_ubsan_type_info_for_type (type);
433 /* Create a new VAR_DECL of type descriptor. */
434 char tmp_name[32];
435 static unsigned int type_var_id_num;
436 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_type", type_var_id_num++);
437 decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name),
438 dtype);
439 TREE_STATIC (decl) = 1;
440 TREE_PUBLIC (decl) = 0;
441 DECL_ARTIFICIAL (decl) = 1;
442 DECL_IGNORED_P (decl) = 1;
443 DECL_EXTERNAL (decl) = 0;
445 size_t len = strlen (pretty_name);
446 tree str = build_string (len + 1, pretty_name);
447 TREE_TYPE (str) = build_array_type (char_type_node,
448 build_index_type (size_int (len)));
449 TREE_READONLY (str) = 1;
450 TREE_STATIC (str) = 1;
451 tree ctor = build_constructor_va (dtype, 3, NULL_TREE,
452 build_int_cst (short_unsigned_type_node,
453 tkind), NULL_TREE,
454 build_int_cst (short_unsigned_type_node,
455 tinfo), NULL_TREE, str);
456 TREE_CONSTANT (ctor) = 1;
457 TREE_STATIC (ctor) = 1;
458 DECL_INITIAL (decl) = ctor;
459 varpool_node::finalize_decl (decl);
461 /* Save the VAR_DECL into the hash table. */
462 decl_for_type_insert (type, decl);
464 return build_fold_addr_expr (decl);
467 /* Create a structure for the ubsan library. NAME is a name of the new
468 structure. LOCCNT is number of locations, PLOC points to array of
469 locations. The arguments in ... are of __ubsan_type_descriptor type
470 and there are at most two of them, followed by NULL_TREE, followed
471 by optional extra arguments and another NULL_TREE. */
473 tree
474 ubsan_create_data (const char *name, int loccnt, const location_t *ploc, ...)
476 va_list args;
477 tree ret, t;
478 tree fields[6];
479 vec<tree, va_gc> *saved_args = NULL;
480 size_t i = 0;
481 int j;
483 /* Firstly, create a pointer to type descriptor type. */
484 tree td_type = ubsan_type_descriptor_type ();
485 TYPE_READONLY (td_type) = 1;
486 td_type = build_pointer_type (td_type);
488 /* Create the structure type. */
489 ret = make_node (RECORD_TYPE);
490 for (j = 0; j < loccnt; j++)
492 gcc_checking_assert (i < 2);
493 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
494 ubsan_get_source_location_type ());
495 DECL_CONTEXT (fields[i]) = ret;
496 if (i)
497 DECL_CHAIN (fields[i - 1]) = fields[i];
498 i++;
501 va_start (args, ploc);
502 for (t = va_arg (args, tree); t != NULL_TREE;
503 i++, t = va_arg (args, tree))
505 gcc_checking_assert (i < 4);
506 /* Save the tree arguments for later use. */
507 vec_safe_push (saved_args, t);
508 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
509 td_type);
510 DECL_CONTEXT (fields[i]) = ret;
511 if (i)
512 DECL_CHAIN (fields[i - 1]) = fields[i];
515 for (t = va_arg (args, tree); t != NULL_TREE;
516 i++, t = va_arg (args, tree))
518 gcc_checking_assert (i < 6);
519 /* Save the tree arguments for later use. */
520 vec_safe_push (saved_args, t);
521 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
522 TREE_TYPE (t));
523 DECL_CONTEXT (fields[i]) = ret;
524 if (i)
525 DECL_CHAIN (fields[i - 1]) = fields[i];
527 va_end (args);
529 TYPE_FIELDS (ret) = fields[0];
530 TYPE_NAME (ret) = get_identifier (name);
531 layout_type (ret);
533 /* Now, fill in the type. */
534 char tmp_name[32];
535 static unsigned int ubsan_var_id_num;
536 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_data", ubsan_var_id_num++);
537 tree var = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name),
538 ret);
539 TREE_STATIC (var) = 1;
540 TREE_PUBLIC (var) = 0;
541 DECL_ARTIFICIAL (var) = 1;
542 DECL_IGNORED_P (var) = 1;
543 DECL_EXTERNAL (var) = 0;
545 vec<constructor_elt, va_gc> *v;
546 vec_alloc (v, i);
547 tree ctor = build_constructor (ret, v);
549 /* If desirable, set the __ubsan_source_location element. */
550 for (j = 0; j < loccnt; j++)
552 location_t loc = LOCATION_LOCUS (ploc[j]);
553 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, ubsan_source_location (loc));
556 size_t nelts = vec_safe_length (saved_args);
557 for (i = 0; i < nelts; i++)
559 t = (*saved_args)[i];
560 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, t);
563 TREE_CONSTANT (ctor) = 1;
564 TREE_STATIC (ctor) = 1;
565 DECL_INITIAL (var) = ctor;
566 varpool_node::finalize_decl (var);
568 return var;
571 /* Instrument the __builtin_unreachable call. We just call the libubsan
572 routine instead. */
574 tree
575 ubsan_instrument_unreachable (location_t loc)
577 if (flag_sanitize_undefined_trap_on_error)
578 return build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
580 initialize_sanitizer_builtins ();
581 tree data = ubsan_create_data ("__ubsan_unreachable_data", 1, &loc, NULL_TREE,
582 NULL_TREE);
583 tree t = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE);
584 return build_call_expr_loc (loc, t, 1, build_fold_addr_expr_loc (loc, data));
587 /* Return true if T is a call to a libubsan routine. */
589 bool
590 is_ubsan_builtin_p (tree t)
592 return TREE_CODE (t) == FUNCTION_DECL
593 && strncmp (IDENTIFIER_POINTER (DECL_NAME (t)),
594 "__builtin___ubsan_", 18) == 0;
597 /* Expand the UBSAN_BOUNDS special builtin function. */
599 bool
600 ubsan_expand_bounds_ifn (gimple_stmt_iterator *gsi)
602 gimple stmt = gsi_stmt (*gsi);
603 location_t loc = gimple_location (stmt);
604 gcc_assert (gimple_call_num_args (stmt) == 3);
606 /* Pick up the arguments of the UBSAN_BOUNDS call. */
607 tree type = TREE_TYPE (TREE_TYPE (gimple_call_arg (stmt, 0)));
608 tree index = gimple_call_arg (stmt, 1);
609 tree orig_index_type = TREE_TYPE (index);
610 tree bound = gimple_call_arg (stmt, 2);
612 gimple_stmt_iterator gsi_orig = *gsi;
614 /* Create condition "if (index > bound)". */
615 basic_block then_bb, fallthru_bb;
616 gimple_stmt_iterator cond_insert_point
617 = create_cond_insert_point (gsi, 0/*before_p*/, false, true,
618 &then_bb, &fallthru_bb);
619 index = fold_convert (TREE_TYPE (bound), index);
620 index = force_gimple_operand_gsi (&cond_insert_point, index,
621 true/*simple_p*/, NULL_TREE,
622 false/*before*/, GSI_NEW_STMT);
623 gimple g = gimple_build_cond (GT_EXPR, index, bound, NULL_TREE, NULL_TREE);
624 gimple_set_location (g, loc);
625 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
627 /* Generate __ubsan_handle_out_of_bounds call. */
628 *gsi = gsi_after_labels (then_bb);
629 if (flag_sanitize_undefined_trap_on_error)
630 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
631 else
633 tree data
634 = ubsan_create_data ("__ubsan_out_of_bounds_data", 1, &loc,
635 ubsan_type_descriptor (type, UBSAN_PRINT_ARRAY),
636 ubsan_type_descriptor (orig_index_type),
637 NULL_TREE, NULL_TREE);
638 data = build_fold_addr_expr_loc (loc, data);
639 enum built_in_function bcode
640 = flag_sanitize_recover
641 ? BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS
642 : BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS_ABORT;
643 tree fn = builtin_decl_explicit (bcode);
644 tree val = force_gimple_operand_gsi (gsi, ubsan_encode_value (index),
645 true, NULL_TREE, true,
646 GSI_SAME_STMT);
647 g = gimple_build_call (fn, 2, data, val);
649 gimple_set_location (g, loc);
650 gsi_insert_before (gsi, g, GSI_SAME_STMT);
652 /* Get rid of the UBSAN_BOUNDS call from the IR. */
653 unlink_stmt_vdef (stmt);
654 gsi_remove (&gsi_orig, true);
656 /* Point GSI to next logical statement. */
657 *gsi = gsi_start_bb (fallthru_bb);
658 return true;
661 /* Expand UBSAN_NULL internal call. The type is kept on the ckind
662 argument which is a constant, because the middle-end treats pointer
663 conversions as useless and therefore the type of the first argument
664 could be changed to any other pointer type. */
666 bool
667 ubsan_expand_null_ifn (gimple_stmt_iterator *gsip)
669 gimple_stmt_iterator gsi = *gsip;
670 gimple stmt = gsi_stmt (gsi);
671 location_t loc = gimple_location (stmt);
672 gcc_assert (gimple_call_num_args (stmt) == 3);
673 tree ptr = gimple_call_arg (stmt, 0);
674 tree ckind = gimple_call_arg (stmt, 1);
675 tree align = gimple_call_arg (stmt, 2);
676 tree check_align = NULL_TREE;
677 bool check_null;
679 basic_block cur_bb = gsi_bb (gsi);
681 gimple g;
682 if (!integer_zerop (align))
684 unsigned int ptralign = get_pointer_alignment (ptr) / BITS_PER_UNIT;
685 if (compare_tree_int (align, ptralign) == 1)
687 check_align = make_ssa_name (pointer_sized_int_node, NULL);
688 g = gimple_build_assign_with_ops (NOP_EXPR, check_align,
689 ptr, NULL_TREE);
690 gimple_set_location (g, loc);
691 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
694 check_null = (flag_sanitize & SANITIZE_NULL) != 0;
696 if (check_align == NULL_TREE && !check_null)
698 gsi_remove (gsip, true);
699 /* Unlink the UBSAN_NULLs vops before replacing it. */
700 unlink_stmt_vdef (stmt);
701 return true;
704 /* Split the original block holding the pointer dereference. */
705 edge e = split_block (cur_bb, stmt);
707 /* Get a hold on the 'condition block', the 'then block' and the
708 'else block'. */
709 basic_block cond_bb = e->src;
710 basic_block fallthru_bb = e->dest;
711 basic_block then_bb = create_empty_bb (cond_bb);
712 add_bb_to_loop (then_bb, cond_bb->loop_father);
713 loops_state_set (LOOPS_NEED_FIXUP);
715 /* Make an edge coming from the 'cond block' into the 'then block';
716 this edge is unlikely taken, so set up the probability accordingly. */
717 e = make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
718 e->probability = PROB_VERY_UNLIKELY;
720 /* Connect 'then block' with the 'else block'. This is needed
721 as the ubsan routines we call in the 'then block' are not noreturn.
722 The 'then block' only has one outcoming edge. */
723 make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);
725 /* Set up the fallthrough basic block. */
726 e = find_edge (cond_bb, fallthru_bb);
727 e->flags = EDGE_FALSE_VALUE;
728 e->count = cond_bb->count;
729 e->probability = REG_BR_PROB_BASE - PROB_VERY_UNLIKELY;
731 /* Update dominance info for the newly created then_bb; note that
732 fallthru_bb's dominance info has already been updated by
733 split_block. */
734 if (dom_info_available_p (CDI_DOMINATORS))
735 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
737 /* Put the ubsan builtin call into the newly created BB. */
738 if (flag_sanitize_undefined_trap_on_error)
739 g = gimple_build_call (builtin_decl_implicit (BUILT_IN_TRAP), 0);
740 else
742 enum built_in_function bcode
743 = flag_sanitize_recover
744 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
745 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT;
746 tree fn = builtin_decl_implicit (bcode);
747 tree data
748 = ubsan_create_data ("__ubsan_null_data", 1, &loc,
749 ubsan_type_descriptor (TREE_TYPE (ckind),
750 UBSAN_PRINT_POINTER),
751 NULL_TREE,
752 align,
753 fold_convert (unsigned_char_type_node, ckind),
754 NULL_TREE);
755 data = build_fold_addr_expr_loc (loc, data);
756 g = gimple_build_call (fn, 2, data,
757 check_align ? check_align
758 : build_zero_cst (pointer_sized_int_node));
760 gimple_stmt_iterator gsi2 = gsi_start_bb (then_bb);
761 gimple_set_location (g, loc);
762 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
764 /* Unlink the UBSAN_NULLs vops before replacing it. */
765 unlink_stmt_vdef (stmt);
767 if (check_null)
769 g = gimple_build_cond (EQ_EXPR, ptr, build_int_cst (TREE_TYPE (ptr), 0),
770 NULL_TREE, NULL_TREE);
771 gimple_set_location (g, loc);
773 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
774 gsi_replace (&gsi, g, false);
777 if (check_align)
779 if (check_null)
781 /* Split the block with the condition again. */
782 e = split_block (cond_bb, stmt);
783 basic_block cond1_bb = e->src;
784 basic_block cond2_bb = e->dest;
786 /* Make an edge coming from the 'cond1 block' into the 'then block';
787 this edge is unlikely taken, so set up the probability
788 accordingly. */
789 e = make_edge (cond1_bb, then_bb, EDGE_TRUE_VALUE);
790 e->probability = PROB_VERY_UNLIKELY;
792 /* Set up the fallthrough basic block. */
793 e = find_edge (cond1_bb, cond2_bb);
794 e->flags = EDGE_FALSE_VALUE;
795 e->count = cond1_bb->count;
796 e->probability = REG_BR_PROB_BASE - PROB_VERY_UNLIKELY;
798 /* Update dominance info. */
799 if (dom_info_available_p (CDI_DOMINATORS))
801 set_immediate_dominator (CDI_DOMINATORS, fallthru_bb, cond1_bb);
802 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond1_bb);
805 gsi2 = gsi_start_bb (cond2_bb);
808 tree mask = build_int_cst (pointer_sized_int_node,
809 tree_to_uhwi (align) - 1);
810 g = gimple_build_assign_with_ops (BIT_AND_EXPR,
811 make_ssa_name (pointer_sized_int_node,
812 NULL),
813 check_align, mask);
814 gimple_set_location (g, loc);
815 if (check_null)
816 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
817 else
818 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
820 g = gimple_build_cond (NE_EXPR, gimple_assign_lhs (g),
821 build_int_cst (pointer_sized_int_node, 0),
822 NULL_TREE, NULL_TREE);
823 gimple_set_location (g, loc);
824 if (check_null)
825 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
826 else
827 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
828 gsi_replace (&gsi, g, false);
830 return false;
833 /* Instrument a memory reference. BASE is the base of MEM, IS_LHS says
834 whether the pointer is on the left hand side of the assignment. */
836 static void
837 instrument_mem_ref (tree mem, tree base, gimple_stmt_iterator *iter,
838 bool is_lhs)
840 enum ubsan_null_ckind ikind = is_lhs ? UBSAN_STORE_OF : UBSAN_LOAD_OF;
841 unsigned int align = 0;
842 if (flag_sanitize & SANITIZE_ALIGNMENT)
844 align = min_align_of_type (TREE_TYPE (base));
845 if (align <= 1)
846 align = 0;
848 if (align == 0 && (flag_sanitize & SANITIZE_NULL) == 0)
849 return;
850 tree t = TREE_OPERAND (base, 0);
851 if (!POINTER_TYPE_P (TREE_TYPE (t)))
852 return;
853 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (TREE_TYPE (t))) && mem != base)
854 ikind = UBSAN_MEMBER_ACCESS;
855 tree kind = build_int_cst (TREE_TYPE (t), ikind);
856 tree alignt = build_int_cst (pointer_sized_int_node, align);
857 gimple g = gimple_build_call_internal (IFN_UBSAN_NULL, 3, t, kind, alignt);
858 gimple_set_location (g, gimple_location (gsi_stmt (*iter)));
859 gsi_insert_before (iter, g, GSI_SAME_STMT);
862 /* Perform the pointer instrumentation. */
864 static void
865 instrument_null (gimple_stmt_iterator gsi, bool is_lhs)
867 gimple stmt = gsi_stmt (gsi);
868 tree t = is_lhs ? gimple_get_lhs (stmt) : gimple_assign_rhs1 (stmt);
869 tree base = get_base_address (t);
870 const enum tree_code code = TREE_CODE (base);
871 if (code == MEM_REF
872 && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
873 instrument_mem_ref (t, base, &gsi, is_lhs);
876 /* Build an ubsan builtin call for the signed-integer-overflow
877 sanitization. CODE says what kind of builtin are we building,
878 LOC is a location, LHSTYPE is the type of LHS, OP0 and OP1
879 are operands of the binary operation. */
881 tree
882 ubsan_build_overflow_builtin (tree_code code, location_t loc, tree lhstype,
883 tree op0, tree op1)
885 if (flag_sanitize_undefined_trap_on_error)
886 return build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
888 tree data = ubsan_create_data ("__ubsan_overflow_data", 1, &loc,
889 ubsan_type_descriptor (lhstype), NULL_TREE,
890 NULL_TREE);
891 enum built_in_function fn_code;
893 switch (code)
895 case PLUS_EXPR:
896 fn_code = flag_sanitize_recover
897 ? BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW
898 : BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW_ABORT;
899 break;
900 case MINUS_EXPR:
901 fn_code = flag_sanitize_recover
902 ? BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW
903 : BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW_ABORT;
904 break;
905 case MULT_EXPR:
906 fn_code = flag_sanitize_recover
907 ? BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW
908 : BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW_ABORT;
909 break;
910 case NEGATE_EXPR:
911 fn_code = flag_sanitize_recover
912 ? BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW
913 : BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW_ABORT;
914 break;
915 default:
916 gcc_unreachable ();
918 tree fn = builtin_decl_explicit (fn_code);
919 return build_call_expr_loc (loc, fn, 2 + (code != NEGATE_EXPR),
920 build_fold_addr_expr_loc (loc, data),
921 ubsan_encode_value (op0, true),
922 op1 ? ubsan_encode_value (op1, true)
923 : NULL_TREE);
926 /* Perform the signed integer instrumentation. GSI is the iterator
927 pointing at statement we are trying to instrument. */
929 static void
930 instrument_si_overflow (gimple_stmt_iterator gsi)
932 gimple stmt = gsi_stmt (gsi);
933 tree_code code = gimple_assign_rhs_code (stmt);
934 tree lhs = gimple_assign_lhs (stmt);
935 tree lhstype = TREE_TYPE (lhs);
936 tree a, b;
937 gimple g;
939 /* If this is not a signed operation, don't instrument anything here.
940 Also punt on bit-fields. */
941 if (!INTEGRAL_TYPE_P (lhstype)
942 || TYPE_OVERFLOW_WRAPS (lhstype)
943 || GET_MODE_BITSIZE (TYPE_MODE (lhstype)) != TYPE_PRECISION (lhstype))
944 return;
946 switch (code)
948 case MINUS_EXPR:
949 case PLUS_EXPR:
950 case MULT_EXPR:
951 /* Transform
952 i = u {+,-,*} 5;
953 into
954 i = UBSAN_CHECK_{ADD,SUB,MUL} (u, 5); */
955 a = gimple_assign_rhs1 (stmt);
956 b = gimple_assign_rhs2 (stmt);
957 g = gimple_build_call_internal (code == PLUS_EXPR
958 ? IFN_UBSAN_CHECK_ADD
959 : code == MINUS_EXPR
960 ? IFN_UBSAN_CHECK_SUB
961 : IFN_UBSAN_CHECK_MUL, 2, a, b);
962 gimple_call_set_lhs (g, lhs);
963 gsi_replace (&gsi, g, false);
964 break;
965 case NEGATE_EXPR:
966 /* Represent i = -u;
968 i = UBSAN_CHECK_SUB (0, u); */
969 a = build_int_cst (lhstype, 0);
970 b = gimple_assign_rhs1 (stmt);
971 g = gimple_build_call_internal (IFN_UBSAN_CHECK_SUB, 2, a, b);
972 gimple_call_set_lhs (g, lhs);
973 gsi_replace (&gsi, g, false);
974 break;
975 case ABS_EXPR:
976 /* Transform i = ABS_EXPR<u>;
977 into
978 _N = UBSAN_CHECK_SUB (0, u);
979 i = ABS_EXPR<_N>; */
980 a = build_int_cst (lhstype, 0);
981 b = gimple_assign_rhs1 (stmt);
982 g = gimple_build_call_internal (IFN_UBSAN_CHECK_SUB, 2, a, b);
983 a = make_ssa_name (lhstype, NULL);
984 gimple_call_set_lhs (g, a);
985 gimple_set_location (g, gimple_location (stmt));
986 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
987 gimple_assign_set_rhs1 (stmt, a);
988 update_stmt (stmt);
989 break;
990 default:
991 break;
995 /* Instrument loads from (non-bitfield) bool and C++ enum values
996 to check if the memory value is outside of the range of the valid
997 type values. */
999 static void
1000 instrument_bool_enum_load (gimple_stmt_iterator *gsi)
1002 gimple stmt = gsi_stmt (*gsi);
1003 tree rhs = gimple_assign_rhs1 (stmt);
1004 tree type = TREE_TYPE (rhs);
1005 tree minv = NULL_TREE, maxv = NULL_TREE;
1007 if (TREE_CODE (type) == BOOLEAN_TYPE && (flag_sanitize & SANITIZE_BOOL))
1009 minv = boolean_false_node;
1010 maxv = boolean_true_node;
1012 else if (TREE_CODE (type) == ENUMERAL_TYPE
1013 && (flag_sanitize & SANITIZE_ENUM)
1014 && TREE_TYPE (type) != NULL_TREE
1015 && TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE
1016 && (TYPE_PRECISION (TREE_TYPE (type))
1017 < GET_MODE_PRECISION (TYPE_MODE (type))))
1019 minv = TYPE_MIN_VALUE (TREE_TYPE (type));
1020 maxv = TYPE_MAX_VALUE (TREE_TYPE (type));
1022 else
1023 return;
1025 int modebitsize = GET_MODE_BITSIZE (TYPE_MODE (type));
1026 HOST_WIDE_INT bitsize, bitpos;
1027 tree offset;
1028 enum machine_mode mode;
1029 int volatilep = 0, unsignedp = 0;
1030 tree base = get_inner_reference (rhs, &bitsize, &bitpos, &offset, &mode,
1031 &unsignedp, &volatilep, false);
1032 tree utype = build_nonstandard_integer_type (modebitsize, 1);
1034 if ((TREE_CODE (base) == VAR_DECL && DECL_HARD_REGISTER (base))
1035 || (bitpos % modebitsize) != 0
1036 || bitsize != modebitsize
1037 || GET_MODE_BITSIZE (TYPE_MODE (utype)) != modebitsize
1038 || TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME)
1039 return;
1041 location_t loc = gimple_location (stmt);
1042 tree ptype = build_pointer_type (TREE_TYPE (rhs));
1043 tree atype = reference_alias_ptr_type (rhs);
1044 gimple g = gimple_build_assign (make_ssa_name (ptype, NULL),
1045 build_fold_addr_expr (rhs));
1046 gimple_set_location (g, loc);
1047 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1048 tree mem = build2 (MEM_REF, utype, gimple_assign_lhs (g),
1049 build_int_cst (atype, 0));
1050 tree urhs = make_ssa_name (utype, NULL);
1051 g = gimple_build_assign (urhs, mem);
1052 gimple_set_location (g, loc);
1053 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1054 minv = fold_convert (utype, minv);
1055 maxv = fold_convert (utype, maxv);
1056 if (!integer_zerop (minv))
1058 g = gimple_build_assign_with_ops (MINUS_EXPR,
1059 make_ssa_name (utype, NULL),
1060 urhs, minv);
1061 gimple_set_location (g, loc);
1062 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1065 gimple_stmt_iterator gsi2 = *gsi;
1066 basic_block then_bb, fallthru_bb;
1067 *gsi = create_cond_insert_point (gsi, true, false, true,
1068 &then_bb, &fallthru_bb);
1069 g = gimple_build_cond (GT_EXPR, gimple_assign_lhs (g),
1070 int_const_binop (MINUS_EXPR, maxv, minv),
1071 NULL_TREE, NULL_TREE);
1072 gimple_set_location (g, loc);
1073 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1075 gimple_assign_set_rhs_with_ops (&gsi2, NOP_EXPR, urhs, NULL_TREE);
1076 update_stmt (stmt);
1078 gsi2 = gsi_after_labels (then_bb);
1079 if (flag_sanitize_undefined_trap_on_error)
1080 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1081 else
1083 tree data = ubsan_create_data ("__ubsan_invalid_value_data", 1, &loc,
1084 ubsan_type_descriptor (type), NULL_TREE,
1085 NULL_TREE);
1086 data = build_fold_addr_expr_loc (loc, data);
1087 enum built_in_function bcode
1088 = flag_sanitize_recover
1089 ? BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE
1090 : BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE_ABORT;
1091 tree fn = builtin_decl_explicit (bcode);
1093 tree val = force_gimple_operand_gsi (&gsi2, ubsan_encode_value (urhs),
1094 true, NULL_TREE, true,
1095 GSI_SAME_STMT);
1096 g = gimple_build_call (fn, 2, data, val);
1098 gimple_set_location (g, loc);
1099 gsi_insert_before (&gsi2, g, GSI_SAME_STMT);
1100 *gsi = gsi_for_stmt (stmt);
1103 /* Instrument float point-to-integer conversion. TYPE is an integer type of
1104 destination, EXPR is floating-point expression. */
1106 tree
1107 ubsan_instrument_float_cast (location_t loc, tree type, tree expr)
1109 tree expr_type = TREE_TYPE (expr);
1110 tree t, tt, fn, min, max;
1111 enum machine_mode mode = TYPE_MODE (expr_type);
1112 int prec = TYPE_PRECISION (type);
1113 bool uns_p = TYPE_UNSIGNED (type);
1115 /* Float to integer conversion first truncates toward zero, so
1116 even signed char c = 127.875f; is not problematic.
1117 Therefore, we should complain only if EXPR is unordered or smaller
1118 or equal than TYPE_MIN_VALUE - 1.0 or greater or equal than
1119 TYPE_MAX_VALUE + 1.0. */
1120 if (REAL_MODE_FORMAT (mode)->b == 2)
1122 /* For maximum, TYPE_MAX_VALUE might not be representable
1123 in EXPR_TYPE, e.g. if TYPE is 64-bit long long and
1124 EXPR_TYPE is IEEE single float, but TYPE_MAX_VALUE + 1.0 is
1125 either representable or infinity. */
1126 REAL_VALUE_TYPE maxval = dconst1;
1127 SET_REAL_EXP (&maxval, REAL_EXP (&maxval) + prec - !uns_p);
1128 real_convert (&maxval, mode, &maxval);
1129 max = build_real (expr_type, maxval);
1131 /* For unsigned, assume -1.0 is always representable. */
1132 if (uns_p)
1133 min = build_minus_one_cst (expr_type);
1134 else
1136 /* TYPE_MIN_VALUE is generally representable (or -inf),
1137 but TYPE_MIN_VALUE - 1.0 might not be. */
1138 REAL_VALUE_TYPE minval = dconstm1, minval2;
1139 SET_REAL_EXP (&minval, REAL_EXP (&minval) + prec - 1);
1140 real_convert (&minval, mode, &minval);
1141 real_arithmetic (&minval2, MINUS_EXPR, &minval, &dconst1);
1142 real_convert (&minval2, mode, &minval2);
1143 if (real_compare (EQ_EXPR, &minval, &minval2)
1144 && !real_isinf (&minval))
1146 /* If TYPE_MIN_VALUE - 1.0 is not representable and
1147 rounds to TYPE_MIN_VALUE, we need to subtract
1148 more. As REAL_MODE_FORMAT (mode)->p is the number
1149 of base digits, we want to subtract a number that
1150 will be 1 << (REAL_MODE_FORMAT (mode)->p - 1)
1151 times smaller than minval. */
1152 minval2 = dconst1;
1153 gcc_assert (prec > REAL_MODE_FORMAT (mode)->p);
1154 SET_REAL_EXP (&minval2,
1155 REAL_EXP (&minval2) + prec - 1
1156 - REAL_MODE_FORMAT (mode)->p + 1);
1157 real_arithmetic (&minval2, MINUS_EXPR, &minval, &minval2);
1158 real_convert (&minval2, mode, &minval2);
1160 min = build_real (expr_type, minval2);
1163 else if (REAL_MODE_FORMAT (mode)->b == 10)
1165 /* For _Decimal128 up to 34 decimal digits, - sign,
1166 dot, e, exponent. */
1167 char buf[64];
1168 mpfr_t m;
1169 int p = REAL_MODE_FORMAT (mode)->p;
1170 REAL_VALUE_TYPE maxval, minval;
1172 /* Use mpfr_snprintf rounding to compute the smallest
1173 representable decimal number greater or equal than
1174 1 << (prec - !uns_p). */
1175 mpfr_init2 (m, prec + 2);
1176 mpfr_set_ui_2exp (m, 1, prec - !uns_p, GMP_RNDN);
1177 mpfr_snprintf (buf, sizeof buf, "%.*RUe", p - 1, m);
1178 decimal_real_from_string (&maxval, buf);
1179 max = build_real (expr_type, maxval);
1181 /* For unsigned, assume -1.0 is always representable. */
1182 if (uns_p)
1183 min = build_minus_one_cst (expr_type);
1184 else
1186 /* Use mpfr_snprintf rounding to compute the largest
1187 representable decimal number less or equal than
1188 (-1 << (prec - 1)) - 1. */
1189 mpfr_set_si_2exp (m, -1, prec - 1, GMP_RNDN);
1190 mpfr_sub_ui (m, m, 1, GMP_RNDN);
1191 mpfr_snprintf (buf, sizeof buf, "%.*RDe", p - 1, m);
1192 decimal_real_from_string (&minval, buf);
1193 min = build_real (expr_type, minval);
1195 mpfr_clear (m);
1197 else
1198 return NULL_TREE;
1200 if (flag_sanitize_undefined_trap_on_error)
1201 fn = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
1202 else
1204 /* Create the __ubsan_handle_float_cast_overflow fn call. */
1205 tree data = ubsan_create_data ("__ubsan_float_cast_overflow_data", 0,
1206 NULL, ubsan_type_descriptor (expr_type),
1207 ubsan_type_descriptor (type), NULL_TREE,
1208 NULL_TREE);
1209 enum built_in_function bcode
1210 = flag_sanitize_recover
1211 ? BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW
1212 : BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW_ABORT;
1213 fn = builtin_decl_explicit (bcode);
1214 fn = build_call_expr_loc (loc, fn, 2,
1215 build_fold_addr_expr_loc (loc, data),
1216 ubsan_encode_value (expr, false));
1219 t = fold_build2 (UNLE_EXPR, boolean_type_node, expr, min);
1220 tt = fold_build2 (UNGE_EXPR, boolean_type_node, expr, max);
1221 return fold_build3 (COND_EXPR, void_type_node,
1222 fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t, tt),
1223 fn, integer_zero_node);
1226 /* Instrument values passed to function arguments with nonnull attribute. */
1228 static void
1229 instrument_nonnull_arg (gimple_stmt_iterator *gsi)
1231 gimple stmt = gsi_stmt (*gsi);
1232 location_t loc[2];
1233 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
1234 while for nonnull sanitization it is clear. */
1235 int save_flag_delete_null_pointer_checks = flag_delete_null_pointer_checks;
1236 flag_delete_null_pointer_checks = 1;
1237 loc[0] = gimple_location (stmt);
1238 loc[1] = UNKNOWN_LOCATION;
1239 for (unsigned int i = 0; i < gimple_call_num_args (stmt); i++)
1241 tree arg = gimple_call_arg (stmt, i);
1242 if (POINTER_TYPE_P (TREE_TYPE (arg))
1243 && infer_nonnull_range (stmt, arg, false, true))
1245 gimple g;
1246 if (!is_gimple_val (arg))
1248 g = gimple_build_assign (make_ssa_name (TREE_TYPE (arg), NULL),
1249 arg);
1250 gimple_set_location (g, loc[0]);
1251 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1252 arg = gimple_assign_lhs (g);
1255 basic_block then_bb, fallthru_bb;
1256 *gsi = create_cond_insert_point (gsi, true, false, true,
1257 &then_bb, &fallthru_bb);
1258 g = gimple_build_cond (EQ_EXPR, arg,
1259 build_zero_cst (TREE_TYPE (arg)),
1260 NULL_TREE, NULL_TREE);
1261 gimple_set_location (g, loc[0]);
1262 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1264 *gsi = gsi_after_labels (then_bb);
1265 if (flag_sanitize_undefined_trap_on_error)
1266 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1267 else
1269 tree data = ubsan_create_data ("__ubsan_nonnull_arg_data",
1270 2, loc, NULL_TREE,
1271 build_int_cst (integer_type_node,
1272 i + 1),
1273 NULL_TREE);
1274 data = build_fold_addr_expr_loc (loc[0], data);
1275 enum built_in_function bcode
1276 = flag_sanitize_recover
1277 ? BUILT_IN_UBSAN_HANDLE_NONNULL_ARG
1278 : BUILT_IN_UBSAN_HANDLE_NONNULL_ARG_ABORT;
1279 tree fn = builtin_decl_explicit (bcode);
1281 g = gimple_build_call (fn, 1, data);
1283 gimple_set_location (g, loc[0]);
1284 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1286 *gsi = gsi_for_stmt (stmt);
1288 flag_delete_null_pointer_checks = save_flag_delete_null_pointer_checks;
1291 /* Instrument returns in functions with returns_nonnull attribute. */
1293 static void
1294 instrument_nonnull_return (gimple_stmt_iterator *gsi)
1296 gimple stmt = gsi_stmt (*gsi);
1297 location_t loc[2];
1298 tree arg = gimple_return_retval (stmt);
1299 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
1300 while for nonnull return sanitization it is clear. */
1301 int save_flag_delete_null_pointer_checks = flag_delete_null_pointer_checks;
1302 flag_delete_null_pointer_checks = 1;
1303 loc[0] = gimple_location (stmt);
1304 loc[1] = UNKNOWN_LOCATION;
1305 if (arg
1306 && POINTER_TYPE_P (TREE_TYPE (arg))
1307 && is_gimple_val (arg)
1308 && infer_nonnull_range (stmt, arg, false, true))
1310 basic_block then_bb, fallthru_bb;
1311 *gsi = create_cond_insert_point (gsi, true, false, true,
1312 &then_bb, &fallthru_bb);
1313 gimple g = gimple_build_cond (EQ_EXPR, arg,
1314 build_zero_cst (TREE_TYPE (arg)),
1315 NULL_TREE, NULL_TREE);
1316 gimple_set_location (g, loc[0]);
1317 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1319 *gsi = gsi_after_labels (then_bb);
1320 if (flag_sanitize_undefined_trap_on_error)
1321 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1322 else
1324 tree data = ubsan_create_data ("__ubsan_nonnull_return_data",
1325 2, loc, NULL_TREE, NULL_TREE);
1326 data = build_fold_addr_expr_loc (loc[0], data);
1327 enum built_in_function bcode
1328 = flag_sanitize_recover
1329 ? BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN
1330 : BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_ABORT;
1331 tree fn = builtin_decl_explicit (bcode);
1333 g = gimple_build_call (fn, 1, data);
1335 gimple_set_location (g, loc[0]);
1336 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1337 *gsi = gsi_for_stmt (stmt);
1339 flag_delete_null_pointer_checks = save_flag_delete_null_pointer_checks;
1342 namespace {
1344 const pass_data pass_data_ubsan =
1346 GIMPLE_PASS, /* type */
1347 "ubsan", /* name */
1348 OPTGROUP_NONE, /* optinfo_flags */
1349 TV_TREE_UBSAN, /* tv_id */
1350 ( PROP_cfg | PROP_ssa ), /* properties_required */
1351 0, /* properties_provided */
1352 0, /* properties_destroyed */
1353 0, /* todo_flags_start */
1354 TODO_update_ssa, /* todo_flags_finish */
1357 class pass_ubsan : public gimple_opt_pass
1359 public:
1360 pass_ubsan (gcc::context *ctxt)
1361 : gimple_opt_pass (pass_data_ubsan, ctxt)
1364 /* opt_pass methods: */
1365 virtual bool gate (function *)
1367 return flag_sanitize & (SANITIZE_NULL | SANITIZE_SI_OVERFLOW
1368 | SANITIZE_BOOL | SANITIZE_ENUM
1369 | SANITIZE_ALIGNMENT
1370 | SANITIZE_NONNULL_ATTRIBUTE
1371 | SANITIZE_RETURNS_NONNULL_ATTRIBUTE)
1372 && current_function_decl != NULL_TREE
1373 && !lookup_attribute ("no_sanitize_undefined",
1374 DECL_ATTRIBUTES (current_function_decl));
1377 virtual unsigned int execute (function *);
1379 }; // class pass_ubsan
1381 unsigned int
1382 pass_ubsan::execute (function *fun)
1384 basic_block bb;
1385 gimple_stmt_iterator gsi;
1387 initialize_sanitizer_builtins ();
1389 FOR_EACH_BB_FN (bb, fun)
1391 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
1393 gimple stmt = gsi_stmt (gsi);
1394 if (is_gimple_debug (stmt) || gimple_clobber_p (stmt))
1396 gsi_next (&gsi);
1397 continue;
1400 if ((flag_sanitize & SANITIZE_SI_OVERFLOW)
1401 && is_gimple_assign (stmt))
1402 instrument_si_overflow (gsi);
1404 if (flag_sanitize & (SANITIZE_NULL | SANITIZE_ALIGNMENT))
1406 if (gimple_store_p (stmt))
1407 instrument_null (gsi, true);
1408 if (gimple_assign_load_p (stmt))
1409 instrument_null (gsi, false);
1412 if (flag_sanitize & (SANITIZE_BOOL | SANITIZE_ENUM)
1413 && gimple_assign_load_p (stmt))
1415 instrument_bool_enum_load (&gsi);
1416 bb = gimple_bb (stmt);
1419 if ((flag_sanitize & SANITIZE_NONNULL_ATTRIBUTE)
1420 && is_gimple_call (stmt)
1421 && !gimple_call_internal_p (stmt))
1423 instrument_nonnull_arg (&gsi);
1424 bb = gimple_bb (stmt);
1427 if ((flag_sanitize & SANITIZE_RETURNS_NONNULL_ATTRIBUTE)
1428 && gimple_code (stmt) == GIMPLE_RETURN)
1430 instrument_nonnull_return (&gsi);
1431 bb = gimple_bb (stmt);
1434 gsi_next (&gsi);
1437 return 0;
1440 } // anon namespace
1442 gimple_opt_pass *
1443 make_pass_ubsan (gcc::context *ctxt)
1445 return new pass_ubsan (ctxt);
1448 #include "gt-ubsan.h"