Introduce gimple_assign and use it in various places
[official-gcc.git] / gcc / ubsan.c
blobdde0418dca305053c4a51d129cc8acac804a2a05
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
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
745 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
746 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT;
747 tree fn = builtin_decl_implicit (bcode);
748 tree data
749 = ubsan_create_data ("__ubsan_null_data", 1, &loc,
750 ubsan_type_descriptor (TREE_TYPE (ckind),
751 UBSAN_PRINT_POINTER),
752 NULL_TREE,
753 align,
754 fold_convert (unsigned_char_type_node, ckind),
755 NULL_TREE);
756 data = build_fold_addr_expr_loc (loc, data);
757 g = gimple_build_call (fn, 2, data,
758 check_align ? check_align
759 : build_zero_cst (pointer_sized_int_node));
761 gimple_stmt_iterator gsi2 = gsi_start_bb (then_bb);
762 gimple_set_location (g, loc);
763 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
765 /* Unlink the UBSAN_NULLs vops before replacing it. */
766 unlink_stmt_vdef (stmt);
768 if (check_null)
770 g = gimple_build_cond (EQ_EXPR, ptr, build_int_cst (TREE_TYPE (ptr), 0),
771 NULL_TREE, NULL_TREE);
772 gimple_set_location (g, loc);
774 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
775 gsi_replace (&gsi, g, false);
778 if (check_align)
780 if (check_null)
782 /* Split the block with the condition again. */
783 e = split_block (cond_bb, stmt);
784 basic_block cond1_bb = e->src;
785 basic_block cond2_bb = e->dest;
787 /* Make an edge coming from the 'cond1 block' into the 'then block';
788 this edge is unlikely taken, so set up the probability
789 accordingly. */
790 e = make_edge (cond1_bb, then_bb, EDGE_TRUE_VALUE);
791 e->probability = PROB_VERY_UNLIKELY;
793 /* Set up the fallthrough basic block. */
794 e = find_edge (cond1_bb, cond2_bb);
795 e->flags = EDGE_FALSE_VALUE;
796 e->count = cond1_bb->count;
797 e->probability = REG_BR_PROB_BASE - PROB_VERY_UNLIKELY;
799 /* Update dominance info. */
800 if (dom_info_available_p (CDI_DOMINATORS))
802 set_immediate_dominator (CDI_DOMINATORS, fallthru_bb, cond1_bb);
803 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond1_bb);
806 gsi2 = gsi_start_bb (cond2_bb);
809 tree mask = build_int_cst (pointer_sized_int_node,
810 tree_to_uhwi (align) - 1);
811 g = gimple_build_assign_with_ops (BIT_AND_EXPR,
812 make_ssa_name (pointer_sized_int_node,
813 NULL),
814 check_align, mask);
815 gimple_set_location (g, loc);
816 if (check_null)
817 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
818 else
819 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
821 g = gimple_build_cond (NE_EXPR, gimple_assign_lhs (g),
822 build_int_cst (pointer_sized_int_node, 0),
823 NULL_TREE, NULL_TREE);
824 gimple_set_location (g, loc);
825 if (check_null)
826 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
827 else
828 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
829 gsi_replace (&gsi, g, false);
831 return false;
834 /* Expand UBSAN_OBJECT_SIZE internal call. */
836 bool
837 ubsan_expand_objsize_ifn (gimple_stmt_iterator *gsi)
839 gimple stmt = gsi_stmt (*gsi);
840 location_t loc = gimple_location (stmt);
841 gcc_assert (gimple_call_num_args (stmt) == 4);
843 tree ptr = gimple_call_arg (stmt, 0);
844 tree offset = gimple_call_arg (stmt, 1);
845 tree size = gimple_call_arg (stmt, 2);
846 tree ckind = gimple_call_arg (stmt, 3);
847 gimple_stmt_iterator gsi_orig = *gsi;
848 gimple g;
850 /* See if we can discard the check. */
851 if (TREE_CODE (size) != INTEGER_CST
852 || integer_all_onesp (size))
853 /* Yes, __builtin_object_size couldn't determine the
854 object size. */;
855 else
857 /* if (offset > objsize) */
858 basic_block then_bb, fallthru_bb;
859 gimple_stmt_iterator cond_insert_point
860 = create_cond_insert_point (gsi, false, false, true,
861 &then_bb, &fallthru_bb);
862 g = gimple_build_cond (GT_EXPR, offset, size, NULL_TREE, NULL_TREE);
863 gimple_set_location (g, loc);
864 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
866 /* Generate __ubsan_handle_type_mismatch call. */
867 *gsi = gsi_after_labels (then_bb);
868 if (flag_sanitize_undefined_trap_on_error)
869 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
870 else
872 tree data
873 = ubsan_create_data ("__ubsan_objsz_data", 1, &loc,
874 ubsan_type_descriptor (TREE_TYPE (ptr),
875 UBSAN_PRINT_POINTER),
876 NULL_TREE,
877 build_zero_cst (pointer_sized_int_node),
878 ckind,
879 NULL_TREE);
880 data = build_fold_addr_expr_loc (loc, data);
881 enum built_in_function bcode
882 = flag_sanitize_recover
883 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
884 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT;
885 tree p = make_ssa_name (pointer_sized_int_node, NULL);
886 g = gimple_build_assign_with_ops (NOP_EXPR, p, ptr, NULL_TREE);
887 gimple_set_location (g, loc);
888 gsi_insert_before (gsi, g, GSI_SAME_STMT);
889 g = gimple_build_call (builtin_decl_explicit (bcode), 2, data, p);
891 gimple_set_location (g, loc);
892 gsi_insert_before (gsi, g, GSI_SAME_STMT);
894 /* Point GSI to next logical statement. */
895 *gsi = gsi_start_bb (fallthru_bb);
898 /* Get rid of the UBSAN_OBJECT_SIZE call from the IR. */
899 unlink_stmt_vdef (stmt);
900 gsi_remove (&gsi_orig, true);
901 return gsi_end_p (*gsi);
904 /* Instrument a memory reference. BASE is the base of MEM, IS_LHS says
905 whether the pointer is on the left hand side of the assignment. */
907 static void
908 instrument_mem_ref (tree mem, tree base, gimple_stmt_iterator *iter,
909 bool is_lhs)
911 enum ubsan_null_ckind ikind = is_lhs ? UBSAN_STORE_OF : UBSAN_LOAD_OF;
912 unsigned int align = 0;
913 if (flag_sanitize & SANITIZE_ALIGNMENT)
915 align = min_align_of_type (TREE_TYPE (base));
916 if (align <= 1)
917 align = 0;
919 if (align == 0 && (flag_sanitize & SANITIZE_NULL) == 0)
920 return;
921 tree t = TREE_OPERAND (base, 0);
922 if (!POINTER_TYPE_P (TREE_TYPE (t)))
923 return;
924 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (TREE_TYPE (t))) && mem != base)
925 ikind = UBSAN_MEMBER_ACCESS;
926 tree kind = build_int_cst (TREE_TYPE (t), ikind);
927 tree alignt = build_int_cst (pointer_sized_int_node, align);
928 gimple g = gimple_build_call_internal (IFN_UBSAN_NULL, 3, t, kind, alignt);
929 gimple_set_location (g, gimple_location (gsi_stmt (*iter)));
930 gsi_insert_before (iter, g, GSI_SAME_STMT);
933 /* Perform the pointer instrumentation. */
935 static void
936 instrument_null (gimple_stmt_iterator gsi, bool is_lhs)
938 gimple stmt = gsi_stmt (gsi);
939 tree t = is_lhs ? gimple_get_lhs (stmt) : gimple_assign_rhs1 (stmt);
940 tree base = get_base_address (t);
941 const enum tree_code code = TREE_CODE (base);
942 if (code == MEM_REF
943 && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
944 instrument_mem_ref (t, base, &gsi, is_lhs);
947 /* Build an ubsan builtin call for the signed-integer-overflow
948 sanitization. CODE says what kind of builtin are we building,
949 LOC is a location, LHSTYPE is the type of LHS, OP0 and OP1
950 are operands of the binary operation. */
952 tree
953 ubsan_build_overflow_builtin (tree_code code, location_t loc, tree lhstype,
954 tree op0, tree op1)
956 if (flag_sanitize_undefined_trap_on_error)
957 return build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
959 tree data = ubsan_create_data ("__ubsan_overflow_data", 1, &loc,
960 ubsan_type_descriptor (lhstype), NULL_TREE,
961 NULL_TREE);
962 enum built_in_function fn_code;
964 switch (code)
966 case PLUS_EXPR:
967 fn_code = flag_sanitize_recover
968 ? BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW
969 : BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW_ABORT;
970 break;
971 case MINUS_EXPR:
972 fn_code = flag_sanitize_recover
973 ? BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW
974 : BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW_ABORT;
975 break;
976 case MULT_EXPR:
977 fn_code = flag_sanitize_recover
978 ? BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW
979 : BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW_ABORT;
980 break;
981 case NEGATE_EXPR:
982 fn_code = flag_sanitize_recover
983 ? BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW
984 : BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW_ABORT;
985 break;
986 default:
987 gcc_unreachable ();
989 tree fn = builtin_decl_explicit (fn_code);
990 return build_call_expr_loc (loc, fn, 2 + (code != NEGATE_EXPR),
991 build_fold_addr_expr_loc (loc, data),
992 ubsan_encode_value (op0, true),
993 op1 ? ubsan_encode_value (op1, true)
994 : NULL_TREE);
997 /* Perform the signed integer instrumentation. GSI is the iterator
998 pointing at statement we are trying to instrument. */
1000 static void
1001 instrument_si_overflow (gimple_stmt_iterator gsi)
1003 gimple stmt = gsi_stmt (gsi);
1004 tree_code code = gimple_assign_rhs_code (stmt);
1005 tree lhs = gimple_assign_lhs (stmt);
1006 tree lhstype = TREE_TYPE (lhs);
1007 tree a, b;
1008 gimple g;
1010 /* If this is not a signed operation, don't instrument anything here.
1011 Also punt on bit-fields. */
1012 if (!INTEGRAL_TYPE_P (lhstype)
1013 || TYPE_OVERFLOW_WRAPS (lhstype)
1014 || GET_MODE_BITSIZE (TYPE_MODE (lhstype)) != TYPE_PRECISION (lhstype))
1015 return;
1017 switch (code)
1019 case MINUS_EXPR:
1020 case PLUS_EXPR:
1021 case MULT_EXPR:
1022 /* Transform
1023 i = u {+,-,*} 5;
1024 into
1025 i = UBSAN_CHECK_{ADD,SUB,MUL} (u, 5); */
1026 a = gimple_assign_rhs1 (stmt);
1027 b = gimple_assign_rhs2 (stmt);
1028 g = gimple_build_call_internal (code == PLUS_EXPR
1029 ? IFN_UBSAN_CHECK_ADD
1030 : code == MINUS_EXPR
1031 ? IFN_UBSAN_CHECK_SUB
1032 : IFN_UBSAN_CHECK_MUL, 2, a, b);
1033 gimple_call_set_lhs (g, lhs);
1034 gsi_replace (&gsi, g, false);
1035 break;
1036 case NEGATE_EXPR:
1037 /* Represent i = -u;
1039 i = UBSAN_CHECK_SUB (0, u); */
1040 a = build_int_cst (lhstype, 0);
1041 b = gimple_assign_rhs1 (stmt);
1042 g = gimple_build_call_internal (IFN_UBSAN_CHECK_SUB, 2, a, b);
1043 gimple_call_set_lhs (g, lhs);
1044 gsi_replace (&gsi, g, false);
1045 break;
1046 case ABS_EXPR:
1047 /* Transform i = ABS_EXPR<u>;
1048 into
1049 _N = UBSAN_CHECK_SUB (0, u);
1050 i = ABS_EXPR<_N>; */
1051 a = build_int_cst (lhstype, 0);
1052 b = gimple_assign_rhs1 (stmt);
1053 g = gimple_build_call_internal (IFN_UBSAN_CHECK_SUB, 2, a, b);
1054 a = make_ssa_name (lhstype, NULL);
1055 gimple_call_set_lhs (g, a);
1056 gimple_set_location (g, gimple_location (stmt));
1057 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
1058 gimple_assign_set_rhs1 (stmt, a);
1059 update_stmt (stmt);
1060 break;
1061 default:
1062 break;
1066 /* Instrument loads from (non-bitfield) bool and C++ enum values
1067 to check if the memory value is outside of the range of the valid
1068 type values. */
1070 static void
1071 instrument_bool_enum_load (gimple_stmt_iterator *gsi)
1073 gimple stmt = gsi_stmt (*gsi);
1074 tree rhs = gimple_assign_rhs1 (stmt);
1075 tree type = TREE_TYPE (rhs);
1076 tree minv = NULL_TREE, maxv = NULL_TREE;
1078 if (TREE_CODE (type) == BOOLEAN_TYPE && (flag_sanitize & SANITIZE_BOOL))
1080 minv = boolean_false_node;
1081 maxv = boolean_true_node;
1083 else if (TREE_CODE (type) == ENUMERAL_TYPE
1084 && (flag_sanitize & SANITIZE_ENUM)
1085 && TREE_TYPE (type) != NULL_TREE
1086 && TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE
1087 && (TYPE_PRECISION (TREE_TYPE (type))
1088 < GET_MODE_PRECISION (TYPE_MODE (type))))
1090 minv = TYPE_MIN_VALUE (TREE_TYPE (type));
1091 maxv = TYPE_MAX_VALUE (TREE_TYPE (type));
1093 else
1094 return;
1096 int modebitsize = GET_MODE_BITSIZE (TYPE_MODE (type));
1097 HOST_WIDE_INT bitsize, bitpos;
1098 tree offset;
1099 enum machine_mode mode;
1100 int volatilep = 0, unsignedp = 0;
1101 tree base = get_inner_reference (rhs, &bitsize, &bitpos, &offset, &mode,
1102 &unsignedp, &volatilep, false);
1103 tree utype = build_nonstandard_integer_type (modebitsize, 1);
1105 if ((TREE_CODE (base) == VAR_DECL && DECL_HARD_REGISTER (base))
1106 || (bitpos % modebitsize) != 0
1107 || bitsize != modebitsize
1108 || GET_MODE_BITSIZE (TYPE_MODE (utype)) != modebitsize
1109 || TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME)
1110 return;
1112 location_t loc = gimple_location (stmt);
1113 tree ptype = build_pointer_type (TREE_TYPE (rhs));
1114 tree atype = reference_alias_ptr_type (rhs);
1115 gimple g = gimple_build_assign (make_ssa_name (ptype, NULL),
1116 build_fold_addr_expr (rhs));
1117 gimple_set_location (g, loc);
1118 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1119 tree mem = build2 (MEM_REF, utype, gimple_assign_lhs (g),
1120 build_int_cst (atype, 0));
1121 tree urhs = make_ssa_name (utype, NULL);
1122 g = gimple_build_assign (urhs, mem);
1123 gimple_set_location (g, loc);
1124 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1125 minv = fold_convert (utype, minv);
1126 maxv = fold_convert (utype, maxv);
1127 if (!integer_zerop (minv))
1129 g = gimple_build_assign_with_ops (MINUS_EXPR,
1130 make_ssa_name (utype, NULL),
1131 urhs, minv);
1132 gimple_set_location (g, loc);
1133 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1136 gimple_stmt_iterator gsi2 = *gsi;
1137 basic_block then_bb, fallthru_bb;
1138 *gsi = create_cond_insert_point (gsi, true, false, true,
1139 &then_bb, &fallthru_bb);
1140 g = gimple_build_cond (GT_EXPR, gimple_assign_lhs (g),
1141 int_const_binop (MINUS_EXPR, maxv, minv),
1142 NULL_TREE, NULL_TREE);
1143 gimple_set_location (g, loc);
1144 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1146 gimple_assign_set_rhs_with_ops (&gsi2, NOP_EXPR, urhs, NULL_TREE);
1147 update_stmt (stmt);
1149 gsi2 = gsi_after_labels (then_bb);
1150 if (flag_sanitize_undefined_trap_on_error)
1151 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1152 else
1154 tree data = ubsan_create_data ("__ubsan_invalid_value_data", 1, &loc,
1155 ubsan_type_descriptor (type), NULL_TREE,
1156 NULL_TREE);
1157 data = build_fold_addr_expr_loc (loc, data);
1158 enum built_in_function bcode
1159 = flag_sanitize_recover
1160 ? BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE
1161 : BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE_ABORT;
1162 tree fn = builtin_decl_explicit (bcode);
1164 tree val = force_gimple_operand_gsi (&gsi2, ubsan_encode_value (urhs),
1165 true, NULL_TREE, true,
1166 GSI_SAME_STMT);
1167 g = gimple_build_call (fn, 2, data, val);
1169 gimple_set_location (g, loc);
1170 gsi_insert_before (&gsi2, g, GSI_SAME_STMT);
1171 *gsi = gsi_for_stmt (stmt);
1174 /* Instrument float point-to-integer conversion. TYPE is an integer type of
1175 destination, EXPR is floating-point expression. */
1177 tree
1178 ubsan_instrument_float_cast (location_t loc, tree type, tree expr)
1180 tree expr_type = TREE_TYPE (expr);
1181 tree t, tt, fn, min, max;
1182 enum machine_mode mode = TYPE_MODE (expr_type);
1183 int prec = TYPE_PRECISION (type);
1184 bool uns_p = TYPE_UNSIGNED (type);
1186 /* Float to integer conversion first truncates toward zero, so
1187 even signed char c = 127.875f; is not problematic.
1188 Therefore, we should complain only if EXPR is unordered or smaller
1189 or equal than TYPE_MIN_VALUE - 1.0 or greater or equal than
1190 TYPE_MAX_VALUE + 1.0. */
1191 if (REAL_MODE_FORMAT (mode)->b == 2)
1193 /* For maximum, TYPE_MAX_VALUE might not be representable
1194 in EXPR_TYPE, e.g. if TYPE is 64-bit long long and
1195 EXPR_TYPE is IEEE single float, but TYPE_MAX_VALUE + 1.0 is
1196 either representable or infinity. */
1197 REAL_VALUE_TYPE maxval = dconst1;
1198 SET_REAL_EXP (&maxval, REAL_EXP (&maxval) + prec - !uns_p);
1199 real_convert (&maxval, mode, &maxval);
1200 max = build_real (expr_type, maxval);
1202 /* For unsigned, assume -1.0 is always representable. */
1203 if (uns_p)
1204 min = build_minus_one_cst (expr_type);
1205 else
1207 /* TYPE_MIN_VALUE is generally representable (or -inf),
1208 but TYPE_MIN_VALUE - 1.0 might not be. */
1209 REAL_VALUE_TYPE minval = dconstm1, minval2;
1210 SET_REAL_EXP (&minval, REAL_EXP (&minval) + prec - 1);
1211 real_convert (&minval, mode, &minval);
1212 real_arithmetic (&minval2, MINUS_EXPR, &minval, &dconst1);
1213 real_convert (&minval2, mode, &minval2);
1214 if (real_compare (EQ_EXPR, &minval, &minval2)
1215 && !real_isinf (&minval))
1217 /* If TYPE_MIN_VALUE - 1.0 is not representable and
1218 rounds to TYPE_MIN_VALUE, we need to subtract
1219 more. As REAL_MODE_FORMAT (mode)->p is the number
1220 of base digits, we want to subtract a number that
1221 will be 1 << (REAL_MODE_FORMAT (mode)->p - 1)
1222 times smaller than minval. */
1223 minval2 = dconst1;
1224 gcc_assert (prec > REAL_MODE_FORMAT (mode)->p);
1225 SET_REAL_EXP (&minval2,
1226 REAL_EXP (&minval2) + prec - 1
1227 - REAL_MODE_FORMAT (mode)->p + 1);
1228 real_arithmetic (&minval2, MINUS_EXPR, &minval, &minval2);
1229 real_convert (&minval2, mode, &minval2);
1231 min = build_real (expr_type, minval2);
1234 else if (REAL_MODE_FORMAT (mode)->b == 10)
1236 /* For _Decimal128 up to 34 decimal digits, - sign,
1237 dot, e, exponent. */
1238 char buf[64];
1239 mpfr_t m;
1240 int p = REAL_MODE_FORMAT (mode)->p;
1241 REAL_VALUE_TYPE maxval, minval;
1243 /* Use mpfr_snprintf rounding to compute the smallest
1244 representable decimal number greater or equal than
1245 1 << (prec - !uns_p). */
1246 mpfr_init2 (m, prec + 2);
1247 mpfr_set_ui_2exp (m, 1, prec - !uns_p, GMP_RNDN);
1248 mpfr_snprintf (buf, sizeof buf, "%.*RUe", p - 1, m);
1249 decimal_real_from_string (&maxval, buf);
1250 max = build_real (expr_type, maxval);
1252 /* For unsigned, assume -1.0 is always representable. */
1253 if (uns_p)
1254 min = build_minus_one_cst (expr_type);
1255 else
1257 /* Use mpfr_snprintf rounding to compute the largest
1258 representable decimal number less or equal than
1259 (-1 << (prec - 1)) - 1. */
1260 mpfr_set_si_2exp (m, -1, prec - 1, GMP_RNDN);
1261 mpfr_sub_ui (m, m, 1, GMP_RNDN);
1262 mpfr_snprintf (buf, sizeof buf, "%.*RDe", p - 1, m);
1263 decimal_real_from_string (&minval, buf);
1264 min = build_real (expr_type, minval);
1266 mpfr_clear (m);
1268 else
1269 return NULL_TREE;
1271 if (flag_sanitize_undefined_trap_on_error)
1272 fn = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
1273 else
1275 /* Create the __ubsan_handle_float_cast_overflow fn call. */
1276 tree data = ubsan_create_data ("__ubsan_float_cast_overflow_data", 0,
1277 NULL, ubsan_type_descriptor (expr_type),
1278 ubsan_type_descriptor (type), NULL_TREE,
1279 NULL_TREE);
1280 enum built_in_function bcode
1281 = flag_sanitize_recover
1282 ? BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW
1283 : BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW_ABORT;
1284 fn = builtin_decl_explicit (bcode);
1285 fn = build_call_expr_loc (loc, fn, 2,
1286 build_fold_addr_expr_loc (loc, data),
1287 ubsan_encode_value (expr, false));
1290 t = fold_build2 (UNLE_EXPR, boolean_type_node, expr, min);
1291 tt = fold_build2 (UNGE_EXPR, boolean_type_node, expr, max);
1292 return fold_build3 (COND_EXPR, void_type_node,
1293 fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t, tt),
1294 fn, integer_zero_node);
1297 /* Instrument values passed to function arguments with nonnull attribute. */
1299 static void
1300 instrument_nonnull_arg (gimple_stmt_iterator *gsi)
1302 gimple stmt = gsi_stmt (*gsi);
1303 location_t loc[2];
1304 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
1305 while for nonnull sanitization it is clear. */
1306 int save_flag_delete_null_pointer_checks = flag_delete_null_pointer_checks;
1307 flag_delete_null_pointer_checks = 1;
1308 loc[0] = gimple_location (stmt);
1309 loc[1] = UNKNOWN_LOCATION;
1310 for (unsigned int i = 0; i < gimple_call_num_args (stmt); i++)
1312 tree arg = gimple_call_arg (stmt, i);
1313 if (POINTER_TYPE_P (TREE_TYPE (arg))
1314 && infer_nonnull_range (stmt, arg, false, true))
1316 gimple g;
1317 if (!is_gimple_val (arg))
1319 g = gimple_build_assign (make_ssa_name (TREE_TYPE (arg), NULL),
1320 arg);
1321 gimple_set_location (g, loc[0]);
1322 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1323 arg = gimple_assign_lhs (g);
1326 basic_block then_bb, fallthru_bb;
1327 *gsi = create_cond_insert_point (gsi, true, false, true,
1328 &then_bb, &fallthru_bb);
1329 g = gimple_build_cond (EQ_EXPR, arg,
1330 build_zero_cst (TREE_TYPE (arg)),
1331 NULL_TREE, NULL_TREE);
1332 gimple_set_location (g, loc[0]);
1333 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1335 *gsi = gsi_after_labels (then_bb);
1336 if (flag_sanitize_undefined_trap_on_error)
1337 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1338 else
1340 tree data = ubsan_create_data ("__ubsan_nonnull_arg_data",
1341 2, loc, NULL_TREE,
1342 build_int_cst (integer_type_node,
1343 i + 1),
1344 NULL_TREE);
1345 data = build_fold_addr_expr_loc (loc[0], data);
1346 enum built_in_function bcode
1347 = flag_sanitize_recover
1348 ? BUILT_IN_UBSAN_HANDLE_NONNULL_ARG
1349 : BUILT_IN_UBSAN_HANDLE_NONNULL_ARG_ABORT;
1350 tree fn = builtin_decl_explicit (bcode);
1352 g = gimple_build_call (fn, 1, data);
1354 gimple_set_location (g, loc[0]);
1355 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1357 *gsi = gsi_for_stmt (stmt);
1359 flag_delete_null_pointer_checks = save_flag_delete_null_pointer_checks;
1362 /* Instrument returns in functions with returns_nonnull attribute. */
1364 static void
1365 instrument_nonnull_return (gimple_stmt_iterator *gsi)
1367 gimple stmt = gsi_stmt (*gsi);
1368 location_t loc[2];
1369 tree arg = gimple_return_retval (stmt);
1370 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
1371 while for nonnull return sanitization it is clear. */
1372 int save_flag_delete_null_pointer_checks = flag_delete_null_pointer_checks;
1373 flag_delete_null_pointer_checks = 1;
1374 loc[0] = gimple_location (stmt);
1375 loc[1] = UNKNOWN_LOCATION;
1376 if (arg
1377 && POINTER_TYPE_P (TREE_TYPE (arg))
1378 && is_gimple_val (arg)
1379 && infer_nonnull_range (stmt, arg, false, true))
1381 basic_block then_bb, fallthru_bb;
1382 *gsi = create_cond_insert_point (gsi, true, false, true,
1383 &then_bb, &fallthru_bb);
1384 gimple g = gimple_build_cond (EQ_EXPR, arg,
1385 build_zero_cst (TREE_TYPE (arg)),
1386 NULL_TREE, NULL_TREE);
1387 gimple_set_location (g, loc[0]);
1388 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1390 *gsi = gsi_after_labels (then_bb);
1391 if (flag_sanitize_undefined_trap_on_error)
1392 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1393 else
1395 tree data = ubsan_create_data ("__ubsan_nonnull_return_data",
1396 2, loc, NULL_TREE, NULL_TREE);
1397 data = build_fold_addr_expr_loc (loc[0], data);
1398 enum built_in_function bcode
1399 = flag_sanitize_recover
1400 ? BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN
1401 : BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_ABORT;
1402 tree fn = builtin_decl_explicit (bcode);
1404 g = gimple_build_call (fn, 1, data);
1406 gimple_set_location (g, loc[0]);
1407 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1408 *gsi = gsi_for_stmt (stmt);
1410 flag_delete_null_pointer_checks = save_flag_delete_null_pointer_checks;
1413 /* Instrument memory references. Here we check whether the pointer
1414 points to an out-of-bounds location. */
1416 static void
1417 instrument_object_size (gimple_stmt_iterator *gsi, bool is_lhs)
1419 gimple stmt = gsi_stmt (*gsi);
1420 location_t loc = gimple_location (stmt);
1421 tree t = is_lhs ? gimple_get_lhs (stmt) : gimple_assign_rhs1 (stmt);
1422 tree type;
1423 HOST_WIDE_INT size_in_bytes;
1425 type = TREE_TYPE (t);
1426 if (VOID_TYPE_P (type))
1427 return;
1429 switch (TREE_CODE (t))
1431 case COMPONENT_REF:
1432 if (TREE_CODE (t) == COMPONENT_REF
1433 && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1)) != NULL_TREE)
1435 tree repr = DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1));
1436 t = build3 (COMPONENT_REF, TREE_TYPE (repr), TREE_OPERAND (t, 0),
1437 repr, NULL_TREE);
1439 break;
1440 case ARRAY_REF:
1441 case INDIRECT_REF:
1442 case MEM_REF:
1443 case VAR_DECL:
1444 case PARM_DECL:
1445 case RESULT_DECL:
1446 break;
1447 default:
1448 return;
1451 size_in_bytes = int_size_in_bytes (type);
1452 if (size_in_bytes <= 0)
1453 return;
1455 HOST_WIDE_INT bitsize, bitpos;
1456 tree offset;
1457 enum machine_mode mode;
1458 int volatilep = 0, unsignedp = 0;
1459 tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset, &mode,
1460 &unsignedp, &volatilep, false);
1462 if (bitpos % BITS_PER_UNIT != 0
1463 || bitsize != size_in_bytes * BITS_PER_UNIT)
1464 return;
1466 bool decl_p = DECL_P (inner);
1467 tree base = decl_p ? inner : TREE_OPERAND (inner, 0);
1468 tree ptr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (t)), t);
1470 while (TREE_CODE (base) == SSA_NAME)
1472 gimple def_stmt = SSA_NAME_DEF_STMT (base);
1473 if (gimple_assign_ssa_name_copy_p (def_stmt)
1474 || (gimple_assign_cast_p (def_stmt)
1475 && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (def_stmt))))
1476 || (is_gimple_assign (def_stmt)
1477 && gimple_assign_rhs_code (def_stmt) == POINTER_PLUS_EXPR))
1478 base = gimple_assign_rhs1 (def_stmt);
1479 else
1480 break;
1483 if (!POINTER_TYPE_P (TREE_TYPE (base)) && !DECL_P (base))
1484 return;
1486 tree sizet;
1487 tree base_addr = base;
1488 if (decl_p)
1489 base_addr = build1 (ADDR_EXPR,
1490 build_pointer_type (TREE_TYPE (base)), base);
1491 unsigned HOST_WIDE_INT size = compute_builtin_object_size (base_addr, 0);
1492 if (size != (unsigned HOST_WIDE_INT) -1)
1493 sizet = build_int_cst (sizetype, size);
1494 else if (optimize)
1496 if (LOCATION_LOCUS (loc) == UNKNOWN_LOCATION)
1497 loc = input_location;
1498 /* Generate __builtin_object_size call. */
1499 sizet = builtin_decl_explicit (BUILT_IN_OBJECT_SIZE);
1500 sizet = build_call_expr_loc (loc, sizet, 2, base_addr,
1501 integer_zero_node);
1502 sizet = force_gimple_operand_gsi (gsi, sizet, false, NULL_TREE, true,
1503 GSI_SAME_STMT);
1505 else
1506 return;
1508 /* Generate UBSAN_OBJECT_SIZE (ptr, ptr+sizeof(*ptr)-base, objsize, ckind)
1509 call. */
1510 /* ptr + sizeof (*ptr) - base */
1511 t = fold_build2 (MINUS_EXPR, sizetype,
1512 fold_convert (pointer_sized_int_node, ptr),
1513 fold_convert (pointer_sized_int_node, base_addr));
1514 t = fold_build2 (PLUS_EXPR, sizetype, t, TYPE_SIZE_UNIT (type));
1516 /* Perhaps we can omit the check. */
1517 if (TREE_CODE (t) == INTEGER_CST
1518 && TREE_CODE (sizet) == INTEGER_CST
1519 && tree_int_cst_le (t, sizet))
1520 return;
1522 /* Nope. Emit the check. */
1523 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE, true,
1524 GSI_SAME_STMT);
1525 ptr = force_gimple_operand_gsi (gsi, ptr, true, NULL_TREE, true,
1526 GSI_SAME_STMT);
1527 tree ckind = build_int_cst (unsigned_char_type_node,
1528 is_lhs ? UBSAN_STORE_OF : UBSAN_LOAD_OF);
1529 gimple g = gimple_build_call_internal (IFN_UBSAN_OBJECT_SIZE, 4,
1530 ptr, t, sizet, ckind);
1531 gimple_set_location (g, loc);
1532 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1535 namespace {
1537 const pass_data pass_data_ubsan =
1539 GIMPLE_PASS, /* type */
1540 "ubsan", /* name */
1541 OPTGROUP_NONE, /* optinfo_flags */
1542 TV_TREE_UBSAN, /* tv_id */
1543 ( PROP_cfg | PROP_ssa ), /* properties_required */
1544 0, /* properties_provided */
1545 0, /* properties_destroyed */
1546 0, /* todo_flags_start */
1547 TODO_update_ssa, /* todo_flags_finish */
1550 class pass_ubsan : public gimple_opt_pass
1552 public:
1553 pass_ubsan (gcc::context *ctxt)
1554 : gimple_opt_pass (pass_data_ubsan, ctxt)
1557 /* opt_pass methods: */
1558 virtual bool gate (function *)
1560 return flag_sanitize & (SANITIZE_NULL | SANITIZE_SI_OVERFLOW
1561 | SANITIZE_BOOL | SANITIZE_ENUM
1562 | SANITIZE_ALIGNMENT
1563 | SANITIZE_NONNULL_ATTRIBUTE
1564 | SANITIZE_RETURNS_NONNULL_ATTRIBUTE
1565 | SANITIZE_OBJECT_SIZE)
1566 && current_function_decl != NULL_TREE
1567 && !lookup_attribute ("no_sanitize_undefined",
1568 DECL_ATTRIBUTES (current_function_decl));
1571 virtual unsigned int execute (function *);
1573 }; // class pass_ubsan
1575 unsigned int
1576 pass_ubsan::execute (function *fun)
1578 basic_block bb;
1579 gimple_stmt_iterator gsi;
1581 initialize_sanitizer_builtins ();
1583 FOR_EACH_BB_FN (bb, fun)
1585 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
1587 gimple stmt = gsi_stmt (gsi);
1588 if (is_gimple_debug (stmt) || gimple_clobber_p (stmt))
1590 gsi_next (&gsi);
1591 continue;
1594 if ((flag_sanitize & SANITIZE_SI_OVERFLOW)
1595 && is_gimple_assign (stmt))
1596 instrument_si_overflow (gsi);
1598 if (flag_sanitize & (SANITIZE_NULL | SANITIZE_ALIGNMENT))
1600 if (gimple_store_p (stmt))
1601 instrument_null (gsi, true);
1602 if (gimple_assign_load_p (stmt))
1603 instrument_null (gsi, false);
1606 if (flag_sanitize & (SANITIZE_BOOL | SANITIZE_ENUM)
1607 && gimple_assign_load_p (stmt))
1609 instrument_bool_enum_load (&gsi);
1610 bb = gimple_bb (stmt);
1613 if ((flag_sanitize & SANITIZE_NONNULL_ATTRIBUTE)
1614 && is_gimple_call (stmt)
1615 && !gimple_call_internal_p (stmt))
1617 instrument_nonnull_arg (&gsi);
1618 bb = gimple_bb (stmt);
1621 if ((flag_sanitize & SANITIZE_RETURNS_NONNULL_ATTRIBUTE)
1622 && gimple_code (stmt) == GIMPLE_RETURN)
1624 instrument_nonnull_return (&gsi);
1625 bb = gimple_bb (stmt);
1628 if (flag_sanitize & SANITIZE_OBJECT_SIZE)
1630 if (gimple_store_p (stmt))
1631 instrument_object_size (&gsi, true);
1632 if (gimple_assign_load_p (stmt))
1633 instrument_object_size (&gsi, false);
1636 gsi_next (&gsi);
1639 return 0;
1642 } // anon namespace
1644 gimple_opt_pass *
1645 make_pass_ubsan (gcc::context *ctxt)
1647 return new pass_ubsan (ctxt);
1650 #include "gt-ubsan.h"