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 (location_t loc
)
594 if (flag_sanitize_undefined_trap_on_error
)
595 return build_call_expr_loc (loc
, builtin_decl_explicit (BUILT_IN_TRAP
), 0);
597 initialize_sanitizer_builtins ();
598 tree data
= ubsan_create_data ("__ubsan_unreachable_data", 1, &loc
, NULL_TREE
,
600 tree t
= builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE
);
601 return build_call_expr_loc (loc
, t
, 1, build_fold_addr_expr_loc (loc
, data
));
604 /* Return true if T is a call to a libubsan routine. */
607 is_ubsan_builtin_p (tree t
)
609 return TREE_CODE (t
) == FUNCTION_DECL
610 && strncmp (IDENTIFIER_POINTER (DECL_NAME (t
)),
611 "__builtin___ubsan_", 18) == 0;
614 /* Expand the UBSAN_BOUNDS special builtin function. */
617 ubsan_expand_bounds_ifn (gimple_stmt_iterator
*gsi
)
619 gimple stmt
= gsi_stmt (*gsi
);
620 location_t loc
= gimple_location (stmt
);
621 gcc_assert (gimple_call_num_args (stmt
) == 3);
623 /* Pick up the arguments of the UBSAN_BOUNDS call. */
624 tree type
= TREE_TYPE (TREE_TYPE (gimple_call_arg (stmt
, 0)));
625 tree index
= gimple_call_arg (stmt
, 1);
626 tree orig_index_type
= TREE_TYPE (index
);
627 tree bound
= gimple_call_arg (stmt
, 2);
629 gimple_stmt_iterator gsi_orig
= *gsi
;
631 /* Create condition "if (index > bound)". */
632 basic_block then_bb
, fallthru_bb
;
633 gimple_stmt_iterator cond_insert_point
634 = create_cond_insert_point (gsi
, false, false, true,
635 &then_bb
, &fallthru_bb
);
636 index
= fold_convert (TREE_TYPE (bound
), index
);
637 index
= force_gimple_operand_gsi (&cond_insert_point
, index
,
639 false, GSI_NEW_STMT
);
640 gimple g
= gimple_build_cond (GT_EXPR
, index
, bound
, NULL_TREE
, NULL_TREE
);
641 gimple_set_location (g
, loc
);
642 gsi_insert_after (&cond_insert_point
, g
, GSI_NEW_STMT
);
644 /* Generate __ubsan_handle_out_of_bounds call. */
645 *gsi
= gsi_after_labels (then_bb
);
646 if (flag_sanitize_undefined_trap_on_error
)
647 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
651 = ubsan_create_data ("__ubsan_out_of_bounds_data", 1, &loc
,
652 ubsan_type_descriptor (type
, UBSAN_PRINT_ARRAY
),
653 ubsan_type_descriptor (orig_index_type
),
654 NULL_TREE
, NULL_TREE
);
655 data
= build_fold_addr_expr_loc (loc
, data
);
656 enum built_in_function bcode
657 = (flag_sanitize_recover
& SANITIZE_BOUNDS
)
658 ? BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS
659 : BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS_ABORT
;
660 tree fn
= builtin_decl_explicit (bcode
);
661 tree val
= force_gimple_operand_gsi (gsi
, ubsan_encode_value (index
),
662 true, NULL_TREE
, true,
664 g
= gimple_build_call (fn
, 2, data
, val
);
666 gimple_set_location (g
, loc
);
667 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
669 /* Get rid of the UBSAN_BOUNDS call from the IR. */
670 unlink_stmt_vdef (stmt
);
671 gsi_remove (&gsi_orig
, true);
673 /* Point GSI to next logical statement. */
674 *gsi
= gsi_start_bb (fallthru_bb
);
678 /* Expand UBSAN_NULL internal call. The type is kept on the ckind
679 argument which is a constant, because the middle-end treats pointer
680 conversions as useless and therefore the type of the first argument
681 could be changed to any other pointer type. */
684 ubsan_expand_null_ifn (gimple_stmt_iterator
*gsip
)
686 gimple_stmt_iterator gsi
= *gsip
;
687 gimple stmt
= gsi_stmt (gsi
);
688 location_t loc
= gimple_location (stmt
);
689 gcc_assert (gimple_call_num_args (stmt
) == 3);
690 tree ptr
= gimple_call_arg (stmt
, 0);
691 tree ckind
= gimple_call_arg (stmt
, 1);
692 tree align
= gimple_call_arg (stmt
, 2);
693 tree check_align
= NULL_TREE
;
696 basic_block cur_bb
= gsi_bb (gsi
);
699 if (!integer_zerop (align
))
701 unsigned int ptralign
= get_pointer_alignment (ptr
) / BITS_PER_UNIT
;
702 if (compare_tree_int (align
, ptralign
) == 1)
704 check_align
= make_ssa_name (pointer_sized_int_node
, NULL
);
705 g
= gimple_build_assign_with_ops (NOP_EXPR
, check_align
,
707 gimple_set_location (g
, loc
);
708 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
711 check_null
= (flag_sanitize
& SANITIZE_NULL
) != 0;
713 if (check_align
== NULL_TREE
&& !check_null
)
715 gsi_remove (gsip
, true);
716 /* Unlink the UBSAN_NULLs vops before replacing it. */
717 unlink_stmt_vdef (stmt
);
721 /* Split the original block holding the pointer dereference. */
722 edge e
= split_block (cur_bb
, stmt
);
724 /* Get a hold on the 'condition block', the 'then block' and the
726 basic_block cond_bb
= e
->src
;
727 basic_block fallthru_bb
= e
->dest
;
728 basic_block then_bb
= create_empty_bb (cond_bb
);
729 add_bb_to_loop (then_bb
, cond_bb
->loop_father
);
730 loops_state_set (LOOPS_NEED_FIXUP
);
732 /* Make an edge coming from the 'cond block' into the 'then block';
733 this edge is unlikely taken, so set up the probability accordingly. */
734 e
= make_edge (cond_bb
, then_bb
, EDGE_TRUE_VALUE
);
735 e
->probability
= PROB_VERY_UNLIKELY
;
737 /* Connect 'then block' with the 'else block'. This is needed
738 as the ubsan routines we call in the 'then block' are not noreturn.
739 The 'then block' only has one outcoming edge. */
740 make_single_succ_edge (then_bb
, fallthru_bb
, EDGE_FALLTHRU
);
742 /* Set up the fallthrough basic block. */
743 e
= find_edge (cond_bb
, fallthru_bb
);
744 e
->flags
= EDGE_FALSE_VALUE
;
745 e
->count
= cond_bb
->count
;
746 e
->probability
= REG_BR_PROB_BASE
- PROB_VERY_UNLIKELY
;
748 /* Update dominance info for the newly created then_bb; note that
749 fallthru_bb's dominance info has already been updated by
751 if (dom_info_available_p (CDI_DOMINATORS
))
752 set_immediate_dominator (CDI_DOMINATORS
, then_bb
, cond_bb
);
754 /* Put the ubsan builtin call into the newly created BB. */
755 if (flag_sanitize_undefined_trap_on_error
)
756 g
= gimple_build_call (builtin_decl_implicit (BUILT_IN_TRAP
), 0);
759 enum built_in_function bcode
760 = (flag_sanitize_recover
& ((check_align
? SANITIZE_ALIGNMENT
: 0)
761 | (check_null
? SANITIZE_NULL
: 0)))
762 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
763 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT
;
764 tree fn
= builtin_decl_implicit (bcode
);
766 = ubsan_create_data ("__ubsan_null_data", 1, &loc
,
767 ubsan_type_descriptor (TREE_TYPE (ckind
),
768 UBSAN_PRINT_POINTER
),
771 fold_convert (unsigned_char_type_node
, ckind
),
773 data
= build_fold_addr_expr_loc (loc
, data
);
774 g
= gimple_build_call (fn
, 2, data
,
775 check_align
? check_align
776 : build_zero_cst (pointer_sized_int_node
));
778 gimple_stmt_iterator gsi2
= gsi_start_bb (then_bb
);
779 gimple_set_location (g
, loc
);
780 gsi_insert_after (&gsi2
, g
, GSI_NEW_STMT
);
782 /* Unlink the UBSAN_NULLs vops before replacing it. */
783 unlink_stmt_vdef (stmt
);
787 g
= gimple_build_cond (EQ_EXPR
, ptr
, build_int_cst (TREE_TYPE (ptr
), 0),
788 NULL_TREE
, NULL_TREE
);
789 gimple_set_location (g
, loc
);
791 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
792 gsi_replace (&gsi
, g
, false);
799 /* Split the block with the condition again. */
800 e
= split_block (cond_bb
, stmt
);
801 basic_block cond1_bb
= e
->src
;
802 basic_block cond2_bb
= e
->dest
;
804 /* Make an edge coming from the 'cond1 block' into the 'then block';
805 this edge is unlikely taken, so set up the probability
807 e
= make_edge (cond1_bb
, then_bb
, EDGE_TRUE_VALUE
);
808 e
->probability
= PROB_VERY_UNLIKELY
;
810 /* Set up the fallthrough basic block. */
811 e
= find_edge (cond1_bb
, cond2_bb
);
812 e
->flags
= EDGE_FALSE_VALUE
;
813 e
->count
= cond1_bb
->count
;
814 e
->probability
= REG_BR_PROB_BASE
- PROB_VERY_UNLIKELY
;
816 /* Update dominance info. */
817 if (dom_info_available_p (CDI_DOMINATORS
))
819 set_immediate_dominator (CDI_DOMINATORS
, fallthru_bb
, cond1_bb
);
820 set_immediate_dominator (CDI_DOMINATORS
, then_bb
, cond1_bb
);
823 gsi2
= gsi_start_bb (cond2_bb
);
826 tree mask
= build_int_cst (pointer_sized_int_node
,
827 tree_to_uhwi (align
) - 1);
828 g
= gimple_build_assign_with_ops (BIT_AND_EXPR
,
829 make_ssa_name (pointer_sized_int_node
,
832 gimple_set_location (g
, loc
);
834 gsi_insert_after (&gsi2
, g
, GSI_NEW_STMT
);
836 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
838 g
= gimple_build_cond (NE_EXPR
, gimple_assign_lhs (g
),
839 build_int_cst (pointer_sized_int_node
, 0),
840 NULL_TREE
, NULL_TREE
);
841 gimple_set_location (g
, loc
);
843 gsi_insert_after (&gsi2
, g
, GSI_NEW_STMT
);
845 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
846 gsi_replace (&gsi
, g
, false);
851 /* Expand UBSAN_OBJECT_SIZE internal call. */
854 ubsan_expand_objsize_ifn (gimple_stmt_iterator
*gsi
)
856 gimple stmt
= gsi_stmt (*gsi
);
857 location_t loc
= gimple_location (stmt
);
858 gcc_assert (gimple_call_num_args (stmt
) == 4);
860 tree ptr
= gimple_call_arg (stmt
, 0);
861 tree offset
= gimple_call_arg (stmt
, 1);
862 tree size
= gimple_call_arg (stmt
, 2);
863 tree ckind
= gimple_call_arg (stmt
, 3);
864 gimple_stmt_iterator gsi_orig
= *gsi
;
867 /* See if we can discard the check. */
868 if (TREE_CODE (size
) != INTEGER_CST
869 || integer_all_onesp (size
))
870 /* Yes, __builtin_object_size couldn't determine the
874 /* if (offset > objsize) */
875 basic_block then_bb
, fallthru_bb
;
876 gimple_stmt_iterator cond_insert_point
877 = create_cond_insert_point (gsi
, false, false, true,
878 &then_bb
, &fallthru_bb
);
879 g
= gimple_build_cond (GT_EXPR
, offset
, size
, NULL_TREE
, NULL_TREE
);
880 gimple_set_location (g
, loc
);
881 gsi_insert_after (&cond_insert_point
, g
, GSI_NEW_STMT
);
883 /* Generate __ubsan_handle_type_mismatch call. */
884 *gsi
= gsi_after_labels (then_bb
);
885 if (flag_sanitize_undefined_trap_on_error
)
886 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
890 = ubsan_create_data ("__ubsan_objsz_data", 1, &loc
,
891 ubsan_type_descriptor (TREE_TYPE (ptr
),
892 UBSAN_PRINT_POINTER
),
894 build_zero_cst (pointer_sized_int_node
),
897 data
= build_fold_addr_expr_loc (loc
, data
);
898 enum built_in_function bcode
899 = (flag_sanitize_recover
& SANITIZE_OBJECT_SIZE
)
900 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
901 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT
;
902 tree p
= make_ssa_name (pointer_sized_int_node
, NULL
);
903 g
= gimple_build_assign_with_ops (NOP_EXPR
, p
, ptr
, NULL_TREE
);
904 gimple_set_location (g
, loc
);
905 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
906 g
= gimple_build_call (builtin_decl_explicit (bcode
), 2, data
, p
);
908 gimple_set_location (g
, loc
);
909 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
911 /* Point GSI to next logical statement. */
912 *gsi
= gsi_start_bb (fallthru_bb
);
915 /* Get rid of the UBSAN_OBJECT_SIZE call from the IR. */
916 unlink_stmt_vdef (stmt
);
917 gsi_remove (&gsi_orig
, true);
918 return gsi_end_p (*gsi
);
921 /* Instrument a memory reference. BASE is the base of MEM, IS_LHS says
922 whether the pointer is on the left hand side of the assignment. */
925 instrument_mem_ref (tree mem
, tree base
, gimple_stmt_iterator
*iter
,
928 enum ubsan_null_ckind ikind
= is_lhs
? UBSAN_STORE_OF
: UBSAN_LOAD_OF
;
929 unsigned int align
= 0;
930 if (flag_sanitize
& SANITIZE_ALIGNMENT
)
932 align
= min_align_of_type (TREE_TYPE (base
));
936 if (align
== 0 && (flag_sanitize
& SANITIZE_NULL
) == 0)
938 tree t
= TREE_OPERAND (base
, 0);
939 if (!POINTER_TYPE_P (TREE_TYPE (t
)))
941 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (TREE_TYPE (t
))) && mem
!= base
)
942 ikind
= UBSAN_MEMBER_ACCESS
;
943 tree kind
= build_int_cst (TREE_TYPE (t
), ikind
);
944 tree alignt
= build_int_cst (pointer_sized_int_node
, align
);
945 gimple g
= gimple_build_call_internal (IFN_UBSAN_NULL
, 3, t
, kind
, alignt
);
946 gimple_set_location (g
, gimple_location (gsi_stmt (*iter
)));
947 gsi_insert_before (iter
, g
, GSI_SAME_STMT
);
950 /* Perform the pointer instrumentation. */
953 instrument_null (gimple_stmt_iterator gsi
, bool is_lhs
)
955 gimple stmt
= gsi_stmt (gsi
);
956 tree t
= is_lhs
? gimple_get_lhs (stmt
) : gimple_assign_rhs1 (stmt
);
957 tree base
= get_base_address (t
);
958 const enum tree_code code
= TREE_CODE (base
);
960 && TREE_CODE (TREE_OPERAND (base
, 0)) == SSA_NAME
)
961 instrument_mem_ref (t
, base
, &gsi
, is_lhs
);
964 /* Build an ubsan builtin call for the signed-integer-overflow
965 sanitization. CODE says what kind of builtin are we building,
966 LOC is a location, LHSTYPE is the type of LHS, OP0 and OP1
967 are operands of the binary operation. */
970 ubsan_build_overflow_builtin (tree_code code
, location_t loc
, tree lhstype
,
973 if (flag_sanitize_undefined_trap_on_error
)
974 return build_call_expr_loc (loc
, builtin_decl_explicit (BUILT_IN_TRAP
), 0);
976 tree data
= ubsan_create_data ("__ubsan_overflow_data", 1, &loc
,
977 ubsan_type_descriptor (lhstype
), NULL_TREE
,
979 enum built_in_function fn_code
;
984 fn_code
= (flag_sanitize_recover
& SANITIZE_SI_OVERFLOW
)
985 ? BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW
986 : BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW_ABORT
;
989 fn_code
= (flag_sanitize_recover
& SANITIZE_SI_OVERFLOW
)
990 ? BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW
991 : BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW_ABORT
;
994 fn_code
= (flag_sanitize_recover
& SANITIZE_SI_OVERFLOW
)
995 ? BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW
996 : BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW_ABORT
;
999 fn_code
= (flag_sanitize_recover
& SANITIZE_SI_OVERFLOW
)
1000 ? BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW
1001 : BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW_ABORT
;
1006 tree fn
= builtin_decl_explicit (fn_code
);
1007 return build_call_expr_loc (loc
, fn
, 2 + (code
!= NEGATE_EXPR
),
1008 build_fold_addr_expr_loc (loc
, data
),
1009 ubsan_encode_value (op0
, true),
1010 op1
? ubsan_encode_value (op1
, true)
1014 /* Perform the signed integer instrumentation. GSI is the iterator
1015 pointing at statement we are trying to instrument. */
1018 instrument_si_overflow (gimple_stmt_iterator gsi
)
1020 gimple stmt
= gsi_stmt (gsi
);
1021 tree_code code
= gimple_assign_rhs_code (stmt
);
1022 tree lhs
= gimple_assign_lhs (stmt
);
1023 tree lhstype
= TREE_TYPE (lhs
);
1027 /* If this is not a signed operation, don't instrument anything here.
1028 Also punt on bit-fields. */
1029 if (!INTEGRAL_TYPE_P (lhstype
)
1030 || TYPE_OVERFLOW_WRAPS (lhstype
)
1031 || GET_MODE_BITSIZE (TYPE_MODE (lhstype
)) != TYPE_PRECISION (lhstype
))
1042 i = UBSAN_CHECK_{ADD,SUB,MUL} (u, 5); */
1043 a
= gimple_assign_rhs1 (stmt
);
1044 b
= gimple_assign_rhs2 (stmt
);
1045 g
= gimple_build_call_internal (code
== PLUS_EXPR
1046 ? IFN_UBSAN_CHECK_ADD
1047 : code
== MINUS_EXPR
1048 ? IFN_UBSAN_CHECK_SUB
1049 : IFN_UBSAN_CHECK_MUL
, 2, a
, b
);
1050 gimple_call_set_lhs (g
, lhs
);
1051 gsi_replace (&gsi
, g
, false);
1054 /* Represent i = -u;
1056 i = UBSAN_CHECK_SUB (0, u); */
1057 a
= build_int_cst (lhstype
, 0);
1058 b
= gimple_assign_rhs1 (stmt
);
1059 g
= gimple_build_call_internal (IFN_UBSAN_CHECK_SUB
, 2, a
, b
);
1060 gimple_call_set_lhs (g
, lhs
);
1061 gsi_replace (&gsi
, g
, false);
1064 /* Transform i = ABS_EXPR<u>;
1066 _N = UBSAN_CHECK_SUB (0, u);
1067 i = ABS_EXPR<_N>; */
1068 a
= build_int_cst (lhstype
, 0);
1069 b
= gimple_assign_rhs1 (stmt
);
1070 g
= gimple_build_call_internal (IFN_UBSAN_CHECK_SUB
, 2, a
, b
);
1071 a
= make_ssa_name (lhstype
, NULL
);
1072 gimple_call_set_lhs (g
, a
);
1073 gimple_set_location (g
, gimple_location (stmt
));
1074 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
1075 gimple_assign_set_rhs1 (stmt
, a
);
1083 /* Instrument loads from (non-bitfield) bool and C++ enum values
1084 to check if the memory value is outside of the range of the valid
1088 instrument_bool_enum_load (gimple_stmt_iterator
*gsi
)
1090 gimple stmt
= gsi_stmt (*gsi
);
1091 tree rhs
= gimple_assign_rhs1 (stmt
);
1092 tree type
= TREE_TYPE (rhs
);
1093 tree minv
= NULL_TREE
, maxv
= NULL_TREE
;
1095 if (TREE_CODE (type
) == BOOLEAN_TYPE
&& (flag_sanitize
& SANITIZE_BOOL
))
1097 minv
= boolean_false_node
;
1098 maxv
= boolean_true_node
;
1100 else if (TREE_CODE (type
) == ENUMERAL_TYPE
1101 && (flag_sanitize
& SANITIZE_ENUM
)
1102 && TREE_TYPE (type
) != NULL_TREE
1103 && TREE_CODE (TREE_TYPE (type
)) == INTEGER_TYPE
1104 && (TYPE_PRECISION (TREE_TYPE (type
))
1105 < GET_MODE_PRECISION (TYPE_MODE (type
))))
1107 minv
= TYPE_MIN_VALUE (TREE_TYPE (type
));
1108 maxv
= TYPE_MAX_VALUE (TREE_TYPE (type
));
1113 int modebitsize
= GET_MODE_BITSIZE (TYPE_MODE (type
));
1114 HOST_WIDE_INT bitsize
, bitpos
;
1116 enum machine_mode mode
;
1117 int volatilep
= 0, unsignedp
= 0;
1118 tree base
= get_inner_reference (rhs
, &bitsize
, &bitpos
, &offset
, &mode
,
1119 &unsignedp
, &volatilep
, false);
1120 tree utype
= build_nonstandard_integer_type (modebitsize
, 1);
1122 if ((TREE_CODE (base
) == VAR_DECL
&& DECL_HARD_REGISTER (base
))
1123 || (bitpos
% modebitsize
) != 0
1124 || bitsize
!= modebitsize
1125 || GET_MODE_BITSIZE (TYPE_MODE (utype
)) != modebitsize
1126 || TREE_CODE (gimple_assign_lhs (stmt
)) != SSA_NAME
)
1129 location_t loc
= gimple_location (stmt
);
1130 tree ptype
= build_pointer_type (TREE_TYPE (rhs
));
1131 tree atype
= reference_alias_ptr_type (rhs
);
1132 gimple g
= gimple_build_assign (make_ssa_name (ptype
, NULL
),
1133 build_fold_addr_expr (rhs
));
1134 gimple_set_location (g
, loc
);
1135 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1136 tree mem
= build2 (MEM_REF
, utype
, gimple_assign_lhs (g
),
1137 build_int_cst (atype
, 0));
1138 tree urhs
= make_ssa_name (utype
, NULL
);
1139 g
= gimple_build_assign (urhs
, mem
);
1140 gimple_set_location (g
, loc
);
1141 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1142 minv
= fold_convert (utype
, minv
);
1143 maxv
= fold_convert (utype
, maxv
);
1144 if (!integer_zerop (minv
))
1146 g
= gimple_build_assign_with_ops (MINUS_EXPR
,
1147 make_ssa_name (utype
, NULL
),
1149 gimple_set_location (g
, loc
);
1150 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1153 gimple_stmt_iterator gsi2
= *gsi
;
1154 basic_block then_bb
, fallthru_bb
;
1155 *gsi
= create_cond_insert_point (gsi
, true, false, true,
1156 &then_bb
, &fallthru_bb
);
1157 g
= gimple_build_cond (GT_EXPR
, gimple_assign_lhs (g
),
1158 int_const_binop (MINUS_EXPR
, maxv
, minv
),
1159 NULL_TREE
, NULL_TREE
);
1160 gimple_set_location (g
, loc
);
1161 gsi_insert_after (gsi
, g
, GSI_NEW_STMT
);
1163 gimple_assign_set_rhs_with_ops (&gsi2
, NOP_EXPR
, urhs
, NULL_TREE
);
1166 gsi2
= gsi_after_labels (then_bb
);
1167 if (flag_sanitize_undefined_trap_on_error
)
1168 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
1171 tree data
= ubsan_create_data ("__ubsan_invalid_value_data", 1, &loc
,
1172 ubsan_type_descriptor (type
), NULL_TREE
,
1174 data
= build_fold_addr_expr_loc (loc
, data
);
1175 enum built_in_function bcode
1176 = (flag_sanitize_recover
& (TREE_CODE (type
) == BOOLEAN_TYPE
1177 ? SANITIZE_BOOL
: SANITIZE_ENUM
))
1178 ? BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE
1179 : BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE_ABORT
;
1180 tree fn
= builtin_decl_explicit (bcode
);
1182 tree val
= force_gimple_operand_gsi (&gsi2
, ubsan_encode_value (urhs
),
1183 true, NULL_TREE
, true,
1185 g
= gimple_build_call (fn
, 2, data
, val
);
1187 gimple_set_location (g
, loc
);
1188 gsi_insert_before (&gsi2
, g
, GSI_SAME_STMT
);
1189 *gsi
= gsi_for_stmt (stmt
);
1192 /* Instrument float point-to-integer conversion. TYPE is an integer type of
1193 destination, EXPR is floating-point expression. */
1196 ubsan_instrument_float_cast (location_t loc
, tree type
, tree expr
)
1198 tree expr_type
= TREE_TYPE (expr
);
1199 tree t
, tt
, fn
, min
, max
;
1200 enum machine_mode mode
= TYPE_MODE (expr_type
);
1201 int prec
= TYPE_PRECISION (type
);
1202 bool uns_p
= TYPE_UNSIGNED (type
);
1204 /* Float to integer conversion first truncates toward zero, so
1205 even signed char c = 127.875f; is not problematic.
1206 Therefore, we should complain only if EXPR is unordered or smaller
1207 or equal than TYPE_MIN_VALUE - 1.0 or greater or equal than
1208 TYPE_MAX_VALUE + 1.0. */
1209 if (REAL_MODE_FORMAT (mode
)->b
== 2)
1211 /* For maximum, TYPE_MAX_VALUE might not be representable
1212 in EXPR_TYPE, e.g. if TYPE is 64-bit long long and
1213 EXPR_TYPE is IEEE single float, but TYPE_MAX_VALUE + 1.0 is
1214 either representable or infinity. */
1215 REAL_VALUE_TYPE maxval
= dconst1
;
1216 SET_REAL_EXP (&maxval
, REAL_EXP (&maxval
) + prec
- !uns_p
);
1217 real_convert (&maxval
, mode
, &maxval
);
1218 max
= build_real (expr_type
, maxval
);
1220 /* For unsigned, assume -1.0 is always representable. */
1222 min
= build_minus_one_cst (expr_type
);
1225 /* TYPE_MIN_VALUE is generally representable (or -inf),
1226 but TYPE_MIN_VALUE - 1.0 might not be. */
1227 REAL_VALUE_TYPE minval
= dconstm1
, minval2
;
1228 SET_REAL_EXP (&minval
, REAL_EXP (&minval
) + prec
- 1);
1229 real_convert (&minval
, mode
, &minval
);
1230 real_arithmetic (&minval2
, MINUS_EXPR
, &minval
, &dconst1
);
1231 real_convert (&minval2
, mode
, &minval2
);
1232 if (real_compare (EQ_EXPR
, &minval
, &minval2
)
1233 && !real_isinf (&minval
))
1235 /* If TYPE_MIN_VALUE - 1.0 is not representable and
1236 rounds to TYPE_MIN_VALUE, we need to subtract
1237 more. As REAL_MODE_FORMAT (mode)->p is the number
1238 of base digits, we want to subtract a number that
1239 will be 1 << (REAL_MODE_FORMAT (mode)->p - 1)
1240 times smaller than minval. */
1242 gcc_assert (prec
> REAL_MODE_FORMAT (mode
)->p
);
1243 SET_REAL_EXP (&minval2
,
1244 REAL_EXP (&minval2
) + prec
- 1
1245 - REAL_MODE_FORMAT (mode
)->p
+ 1);
1246 real_arithmetic (&minval2
, MINUS_EXPR
, &minval
, &minval2
);
1247 real_convert (&minval2
, mode
, &minval2
);
1249 min
= build_real (expr_type
, minval2
);
1252 else if (REAL_MODE_FORMAT (mode
)->b
== 10)
1254 /* For _Decimal128 up to 34 decimal digits, - sign,
1255 dot, e, exponent. */
1258 int p
= REAL_MODE_FORMAT (mode
)->p
;
1259 REAL_VALUE_TYPE maxval
, minval
;
1261 /* Use mpfr_snprintf rounding to compute the smallest
1262 representable decimal number greater or equal than
1263 1 << (prec - !uns_p). */
1264 mpfr_init2 (m
, prec
+ 2);
1265 mpfr_set_ui_2exp (m
, 1, prec
- !uns_p
, GMP_RNDN
);
1266 mpfr_snprintf (buf
, sizeof buf
, "%.*RUe", p
- 1, m
);
1267 decimal_real_from_string (&maxval
, buf
);
1268 max
= build_real (expr_type
, maxval
);
1270 /* For unsigned, assume -1.0 is always representable. */
1272 min
= build_minus_one_cst (expr_type
);
1275 /* Use mpfr_snprintf rounding to compute the largest
1276 representable decimal number less or equal than
1277 (-1 << (prec - 1)) - 1. */
1278 mpfr_set_si_2exp (m
, -1, prec
- 1, GMP_RNDN
);
1279 mpfr_sub_ui (m
, m
, 1, GMP_RNDN
);
1280 mpfr_snprintf (buf
, sizeof buf
, "%.*RDe", p
- 1, m
);
1281 decimal_real_from_string (&minval
, buf
);
1282 min
= build_real (expr_type
, minval
);
1289 if (flag_sanitize_undefined_trap_on_error
)
1290 fn
= build_call_expr_loc (loc
, builtin_decl_explicit (BUILT_IN_TRAP
), 0);
1293 /* Create the __ubsan_handle_float_cast_overflow fn call. */
1294 tree data
= ubsan_create_data ("__ubsan_float_cast_overflow_data", 0,
1295 NULL
, ubsan_type_descriptor (expr_type
),
1296 ubsan_type_descriptor (type
), NULL_TREE
,
1298 enum built_in_function bcode
1299 = (flag_sanitize_recover
& SANITIZE_FLOAT_CAST
)
1300 ? BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW
1301 : BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW_ABORT
;
1302 fn
= builtin_decl_explicit (bcode
);
1303 fn
= build_call_expr_loc (loc
, fn
, 2,
1304 build_fold_addr_expr_loc (loc
, data
),
1305 ubsan_encode_value (expr
, false));
1308 t
= fold_build2 (UNLE_EXPR
, boolean_type_node
, expr
, min
);
1309 tt
= fold_build2 (UNGE_EXPR
, boolean_type_node
, expr
, max
);
1310 return fold_build3 (COND_EXPR
, void_type_node
,
1311 fold_build2 (TRUTH_OR_EXPR
, boolean_type_node
, t
, tt
),
1312 fn
, integer_zero_node
);
1315 /* Instrument values passed to function arguments with nonnull attribute. */
1318 instrument_nonnull_arg (gimple_stmt_iterator
*gsi
)
1320 gimple stmt
= gsi_stmt (*gsi
);
1322 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
1323 while for nonnull sanitization it is clear. */
1324 int save_flag_delete_null_pointer_checks
= flag_delete_null_pointer_checks
;
1325 flag_delete_null_pointer_checks
= 1;
1326 loc
[0] = gimple_location (stmt
);
1327 loc
[1] = UNKNOWN_LOCATION
;
1328 for (unsigned int i
= 0; i
< gimple_call_num_args (stmt
); i
++)
1330 tree arg
= gimple_call_arg (stmt
, i
);
1331 if (POINTER_TYPE_P (TREE_TYPE (arg
))
1332 && infer_nonnull_range (stmt
, arg
, false, true))
1335 if (!is_gimple_val (arg
))
1337 g
= gimple_build_assign (make_ssa_name (TREE_TYPE (arg
), NULL
),
1339 gimple_set_location (g
, loc
[0]);
1340 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1341 arg
= gimple_assign_lhs (g
);
1344 basic_block then_bb
, fallthru_bb
;
1345 *gsi
= create_cond_insert_point (gsi
, true, false, true,
1346 &then_bb
, &fallthru_bb
);
1347 g
= gimple_build_cond (EQ_EXPR
, arg
,
1348 build_zero_cst (TREE_TYPE (arg
)),
1349 NULL_TREE
, NULL_TREE
);
1350 gimple_set_location (g
, loc
[0]);
1351 gsi_insert_after (gsi
, g
, GSI_NEW_STMT
);
1353 *gsi
= gsi_after_labels (then_bb
);
1354 if (flag_sanitize_undefined_trap_on_error
)
1355 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
1358 tree data
= ubsan_create_data ("__ubsan_nonnull_arg_data",
1360 build_int_cst (integer_type_node
,
1363 data
= build_fold_addr_expr_loc (loc
[0], data
);
1364 enum built_in_function bcode
1365 = (flag_sanitize_recover
& SANITIZE_NONNULL_ATTRIBUTE
)
1366 ? BUILT_IN_UBSAN_HANDLE_NONNULL_ARG
1367 : BUILT_IN_UBSAN_HANDLE_NONNULL_ARG_ABORT
;
1368 tree fn
= builtin_decl_explicit (bcode
);
1370 g
= gimple_build_call (fn
, 1, data
);
1372 gimple_set_location (g
, loc
[0]);
1373 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1375 *gsi
= gsi_for_stmt (stmt
);
1377 flag_delete_null_pointer_checks
= save_flag_delete_null_pointer_checks
;
1380 /* Instrument returns in functions with returns_nonnull attribute. */
1383 instrument_nonnull_return (gimple_stmt_iterator
*gsi
)
1385 gimple stmt
= gsi_stmt (*gsi
);
1387 tree arg
= gimple_return_retval (stmt
);
1388 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
1389 while for nonnull return sanitization it is clear. */
1390 int save_flag_delete_null_pointer_checks
= flag_delete_null_pointer_checks
;
1391 flag_delete_null_pointer_checks
= 1;
1392 loc
[0] = gimple_location (stmt
);
1393 loc
[1] = UNKNOWN_LOCATION
;
1395 && POINTER_TYPE_P (TREE_TYPE (arg
))
1396 && is_gimple_val (arg
)
1397 && infer_nonnull_range (stmt
, arg
, false, true))
1399 basic_block then_bb
, fallthru_bb
;
1400 *gsi
= create_cond_insert_point (gsi
, true, false, true,
1401 &then_bb
, &fallthru_bb
);
1402 gimple g
= gimple_build_cond (EQ_EXPR
, arg
,
1403 build_zero_cst (TREE_TYPE (arg
)),
1404 NULL_TREE
, NULL_TREE
);
1405 gimple_set_location (g
, loc
[0]);
1406 gsi_insert_after (gsi
, g
, GSI_NEW_STMT
);
1408 *gsi
= gsi_after_labels (then_bb
);
1409 if (flag_sanitize_undefined_trap_on_error
)
1410 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
1413 tree data
= ubsan_create_data ("__ubsan_nonnull_return_data",
1414 2, loc
, NULL_TREE
, NULL_TREE
);
1415 data
= build_fold_addr_expr_loc (loc
[0], data
);
1416 enum built_in_function bcode
1417 = (flag_sanitize_recover
& SANITIZE_RETURNS_NONNULL_ATTRIBUTE
)
1418 ? BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN
1419 : BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_ABORT
;
1420 tree fn
= builtin_decl_explicit (bcode
);
1422 g
= gimple_build_call (fn
, 1, data
);
1424 gimple_set_location (g
, loc
[0]);
1425 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1426 *gsi
= gsi_for_stmt (stmt
);
1428 flag_delete_null_pointer_checks
= save_flag_delete_null_pointer_checks
;
1431 /* Instrument memory references. Here we check whether the pointer
1432 points to an out-of-bounds location. */
1435 instrument_object_size (gimple_stmt_iterator
*gsi
, bool is_lhs
)
1437 gimple stmt
= gsi_stmt (*gsi
);
1438 location_t loc
= gimple_location (stmt
);
1439 tree t
= is_lhs
? gimple_get_lhs (stmt
) : gimple_assign_rhs1 (stmt
);
1441 HOST_WIDE_INT size_in_bytes
;
1443 type
= TREE_TYPE (t
);
1444 if (VOID_TYPE_P (type
))
1447 switch (TREE_CODE (t
))
1450 if (TREE_CODE (t
) == COMPONENT_REF
1451 && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t
, 1)) != NULL_TREE
)
1453 tree repr
= DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t
, 1));
1454 t
= build3 (COMPONENT_REF
, TREE_TYPE (repr
), TREE_OPERAND (t
, 0),
1469 size_in_bytes
= int_size_in_bytes (type
);
1470 if (size_in_bytes
<= 0)
1473 HOST_WIDE_INT bitsize
, bitpos
;
1475 enum machine_mode mode
;
1476 int volatilep
= 0, unsignedp
= 0;
1477 tree inner
= get_inner_reference (t
, &bitsize
, &bitpos
, &offset
, &mode
,
1478 &unsignedp
, &volatilep
, false);
1480 if (bitpos
% BITS_PER_UNIT
!= 0
1481 || bitsize
!= size_in_bytes
* BITS_PER_UNIT
)
1484 bool decl_p
= DECL_P (inner
);
1485 tree base
= decl_p
? inner
: TREE_OPERAND (inner
, 0);
1486 tree ptr
= build1 (ADDR_EXPR
, build_pointer_type (TREE_TYPE (t
)), t
);
1488 while (TREE_CODE (base
) == SSA_NAME
)
1490 gimple def_stmt
= SSA_NAME_DEF_STMT (base
);
1491 if (gimple_assign_ssa_name_copy_p (def_stmt
)
1492 || (gimple_assign_cast_p (def_stmt
)
1493 && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (def_stmt
))))
1494 || (is_gimple_assign (def_stmt
)
1495 && gimple_assign_rhs_code (def_stmt
) == POINTER_PLUS_EXPR
))
1496 base
= gimple_assign_rhs1 (def_stmt
);
1501 if (!POINTER_TYPE_P (TREE_TYPE (base
)) && !DECL_P (base
))
1505 tree base_addr
= base
;
1507 base_addr
= build1 (ADDR_EXPR
,
1508 build_pointer_type (TREE_TYPE (base
)), base
);
1509 unsigned HOST_WIDE_INT size
= compute_builtin_object_size (base_addr
, 0);
1510 if (size
!= (unsigned HOST_WIDE_INT
) -1)
1511 sizet
= build_int_cst (sizetype
, size
);
1514 if (LOCATION_LOCUS (loc
) == UNKNOWN_LOCATION
)
1515 loc
= input_location
;
1516 /* Generate __builtin_object_size call. */
1517 sizet
= builtin_decl_explicit (BUILT_IN_OBJECT_SIZE
);
1518 sizet
= build_call_expr_loc (loc
, sizet
, 2, base_addr
,
1520 sizet
= force_gimple_operand_gsi (gsi
, sizet
, false, NULL_TREE
, true,
1526 /* Generate UBSAN_OBJECT_SIZE (ptr, ptr+sizeof(*ptr)-base, objsize, ckind)
1528 /* ptr + sizeof (*ptr) - base */
1529 t
= fold_build2 (MINUS_EXPR
, sizetype
,
1530 fold_convert (pointer_sized_int_node
, ptr
),
1531 fold_convert (pointer_sized_int_node
, base_addr
));
1532 t
= fold_build2 (PLUS_EXPR
, sizetype
, t
, TYPE_SIZE_UNIT (type
));
1534 /* Perhaps we can omit the check. */
1535 if (TREE_CODE (t
) == INTEGER_CST
1536 && TREE_CODE (sizet
) == INTEGER_CST
1537 && tree_int_cst_le (t
, sizet
))
1540 /* Nope. Emit the check. */
1541 t
= force_gimple_operand_gsi (gsi
, t
, true, NULL_TREE
, true,
1543 ptr
= force_gimple_operand_gsi (gsi
, ptr
, true, NULL_TREE
, true,
1545 tree ckind
= build_int_cst (unsigned_char_type_node
,
1546 is_lhs
? UBSAN_STORE_OF
: UBSAN_LOAD_OF
);
1547 gimple g
= gimple_build_call_internal (IFN_UBSAN_OBJECT_SIZE
, 4,
1548 ptr
, t
, sizet
, ckind
);
1549 gimple_set_location (g
, loc
);
1550 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1555 const pass_data pass_data_ubsan
=
1557 GIMPLE_PASS
, /* type */
1559 OPTGROUP_NONE
, /* optinfo_flags */
1560 TV_TREE_UBSAN
, /* tv_id */
1561 ( PROP_cfg
| PROP_ssa
), /* properties_required */
1562 0, /* properties_provided */
1563 0, /* properties_destroyed */
1564 0, /* todo_flags_start */
1565 TODO_update_ssa
, /* todo_flags_finish */
1568 class pass_ubsan
: public gimple_opt_pass
1571 pass_ubsan (gcc::context
*ctxt
)
1572 : gimple_opt_pass (pass_data_ubsan
, ctxt
)
1575 /* opt_pass methods: */
1576 virtual bool gate (function
*)
1578 return flag_sanitize
& (SANITIZE_NULL
| SANITIZE_SI_OVERFLOW
1579 | SANITIZE_BOOL
| SANITIZE_ENUM
1580 | SANITIZE_ALIGNMENT
1581 | SANITIZE_NONNULL_ATTRIBUTE
1582 | SANITIZE_RETURNS_NONNULL_ATTRIBUTE
1583 | SANITIZE_OBJECT_SIZE
)
1584 && current_function_decl
!= NULL_TREE
1585 && !lookup_attribute ("no_sanitize_undefined",
1586 DECL_ATTRIBUTES (current_function_decl
));
1589 virtual unsigned int execute (function
*);
1591 }; // class pass_ubsan
1594 pass_ubsan::execute (function
*fun
)
1597 gimple_stmt_iterator gsi
;
1599 initialize_sanitizer_builtins ();
1601 FOR_EACH_BB_FN (bb
, fun
)
1603 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
);)
1605 gimple stmt
= gsi_stmt (gsi
);
1606 if (is_gimple_debug (stmt
) || gimple_clobber_p (stmt
))
1612 if ((flag_sanitize
& SANITIZE_SI_OVERFLOW
)
1613 && is_gimple_assign (stmt
))
1614 instrument_si_overflow (gsi
);
1616 if (flag_sanitize
& (SANITIZE_NULL
| SANITIZE_ALIGNMENT
))
1618 if (gimple_store_p (stmt
))
1619 instrument_null (gsi
, true);
1620 if (gimple_assign_load_p (stmt
))
1621 instrument_null (gsi
, false);
1624 if (flag_sanitize
& (SANITIZE_BOOL
| SANITIZE_ENUM
)
1625 && gimple_assign_load_p (stmt
))
1627 instrument_bool_enum_load (&gsi
);
1628 bb
= gimple_bb (stmt
);
1631 if ((flag_sanitize
& SANITIZE_NONNULL_ATTRIBUTE
)
1632 && is_gimple_call (stmt
)
1633 && !gimple_call_internal_p (stmt
))
1635 instrument_nonnull_arg (&gsi
);
1636 bb
= gimple_bb (stmt
);
1639 if ((flag_sanitize
& SANITIZE_RETURNS_NONNULL_ATTRIBUTE
)
1640 && gimple_code (stmt
) == GIMPLE_RETURN
)
1642 instrument_nonnull_return (&gsi
);
1643 bb
= gimple_bb (stmt
);
1646 if (flag_sanitize
& SANITIZE_OBJECT_SIZE
)
1648 if (gimple_store_p (stmt
))
1649 instrument_object_size (&gsi
, true);
1650 if (gimple_assign_load_p (stmt
))
1651 instrument_object_size (&gsi
, false);
1663 make_pass_ubsan (gcc::context
*ctxt
)
1665 return new pass_ubsan (ctxt
);
1668 #include "gt-ubsan.h"