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
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
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/>. */
23 #include "coretypes.h"
25 #include "stor-layout.h"
26 #include "stringpool.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"
34 #include "gimple-iterator.h"
35 #include "gimple-ssa.h"
36 #include "gimple-walk.h"
43 #include "c-family/c-common.h"
46 #include "tree-ssanames.h"
48 #include "gimplify-me.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
;
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. */
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. */
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
,
86 /* That also means we don't have to bother with the lookup. */
90 struct tree_type_map
*h
, in
;
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. */
101 decl_for_type_insert (tree type
, tree decl
)
103 struct tree_type_map
*h
;
106 h
= ggc_alloc
<tree_type_map
> ();
109 slot
= htab_find_slot_with_hash (decl_tree_for_type
, h
, TYPE_UID (type
),
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. */
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
))
130 return fold_build1 (NOP_EXPR
, pointer_sized_int_node
, t
);
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
);
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
);
151 = assign_stack_temp_for_type (TYPE_MODE (type
),
152 GET_MODE_SIZE (TYPE_MODE (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
);
162 return build_fold_addr_expr (t
);
167 struct __ubsan_type_descriptor
169 unsigned short __typekind;
170 unsigned short __typeinfo;
176 ubsan_type_descriptor_type (void)
178 static const char *field_names
[3]
179 = { "__typekind", "__typeinfo", "__typename" };
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
;
193 DECL_CHAIN (fields
[i
- 1]) = fields
[i
];
195 TYPE_FIELDS (ret
) = fields
[0];
196 TYPE_NAME (ret
) = get_identifier ("__ubsan_type_descriptor");
201 /* Cached ubsan_get_source_location_type () return value. */
202 static GTY(()) tree ubsan_source_location_type
;
205 struct __ubsan_source_location
207 const char *__filename;
209 unsigned int __column;
214 ubsan_get_source_location_type (void)
216 static const char *field_names
[3]
217 = { "__filename", "__line", "__column" };
219 if (ubsan_source_location_type
)
220 return ubsan_source_location_type
;
222 tree const_char_type
= build_qualified_type (char_type_node
,
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
;
234 DECL_CHAIN (fields
[i
- 1]) = fields
[i
];
236 TYPE_FIELDS (ret
) = fields
[0];
237 TYPE_NAME (ret
) = get_identifier ("__ubsan_source_location");
239 ubsan_source_location_type
= ret
;
243 /* Helper routine that returns a CONSTRUCTOR of __ubsan_source_location
244 type with its fields filled from a location_t LOC. */
247 ubsan_source_location (location_t loc
)
249 expanded_location xloc
;
250 tree type
= ubsan_get_source_location_type ();
252 xloc
= expand_location (loc
);
254 if (xloc
.file
== NULL
)
256 str
= build_int_cst (ptr_type_node
, 0);
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
,
276 TREE_CONSTANT (ctor
) = 1;
277 TREE_STATIC (ctor
) = 1;
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
);
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. */
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,
317 if (decl
!= NULL_TREE
&& varpool_node::get (decl
))
318 return build_fold_addr_expr (decl
);
320 tree dtype
= ubsan_type_descriptor_type ();
322 const char *tname
= NULL
;
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
)));
359 /* We weren't able to determine the type name. */
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
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
);
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);
397 /* ??? We can't determine the variable name; print VLA unspec. */
398 pretty_name
[pos
++] = '*';
399 pretty_name
[pos
++] = ']';
402 pretty_name
[pos
++] = '\'';
403 pretty_name
[pos
] = '\0';
405 /* Save the tree with stripped types. */
409 sprintf (pretty_name
, "'%s'", tname
);
411 switch (TREE_CODE (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
))
432 tinfo
= get_ubsan_type_info_for_type (type
);
434 /* Create a new VAR_DECL of type descriptor. */
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
),
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
,
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. */
475 ubsan_create_data (const char *name
, int loccnt
, const location_t
*ploc
, ...)
480 vec
<tree
, va_gc
> *saved_args
= NULL
;
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
;
498 DECL_CHAIN (fields
[i
- 1]) = fields
[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
,
511 DECL_CONTEXT (fields
[i
]) = ret
;
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
,
524 DECL_CONTEXT (fields
[i
]) = ret
;
526 DECL_CHAIN (fields
[i
- 1]) = fields
[i
];
530 TYPE_FIELDS (ret
) = fields
[0];
531 TYPE_NAME (ret
) = get_identifier (name
);
534 /* Now, fill in the type. */
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
),
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
;
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
);
572 /* Instrument the __builtin_unreachable call. We just call the libubsan
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
,
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. */
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. */
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
,
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);
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,
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
);
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. */
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
;
680 basic_block cur_bb
= gsi_bb (gsi
);
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
,
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
);
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
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
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);
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
);
749 = ubsan_create_data ("__ubsan_null_data", 1, &loc
,
750 ubsan_type_descriptor (TREE_TYPE (ckind
),
751 UBSAN_PRINT_POINTER
),
754 fold_convert (unsigned_char_type_node
, ckind
),
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
);
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);
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
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
,
815 gimple_set_location (g
, loc
);
817 gsi_insert_after (&gsi2
, g
, GSI_NEW_STMT
);
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
);
826 gsi_insert_after (&gsi2
, g
, GSI_NEW_STMT
);
828 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
829 gsi_replace (&gsi
, g
, false);
834 /* Expand UBSAN_OBJECT_SIZE internal call. */
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
;
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
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);
873 = ubsan_create_data ("__ubsan_objsz_data", 1, &loc
,
874 ubsan_type_descriptor (TREE_TYPE (ptr
),
875 UBSAN_PRINT_POINTER
),
877 build_zero_cst (pointer_sized_int_node
),
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. */
908 instrument_mem_ref (tree mem
, tree base
, gimple_stmt_iterator
*iter
,
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
));
919 if (align
== 0 && (flag_sanitize
& SANITIZE_NULL
) == 0)
921 tree t
= TREE_OPERAND (base
, 0);
922 if (!POINTER_TYPE_P (TREE_TYPE (t
)))
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. */
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
);
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. */
953 ubsan_build_overflow_builtin (tree_code code
, location_t loc
, tree lhstype
,
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
,
962 enum built_in_function fn_code
;
967 fn_code
= flag_sanitize_recover
968 ? BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW
969 : BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW_ABORT
;
972 fn_code
= flag_sanitize_recover
973 ? BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW
974 : BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW_ABORT
;
977 fn_code
= flag_sanitize_recover
978 ? BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW
979 : BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW_ABORT
;
982 fn_code
= flag_sanitize_recover
983 ? BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW
984 : BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW_ABORT
;
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)
997 /* Perform the signed integer instrumentation. GSI is the iterator
998 pointing at statement we are trying to instrument. */
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
);
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
))
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);
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);
1047 /* Transform i = ABS_EXPR<u>;
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
);
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
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
));
1096 int modebitsize
= GET_MODE_BITSIZE (TYPE_MODE (type
));
1097 HOST_WIDE_INT bitsize
, bitpos
;
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
)
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
),
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
);
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);
1154 tree data
= ubsan_create_data ("__ubsan_invalid_value_data", 1, &loc
,
1155 ubsan_type_descriptor (type
), 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,
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. */
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. */
1204 min
= build_minus_one_cst (expr_type
);
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. */
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. */
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. */
1254 min
= build_minus_one_cst (expr_type
);
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
);
1271 if (flag_sanitize_undefined_trap_on_error
)
1272 fn
= build_call_expr_loc (loc
, builtin_decl_explicit (BUILT_IN_TRAP
), 0);
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
,
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. */
1300 instrument_nonnull_arg (gimple_stmt_iterator
*gsi
)
1302 gimple stmt
= gsi_stmt (*gsi
);
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))
1317 if (!is_gimple_val (arg
))
1319 g
= gimple_build_assign (make_ssa_name (TREE_TYPE (arg
), NULL
),
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);
1340 tree data
= ubsan_create_data ("__ubsan_nonnull_arg_data",
1342 build_int_cst (integer_type_node
,
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. */
1365 instrument_nonnull_return (gimple_stmt_iterator
*gsi
)
1367 gimple stmt
= gsi_stmt (*gsi
);
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
;
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);
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. */
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
);
1423 HOST_WIDE_INT size_in_bytes
;
1425 type
= TREE_TYPE (t
);
1426 if (VOID_TYPE_P (type
))
1429 switch (TREE_CODE (t
))
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),
1451 size_in_bytes
= int_size_in_bytes (type
);
1452 if (size_in_bytes
<= 0)
1455 HOST_WIDE_INT bitsize
, bitpos
;
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
)
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
);
1483 if (!POINTER_TYPE_P (TREE_TYPE (base
)) && !DECL_P (base
))
1487 tree base_addr
= base
;
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
);
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
,
1502 sizet
= force_gimple_operand_gsi (gsi
, sizet
, false, NULL_TREE
, true,
1508 /* Generate UBSAN_OBJECT_SIZE (ptr, ptr+sizeof(*ptr)-base, objsize, ckind)
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
))
1522 /* Nope. Emit the check. */
1523 t
= force_gimple_operand_gsi (gsi
, t
, true, NULL_TREE
, true,
1525 ptr
= force_gimple_operand_gsi (gsi
, ptr
, true, NULL_TREE
, true,
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
);
1537 const pass_data pass_data_ubsan
=
1539 GIMPLE_PASS
, /* type */
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
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
1576 pass_ubsan::execute (function
*fun
)
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
))
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);
1645 make_pass_ubsan (gcc::context
*ctxt
)
1647 return new pass_ubsan (ctxt
);
1650 #include "gt-ubsan.h"