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 "dominance.h"
31 #include "basic-block.h"
34 #include "plugin-api.h"
40 #include "hard-reg-set.h"
45 #include "tree-pass.h"
46 #include "tree-ssa-alias.h"
47 #include "tree-pretty-print.h"
48 #include "internal-fn.h"
49 #include "gimple-expr.h"
51 #include "gimple-iterator.h"
52 #include "gimple-ssa.h"
53 #include "gimple-walk.h"
59 #include "c-family/c-common.h"
62 #include "tree-ssanames.h"
64 #include "gimplify-me.h"
69 #include "tree-object-size.h"
71 /* Map from a tree to a VAR_DECL tree. */
73 struct GTY(()) tree_type_map
{
74 struct tree_map_base type
;
78 #define tree_type_map_eq tree_map_base_eq
79 #define tree_type_map_marked_p tree_map_base_marked_p
81 /* Hash from a tree in a tree_type_map. */
84 tree_type_map_hash (const void *item
)
86 return TYPE_UID (((const struct tree_type_map
*)item
)->type
.from
);
89 static GTY ((if_marked ("tree_type_map_marked_p"), param_is (struct tree_type_map
)))
90 htab_t decl_tree_for_type
;
92 /* Lookup a VAR_DECL for TYPE, and return it if we find one. */
95 decl_for_type_lookup (tree type
)
97 /* If the hash table is not initialized yet, create it now. */
98 if (decl_tree_for_type
== NULL
)
100 decl_tree_for_type
= htab_create_ggc (10, tree_type_map_hash
,
101 tree_type_map_eq
, 0);
102 /* That also means we don't have to bother with the lookup. */
106 struct tree_type_map
*h
, in
;
109 h
= (struct tree_type_map
*)
110 htab_find_with_hash (decl_tree_for_type
, &in
, TYPE_UID (type
));
111 return h
? h
->decl
: NULL_TREE
;
114 /* Insert a mapping TYPE->DECL in the VAR_DECL for type hashtable. */
117 decl_for_type_insert (tree type
, tree decl
)
119 struct tree_type_map
*h
;
122 h
= ggc_alloc
<tree_type_map
> ();
125 slot
= htab_find_slot_with_hash (decl_tree_for_type
, h
, TYPE_UID (type
),
127 *(struct tree_type_map
**) slot
= h
;
130 /* Helper routine, which encodes a value in the pointer_sized_int_node.
131 Arguments with precision <= POINTER_SIZE are passed directly,
132 the rest is passed by reference. T is a value we are to encode.
133 IN_EXPAND_P is true if this function is called during expansion. */
136 ubsan_encode_value (tree t
, bool in_expand_p
)
138 tree type
= TREE_TYPE (t
);
139 const unsigned int bitsize
= GET_MODE_BITSIZE (TYPE_MODE (type
));
140 if (bitsize
<= POINTER_SIZE
)
141 switch (TREE_CODE (type
))
146 return fold_build1 (NOP_EXPR
, pointer_sized_int_node
, t
);
149 tree itype
= build_nonstandard_integer_type (bitsize
, true);
150 t
= fold_build1 (VIEW_CONVERT_EXPR
, itype
, t
);
151 return fold_convert (pointer_sized_int_node
, t
);
158 if (!DECL_P (t
) || !TREE_ADDRESSABLE (t
))
160 /* The reason for this is that we don't want to pessimize
161 code by making vars unnecessarily addressable. */
162 tree var
= create_tmp_var (type
, NULL
);
163 tree tem
= build2 (MODIFY_EXPR
, void_type_node
, var
, t
);
167 = assign_stack_temp_for_type (TYPE_MODE (type
),
168 GET_MODE_SIZE (TYPE_MODE (type
)),
170 SET_DECL_RTL (var
, mem
);
171 expand_assignment (var
, t
, false);
172 return build_fold_addr_expr (var
);
174 t
= build_fold_addr_expr (var
);
175 return build2 (COMPOUND_EXPR
, TREE_TYPE (t
), tem
, t
);
178 return build_fold_addr_expr (t
);
183 struct __ubsan_type_descriptor
185 unsigned short __typekind;
186 unsigned short __typeinfo;
192 ubsan_type_descriptor_type (void)
194 static const char *field_names
[3]
195 = { "__typekind", "__typeinfo", "__typename" };
197 tree itype
= build_range_type (sizetype
, size_zero_node
, NULL_TREE
);
198 tree flex_arr_type
= build_array_type (char_type_node
, itype
);
200 ret
= make_node (RECORD_TYPE
);
201 for (int i
= 0; i
< 3; i
++)
203 fields
[i
] = build_decl (UNKNOWN_LOCATION
, FIELD_DECL
,
204 get_identifier (field_names
[i
]),
205 (i
== 2) ? flex_arr_type
206 : short_unsigned_type_node
);
207 DECL_CONTEXT (fields
[i
]) = ret
;
209 DECL_CHAIN (fields
[i
- 1]) = fields
[i
];
211 TYPE_FIELDS (ret
) = fields
[0];
212 TYPE_NAME (ret
) = get_identifier ("__ubsan_type_descriptor");
217 /* Cached ubsan_get_source_location_type () return value. */
218 static GTY(()) tree ubsan_source_location_type
;
221 struct __ubsan_source_location
223 const char *__filename;
225 unsigned int __column;
230 ubsan_get_source_location_type (void)
232 static const char *field_names
[3]
233 = { "__filename", "__line", "__column" };
235 if (ubsan_source_location_type
)
236 return ubsan_source_location_type
;
238 tree const_char_type
= build_qualified_type (char_type_node
,
241 ret
= make_node (RECORD_TYPE
);
242 for (int i
= 0; i
< 3; i
++)
244 fields
[i
] = build_decl (UNKNOWN_LOCATION
, FIELD_DECL
,
245 get_identifier (field_names
[i
]),
246 (i
== 0) ? build_pointer_type (const_char_type
)
247 : unsigned_type_node
);
248 DECL_CONTEXT (fields
[i
]) = ret
;
250 DECL_CHAIN (fields
[i
- 1]) = fields
[i
];
252 TYPE_FIELDS (ret
) = fields
[0];
253 TYPE_NAME (ret
) = get_identifier ("__ubsan_source_location");
255 ubsan_source_location_type
= ret
;
259 /* Helper routine that returns a CONSTRUCTOR of __ubsan_source_location
260 type with its fields filled from a location_t LOC. */
263 ubsan_source_location (location_t loc
)
265 expanded_location xloc
;
266 tree type
= ubsan_get_source_location_type ();
268 xloc
= expand_location (loc
);
270 if (xloc
.file
== NULL
)
272 str
= build_int_cst (ptr_type_node
, 0);
278 /* Fill in the values from LOC. */
279 size_t len
= strlen (xloc
.file
);
280 str
= build_string (len
+ 1, xloc
.file
);
281 TREE_TYPE (str
) = build_array_type (char_type_node
,
282 build_index_type (size_int (len
)));
283 TREE_READONLY (str
) = 1;
284 TREE_STATIC (str
) = 1;
285 str
= build_fold_addr_expr (str
);
287 tree ctor
= build_constructor_va (type
, 3, NULL_TREE
, str
, NULL_TREE
,
288 build_int_cst (unsigned_type_node
,
289 xloc
.line
), NULL_TREE
,
290 build_int_cst (unsigned_type_node
,
292 TREE_CONSTANT (ctor
) = 1;
293 TREE_STATIC (ctor
) = 1;
298 /* This routine returns a magic number for TYPE. */
300 static unsigned short
301 get_ubsan_type_info_for_type (tree type
)
303 gcc_assert (TYPE_SIZE (type
) && tree_fits_uhwi_p (TYPE_SIZE (type
)));
304 if (TREE_CODE (type
) == REAL_TYPE
)
305 return tree_to_uhwi (TYPE_SIZE (type
));
306 else if (INTEGRAL_TYPE_P (type
))
308 int prec
= exact_log2 (tree_to_uhwi (TYPE_SIZE (type
)));
309 gcc_assert (prec
!= -1);
310 return (prec
<< 1) | !TYPE_UNSIGNED (type
);
316 /* Helper routine that returns ADDR_EXPR of a VAR_DECL of a type
317 descriptor. It first looks into the hash table; if not found,
318 create the VAR_DECL, put it into the hash table and return the
319 ADDR_EXPR of it. TYPE describes a particular type. PSTYLE is
320 an enum controlling how we want to print the type. */
323 ubsan_type_descriptor (tree type
, enum ubsan_print_style pstyle
)
325 /* See through any typedefs. */
326 type
= TYPE_MAIN_VARIANT (type
);
328 tree decl
= decl_for_type_lookup (type
);
329 /* It is possible that some of the earlier created DECLs were found
330 unused, in that case they weren't emitted and varpool_node::get
331 returns NULL node on them. But now we really need them. Thus,
333 if (decl
!= NULL_TREE
&& varpool_node::get (decl
))
334 return build_fold_addr_expr (decl
);
336 tree dtype
= ubsan_type_descriptor_type ();
338 const char *tname
= NULL
;
340 unsigned char deref_depth
= 0;
341 unsigned short tkind
, tinfo
;
343 /* Get the name of the type, or the name of the pointer type. */
344 if (pstyle
== UBSAN_PRINT_POINTER
)
346 gcc_assert (POINTER_TYPE_P (type
));
347 type2
= TREE_TYPE (type
);
349 /* Remove any '*' operators from TYPE. */
350 while (POINTER_TYPE_P (type2
))
351 deref_depth
++, type2
= TREE_TYPE (type2
);
353 if (TREE_CODE (type2
) == METHOD_TYPE
)
354 type2
= TYPE_METHOD_BASETYPE (type2
);
357 /* If an array, get its type. */
358 type2
= strip_array_types (type2
);
360 if (pstyle
== UBSAN_PRINT_ARRAY
)
362 while (POINTER_TYPE_P (type2
))
363 deref_depth
++, type2
= TREE_TYPE (type2
);
366 if (TYPE_NAME (type2
) != NULL
)
368 if (TREE_CODE (TYPE_NAME (type2
)) == IDENTIFIER_NODE
)
369 tname
= IDENTIFIER_POINTER (TYPE_NAME (type2
));
370 else if (DECL_NAME (TYPE_NAME (type2
)) != NULL
)
371 tname
= IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type2
)));
375 /* We weren't able to determine the type name. */
378 /* Decorate the type name with '', '*', "struct", or "union". */
379 pretty_name
= (char *) alloca (strlen (tname
) + 16 + deref_depth
);
380 if (pstyle
== UBSAN_PRINT_POINTER
)
382 int pos
= sprintf (pretty_name
, "'%s%s%s%s%s%s%s",
383 TYPE_VOLATILE (type2
) ? "volatile " : "",
384 TYPE_READONLY (type2
) ? "const " : "",
385 TYPE_RESTRICT (type2
) ? "restrict " : "",
386 TYPE_ATOMIC (type2
) ? "_Atomic " : "",
387 TREE_CODE (type2
) == RECORD_TYPE
389 : TREE_CODE (type2
) == UNION_TYPE
390 ? "union " : "", tname
,
391 deref_depth
== 0 ? "" : " ");
392 while (deref_depth
-- > 0)
393 pretty_name
[pos
++] = '*';
394 pretty_name
[pos
++] = '\'';
395 pretty_name
[pos
] = '\0';
397 else if (pstyle
== UBSAN_PRINT_ARRAY
)
399 /* Pretty print the array dimensions. */
400 gcc_assert (TREE_CODE (type
) == ARRAY_TYPE
);
402 int pos
= sprintf (pretty_name
, "'%s ", tname
);
403 while (deref_depth
-- > 0)
404 pretty_name
[pos
++] = '*';
405 while (TREE_CODE (t
) == ARRAY_TYPE
)
407 pretty_name
[pos
++] = '[';
408 tree dom
= TYPE_DOMAIN (t
);
409 if (dom
&& TREE_CODE (TYPE_MAX_VALUE (dom
)) == INTEGER_CST
)
410 pos
+= sprintf (&pretty_name
[pos
], HOST_WIDE_INT_PRINT_DEC
,
411 tree_to_uhwi (TYPE_MAX_VALUE (dom
)) + 1);
413 /* ??? We can't determine the variable name; print VLA unspec. */
414 pretty_name
[pos
++] = '*';
415 pretty_name
[pos
++] = ']';
418 pretty_name
[pos
++] = '\'';
419 pretty_name
[pos
] = '\0';
421 /* Save the tree with stripped types. */
425 sprintf (pretty_name
, "'%s'", tname
);
427 switch (TREE_CODE (type
))
435 /* FIXME: libubsan right now only supports float, double and
436 long double type formats. */
437 if (TYPE_MODE (type
) == TYPE_MODE (float_type_node
)
438 || TYPE_MODE (type
) == TYPE_MODE (double_type_node
)
439 || TYPE_MODE (type
) == TYPE_MODE (long_double_type_node
))
448 tinfo
= get_ubsan_type_info_for_type (type
);
450 /* Create a new VAR_DECL of type descriptor. */
452 static unsigned int type_var_id_num
;
453 ASM_GENERATE_INTERNAL_LABEL (tmp_name
, "Lubsan_type", type_var_id_num
++);
454 decl
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
, get_identifier (tmp_name
),
456 TREE_STATIC (decl
) = 1;
457 TREE_PUBLIC (decl
) = 0;
458 DECL_ARTIFICIAL (decl
) = 1;
459 DECL_IGNORED_P (decl
) = 1;
460 DECL_EXTERNAL (decl
) = 0;
462 size_t len
= strlen (pretty_name
);
463 tree str
= build_string (len
+ 1, pretty_name
);
464 TREE_TYPE (str
) = build_array_type (char_type_node
,
465 build_index_type (size_int (len
)));
466 TREE_READONLY (str
) = 1;
467 TREE_STATIC (str
) = 1;
468 tree ctor
= build_constructor_va (dtype
, 3, NULL_TREE
,
469 build_int_cst (short_unsigned_type_node
,
471 build_int_cst (short_unsigned_type_node
,
472 tinfo
), NULL_TREE
, str
);
473 TREE_CONSTANT (ctor
) = 1;
474 TREE_STATIC (ctor
) = 1;
475 DECL_INITIAL (decl
) = ctor
;
476 varpool_node::finalize_decl (decl
);
478 /* Save the VAR_DECL into the hash table. */
479 decl_for_type_insert (type
, decl
);
481 return build_fold_addr_expr (decl
);
484 /* Create a structure for the ubsan library. NAME is a name of the new
485 structure. LOCCNT is number of locations, PLOC points to array of
486 locations. The arguments in ... are of __ubsan_type_descriptor type
487 and there are at most two of them, followed by NULL_TREE, followed
488 by optional extra arguments and another NULL_TREE. */
491 ubsan_create_data (const char *name
, int loccnt
, const location_t
*ploc
, ...)
496 vec
<tree
, va_gc
> *saved_args
= NULL
;
500 /* Firstly, create a pointer to type descriptor type. */
501 tree td_type
= ubsan_type_descriptor_type ();
502 TYPE_READONLY (td_type
) = 1;
503 td_type
= build_pointer_type (td_type
);
505 /* Create the structure type. */
506 ret
= make_node (RECORD_TYPE
);
507 for (j
= 0; j
< loccnt
; j
++)
509 gcc_checking_assert (i
< 2);
510 fields
[i
] = build_decl (UNKNOWN_LOCATION
, FIELD_DECL
, NULL_TREE
,
511 ubsan_get_source_location_type ());
512 DECL_CONTEXT (fields
[i
]) = ret
;
514 DECL_CHAIN (fields
[i
- 1]) = fields
[i
];
518 va_start (args
, ploc
);
519 for (t
= va_arg (args
, tree
); t
!= NULL_TREE
;
520 i
++, t
= va_arg (args
, tree
))
522 gcc_checking_assert (i
< 4);
523 /* Save the tree arguments for later use. */
524 vec_safe_push (saved_args
, t
);
525 fields
[i
] = build_decl (UNKNOWN_LOCATION
, FIELD_DECL
, NULL_TREE
,
527 DECL_CONTEXT (fields
[i
]) = ret
;
529 DECL_CHAIN (fields
[i
- 1]) = fields
[i
];
532 for (t
= va_arg (args
, tree
); t
!= NULL_TREE
;
533 i
++, t
= va_arg (args
, tree
))
535 gcc_checking_assert (i
< 6);
536 /* Save the tree arguments for later use. */
537 vec_safe_push (saved_args
, t
);
538 fields
[i
] = build_decl (UNKNOWN_LOCATION
, FIELD_DECL
, NULL_TREE
,
540 DECL_CONTEXT (fields
[i
]) = ret
;
542 DECL_CHAIN (fields
[i
- 1]) = fields
[i
];
546 TYPE_FIELDS (ret
) = fields
[0];
547 TYPE_NAME (ret
) = get_identifier (name
);
550 /* Now, fill in the type. */
552 static unsigned int ubsan_var_id_num
;
553 ASM_GENERATE_INTERNAL_LABEL (tmp_name
, "Lubsan_data", ubsan_var_id_num
++);
554 tree var
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
, get_identifier (tmp_name
),
556 TREE_STATIC (var
) = 1;
557 TREE_PUBLIC (var
) = 0;
558 DECL_ARTIFICIAL (var
) = 1;
559 DECL_IGNORED_P (var
) = 1;
560 DECL_EXTERNAL (var
) = 0;
562 vec
<constructor_elt
, va_gc
> *v
;
564 tree ctor
= build_constructor (ret
, v
);
566 /* If desirable, set the __ubsan_source_location element. */
567 for (j
= 0; j
< loccnt
; j
++)
569 location_t loc
= LOCATION_LOCUS (ploc
[j
]);
570 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, ubsan_source_location (loc
));
573 size_t nelts
= vec_safe_length (saved_args
);
574 for (i
= 0; i
< nelts
; i
++)
576 t
= (*saved_args
)[i
];
577 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, t
);
580 TREE_CONSTANT (ctor
) = 1;
581 TREE_STATIC (ctor
) = 1;
582 DECL_INITIAL (var
) = ctor
;
583 varpool_node::finalize_decl (var
);
588 /* Instrument the __builtin_unreachable call. We just call the libubsan
592 ubsan_instrument_unreachable (gimple_stmt_iterator
*gsi
)
595 location_t loc
= gimple_location (gsi_stmt (*gsi
));
597 if (flag_sanitize_undefined_trap_on_error
)
598 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
601 tree data
= ubsan_create_data ("__ubsan_unreachable_data", 1, &loc
,
602 NULL_TREE
, NULL_TREE
);
603 data
= build_fold_addr_expr_loc (loc
, data
);
605 = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE
);
606 g
= gimple_build_call (fn
, 1, data
);
608 gimple_set_location (g
, loc
);
609 gsi_replace (gsi
, g
, false);
613 /* Return true if T is a call to a libubsan routine. */
616 is_ubsan_builtin_p (tree t
)
618 return TREE_CODE (t
) == FUNCTION_DECL
619 && strncmp (IDENTIFIER_POINTER (DECL_NAME (t
)),
620 "__builtin___ubsan_", 18) == 0;
623 /* Expand the UBSAN_BOUNDS special builtin function. */
626 ubsan_expand_bounds_ifn (gimple_stmt_iterator
*gsi
)
628 gimple stmt
= gsi_stmt (*gsi
);
629 location_t loc
= gimple_location (stmt
);
630 gcc_assert (gimple_call_num_args (stmt
) == 3);
632 /* Pick up the arguments of the UBSAN_BOUNDS call. */
633 tree type
= TREE_TYPE (TREE_TYPE (gimple_call_arg (stmt
, 0)));
634 tree index
= gimple_call_arg (stmt
, 1);
635 tree orig_index_type
= TREE_TYPE (index
);
636 tree bound
= gimple_call_arg (stmt
, 2);
638 gimple_stmt_iterator gsi_orig
= *gsi
;
640 /* Create condition "if (index > bound)". */
641 basic_block then_bb
, fallthru_bb
;
642 gimple_stmt_iterator cond_insert_point
643 = create_cond_insert_point (gsi
, false, false, true,
644 &then_bb
, &fallthru_bb
);
645 index
= fold_convert (TREE_TYPE (bound
), index
);
646 index
= force_gimple_operand_gsi (&cond_insert_point
, index
,
648 false, GSI_NEW_STMT
);
649 gimple g
= gimple_build_cond (GT_EXPR
, index
, bound
, NULL_TREE
, NULL_TREE
);
650 gimple_set_location (g
, loc
);
651 gsi_insert_after (&cond_insert_point
, g
, GSI_NEW_STMT
);
653 /* Generate __ubsan_handle_out_of_bounds call. */
654 *gsi
= gsi_after_labels (then_bb
);
655 if (flag_sanitize_undefined_trap_on_error
)
656 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
660 = ubsan_create_data ("__ubsan_out_of_bounds_data", 1, &loc
,
661 ubsan_type_descriptor (type
, UBSAN_PRINT_ARRAY
),
662 ubsan_type_descriptor (orig_index_type
),
663 NULL_TREE
, NULL_TREE
);
664 data
= build_fold_addr_expr_loc (loc
, data
);
665 enum built_in_function bcode
666 = (flag_sanitize_recover
& SANITIZE_BOUNDS
)
667 ? BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS
668 : BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS_ABORT
;
669 tree fn
= builtin_decl_explicit (bcode
);
670 tree val
= force_gimple_operand_gsi (gsi
, ubsan_encode_value (index
),
671 true, NULL_TREE
, true,
673 g
= gimple_build_call (fn
, 2, data
, val
);
675 gimple_set_location (g
, loc
);
676 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
678 /* Get rid of the UBSAN_BOUNDS call from the IR. */
679 unlink_stmt_vdef (stmt
);
680 gsi_remove (&gsi_orig
, true);
682 /* Point GSI to next logical statement. */
683 *gsi
= gsi_start_bb (fallthru_bb
);
687 /* Expand UBSAN_NULL internal call. The type is kept on the ckind
688 argument which is a constant, because the middle-end treats pointer
689 conversions as useless and therefore the type of the first argument
690 could be changed to any other pointer type. */
693 ubsan_expand_null_ifn (gimple_stmt_iterator
*gsip
)
695 gimple_stmt_iterator gsi
= *gsip
;
696 gimple stmt
= gsi_stmt (gsi
);
697 location_t loc
= gimple_location (stmt
);
698 gcc_assert (gimple_call_num_args (stmt
) == 3);
699 tree ptr
= gimple_call_arg (stmt
, 0);
700 tree ckind
= gimple_call_arg (stmt
, 1);
701 tree align
= gimple_call_arg (stmt
, 2);
702 tree check_align
= NULL_TREE
;
705 basic_block cur_bb
= gsi_bb (gsi
);
708 if (!integer_zerop (align
))
710 unsigned int ptralign
= get_pointer_alignment (ptr
) / BITS_PER_UNIT
;
711 if (compare_tree_int (align
, ptralign
) == 1)
713 check_align
= make_ssa_name (pointer_sized_int_node
, NULL
);
714 g
= gimple_build_assign_with_ops (NOP_EXPR
, check_align
,
716 gimple_set_location (g
, loc
);
717 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
720 check_null
= (flag_sanitize
& SANITIZE_NULL
) != 0;
722 if (check_align
== NULL_TREE
&& !check_null
)
724 gsi_remove (gsip
, true);
725 /* Unlink the UBSAN_NULLs vops before replacing it. */
726 unlink_stmt_vdef (stmt
);
730 /* Split the original block holding the pointer dereference. */
731 edge e
= split_block (cur_bb
, stmt
);
733 /* Get a hold on the 'condition block', the 'then block' and the
735 basic_block cond_bb
= e
->src
;
736 basic_block fallthru_bb
= e
->dest
;
737 basic_block then_bb
= create_empty_bb (cond_bb
);
738 add_bb_to_loop (then_bb
, cond_bb
->loop_father
);
739 loops_state_set (LOOPS_NEED_FIXUP
);
741 /* Make an edge coming from the 'cond block' into the 'then block';
742 this edge is unlikely taken, so set up the probability accordingly. */
743 e
= make_edge (cond_bb
, then_bb
, EDGE_TRUE_VALUE
);
744 e
->probability
= PROB_VERY_UNLIKELY
;
746 /* Connect 'then block' with the 'else block'. This is needed
747 as the ubsan routines we call in the 'then block' are not noreturn.
748 The 'then block' only has one outcoming edge. */
749 make_single_succ_edge (then_bb
, fallthru_bb
, EDGE_FALLTHRU
);
751 /* Set up the fallthrough basic block. */
752 e
= find_edge (cond_bb
, fallthru_bb
);
753 e
->flags
= EDGE_FALSE_VALUE
;
754 e
->count
= cond_bb
->count
;
755 e
->probability
= REG_BR_PROB_BASE
- PROB_VERY_UNLIKELY
;
757 /* Update dominance info for the newly created then_bb; note that
758 fallthru_bb's dominance info has already been updated by
760 if (dom_info_available_p (CDI_DOMINATORS
))
761 set_immediate_dominator (CDI_DOMINATORS
, then_bb
, cond_bb
);
763 /* Put the ubsan builtin call into the newly created BB. */
764 if (flag_sanitize_undefined_trap_on_error
)
765 g
= gimple_build_call (builtin_decl_implicit (BUILT_IN_TRAP
), 0);
768 enum built_in_function bcode
769 = (flag_sanitize_recover
& ((check_align
? SANITIZE_ALIGNMENT
: 0)
770 | (check_null
? SANITIZE_NULL
: 0)))
771 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
772 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT
;
773 tree fn
= builtin_decl_implicit (bcode
);
775 = ubsan_create_data ("__ubsan_null_data", 1, &loc
,
776 ubsan_type_descriptor (TREE_TYPE (ckind
),
777 UBSAN_PRINT_POINTER
),
780 fold_convert (unsigned_char_type_node
, ckind
),
782 data
= build_fold_addr_expr_loc (loc
, data
);
783 g
= gimple_build_call (fn
, 2, data
,
784 check_align
? check_align
785 : build_zero_cst (pointer_sized_int_node
));
787 gimple_stmt_iterator gsi2
= gsi_start_bb (then_bb
);
788 gimple_set_location (g
, loc
);
789 gsi_insert_after (&gsi2
, g
, GSI_NEW_STMT
);
791 /* Unlink the UBSAN_NULLs vops before replacing it. */
792 unlink_stmt_vdef (stmt
);
796 g
= gimple_build_cond (EQ_EXPR
, ptr
, build_int_cst (TREE_TYPE (ptr
), 0),
797 NULL_TREE
, NULL_TREE
);
798 gimple_set_location (g
, loc
);
800 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
801 gsi_replace (&gsi
, g
, false);
808 /* Split the block with the condition again. */
809 e
= split_block (cond_bb
, stmt
);
810 basic_block cond1_bb
= e
->src
;
811 basic_block cond2_bb
= e
->dest
;
813 /* Make an edge coming from the 'cond1 block' into the 'then block';
814 this edge is unlikely taken, so set up the probability
816 e
= make_edge (cond1_bb
, then_bb
, EDGE_TRUE_VALUE
);
817 e
->probability
= PROB_VERY_UNLIKELY
;
819 /* Set up the fallthrough basic block. */
820 e
= find_edge (cond1_bb
, cond2_bb
);
821 e
->flags
= EDGE_FALSE_VALUE
;
822 e
->count
= cond1_bb
->count
;
823 e
->probability
= REG_BR_PROB_BASE
- PROB_VERY_UNLIKELY
;
825 /* Update dominance info. */
826 if (dom_info_available_p (CDI_DOMINATORS
))
828 set_immediate_dominator (CDI_DOMINATORS
, fallthru_bb
, cond1_bb
);
829 set_immediate_dominator (CDI_DOMINATORS
, then_bb
, cond1_bb
);
832 gsi2
= gsi_start_bb (cond2_bb
);
835 tree mask
= build_int_cst (pointer_sized_int_node
,
836 tree_to_uhwi (align
) - 1);
837 g
= gimple_build_assign_with_ops (BIT_AND_EXPR
,
838 make_ssa_name (pointer_sized_int_node
,
841 gimple_set_location (g
, loc
);
843 gsi_insert_after (&gsi2
, g
, GSI_NEW_STMT
);
845 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
847 g
= gimple_build_cond (NE_EXPR
, gimple_assign_lhs (g
),
848 build_int_cst (pointer_sized_int_node
, 0),
849 NULL_TREE
, NULL_TREE
);
850 gimple_set_location (g
, loc
);
852 gsi_insert_after (&gsi2
, g
, GSI_NEW_STMT
);
854 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
855 gsi_replace (&gsi
, g
, false);
860 /* Expand UBSAN_OBJECT_SIZE internal call. */
863 ubsan_expand_objsize_ifn (gimple_stmt_iterator
*gsi
)
865 gimple stmt
= gsi_stmt (*gsi
);
866 location_t loc
= gimple_location (stmt
);
867 gcc_assert (gimple_call_num_args (stmt
) == 4);
869 tree ptr
= gimple_call_arg (stmt
, 0);
870 tree offset
= gimple_call_arg (stmt
, 1);
871 tree size
= gimple_call_arg (stmt
, 2);
872 tree ckind
= gimple_call_arg (stmt
, 3);
873 gimple_stmt_iterator gsi_orig
= *gsi
;
876 /* See if we can discard the check. */
877 if (TREE_CODE (size
) != INTEGER_CST
878 || integer_all_onesp (size
))
879 /* Yes, __builtin_object_size couldn't determine the
883 /* if (offset > objsize) */
884 basic_block then_bb
, fallthru_bb
;
885 gimple_stmt_iterator cond_insert_point
886 = create_cond_insert_point (gsi
, false, false, true,
887 &then_bb
, &fallthru_bb
);
888 g
= gimple_build_cond (GT_EXPR
, offset
, size
, NULL_TREE
, NULL_TREE
);
889 gimple_set_location (g
, loc
);
890 gsi_insert_after (&cond_insert_point
, g
, GSI_NEW_STMT
);
892 /* Generate __ubsan_handle_type_mismatch call. */
893 *gsi
= gsi_after_labels (then_bb
);
894 if (flag_sanitize_undefined_trap_on_error
)
895 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
899 = ubsan_create_data ("__ubsan_objsz_data", 1, &loc
,
900 ubsan_type_descriptor (TREE_TYPE (ptr
),
901 UBSAN_PRINT_POINTER
),
903 build_zero_cst (pointer_sized_int_node
),
906 data
= build_fold_addr_expr_loc (loc
, data
);
907 enum built_in_function bcode
908 = (flag_sanitize_recover
& SANITIZE_OBJECT_SIZE
)
909 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
910 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT
;
911 tree p
= make_ssa_name (pointer_sized_int_node
, NULL
);
912 g
= gimple_build_assign_with_ops (NOP_EXPR
, p
, ptr
, NULL_TREE
);
913 gimple_set_location (g
, loc
);
914 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
915 g
= gimple_build_call (builtin_decl_explicit (bcode
), 2, data
, p
);
917 gimple_set_location (g
, loc
);
918 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
920 /* Point GSI to next logical statement. */
921 *gsi
= gsi_start_bb (fallthru_bb
);
924 /* Get rid of the UBSAN_OBJECT_SIZE call from the IR. */
925 unlink_stmt_vdef (stmt
);
926 gsi_remove (&gsi_orig
, true);
927 return gsi_end_p (*gsi
);
930 /* Instrument a memory reference. BASE is the base of MEM, IS_LHS says
931 whether the pointer is on the left hand side of the assignment. */
934 instrument_mem_ref (tree mem
, tree base
, gimple_stmt_iterator
*iter
,
937 enum ubsan_null_ckind ikind
= is_lhs
? UBSAN_STORE_OF
: UBSAN_LOAD_OF
;
938 unsigned int align
= 0;
939 if (flag_sanitize
& SANITIZE_ALIGNMENT
)
941 align
= min_align_of_type (TREE_TYPE (base
));
945 if (align
== 0 && (flag_sanitize
& SANITIZE_NULL
) == 0)
947 tree t
= TREE_OPERAND (base
, 0);
948 if (!POINTER_TYPE_P (TREE_TYPE (t
)))
950 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (TREE_TYPE (t
))) && mem
!= base
)
951 ikind
= UBSAN_MEMBER_ACCESS
;
952 tree kind
= build_int_cst (TREE_TYPE (t
), ikind
);
953 tree alignt
= build_int_cst (pointer_sized_int_node
, align
);
954 gimple g
= gimple_build_call_internal (IFN_UBSAN_NULL
, 3, t
, kind
, alignt
);
955 gimple_set_location (g
, gimple_location (gsi_stmt (*iter
)));
956 gsi_insert_before (iter
, g
, GSI_SAME_STMT
);
959 /* Perform the pointer instrumentation. */
962 instrument_null (gimple_stmt_iterator gsi
, bool is_lhs
)
964 gimple stmt
= gsi_stmt (gsi
);
965 tree t
= is_lhs
? gimple_get_lhs (stmt
) : gimple_assign_rhs1 (stmt
);
966 tree base
= get_base_address (t
);
967 const enum tree_code code
= TREE_CODE (base
);
969 && TREE_CODE (TREE_OPERAND (base
, 0)) == SSA_NAME
)
970 instrument_mem_ref (t
, base
, &gsi
, is_lhs
);
973 /* Build an ubsan builtin call for the signed-integer-overflow
974 sanitization. CODE says what kind of builtin are we building,
975 LOC is a location, LHSTYPE is the type of LHS, OP0 and OP1
976 are operands of the binary operation. */
979 ubsan_build_overflow_builtin (tree_code code
, location_t loc
, tree lhstype
,
982 if (flag_sanitize_undefined_trap_on_error
)
983 return build_call_expr_loc (loc
, builtin_decl_explicit (BUILT_IN_TRAP
), 0);
985 tree data
= ubsan_create_data ("__ubsan_overflow_data", 1, &loc
,
986 ubsan_type_descriptor (lhstype
), NULL_TREE
,
988 enum built_in_function fn_code
;
993 fn_code
= (flag_sanitize_recover
& SANITIZE_SI_OVERFLOW
)
994 ? BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW
995 : BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW_ABORT
;
998 fn_code
= (flag_sanitize_recover
& SANITIZE_SI_OVERFLOW
)
999 ? BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW
1000 : BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW_ABORT
;
1003 fn_code
= (flag_sanitize_recover
& SANITIZE_SI_OVERFLOW
)
1004 ? BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW
1005 : BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW_ABORT
;
1008 fn_code
= (flag_sanitize_recover
& SANITIZE_SI_OVERFLOW
)
1009 ? BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW
1010 : BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW_ABORT
;
1015 tree fn
= builtin_decl_explicit (fn_code
);
1016 return build_call_expr_loc (loc
, fn
, 2 + (code
!= NEGATE_EXPR
),
1017 build_fold_addr_expr_loc (loc
, data
),
1018 ubsan_encode_value (op0
, true),
1019 op1
? ubsan_encode_value (op1
, true)
1023 /* Perform the signed integer instrumentation. GSI is the iterator
1024 pointing at statement we are trying to instrument. */
1027 instrument_si_overflow (gimple_stmt_iterator gsi
)
1029 gimple stmt
= gsi_stmt (gsi
);
1030 tree_code code
= gimple_assign_rhs_code (stmt
);
1031 tree lhs
= gimple_assign_lhs (stmt
);
1032 tree lhstype
= TREE_TYPE (lhs
);
1036 /* If this is not a signed operation, don't instrument anything here.
1037 Also punt on bit-fields. */
1038 if (!INTEGRAL_TYPE_P (lhstype
)
1039 || TYPE_OVERFLOW_WRAPS (lhstype
)
1040 || GET_MODE_BITSIZE (TYPE_MODE (lhstype
)) != TYPE_PRECISION (lhstype
))
1051 i = UBSAN_CHECK_{ADD,SUB,MUL} (u, 5); */
1052 a
= gimple_assign_rhs1 (stmt
);
1053 b
= gimple_assign_rhs2 (stmt
);
1054 g
= gimple_build_call_internal (code
== PLUS_EXPR
1055 ? IFN_UBSAN_CHECK_ADD
1056 : code
== MINUS_EXPR
1057 ? IFN_UBSAN_CHECK_SUB
1058 : IFN_UBSAN_CHECK_MUL
, 2, a
, b
);
1059 gimple_call_set_lhs (g
, lhs
);
1060 gsi_replace (&gsi
, g
, false);
1063 /* Represent i = -u;
1065 i = UBSAN_CHECK_SUB (0, u); */
1066 a
= build_int_cst (lhstype
, 0);
1067 b
= gimple_assign_rhs1 (stmt
);
1068 g
= gimple_build_call_internal (IFN_UBSAN_CHECK_SUB
, 2, a
, b
);
1069 gimple_call_set_lhs (g
, lhs
);
1070 gsi_replace (&gsi
, g
, false);
1073 /* Transform i = ABS_EXPR<u>;
1075 _N = UBSAN_CHECK_SUB (0, u);
1076 i = ABS_EXPR<_N>; */
1077 a
= build_int_cst (lhstype
, 0);
1078 b
= gimple_assign_rhs1 (stmt
);
1079 g
= gimple_build_call_internal (IFN_UBSAN_CHECK_SUB
, 2, a
, b
);
1080 a
= make_ssa_name (lhstype
, NULL
);
1081 gimple_call_set_lhs (g
, a
);
1082 gimple_set_location (g
, gimple_location (stmt
));
1083 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
1084 gimple_assign_set_rhs1 (stmt
, a
);
1092 /* Instrument loads from (non-bitfield) bool and C++ enum values
1093 to check if the memory value is outside of the range of the valid
1097 instrument_bool_enum_load (gimple_stmt_iterator
*gsi
)
1099 gimple stmt
= gsi_stmt (*gsi
);
1100 tree rhs
= gimple_assign_rhs1 (stmt
);
1101 tree type
= TREE_TYPE (rhs
);
1102 tree minv
= NULL_TREE
, maxv
= NULL_TREE
;
1104 if (TREE_CODE (type
) == BOOLEAN_TYPE
&& (flag_sanitize
& SANITIZE_BOOL
))
1106 minv
= boolean_false_node
;
1107 maxv
= boolean_true_node
;
1109 else if (TREE_CODE (type
) == ENUMERAL_TYPE
1110 && (flag_sanitize
& SANITIZE_ENUM
)
1111 && TREE_TYPE (type
) != NULL_TREE
1112 && TREE_CODE (TREE_TYPE (type
)) == INTEGER_TYPE
1113 && (TYPE_PRECISION (TREE_TYPE (type
))
1114 < GET_MODE_PRECISION (TYPE_MODE (type
))))
1116 minv
= TYPE_MIN_VALUE (TREE_TYPE (type
));
1117 maxv
= TYPE_MAX_VALUE (TREE_TYPE (type
));
1122 int modebitsize
= GET_MODE_BITSIZE (TYPE_MODE (type
));
1123 HOST_WIDE_INT bitsize
, bitpos
;
1126 int volatilep
= 0, unsignedp
= 0;
1127 tree base
= get_inner_reference (rhs
, &bitsize
, &bitpos
, &offset
, &mode
,
1128 &unsignedp
, &volatilep
, false);
1129 tree utype
= build_nonstandard_integer_type (modebitsize
, 1);
1131 if ((TREE_CODE (base
) == VAR_DECL
&& DECL_HARD_REGISTER (base
))
1132 || (bitpos
% modebitsize
) != 0
1133 || bitsize
!= modebitsize
1134 || GET_MODE_BITSIZE (TYPE_MODE (utype
)) != modebitsize
1135 || TREE_CODE (gimple_assign_lhs (stmt
)) != SSA_NAME
)
1138 location_t loc
= gimple_location (stmt
);
1139 tree ptype
= build_pointer_type (TREE_TYPE (rhs
));
1140 tree atype
= reference_alias_ptr_type (rhs
);
1141 gimple g
= gimple_build_assign (make_ssa_name (ptype
, NULL
),
1142 build_fold_addr_expr (rhs
));
1143 gimple_set_location (g
, loc
);
1144 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1145 tree mem
= build2 (MEM_REF
, utype
, gimple_assign_lhs (g
),
1146 build_int_cst (atype
, 0));
1147 tree urhs
= make_ssa_name (utype
, NULL
);
1148 g
= gimple_build_assign (urhs
, mem
);
1149 gimple_set_location (g
, loc
);
1150 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1151 minv
= fold_convert (utype
, minv
);
1152 maxv
= fold_convert (utype
, maxv
);
1153 if (!integer_zerop (minv
))
1155 g
= gimple_build_assign_with_ops (MINUS_EXPR
,
1156 make_ssa_name (utype
, NULL
),
1158 gimple_set_location (g
, loc
);
1159 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1162 gimple_stmt_iterator gsi2
= *gsi
;
1163 basic_block then_bb
, fallthru_bb
;
1164 *gsi
= create_cond_insert_point (gsi
, true, false, true,
1165 &then_bb
, &fallthru_bb
);
1166 g
= gimple_build_cond (GT_EXPR
, gimple_assign_lhs (g
),
1167 int_const_binop (MINUS_EXPR
, maxv
, minv
),
1168 NULL_TREE
, NULL_TREE
);
1169 gimple_set_location (g
, loc
);
1170 gsi_insert_after (gsi
, g
, GSI_NEW_STMT
);
1172 gimple_assign_set_rhs_with_ops (&gsi2
, NOP_EXPR
, urhs
, NULL_TREE
);
1175 gsi2
= gsi_after_labels (then_bb
);
1176 if (flag_sanitize_undefined_trap_on_error
)
1177 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
1180 tree data
= ubsan_create_data ("__ubsan_invalid_value_data", 1, &loc
,
1181 ubsan_type_descriptor (type
), NULL_TREE
,
1183 data
= build_fold_addr_expr_loc (loc
, data
);
1184 enum built_in_function bcode
1185 = (flag_sanitize_recover
& (TREE_CODE (type
) == BOOLEAN_TYPE
1186 ? SANITIZE_BOOL
: SANITIZE_ENUM
))
1187 ? BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE
1188 : BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE_ABORT
;
1189 tree fn
= builtin_decl_explicit (bcode
);
1191 tree val
= force_gimple_operand_gsi (&gsi2
, ubsan_encode_value (urhs
),
1192 true, NULL_TREE
, true,
1194 g
= gimple_build_call (fn
, 2, data
, val
);
1196 gimple_set_location (g
, loc
);
1197 gsi_insert_before (&gsi2
, g
, GSI_SAME_STMT
);
1198 *gsi
= gsi_for_stmt (stmt
);
1201 /* Instrument float point-to-integer conversion. TYPE is an integer type of
1202 destination, EXPR is floating-point expression. */
1205 ubsan_instrument_float_cast (location_t loc
, tree type
, tree expr
)
1207 tree expr_type
= TREE_TYPE (expr
);
1208 tree t
, tt
, fn
, min
, max
;
1209 machine_mode mode
= TYPE_MODE (expr_type
);
1210 int prec
= TYPE_PRECISION (type
);
1211 bool uns_p
= TYPE_UNSIGNED (type
);
1213 /* Float to integer conversion first truncates toward zero, so
1214 even signed char c = 127.875f; is not problematic.
1215 Therefore, we should complain only if EXPR is unordered or smaller
1216 or equal than TYPE_MIN_VALUE - 1.0 or greater or equal than
1217 TYPE_MAX_VALUE + 1.0. */
1218 if (REAL_MODE_FORMAT (mode
)->b
== 2)
1220 /* For maximum, TYPE_MAX_VALUE might not be representable
1221 in EXPR_TYPE, e.g. if TYPE is 64-bit long long and
1222 EXPR_TYPE is IEEE single float, but TYPE_MAX_VALUE + 1.0 is
1223 either representable or infinity. */
1224 REAL_VALUE_TYPE maxval
= dconst1
;
1225 SET_REAL_EXP (&maxval
, REAL_EXP (&maxval
) + prec
- !uns_p
);
1226 real_convert (&maxval
, mode
, &maxval
);
1227 max
= build_real (expr_type
, maxval
);
1229 /* For unsigned, assume -1.0 is always representable. */
1231 min
= build_minus_one_cst (expr_type
);
1234 /* TYPE_MIN_VALUE is generally representable (or -inf),
1235 but TYPE_MIN_VALUE - 1.0 might not be. */
1236 REAL_VALUE_TYPE minval
= dconstm1
, minval2
;
1237 SET_REAL_EXP (&minval
, REAL_EXP (&minval
) + prec
- 1);
1238 real_convert (&minval
, mode
, &minval
);
1239 real_arithmetic (&minval2
, MINUS_EXPR
, &minval
, &dconst1
);
1240 real_convert (&minval2
, mode
, &minval2
);
1241 if (real_compare (EQ_EXPR
, &minval
, &minval2
)
1242 && !real_isinf (&minval
))
1244 /* If TYPE_MIN_VALUE - 1.0 is not representable and
1245 rounds to TYPE_MIN_VALUE, we need to subtract
1246 more. As REAL_MODE_FORMAT (mode)->p is the number
1247 of base digits, we want to subtract a number that
1248 will be 1 << (REAL_MODE_FORMAT (mode)->p - 1)
1249 times smaller than minval. */
1251 gcc_assert (prec
> REAL_MODE_FORMAT (mode
)->p
);
1252 SET_REAL_EXP (&minval2
,
1253 REAL_EXP (&minval2
) + prec
- 1
1254 - REAL_MODE_FORMAT (mode
)->p
+ 1);
1255 real_arithmetic (&minval2
, MINUS_EXPR
, &minval
, &minval2
);
1256 real_convert (&minval2
, mode
, &minval2
);
1258 min
= build_real (expr_type
, minval2
);
1261 else if (REAL_MODE_FORMAT (mode
)->b
== 10)
1263 /* For _Decimal128 up to 34 decimal digits, - sign,
1264 dot, e, exponent. */
1267 int p
= REAL_MODE_FORMAT (mode
)->p
;
1268 REAL_VALUE_TYPE maxval
, minval
;
1270 /* Use mpfr_snprintf rounding to compute the smallest
1271 representable decimal number greater or equal than
1272 1 << (prec - !uns_p). */
1273 mpfr_init2 (m
, prec
+ 2);
1274 mpfr_set_ui_2exp (m
, 1, prec
- !uns_p
, GMP_RNDN
);
1275 mpfr_snprintf (buf
, sizeof buf
, "%.*RUe", p
- 1, m
);
1276 decimal_real_from_string (&maxval
, buf
);
1277 max
= build_real (expr_type
, maxval
);
1279 /* For unsigned, assume -1.0 is always representable. */
1281 min
= build_minus_one_cst (expr_type
);
1284 /* Use mpfr_snprintf rounding to compute the largest
1285 representable decimal number less or equal than
1286 (-1 << (prec - 1)) - 1. */
1287 mpfr_set_si_2exp (m
, -1, prec
- 1, GMP_RNDN
);
1288 mpfr_sub_ui (m
, m
, 1, GMP_RNDN
);
1289 mpfr_snprintf (buf
, sizeof buf
, "%.*RDe", p
- 1, m
);
1290 decimal_real_from_string (&minval
, buf
);
1291 min
= build_real (expr_type
, minval
);
1298 if (flag_sanitize_undefined_trap_on_error
)
1299 fn
= build_call_expr_loc (loc
, builtin_decl_explicit (BUILT_IN_TRAP
), 0);
1302 /* Create the __ubsan_handle_float_cast_overflow fn call. */
1303 tree data
= ubsan_create_data ("__ubsan_float_cast_overflow_data", 0,
1304 NULL
, ubsan_type_descriptor (expr_type
),
1305 ubsan_type_descriptor (type
), NULL_TREE
,
1307 enum built_in_function bcode
1308 = (flag_sanitize_recover
& SANITIZE_FLOAT_CAST
)
1309 ? BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW
1310 : BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW_ABORT
;
1311 fn
= builtin_decl_explicit (bcode
);
1312 fn
= build_call_expr_loc (loc
, fn
, 2,
1313 build_fold_addr_expr_loc (loc
, data
),
1314 ubsan_encode_value (expr
, false));
1317 t
= fold_build2 (UNLE_EXPR
, boolean_type_node
, expr
, min
);
1318 tt
= fold_build2 (UNGE_EXPR
, boolean_type_node
, expr
, max
);
1319 return fold_build3 (COND_EXPR
, void_type_node
,
1320 fold_build2 (TRUTH_OR_EXPR
, boolean_type_node
, t
, tt
),
1321 fn
, integer_zero_node
);
1324 /* Instrument values passed to function arguments with nonnull attribute. */
1327 instrument_nonnull_arg (gimple_stmt_iterator
*gsi
)
1329 gimple stmt
= gsi_stmt (*gsi
);
1331 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
1332 while for nonnull sanitization it is clear. */
1333 int save_flag_delete_null_pointer_checks
= flag_delete_null_pointer_checks
;
1334 flag_delete_null_pointer_checks
= 1;
1335 loc
[0] = gimple_location (stmt
);
1336 loc
[1] = UNKNOWN_LOCATION
;
1337 for (unsigned int i
= 0; i
< gimple_call_num_args (stmt
); i
++)
1339 tree arg
= gimple_call_arg (stmt
, i
);
1340 if (POINTER_TYPE_P (TREE_TYPE (arg
))
1341 && infer_nonnull_range (stmt
, arg
, false, true))
1344 if (!is_gimple_val (arg
))
1346 g
= gimple_build_assign (make_ssa_name (TREE_TYPE (arg
), NULL
),
1348 gimple_set_location (g
, loc
[0]);
1349 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1350 arg
= gimple_assign_lhs (g
);
1353 basic_block then_bb
, fallthru_bb
;
1354 *gsi
= create_cond_insert_point (gsi
, true, false, true,
1355 &then_bb
, &fallthru_bb
);
1356 g
= gimple_build_cond (EQ_EXPR
, arg
,
1357 build_zero_cst (TREE_TYPE (arg
)),
1358 NULL_TREE
, NULL_TREE
);
1359 gimple_set_location (g
, loc
[0]);
1360 gsi_insert_after (gsi
, g
, GSI_NEW_STMT
);
1362 *gsi
= gsi_after_labels (then_bb
);
1363 if (flag_sanitize_undefined_trap_on_error
)
1364 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
1367 tree data
= ubsan_create_data ("__ubsan_nonnull_arg_data",
1369 build_int_cst (integer_type_node
,
1372 data
= build_fold_addr_expr_loc (loc
[0], data
);
1373 enum built_in_function bcode
1374 = (flag_sanitize_recover
& SANITIZE_NONNULL_ATTRIBUTE
)
1375 ? BUILT_IN_UBSAN_HANDLE_NONNULL_ARG
1376 : BUILT_IN_UBSAN_HANDLE_NONNULL_ARG_ABORT
;
1377 tree fn
= builtin_decl_explicit (bcode
);
1379 g
= gimple_build_call (fn
, 1, data
);
1381 gimple_set_location (g
, loc
[0]);
1382 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1384 *gsi
= gsi_for_stmt (stmt
);
1386 flag_delete_null_pointer_checks
= save_flag_delete_null_pointer_checks
;
1389 /* Instrument returns in functions with returns_nonnull attribute. */
1392 instrument_nonnull_return (gimple_stmt_iterator
*gsi
)
1394 gimple stmt
= gsi_stmt (*gsi
);
1396 tree arg
= gimple_return_retval (stmt
);
1397 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
1398 while for nonnull return sanitization it is clear. */
1399 int save_flag_delete_null_pointer_checks
= flag_delete_null_pointer_checks
;
1400 flag_delete_null_pointer_checks
= 1;
1401 loc
[0] = gimple_location (stmt
);
1402 loc
[1] = UNKNOWN_LOCATION
;
1404 && POINTER_TYPE_P (TREE_TYPE (arg
))
1405 && is_gimple_val (arg
)
1406 && infer_nonnull_range (stmt
, arg
, false, true))
1408 basic_block then_bb
, fallthru_bb
;
1409 *gsi
= create_cond_insert_point (gsi
, true, false, true,
1410 &then_bb
, &fallthru_bb
);
1411 gimple g
= gimple_build_cond (EQ_EXPR
, arg
,
1412 build_zero_cst (TREE_TYPE (arg
)),
1413 NULL_TREE
, NULL_TREE
);
1414 gimple_set_location (g
, loc
[0]);
1415 gsi_insert_after (gsi
, g
, GSI_NEW_STMT
);
1417 *gsi
= gsi_after_labels (then_bb
);
1418 if (flag_sanitize_undefined_trap_on_error
)
1419 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
1422 tree data
= ubsan_create_data ("__ubsan_nonnull_return_data",
1423 2, loc
, NULL_TREE
, NULL_TREE
);
1424 data
= build_fold_addr_expr_loc (loc
[0], data
);
1425 enum built_in_function bcode
1426 = (flag_sanitize_recover
& SANITIZE_RETURNS_NONNULL_ATTRIBUTE
)
1427 ? BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN
1428 : BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_ABORT
;
1429 tree fn
= builtin_decl_explicit (bcode
);
1431 g
= gimple_build_call (fn
, 1, data
);
1433 gimple_set_location (g
, loc
[0]);
1434 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1435 *gsi
= gsi_for_stmt (stmt
);
1437 flag_delete_null_pointer_checks
= save_flag_delete_null_pointer_checks
;
1440 /* Instrument memory references. Here we check whether the pointer
1441 points to an out-of-bounds location. */
1444 instrument_object_size (gimple_stmt_iterator
*gsi
, bool is_lhs
)
1446 gimple stmt
= gsi_stmt (*gsi
);
1447 location_t loc
= gimple_location (stmt
);
1448 tree t
= is_lhs
? gimple_get_lhs (stmt
) : gimple_assign_rhs1 (stmt
);
1450 tree index
= NULL_TREE
;
1451 HOST_WIDE_INT size_in_bytes
;
1453 type
= TREE_TYPE (t
);
1454 if (VOID_TYPE_P (type
))
1457 switch (TREE_CODE (t
))
1460 if (TREE_CODE (t
) == COMPONENT_REF
1461 && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t
, 1)) != NULL_TREE
)
1463 tree repr
= DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t
, 1));
1464 t
= build3 (COMPONENT_REF
, TREE_TYPE (repr
), TREE_OPERAND (t
, 0),
1469 index
= TREE_OPERAND (t
, 1);
1481 size_in_bytes
= int_size_in_bytes (type
);
1482 if (size_in_bytes
<= 0)
1485 HOST_WIDE_INT bitsize
, bitpos
;
1488 int volatilep
= 0, unsignedp
= 0;
1489 tree inner
= get_inner_reference (t
, &bitsize
, &bitpos
, &offset
, &mode
,
1490 &unsignedp
, &volatilep
, false);
1492 if (bitpos
% BITS_PER_UNIT
!= 0
1493 || bitsize
!= size_in_bytes
* BITS_PER_UNIT
)
1496 bool decl_p
= DECL_P (inner
);
1497 tree base
= decl_p
? inner
: TREE_OPERAND (inner
, 0);
1498 tree ptr
= build1 (ADDR_EXPR
, build_pointer_type (TREE_TYPE (t
)), t
);
1500 while (TREE_CODE (base
) == SSA_NAME
)
1502 gimple def_stmt
= SSA_NAME_DEF_STMT (base
);
1503 if (gimple_assign_ssa_name_copy_p (def_stmt
)
1504 || (gimple_assign_cast_p (def_stmt
)
1505 && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (def_stmt
))))
1506 || (is_gimple_assign (def_stmt
)
1507 && gimple_assign_rhs_code (def_stmt
) == POINTER_PLUS_EXPR
))
1508 base
= gimple_assign_rhs1 (def_stmt
);
1513 if (!POINTER_TYPE_P (TREE_TYPE (base
)) && !DECL_P (base
))
1517 tree base_addr
= base
;
1519 base_addr
= build1 (ADDR_EXPR
,
1520 build_pointer_type (TREE_TYPE (base
)), base
);
1521 unsigned HOST_WIDE_INT size
= compute_builtin_object_size (base_addr
, 0);
1522 if (size
!= (unsigned HOST_WIDE_INT
) -1)
1523 sizet
= build_int_cst (sizetype
, size
);
1526 if (LOCATION_LOCUS (loc
) == UNKNOWN_LOCATION
)
1527 loc
= input_location
;
1528 /* Generate __builtin_object_size call. */
1529 sizet
= builtin_decl_explicit (BUILT_IN_OBJECT_SIZE
);
1530 sizet
= build_call_expr_loc (loc
, sizet
, 2, base_addr
,
1532 sizet
= force_gimple_operand_gsi (gsi
, sizet
, false, NULL_TREE
, true,
1538 /* Generate UBSAN_OBJECT_SIZE (ptr, ptr+sizeof(*ptr)-base, objsize, ckind)
1540 /* ptr + sizeof (*ptr) - base */
1541 t
= fold_build2 (MINUS_EXPR
, sizetype
,
1542 fold_convert (pointer_sized_int_node
, ptr
),
1543 fold_convert (pointer_sized_int_node
, base_addr
));
1544 t
= fold_build2 (PLUS_EXPR
, sizetype
, t
, TYPE_SIZE_UNIT (type
));
1546 /* Perhaps we can omit the check. */
1547 if (TREE_CODE (t
) == INTEGER_CST
1548 && TREE_CODE (sizet
) == INTEGER_CST
1549 && tree_int_cst_le (t
, sizet
))
1552 if (index
!= NULL_TREE
1553 && TREE_CODE (index
) == SSA_NAME
1554 && TREE_CODE (sizet
) == INTEGER_CST
)
1556 gimple def
= SSA_NAME_DEF_STMT (index
);
1557 if (is_gimple_assign (def
)
1558 && gimple_assign_rhs_code (def
) == BIT_AND_EXPR
1559 && TREE_CODE (gimple_assign_rhs2 (def
)) == INTEGER_CST
)
1561 tree cst
= gimple_assign_rhs2 (def
);
1562 tree sz
= fold_build2 (EXACT_DIV_EXPR
, sizetype
, sizet
,
1563 TYPE_SIZE_UNIT (type
));
1564 if (tree_int_cst_sgn (cst
) >= 0
1565 && tree_int_cst_lt (cst
, sz
))
1570 /* Nope. Emit the check. */
1571 t
= force_gimple_operand_gsi (gsi
, t
, true, NULL_TREE
, true,
1573 ptr
= force_gimple_operand_gsi (gsi
, ptr
, true, NULL_TREE
, true,
1575 tree ckind
= build_int_cst (unsigned_char_type_node
,
1576 is_lhs
? UBSAN_STORE_OF
: UBSAN_LOAD_OF
);
1577 gimple g
= gimple_build_call_internal (IFN_UBSAN_OBJECT_SIZE
, 4,
1578 ptr
, t
, sizet
, ckind
);
1579 gimple_set_location (g
, loc
);
1580 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1585 const pass_data pass_data_ubsan
=
1587 GIMPLE_PASS
, /* type */
1589 OPTGROUP_NONE
, /* optinfo_flags */
1590 TV_TREE_UBSAN
, /* tv_id */
1591 ( PROP_cfg
| PROP_ssa
), /* properties_required */
1592 0, /* properties_provided */
1593 0, /* properties_destroyed */
1594 0, /* todo_flags_start */
1595 TODO_update_ssa
, /* todo_flags_finish */
1598 class pass_ubsan
: public gimple_opt_pass
1601 pass_ubsan (gcc::context
*ctxt
)
1602 : gimple_opt_pass (pass_data_ubsan
, ctxt
)
1605 /* opt_pass methods: */
1606 virtual bool gate (function
*)
1608 return flag_sanitize
& (SANITIZE_NULL
| SANITIZE_SI_OVERFLOW
1609 | SANITIZE_BOOL
| SANITIZE_ENUM
1610 | SANITIZE_ALIGNMENT
1611 | SANITIZE_NONNULL_ATTRIBUTE
1612 | SANITIZE_RETURNS_NONNULL_ATTRIBUTE
1613 | SANITIZE_OBJECT_SIZE
)
1614 && current_function_decl
!= NULL_TREE
1615 && !lookup_attribute ("no_sanitize_undefined",
1616 DECL_ATTRIBUTES (current_function_decl
));
1619 virtual unsigned int execute (function
*);
1621 }; // class pass_ubsan
1624 pass_ubsan::execute (function
*fun
)
1627 gimple_stmt_iterator gsi
;
1629 initialize_sanitizer_builtins ();
1631 FOR_EACH_BB_FN (bb
, fun
)
1633 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
);)
1635 gimple stmt
= gsi_stmt (gsi
);
1636 if (is_gimple_debug (stmt
) || gimple_clobber_p (stmt
))
1642 if ((flag_sanitize
& SANITIZE_SI_OVERFLOW
)
1643 && is_gimple_assign (stmt
))
1644 instrument_si_overflow (gsi
);
1646 if (flag_sanitize
& (SANITIZE_NULL
| SANITIZE_ALIGNMENT
))
1648 if (gimple_store_p (stmt
))
1649 instrument_null (gsi
, true);
1650 if (gimple_assign_load_p (stmt
))
1651 instrument_null (gsi
, false);
1654 if (flag_sanitize
& (SANITIZE_BOOL
| SANITIZE_ENUM
)
1655 && gimple_assign_load_p (stmt
))
1657 instrument_bool_enum_load (&gsi
);
1658 bb
= gimple_bb (stmt
);
1661 if ((flag_sanitize
& SANITIZE_NONNULL_ATTRIBUTE
)
1662 && is_gimple_call (stmt
)
1663 && !gimple_call_internal_p (stmt
))
1665 instrument_nonnull_arg (&gsi
);
1666 bb
= gimple_bb (stmt
);
1669 if ((flag_sanitize
& SANITIZE_RETURNS_NONNULL_ATTRIBUTE
)
1670 && gimple_code (stmt
) == GIMPLE_RETURN
)
1672 instrument_nonnull_return (&gsi
);
1673 bb
= gimple_bb (stmt
);
1676 if (flag_sanitize
& SANITIZE_OBJECT_SIZE
)
1678 if (gimple_store_p (stmt
))
1679 instrument_object_size (&gsi
, true);
1680 if (gimple_assign_load_p (stmt
))
1681 instrument_object_size (&gsi
, false);
1693 make_pass_ubsan (gcc::context
*ctxt
)
1695 return new pass_ubsan (ctxt
);
1698 #include "gt-ubsan.h"