1 /* UndefinedBehaviorSanitizer, undefined behavior detector.
2 Copyright (C) 2013-2016 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"
26 #include "c-family/c-common.h"
29 #include "tree-pass.h"
33 #include "tree-pretty-print.h"
34 #include "stor-layout.h"
36 #include "gimple-iterator.h"
42 #include "gimplify-me.h"
45 #include "tree-object-size.h"
48 /* Map from a tree to a VAR_DECL tree. */
50 struct GTY((for_user
)) tree_type_map
{
51 struct tree_map_base type
;
55 struct tree_type_map_cache_hasher
: ggc_cache_ptr_hash
<tree_type_map
>
57 static inline hashval_t
58 hash (tree_type_map
*t
)
60 return TYPE_UID (t
->type
.from
);
64 equal (tree_type_map
*a
, tree_type_map
*b
)
66 return a
->type
.from
== b
->type
.from
;
70 keep_cache_entry (tree_type_map
*&m
)
72 return ggc_marked_p (m
->type
.from
);
77 hash_table
<tree_type_map_cache_hasher
> *decl_tree_for_type
;
79 /* Lookup a VAR_DECL for TYPE, and return it if we find one. */
82 decl_for_type_lookup (tree type
)
84 /* If the hash table is not initialized yet, create it now. */
85 if (decl_tree_for_type
== NULL
)
88 = hash_table
<tree_type_map_cache_hasher
>::create_ggc (10);
89 /* That also means we don't have to bother with the lookup. */
93 struct tree_type_map
*h
, in
;
96 h
= decl_tree_for_type
->find_with_hash (&in
, TYPE_UID (type
));
97 return h
? h
->decl
: NULL_TREE
;
100 /* Insert a mapping TYPE->DECL in the VAR_DECL for type hashtable. */
103 decl_for_type_insert (tree type
, tree decl
)
105 struct tree_type_map
*h
;
107 h
= ggc_alloc
<tree_type_map
> ();
110 *decl_tree_for_type
->find_slot_with_hash (h
, TYPE_UID (type
), INSERT
) = h
;
113 /* Helper routine, which encodes a value in the pointer_sized_int_node.
114 Arguments with precision <= POINTER_SIZE are passed directly,
115 the rest is passed by reference. T is a value we are to encode.
116 IN_EXPAND_P is true if this function is called during expansion. */
119 ubsan_encode_value (tree t
, bool in_expand_p
)
121 tree type
= TREE_TYPE (t
);
122 const unsigned int bitsize
= GET_MODE_BITSIZE (TYPE_MODE (type
));
123 if (bitsize
<= POINTER_SIZE
)
124 switch (TREE_CODE (type
))
129 return fold_build1 (NOP_EXPR
, pointer_sized_int_node
, t
);
132 tree itype
= build_nonstandard_integer_type (bitsize
, true);
133 t
= fold_build1 (VIEW_CONVERT_EXPR
, itype
, t
);
134 return fold_convert (pointer_sized_int_node
, t
);
141 if (!DECL_P (t
) || !TREE_ADDRESSABLE (t
))
143 /* The reason for this is that we don't want to pessimize
144 code by making vars unnecessarily addressable. */
145 tree var
= create_tmp_var (type
);
146 tree tem
= build2 (MODIFY_EXPR
, void_type_node
, var
, t
);
150 = assign_stack_temp_for_type (TYPE_MODE (type
),
151 GET_MODE_SIZE (TYPE_MODE (type
)),
153 SET_DECL_RTL (var
, mem
);
154 expand_assignment (var
, t
, false);
155 return build_fold_addr_expr (var
);
157 t
= build_fold_addr_expr (var
);
158 return build2 (COMPOUND_EXPR
, TREE_TYPE (t
), tem
, t
);
161 return build_fold_addr_expr (t
);
165 /* Cached ubsan_get_type_descriptor_type () return value. */
166 static GTY(()) tree ubsan_type_descriptor_type
;
169 struct __ubsan_type_descriptor
171 unsigned short __typekind;
172 unsigned short __typeinfo;
178 ubsan_get_type_descriptor_type (void)
180 static const char *field_names
[3]
181 = { "__typekind", "__typeinfo", "__typename" };
184 if (ubsan_type_descriptor_type
)
185 return ubsan_type_descriptor_type
;
187 tree itype
= build_range_type (sizetype
, size_zero_node
, NULL_TREE
);
188 tree flex_arr_type
= build_array_type (char_type_node
, itype
);
190 ret
= make_node (RECORD_TYPE
);
191 for (int i
= 0; i
< 3; i
++)
193 fields
[i
] = build_decl (UNKNOWN_LOCATION
, FIELD_DECL
,
194 get_identifier (field_names
[i
]),
195 (i
== 2) ? flex_arr_type
196 : short_unsigned_type_node
);
197 DECL_CONTEXT (fields
[i
]) = ret
;
199 DECL_CHAIN (fields
[i
- 1]) = fields
[i
];
201 tree type_decl
= build_decl (input_location
, TYPE_DECL
,
202 get_identifier ("__ubsan_type_descriptor"),
204 DECL_IGNORED_P (type_decl
) = 1;
205 DECL_ARTIFICIAL (type_decl
) = 1;
206 TYPE_FIELDS (ret
) = fields
[0];
207 TYPE_NAME (ret
) = type_decl
;
208 TYPE_STUB_DECL (ret
) = type_decl
;
210 ubsan_type_descriptor_type
= ret
;
214 /* Cached ubsan_get_source_location_type () return value. */
215 static GTY(()) tree ubsan_source_location_type
;
218 struct __ubsan_source_location
220 const char *__filename;
222 unsigned int __column;
227 ubsan_get_source_location_type (void)
229 static const char *field_names
[3]
230 = { "__filename", "__line", "__column" };
232 if (ubsan_source_location_type
)
233 return ubsan_source_location_type
;
235 tree const_char_type
= build_qualified_type (char_type_node
,
238 ret
= make_node (RECORD_TYPE
);
239 for (int i
= 0; i
< 3; i
++)
241 fields
[i
] = build_decl (UNKNOWN_LOCATION
, FIELD_DECL
,
242 get_identifier (field_names
[i
]),
243 (i
== 0) ? build_pointer_type (const_char_type
)
244 : unsigned_type_node
);
245 DECL_CONTEXT (fields
[i
]) = ret
;
247 DECL_CHAIN (fields
[i
- 1]) = fields
[i
];
249 tree type_decl
= build_decl (input_location
, TYPE_DECL
,
250 get_identifier ("__ubsan_source_location"),
252 DECL_IGNORED_P (type_decl
) = 1;
253 DECL_ARTIFICIAL (type_decl
) = 1;
254 TYPE_FIELDS (ret
) = fields
[0];
255 TYPE_NAME (ret
) = type_decl
;
256 TYPE_STUB_DECL (ret
) = type_decl
;
258 ubsan_source_location_type
= ret
;
262 /* Helper routine that returns a CONSTRUCTOR of __ubsan_source_location
263 type with its fields filled from a location_t LOC. */
266 ubsan_source_location (location_t loc
)
268 expanded_location xloc
;
269 tree type
= ubsan_get_source_location_type ();
271 xloc
= expand_location (loc
);
273 if (xloc
.file
== NULL
)
275 str
= build_int_cst (ptr_type_node
, 0);
281 /* Fill in the values from LOC. */
282 size_t len
= strlen (xloc
.file
) + 1;
283 str
= build_string (len
, xloc
.file
);
284 TREE_TYPE (str
) = build_array_type_nelts (char_type_node
, len
);
285 TREE_READONLY (str
) = 1;
286 TREE_STATIC (str
) = 1;
287 str
= build_fold_addr_expr (str
);
289 tree ctor
= build_constructor_va (type
, 3, NULL_TREE
, str
, NULL_TREE
,
290 build_int_cst (unsigned_type_node
,
291 xloc
.line
), NULL_TREE
,
292 build_int_cst (unsigned_type_node
,
294 TREE_CONSTANT (ctor
) = 1;
295 TREE_STATIC (ctor
) = 1;
300 /* This routine returns a magic number for TYPE. */
302 static unsigned short
303 get_ubsan_type_info_for_type (tree type
)
305 gcc_assert (TYPE_SIZE (type
) && tree_fits_uhwi_p (TYPE_SIZE (type
)));
306 if (TREE_CODE (type
) == REAL_TYPE
)
307 return tree_to_uhwi (TYPE_SIZE (type
));
308 else if (INTEGRAL_TYPE_P (type
))
310 int prec
= exact_log2 (tree_to_uhwi (TYPE_SIZE (type
)));
311 gcc_assert (prec
!= -1);
312 return (prec
<< 1) | !TYPE_UNSIGNED (type
);
318 /* Helper routine that returns ADDR_EXPR of a VAR_DECL of a type
319 descriptor. It first looks into the hash table; if not found,
320 create the VAR_DECL, put it into the hash table and return the
321 ADDR_EXPR of it. TYPE describes a particular type. PSTYLE is
322 an enum controlling how we want to print the type. */
325 ubsan_type_descriptor (tree type
, enum ubsan_print_style pstyle
)
327 /* See through any typedefs. */
328 type
= TYPE_MAIN_VARIANT (type
);
330 tree decl
= decl_for_type_lookup (type
);
331 /* It is possible that some of the earlier created DECLs were found
332 unused, in that case they weren't emitted and varpool_node::get
333 returns NULL node on them. But now we really need them. Thus,
335 if (decl
!= NULL_TREE
&& varpool_node::get (decl
))
336 return build_fold_addr_expr (decl
);
338 tree dtype
= ubsan_get_type_descriptor_type ();
340 const char *tname
= NULL
;
341 pretty_printer pretty_name
;
342 unsigned char deref_depth
= 0;
343 unsigned short tkind
, tinfo
;
345 /* Get the name of the type, or the name of the pointer type. */
346 if (pstyle
== UBSAN_PRINT_POINTER
)
348 gcc_assert (POINTER_TYPE_P (type
));
349 type2
= TREE_TYPE (type
);
351 /* Remove any '*' operators from TYPE. */
352 while (POINTER_TYPE_P (type2
))
353 deref_depth
++, type2
= TREE_TYPE (type2
);
355 if (TREE_CODE (type2
) == METHOD_TYPE
)
356 type2
= TYPE_METHOD_BASETYPE (type2
);
359 /* If an array, get its type. */
360 type2
= strip_array_types (type2
);
362 if (pstyle
== UBSAN_PRINT_ARRAY
)
364 while (POINTER_TYPE_P (type2
))
365 deref_depth
++, type2
= TREE_TYPE (type2
);
368 if (TYPE_NAME (type2
) != NULL
)
370 if (TREE_CODE (TYPE_NAME (type2
)) == IDENTIFIER_NODE
)
371 tname
= IDENTIFIER_POINTER (TYPE_NAME (type2
));
372 else if (DECL_NAME (TYPE_NAME (type2
)) != NULL
)
373 tname
= IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type2
)));
377 /* We weren't able to determine the type name. */
380 if (pstyle
== UBSAN_PRINT_POINTER
)
382 pp_printf (&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 pp_star (&pretty_name
);
394 pp_quote (&pretty_name
);
396 else if (pstyle
== UBSAN_PRINT_ARRAY
)
398 /* Pretty print the array dimensions. */
399 gcc_assert (TREE_CODE (type
) == ARRAY_TYPE
);
401 pp_printf (&pretty_name
, "'%s ", tname
);
402 while (deref_depth
-- > 0)
403 pp_star (&pretty_name
);
404 while (TREE_CODE (t
) == ARRAY_TYPE
)
406 pp_left_bracket (&pretty_name
);
407 tree dom
= TYPE_DOMAIN (t
);
408 if (dom
&& TREE_CODE (TYPE_MAX_VALUE (dom
)) == INTEGER_CST
)
410 if (tree_fits_uhwi_p (TYPE_MAX_VALUE (dom
))
411 && tree_to_uhwi (TYPE_MAX_VALUE (dom
)) + 1 != 0)
412 pp_printf (&pretty_name
, HOST_WIDE_INT_PRINT_DEC
,
413 tree_to_uhwi (TYPE_MAX_VALUE (dom
)) + 1);
415 pp_wide_int (&pretty_name
,
416 wi::add (wi::to_widest (TYPE_MAX_VALUE (dom
)), 1),
417 TYPE_SIGN (TREE_TYPE (dom
)));
420 /* ??? We can't determine the variable name; print VLA unspec. */
421 pp_star (&pretty_name
);
422 pp_right_bracket (&pretty_name
);
425 pp_quote (&pretty_name
);
427 /* Save the tree with stripped types. */
431 pp_printf (&pretty_name
, "'%s'", tname
);
433 switch (TREE_CODE (type
))
441 /* FIXME: libubsan right now only supports float, double and
442 long double type formats. */
443 if (TYPE_MODE (type
) == TYPE_MODE (float_type_node
)
444 || TYPE_MODE (type
) == TYPE_MODE (double_type_node
)
445 || TYPE_MODE (type
) == TYPE_MODE (long_double_type_node
))
454 tinfo
= get_ubsan_type_info_for_type (type
);
456 /* Create a new VAR_DECL of type descriptor. */
457 const char *tmp
= pp_formatted_text (&pretty_name
);
458 size_t len
= strlen (tmp
) + 1;
459 tree str
= build_string (len
, tmp
);
460 TREE_TYPE (str
) = build_array_type_nelts (char_type_node
, len
);
461 TREE_READONLY (str
) = 1;
462 TREE_STATIC (str
) = 1;
465 static unsigned int type_var_id_num
;
466 ASM_GENERATE_INTERNAL_LABEL (tmp_name
, "Lubsan_type", type_var_id_num
++);
467 decl
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
, get_identifier (tmp_name
),
469 TREE_STATIC (decl
) = 1;
470 TREE_PUBLIC (decl
) = 0;
471 DECL_ARTIFICIAL (decl
) = 1;
472 DECL_IGNORED_P (decl
) = 1;
473 DECL_EXTERNAL (decl
) = 0;
475 = size_binop (PLUS_EXPR
, DECL_SIZE (decl
), TYPE_SIZE (TREE_TYPE (str
)));
476 DECL_SIZE_UNIT (decl
)
477 = size_binop (PLUS_EXPR
, DECL_SIZE_UNIT (decl
),
478 TYPE_SIZE_UNIT (TREE_TYPE (str
)));
480 tree ctor
= build_constructor_va (dtype
, 3, NULL_TREE
,
481 build_int_cst (short_unsigned_type_node
,
483 build_int_cst (short_unsigned_type_node
,
484 tinfo
), NULL_TREE
, str
);
485 TREE_CONSTANT (ctor
) = 1;
486 TREE_STATIC (ctor
) = 1;
487 DECL_INITIAL (decl
) = ctor
;
488 varpool_node::finalize_decl (decl
);
490 /* Save the VAR_DECL into the hash table. */
491 decl_for_type_insert (type
, decl
);
493 return build_fold_addr_expr (decl
);
496 /* Create a structure for the ubsan library. NAME is a name of the new
497 structure. LOCCNT is number of locations, PLOC points to array of
498 locations. The arguments in ... are of __ubsan_type_descriptor type
499 and there are at most two of them, followed by NULL_TREE, followed
500 by optional extra arguments and another NULL_TREE. */
503 ubsan_create_data (const char *name
, int loccnt
, const location_t
*ploc
, ...)
508 vec
<tree
, va_gc
> *saved_args
= NULL
;
512 /* Firstly, create a pointer to type descriptor type. */
513 tree td_type
= ubsan_get_type_descriptor_type ();
514 td_type
= build_pointer_type (td_type
);
516 /* Create the structure type. */
517 ret
= make_node (RECORD_TYPE
);
518 for (j
= 0; j
< loccnt
; j
++)
520 gcc_checking_assert (i
< 2);
521 fields
[i
] = build_decl (UNKNOWN_LOCATION
, FIELD_DECL
, NULL_TREE
,
522 ubsan_get_source_location_type ());
523 DECL_CONTEXT (fields
[i
]) = ret
;
525 DECL_CHAIN (fields
[i
- 1]) = fields
[i
];
529 va_start (args
, ploc
);
530 for (t
= va_arg (args
, tree
); t
!= NULL_TREE
;
531 i
++, t
= va_arg (args
, tree
))
533 gcc_checking_assert (i
< 4);
534 /* Save the tree arguments for later use. */
535 vec_safe_push (saved_args
, t
);
536 fields
[i
] = build_decl (UNKNOWN_LOCATION
, FIELD_DECL
, NULL_TREE
,
538 DECL_CONTEXT (fields
[i
]) = ret
;
540 DECL_CHAIN (fields
[i
- 1]) = fields
[i
];
543 for (t
= va_arg (args
, tree
); t
!= NULL_TREE
;
544 i
++, t
= va_arg (args
, tree
))
546 gcc_checking_assert (i
< 6);
547 /* Save the tree arguments for later use. */
548 vec_safe_push (saved_args
, t
);
549 fields
[i
] = build_decl (UNKNOWN_LOCATION
, FIELD_DECL
, NULL_TREE
,
551 DECL_CONTEXT (fields
[i
]) = ret
;
553 DECL_CHAIN (fields
[i
- 1]) = fields
[i
];
557 tree type_decl
= build_decl (input_location
, TYPE_DECL
,
558 get_identifier (name
), ret
);
559 DECL_IGNORED_P (type_decl
) = 1;
560 DECL_ARTIFICIAL (type_decl
) = 1;
561 TYPE_FIELDS (ret
) = fields
[0];
562 TYPE_NAME (ret
) = type_decl
;
563 TYPE_STUB_DECL (ret
) = type_decl
;
566 /* Now, fill in the type. */
568 static unsigned int ubsan_var_id_num
;
569 ASM_GENERATE_INTERNAL_LABEL (tmp_name
, "Lubsan_data", ubsan_var_id_num
++);
570 tree var
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
, get_identifier (tmp_name
),
572 TREE_STATIC (var
) = 1;
573 TREE_PUBLIC (var
) = 0;
574 DECL_ARTIFICIAL (var
) = 1;
575 DECL_IGNORED_P (var
) = 1;
576 DECL_EXTERNAL (var
) = 0;
578 vec
<constructor_elt
, va_gc
> *v
;
580 tree ctor
= build_constructor (ret
, v
);
582 /* If desirable, set the __ubsan_source_location element. */
583 for (j
= 0; j
< loccnt
; j
++)
585 location_t loc
= LOCATION_LOCUS (ploc
[j
]);
586 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, ubsan_source_location (loc
));
589 size_t nelts
= vec_safe_length (saved_args
);
590 for (i
= 0; i
< nelts
; i
++)
592 t
= (*saved_args
)[i
];
593 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, t
);
596 TREE_CONSTANT (ctor
) = 1;
597 TREE_STATIC (ctor
) = 1;
598 DECL_INITIAL (var
) = ctor
;
599 varpool_node::finalize_decl (var
);
604 /* Instrument the __builtin_unreachable call. We just call the libubsan
608 ubsan_instrument_unreachable (gimple_stmt_iterator
*gsi
)
611 location_t loc
= gimple_location (gsi_stmt (*gsi
));
613 if (flag_sanitize_undefined_trap_on_error
)
614 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
617 tree data
= ubsan_create_data ("__ubsan_unreachable_data", 1, &loc
,
618 NULL_TREE
, NULL_TREE
);
619 data
= build_fold_addr_expr_loc (loc
, data
);
621 = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE
);
622 g
= gimple_build_call (fn
, 1, data
);
624 gimple_set_location (g
, loc
);
625 gsi_replace (gsi
, g
, false);
629 /* Return true if T is a call to a libubsan routine. */
632 is_ubsan_builtin_p (tree t
)
634 return TREE_CODE (t
) == FUNCTION_DECL
635 && DECL_BUILT_IN_CLASS (t
) == BUILT_IN_NORMAL
636 && strncmp (IDENTIFIER_POINTER (DECL_NAME (t
)),
637 "__builtin___ubsan_", 18) == 0;
640 /* Create a callgraph edge for statement STMT. */
643 ubsan_create_edge (gimple
*stmt
)
645 gcall
*call_stmt
= dyn_cast
<gcall
*> (stmt
);
646 basic_block bb
= gimple_bb (stmt
);
647 int freq
= compute_call_stmt_bb_frequency (current_function_decl
, bb
);
648 cgraph_node
*node
= cgraph_node::get (current_function_decl
);
649 tree decl
= gimple_call_fndecl (call_stmt
);
651 node
->create_edge (cgraph_node::get_create (decl
), call_stmt
, bb
->count
,
655 /* Expand the UBSAN_BOUNDS special builtin function. */
658 ubsan_expand_bounds_ifn (gimple_stmt_iterator
*gsi
)
660 gimple
*stmt
= gsi_stmt (*gsi
);
661 location_t loc
= gimple_location (stmt
);
662 gcc_assert (gimple_call_num_args (stmt
) == 3);
664 /* Pick up the arguments of the UBSAN_BOUNDS call. */
665 tree type
= TREE_TYPE (TREE_TYPE (gimple_call_arg (stmt
, 0)));
666 tree index
= gimple_call_arg (stmt
, 1);
667 tree orig_index_type
= TREE_TYPE (index
);
668 tree bound
= gimple_call_arg (stmt
, 2);
670 gimple_stmt_iterator gsi_orig
= *gsi
;
672 /* Create condition "if (index > bound)". */
673 basic_block then_bb
, fallthru_bb
;
674 gimple_stmt_iterator cond_insert_point
675 = create_cond_insert_point (gsi
, false, false, true,
676 &then_bb
, &fallthru_bb
);
677 index
= fold_convert (TREE_TYPE (bound
), index
);
678 index
= force_gimple_operand_gsi (&cond_insert_point
, index
,
680 false, GSI_NEW_STMT
);
681 gimple
*g
= gimple_build_cond (GT_EXPR
, index
, bound
, NULL_TREE
, NULL_TREE
);
682 gimple_set_location (g
, loc
);
683 gsi_insert_after (&cond_insert_point
, g
, GSI_NEW_STMT
);
685 /* Generate __ubsan_handle_out_of_bounds call. */
686 *gsi
= gsi_after_labels (then_bb
);
687 if (flag_sanitize_undefined_trap_on_error
)
688 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
692 = ubsan_create_data ("__ubsan_out_of_bounds_data", 1, &loc
,
693 ubsan_type_descriptor (type
, UBSAN_PRINT_ARRAY
),
694 ubsan_type_descriptor (orig_index_type
),
695 NULL_TREE
, NULL_TREE
);
696 data
= build_fold_addr_expr_loc (loc
, data
);
697 enum built_in_function bcode
698 = (flag_sanitize_recover
& SANITIZE_BOUNDS
)
699 ? BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS
700 : BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS_ABORT
;
701 tree fn
= builtin_decl_explicit (bcode
);
702 tree val
= force_gimple_operand_gsi (gsi
, ubsan_encode_value (index
),
703 true, NULL_TREE
, true,
705 g
= gimple_build_call (fn
, 2, data
, val
);
707 gimple_set_location (g
, loc
);
708 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
710 /* Get rid of the UBSAN_BOUNDS call from the IR. */
711 unlink_stmt_vdef (stmt
);
712 gsi_remove (&gsi_orig
, true);
714 /* Point GSI to next logical statement. */
715 *gsi
= gsi_start_bb (fallthru_bb
);
719 /* Expand UBSAN_NULL internal call. The type is kept on the ckind
720 argument which is a constant, because the middle-end treats pointer
721 conversions as useless and therefore the type of the first argument
722 could be changed to any other pointer type. */
725 ubsan_expand_null_ifn (gimple_stmt_iterator
*gsip
)
727 gimple_stmt_iterator gsi
= *gsip
;
728 gimple
*stmt
= gsi_stmt (gsi
);
729 location_t loc
= gimple_location (stmt
);
730 gcc_assert (gimple_call_num_args (stmt
) == 3);
731 tree ptr
= gimple_call_arg (stmt
, 0);
732 tree ckind
= gimple_call_arg (stmt
, 1);
733 tree align
= gimple_call_arg (stmt
, 2);
734 tree check_align
= NULL_TREE
;
737 basic_block cur_bb
= gsi_bb (gsi
);
740 if (!integer_zerop (align
))
742 unsigned int ptralign
= get_pointer_alignment (ptr
) / BITS_PER_UNIT
;
743 if (compare_tree_int (align
, ptralign
) == 1)
745 check_align
= make_ssa_name (pointer_sized_int_node
);
746 g
= gimple_build_assign (check_align
, NOP_EXPR
, ptr
);
747 gimple_set_location (g
, loc
);
748 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
751 check_null
= (flag_sanitize
& SANITIZE_NULL
) != 0;
753 if (check_align
== NULL_TREE
&& !check_null
)
755 gsi_remove (gsip
, true);
756 /* Unlink the UBSAN_NULLs vops before replacing it. */
757 unlink_stmt_vdef (stmt
);
761 /* Split the original block holding the pointer dereference. */
762 edge e
= split_block (cur_bb
, stmt
);
764 /* Get a hold on the 'condition block', the 'then block' and the
766 basic_block cond_bb
= e
->src
;
767 basic_block fallthru_bb
= e
->dest
;
768 basic_block then_bb
= create_empty_bb (cond_bb
);
769 add_bb_to_loop (then_bb
, cond_bb
->loop_father
);
770 loops_state_set (LOOPS_NEED_FIXUP
);
772 /* Make an edge coming from the 'cond block' into the 'then block';
773 this edge is unlikely taken, so set up the probability accordingly. */
774 e
= make_edge (cond_bb
, then_bb
, EDGE_TRUE_VALUE
);
775 e
->probability
= PROB_VERY_UNLIKELY
;
777 /* Connect 'then block' with the 'else block'. This is needed
778 as the ubsan routines we call in the 'then block' are not noreturn.
779 The 'then block' only has one outcoming edge. */
780 make_single_succ_edge (then_bb
, fallthru_bb
, EDGE_FALLTHRU
);
782 /* Set up the fallthrough basic block. */
783 e
= find_edge (cond_bb
, fallthru_bb
);
784 e
->flags
= EDGE_FALSE_VALUE
;
785 e
->count
= cond_bb
->count
;
786 e
->probability
= REG_BR_PROB_BASE
- PROB_VERY_UNLIKELY
;
788 /* Update dominance info for the newly created then_bb; note that
789 fallthru_bb's dominance info has already been updated by
791 if (dom_info_available_p (CDI_DOMINATORS
))
792 set_immediate_dominator (CDI_DOMINATORS
, then_bb
, cond_bb
);
794 /* Put the ubsan builtin call into the newly created BB. */
795 if (flag_sanitize_undefined_trap_on_error
)
796 g
= gimple_build_call (builtin_decl_implicit (BUILT_IN_TRAP
), 0);
799 enum built_in_function bcode
800 = (flag_sanitize_recover
& ((check_align
? SANITIZE_ALIGNMENT
: 0)
801 | (check_null
? SANITIZE_NULL
: 0)))
802 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
803 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT
;
804 tree fn
= builtin_decl_implicit (bcode
);
806 = ubsan_create_data ("__ubsan_null_data", 1, &loc
,
807 ubsan_type_descriptor (TREE_TYPE (ckind
),
808 UBSAN_PRINT_POINTER
),
811 fold_convert (unsigned_char_type_node
, ckind
),
813 data
= build_fold_addr_expr_loc (loc
, data
);
814 g
= gimple_build_call (fn
, 2, data
,
815 check_align
? check_align
816 : build_zero_cst (pointer_sized_int_node
));
818 gimple_stmt_iterator gsi2
= gsi_start_bb (then_bb
);
819 gimple_set_location (g
, loc
);
820 gsi_insert_after (&gsi2
, g
, GSI_NEW_STMT
);
822 /* Unlink the UBSAN_NULLs vops before replacing it. */
823 unlink_stmt_vdef (stmt
);
827 g
= gimple_build_cond (EQ_EXPR
, ptr
, build_int_cst (TREE_TYPE (ptr
), 0),
828 NULL_TREE
, NULL_TREE
);
829 gimple_set_location (g
, loc
);
831 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
832 gsi_replace (&gsi
, g
, false);
840 /* Split the block with the condition again. */
841 e
= split_block (cond_bb
, stmt
);
842 basic_block cond1_bb
= e
->src
;
843 basic_block cond2_bb
= e
->dest
;
845 /* Make an edge coming from the 'cond1 block' into the 'then block';
846 this edge is unlikely taken, so set up the probability
848 e
= make_edge (cond1_bb
, then_bb
, EDGE_TRUE_VALUE
);
849 e
->probability
= PROB_VERY_UNLIKELY
;
851 /* Set up the fallthrough basic block. */
852 e
= find_edge (cond1_bb
, cond2_bb
);
853 e
->flags
= EDGE_FALSE_VALUE
;
854 e
->count
= cond1_bb
->count
;
855 e
->probability
= REG_BR_PROB_BASE
- PROB_VERY_UNLIKELY
;
857 /* Update dominance info. */
858 if (dom_info_available_p (CDI_DOMINATORS
))
860 set_immediate_dominator (CDI_DOMINATORS
, fallthru_bb
, cond1_bb
);
861 set_immediate_dominator (CDI_DOMINATORS
, then_bb
, cond1_bb
);
864 gsi2
= gsi_start_bb (cond2_bb
);
867 tree mask
= build_int_cst (pointer_sized_int_node
,
868 tree_to_uhwi (align
) - 1);
869 g
= gimple_build_assign (make_ssa_name (pointer_sized_int_node
),
870 BIT_AND_EXPR
, check_align
, mask
);
871 gimple_set_location (g
, loc
);
873 gsi_insert_after (&gsi2
, g
, GSI_NEW_STMT
);
875 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
877 g
= gimple_build_cond (NE_EXPR
, gimple_assign_lhs (g
),
878 build_int_cst (pointer_sized_int_node
, 0),
879 NULL_TREE
, NULL_TREE
);
880 gimple_set_location (g
, loc
);
882 gsi_insert_after (&gsi2
, g
, GSI_NEW_STMT
);
884 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
885 gsi_replace (&gsi
, g
, false);
890 #define OBJSZ_MAX_OFFSET (1024 * 16)
892 /* Expand UBSAN_OBJECT_SIZE internal call. */
895 ubsan_expand_objsize_ifn (gimple_stmt_iterator
*gsi
)
897 gimple
*stmt
= gsi_stmt (*gsi
);
898 location_t loc
= gimple_location (stmt
);
899 gcc_assert (gimple_call_num_args (stmt
) == 4);
901 tree ptr
= gimple_call_arg (stmt
, 0);
902 tree offset
= gimple_call_arg (stmt
, 1);
903 tree size
= gimple_call_arg (stmt
, 2);
904 tree ckind
= gimple_call_arg (stmt
, 3);
905 gimple_stmt_iterator gsi_orig
= *gsi
;
908 /* See if we can discard the check. */
909 if (TREE_CODE (size
) != INTEGER_CST
910 || integer_all_onesp (size
))
911 /* Yes, __builtin_object_size couldn't determine the
913 else if (TREE_CODE (offset
) == INTEGER_CST
914 && wi::ges_p (wi::to_widest (offset
), -OBJSZ_MAX_OFFSET
)
915 && wi::les_p (wi::to_widest (offset
), -1))
916 /* The offset is in range [-16K, -1]. */;
919 /* if (offset > objsize) */
920 basic_block then_bb
, fallthru_bb
;
921 gimple_stmt_iterator cond_insert_point
922 = create_cond_insert_point (gsi
, false, false, true,
923 &then_bb
, &fallthru_bb
);
924 g
= gimple_build_cond (GT_EXPR
, offset
, size
, NULL_TREE
, NULL_TREE
);
925 gimple_set_location (g
, loc
);
926 gsi_insert_after (&cond_insert_point
, g
, GSI_NEW_STMT
);
928 /* If the offset is small enough, we don't need the second
930 if (TREE_CODE (offset
) == INTEGER_CST
931 && wi::ges_p (wi::to_widest (offset
), 0)
932 && wi::les_p (wi::to_widest (offset
), OBJSZ_MAX_OFFSET
))
933 *gsi
= gsi_after_labels (then_bb
);
936 /* Don't issue run-time error if (ptr > ptr + offset). That
937 may happen when computing a POINTER_PLUS_EXPR. */
938 basic_block then2_bb
, fallthru2_bb
;
940 gimple_stmt_iterator gsi2
= gsi_after_labels (then_bb
);
941 cond_insert_point
= create_cond_insert_point (&gsi2
, false, false,
944 /* Convert the pointer to an integer type. */
945 tree p
= make_ssa_name (pointer_sized_int_node
);
946 g
= gimple_build_assign (p
, NOP_EXPR
, ptr
);
947 gimple_set_location (g
, loc
);
948 gsi_insert_before (&cond_insert_point
, g
, GSI_NEW_STMT
);
949 p
= gimple_assign_lhs (g
);
950 /* Compute ptr + offset. */
951 g
= gimple_build_assign (make_ssa_name (pointer_sized_int_node
),
952 PLUS_EXPR
, p
, offset
);
953 gimple_set_location (g
, loc
);
954 gsi_insert_after (&cond_insert_point
, g
, GSI_NEW_STMT
);
955 /* Now build the conditional and put it into the IR. */
956 g
= gimple_build_cond (LE_EXPR
, p
, gimple_assign_lhs (g
),
957 NULL_TREE
, NULL_TREE
);
958 gimple_set_location (g
, loc
);
959 gsi_insert_after (&cond_insert_point
, g
, GSI_NEW_STMT
);
960 *gsi
= gsi_after_labels (then2_bb
);
963 /* Generate __ubsan_handle_type_mismatch call. */
964 if (flag_sanitize_undefined_trap_on_error
)
965 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
969 = ubsan_create_data ("__ubsan_objsz_data", 1, &loc
,
970 ubsan_type_descriptor (TREE_TYPE (ptr
),
971 UBSAN_PRINT_POINTER
),
973 build_zero_cst (pointer_sized_int_node
),
976 data
= build_fold_addr_expr_loc (loc
, data
);
977 enum built_in_function bcode
978 = (flag_sanitize_recover
& SANITIZE_OBJECT_SIZE
)
979 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
980 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT
;
981 tree p
= make_ssa_name (pointer_sized_int_node
);
982 g
= gimple_build_assign (p
, NOP_EXPR
, ptr
);
983 gimple_set_location (g
, loc
);
984 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
985 g
= gimple_build_call (builtin_decl_explicit (bcode
), 2, data
, p
);
987 gimple_set_location (g
, loc
);
988 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
990 /* Point GSI to next logical statement. */
991 *gsi
= gsi_start_bb (fallthru_bb
);
993 /* Get rid of the UBSAN_OBJECT_SIZE call from the IR. */
994 unlink_stmt_vdef (stmt
);
995 gsi_remove (&gsi_orig
, true);
999 /* Get rid of the UBSAN_OBJECT_SIZE call from the IR. */
1000 unlink_stmt_vdef (stmt
);
1001 gsi_remove (gsi
, true);
1005 /* Cached __ubsan_vptr_type_cache decl. */
1006 static GTY(()) tree ubsan_vptr_type_cache_decl
;
1008 /* Expand UBSAN_VPTR internal call. The type is kept on the ckind
1009 argument which is a constant, because the middle-end treats pointer
1010 conversions as useless and therefore the type of the first argument
1011 could be changed to any other pointer type. */
1014 ubsan_expand_vptr_ifn (gimple_stmt_iterator
*gsip
)
1016 gimple_stmt_iterator gsi
= *gsip
;
1017 gimple
*stmt
= gsi_stmt (gsi
);
1018 location_t loc
= gimple_location (stmt
);
1019 gcc_assert (gimple_call_num_args (stmt
) == 5);
1020 tree op
= gimple_call_arg (stmt
, 0);
1021 tree vptr
= gimple_call_arg (stmt
, 1);
1022 tree str_hash
= gimple_call_arg (stmt
, 2);
1023 tree ti_decl_addr
= gimple_call_arg (stmt
, 3);
1024 tree ckind_tree
= gimple_call_arg (stmt
, 4);
1025 ubsan_null_ckind ckind
= (ubsan_null_ckind
) tree_to_uhwi (ckind_tree
);
1026 tree type
= TREE_TYPE (TREE_TYPE (ckind_tree
));
1028 basic_block fallthru_bb
= NULL
;
1030 if (ckind
== UBSAN_DOWNCAST_POINTER
)
1032 /* Guard everything with if (op != NULL) { ... }. */
1033 basic_block then_bb
;
1034 gimple_stmt_iterator cond_insert_point
1035 = create_cond_insert_point (gsip
, false, false, true,
1036 &then_bb
, &fallthru_bb
);
1037 g
= gimple_build_cond (NE_EXPR
, op
, build_zero_cst (TREE_TYPE (op
)),
1038 NULL_TREE
, NULL_TREE
);
1039 gimple_set_location (g
, loc
);
1040 gsi_insert_after (&cond_insert_point
, g
, GSI_NEW_STMT
);
1041 *gsip
= gsi_after_labels (then_bb
);
1042 gsi_remove (&gsi
, false);
1043 gsi_insert_before (gsip
, stmt
, GSI_NEW_STMT
);
1047 tree htype
= TREE_TYPE (str_hash
);
1048 tree cst
= wide_int_to_tree (htype
,
1049 wi::uhwi (((uint64_t) 0x9ddfea08 << 32)
1051 g
= gimple_build_assign (make_ssa_name (htype
), BIT_XOR_EXPR
,
1053 gimple_set_location (g
, loc
);
1054 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1055 g
= gimple_build_assign (make_ssa_name (htype
), MULT_EXPR
,
1056 gimple_assign_lhs (g
), cst
);
1057 gimple_set_location (g
, loc
);
1058 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1059 tree t1
= gimple_assign_lhs (g
);
1060 g
= gimple_build_assign (make_ssa_name (htype
), LSHIFT_EXPR
,
1061 t1
, build_int_cst (integer_type_node
, 47));
1062 gimple_set_location (g
, loc
);
1063 tree t2
= gimple_assign_lhs (g
);
1064 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1065 g
= gimple_build_assign (make_ssa_name (htype
), BIT_XOR_EXPR
,
1067 gimple_set_location (g
, loc
);
1068 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1069 g
= gimple_build_assign (make_ssa_name (htype
), BIT_XOR_EXPR
,
1070 t2
, gimple_assign_lhs (g
));
1071 gimple_set_location (g
, loc
);
1072 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1073 g
= gimple_build_assign (make_ssa_name (htype
), MULT_EXPR
,
1074 gimple_assign_lhs (g
), cst
);
1075 gimple_set_location (g
, loc
);
1076 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1077 tree t3
= gimple_assign_lhs (g
);
1078 g
= gimple_build_assign (make_ssa_name (htype
), LSHIFT_EXPR
,
1079 t3
, build_int_cst (integer_type_node
, 47));
1080 gimple_set_location (g
, loc
);
1081 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1082 g
= gimple_build_assign (make_ssa_name (htype
), BIT_XOR_EXPR
,
1083 t3
, gimple_assign_lhs (g
));
1084 gimple_set_location (g
, loc
);
1085 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1086 g
= gimple_build_assign (make_ssa_name (htype
), MULT_EXPR
,
1087 gimple_assign_lhs (g
), cst
);
1088 gimple_set_location (g
, loc
);
1089 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1090 if (!useless_type_conversion_p (pointer_sized_int_node
, htype
))
1092 g
= gimple_build_assign (make_ssa_name (pointer_sized_int_node
),
1093 NOP_EXPR
, gimple_assign_lhs (g
));
1094 gimple_set_location (g
, loc
);
1095 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1097 tree hash
= gimple_assign_lhs (g
);
1099 if (ubsan_vptr_type_cache_decl
== NULL_TREE
)
1101 tree atype
= build_array_type_nelts (pointer_sized_int_node
, 128);
1102 tree array
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
,
1103 get_identifier ("__ubsan_vptr_type_cache"),
1105 DECL_ARTIFICIAL (array
) = 1;
1106 DECL_IGNORED_P (array
) = 1;
1107 TREE_PUBLIC (array
) = 1;
1108 TREE_STATIC (array
) = 1;
1109 DECL_EXTERNAL (array
) = 1;
1110 DECL_VISIBILITY (array
) = VISIBILITY_DEFAULT
;
1111 DECL_VISIBILITY_SPECIFIED (array
) = 1;
1112 varpool_node::finalize_decl (array
);
1113 ubsan_vptr_type_cache_decl
= array
;
1116 g
= gimple_build_assign (make_ssa_name (pointer_sized_int_node
),
1118 build_int_cst (pointer_sized_int_node
, 127));
1119 gimple_set_location (g
, loc
);
1120 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1122 tree c
= build4_loc (loc
, ARRAY_REF
, pointer_sized_int_node
,
1123 ubsan_vptr_type_cache_decl
, gimple_assign_lhs (g
),
1124 NULL_TREE
, NULL_TREE
);
1125 g
= gimple_build_assign (make_ssa_name (pointer_sized_int_node
),
1127 gimple_set_location (g
, loc
);
1128 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1130 basic_block then_bb
, fallthru2_bb
;
1131 gimple_stmt_iterator cond_insert_point
1132 = create_cond_insert_point (gsip
, false, false, true,
1133 &then_bb
, &fallthru2_bb
);
1134 g
= gimple_build_cond (NE_EXPR
, gimple_assign_lhs (g
), hash
,
1135 NULL_TREE
, NULL_TREE
);
1136 gimple_set_location (g
, loc
);
1137 gsi_insert_after (&cond_insert_point
, g
, GSI_NEW_STMT
);
1138 *gsip
= gsi_after_labels (then_bb
);
1139 if (fallthru_bb
== NULL
)
1140 fallthru_bb
= fallthru2_bb
;
1143 = ubsan_create_data ("__ubsan_vptr_data", 1, &loc
,
1144 ubsan_type_descriptor (type
), NULL_TREE
, ti_decl_addr
,
1145 build_int_cst (unsigned_char_type_node
, ckind
),
1147 data
= build_fold_addr_expr_loc (loc
, data
);
1148 enum built_in_function bcode
1149 = (flag_sanitize_recover
& SANITIZE_VPTR
)
1150 ? BUILT_IN_UBSAN_HANDLE_DYNAMIC_TYPE_CACHE_MISS
1151 : BUILT_IN_UBSAN_HANDLE_DYNAMIC_TYPE_CACHE_MISS_ABORT
;
1153 g
= gimple_build_call (builtin_decl_explicit (bcode
), 3, data
, op
, hash
);
1154 gimple_set_location (g
, loc
);
1155 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1157 /* Point GSI to next logical statement. */
1158 *gsip
= gsi_start_bb (fallthru_bb
);
1160 /* Get rid of the UBSAN_VPTR call from the IR. */
1161 unlink_stmt_vdef (stmt
);
1162 gsi_remove (&gsi
, true);
1166 /* Instrument a memory reference. BASE is the base of MEM, IS_LHS says
1167 whether the pointer is on the left hand side of the assignment. */
1170 instrument_mem_ref (tree mem
, tree base
, gimple_stmt_iterator
*iter
,
1173 enum ubsan_null_ckind ikind
= is_lhs
? UBSAN_STORE_OF
: UBSAN_LOAD_OF
;
1174 unsigned int align
= 0;
1175 if (flag_sanitize
& SANITIZE_ALIGNMENT
)
1177 align
= min_align_of_type (TREE_TYPE (base
));
1181 if (align
== 0 && (flag_sanitize
& SANITIZE_NULL
) == 0)
1183 tree t
= TREE_OPERAND (base
, 0);
1184 if (!POINTER_TYPE_P (TREE_TYPE (t
)))
1186 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (base
)) && mem
!= base
)
1187 ikind
= UBSAN_MEMBER_ACCESS
;
1188 tree kind
= build_int_cst (build_pointer_type (TREE_TYPE (base
)), ikind
);
1189 tree alignt
= build_int_cst (pointer_sized_int_node
, align
);
1190 gcall
*g
= gimple_build_call_internal (IFN_UBSAN_NULL
, 3, t
, kind
, alignt
);
1191 gimple_set_location (g
, gimple_location (gsi_stmt (*iter
)));
1192 gsi_insert_before (iter
, g
, GSI_SAME_STMT
);
1195 /* Perform the pointer instrumentation. */
1198 instrument_null (gimple_stmt_iterator gsi
, bool is_lhs
)
1200 gimple
*stmt
= gsi_stmt (gsi
);
1201 tree t
= is_lhs
? gimple_get_lhs (stmt
) : gimple_assign_rhs1 (stmt
);
1202 tree base
= get_base_address (t
);
1203 const enum tree_code code
= TREE_CODE (base
);
1205 && TREE_CODE (TREE_OPERAND (base
, 0)) == SSA_NAME
)
1206 instrument_mem_ref (t
, base
, &gsi
, is_lhs
);
1209 /* Build an ubsan builtin call for the signed-integer-overflow
1210 sanitization. CODE says what kind of builtin are we building,
1211 LOC is a location, LHSTYPE is the type of LHS, OP0 and OP1
1212 are operands of the binary operation. */
1215 ubsan_build_overflow_builtin (tree_code code
, location_t loc
, tree lhstype
,
1218 if (flag_sanitize_undefined_trap_on_error
)
1219 return build_call_expr_loc (loc
, builtin_decl_explicit (BUILT_IN_TRAP
), 0);
1221 tree data
= ubsan_create_data ("__ubsan_overflow_data", 1, &loc
,
1222 ubsan_type_descriptor (lhstype
), NULL_TREE
,
1224 enum built_in_function fn_code
;
1229 fn_code
= (flag_sanitize_recover
& SANITIZE_SI_OVERFLOW
)
1230 ? BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW
1231 : BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW_ABORT
;
1234 fn_code
= (flag_sanitize_recover
& SANITIZE_SI_OVERFLOW
)
1235 ? BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW
1236 : BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW_ABORT
;
1239 fn_code
= (flag_sanitize_recover
& SANITIZE_SI_OVERFLOW
)
1240 ? BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW
1241 : BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW_ABORT
;
1244 fn_code
= (flag_sanitize_recover
& SANITIZE_SI_OVERFLOW
)
1245 ? BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW
1246 : BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW_ABORT
;
1251 tree fn
= builtin_decl_explicit (fn_code
);
1252 return build_call_expr_loc (loc
, fn
, 2 + (code
!= NEGATE_EXPR
),
1253 build_fold_addr_expr_loc (loc
, data
),
1254 ubsan_encode_value (op0
, true),
1255 op1
? ubsan_encode_value (op1
, true)
1259 /* Perform the signed integer instrumentation. GSI is the iterator
1260 pointing at statement we are trying to instrument. */
1263 instrument_si_overflow (gimple_stmt_iterator gsi
)
1265 gimple
*stmt
= gsi_stmt (gsi
);
1266 tree_code code
= gimple_assign_rhs_code (stmt
);
1267 tree lhs
= gimple_assign_lhs (stmt
);
1268 tree lhstype
= TREE_TYPE (lhs
);
1272 /* If this is not a signed operation, don't instrument anything here.
1273 Also punt on bit-fields. */
1274 if (!INTEGRAL_TYPE_P (lhstype
)
1275 || TYPE_OVERFLOW_WRAPS (lhstype
)
1276 || GET_MODE_BITSIZE (TYPE_MODE (lhstype
)) != TYPE_PRECISION (lhstype
))
1287 i = UBSAN_CHECK_{ADD,SUB,MUL} (u, 5); */
1288 a
= gimple_assign_rhs1 (stmt
);
1289 b
= gimple_assign_rhs2 (stmt
);
1290 g
= gimple_build_call_internal (code
== PLUS_EXPR
1291 ? IFN_UBSAN_CHECK_ADD
1292 : code
== MINUS_EXPR
1293 ? IFN_UBSAN_CHECK_SUB
1294 : IFN_UBSAN_CHECK_MUL
, 2, a
, b
);
1295 gimple_call_set_lhs (g
, lhs
);
1296 gsi_replace (&gsi
, g
, false);
1299 /* Represent i = -u;
1301 i = UBSAN_CHECK_SUB (0, u); */
1302 a
= build_int_cst (lhstype
, 0);
1303 b
= gimple_assign_rhs1 (stmt
);
1304 g
= gimple_build_call_internal (IFN_UBSAN_CHECK_SUB
, 2, a
, b
);
1305 gimple_call_set_lhs (g
, lhs
);
1306 gsi_replace (&gsi
, g
, false);
1309 /* Transform i = ABS_EXPR<u>;
1311 _N = UBSAN_CHECK_SUB (0, u);
1312 i = ABS_EXPR<_N>; */
1313 a
= build_int_cst (lhstype
, 0);
1314 b
= gimple_assign_rhs1 (stmt
);
1315 g
= gimple_build_call_internal (IFN_UBSAN_CHECK_SUB
, 2, a
, b
);
1316 a
= make_ssa_name (lhstype
);
1317 gimple_call_set_lhs (g
, a
);
1318 gimple_set_location (g
, gimple_location (stmt
));
1319 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
1320 gimple_assign_set_rhs1 (stmt
, a
);
1328 /* Instrument loads from (non-bitfield) bool and C++ enum values
1329 to check if the memory value is outside of the range of the valid
1333 instrument_bool_enum_load (gimple_stmt_iterator
*gsi
)
1335 gimple
*stmt
= gsi_stmt (*gsi
);
1336 tree rhs
= gimple_assign_rhs1 (stmt
);
1337 tree type
= TREE_TYPE (rhs
);
1338 tree minv
= NULL_TREE
, maxv
= NULL_TREE
;
1340 if (TREE_CODE (type
) == BOOLEAN_TYPE
&& (flag_sanitize
& SANITIZE_BOOL
))
1342 minv
= boolean_false_node
;
1343 maxv
= boolean_true_node
;
1345 else if (TREE_CODE (type
) == ENUMERAL_TYPE
1346 && (flag_sanitize
& SANITIZE_ENUM
)
1347 && TREE_TYPE (type
) != NULL_TREE
1348 && TREE_CODE (TREE_TYPE (type
)) == INTEGER_TYPE
1349 && (TYPE_PRECISION (TREE_TYPE (type
))
1350 < GET_MODE_PRECISION (TYPE_MODE (type
))))
1352 minv
= TYPE_MIN_VALUE (TREE_TYPE (type
));
1353 maxv
= TYPE_MAX_VALUE (TREE_TYPE (type
));
1358 int modebitsize
= GET_MODE_BITSIZE (TYPE_MODE (type
));
1359 HOST_WIDE_INT bitsize
, bitpos
;
1362 int volatilep
= 0, reversep
, unsignedp
= 0;
1363 tree base
= get_inner_reference (rhs
, &bitsize
, &bitpos
, &offset
, &mode
,
1364 &unsignedp
, &reversep
, &volatilep
, false);
1365 tree utype
= build_nonstandard_integer_type (modebitsize
, 1);
1367 if ((TREE_CODE (base
) == VAR_DECL
&& DECL_HARD_REGISTER (base
))
1368 || (bitpos
% modebitsize
) != 0
1369 || bitsize
!= modebitsize
1370 || GET_MODE_BITSIZE (TYPE_MODE (utype
)) != modebitsize
1371 || TREE_CODE (gimple_assign_lhs (stmt
)) != SSA_NAME
)
1374 bool ends_bb
= stmt_ends_bb_p (stmt
);
1375 location_t loc
= gimple_location (stmt
);
1376 tree lhs
= gimple_assign_lhs (stmt
);
1377 tree ptype
= build_pointer_type (TREE_TYPE (rhs
));
1378 tree atype
= reference_alias_ptr_type (rhs
);
1379 gimple
*g
= gimple_build_assign (make_ssa_name (ptype
),
1380 build_fold_addr_expr (rhs
));
1381 gimple_set_location (g
, loc
);
1382 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1383 tree mem
= build2 (MEM_REF
, utype
, gimple_assign_lhs (g
),
1384 build_int_cst (atype
, 0));
1385 tree urhs
= make_ssa_name (utype
);
1388 gimple_assign_set_lhs (stmt
, urhs
);
1389 g
= gimple_build_assign (lhs
, NOP_EXPR
, urhs
);
1390 gimple_set_location (g
, loc
);
1391 edge e
= find_fallthru_edge (gimple_bb (stmt
)->succs
);
1392 gsi_insert_on_edge_immediate (e
, g
);
1393 gimple_assign_set_rhs_from_tree (gsi
, mem
);
1395 *gsi
= gsi_for_stmt (g
);
1400 g
= gimple_build_assign (urhs
, mem
);
1401 gimple_set_location (g
, loc
);
1402 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1404 minv
= fold_convert (utype
, minv
);
1405 maxv
= fold_convert (utype
, maxv
);
1406 if (!integer_zerop (minv
))
1408 g
= gimple_build_assign (make_ssa_name (utype
), MINUS_EXPR
, urhs
, minv
);
1409 gimple_set_location (g
, loc
);
1410 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1413 gimple_stmt_iterator gsi2
= *gsi
;
1414 basic_block then_bb
, fallthru_bb
;
1415 *gsi
= create_cond_insert_point (gsi
, true, false, true,
1416 &then_bb
, &fallthru_bb
);
1417 g
= gimple_build_cond (GT_EXPR
, gimple_assign_lhs (g
),
1418 int_const_binop (MINUS_EXPR
, maxv
, minv
),
1419 NULL_TREE
, NULL_TREE
);
1420 gimple_set_location (g
, loc
);
1421 gsi_insert_after (gsi
, g
, GSI_NEW_STMT
);
1425 gimple_assign_set_rhs_with_ops (&gsi2
, NOP_EXPR
, urhs
);
1429 gsi2
= gsi_after_labels (then_bb
);
1430 if (flag_sanitize_undefined_trap_on_error
)
1431 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
1434 tree data
= ubsan_create_data ("__ubsan_invalid_value_data", 1, &loc
,
1435 ubsan_type_descriptor (type
), NULL_TREE
,
1437 data
= build_fold_addr_expr_loc (loc
, data
);
1438 enum built_in_function bcode
1439 = (flag_sanitize_recover
& (TREE_CODE (type
) == BOOLEAN_TYPE
1440 ? SANITIZE_BOOL
: SANITIZE_ENUM
))
1441 ? BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE
1442 : BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE_ABORT
;
1443 tree fn
= builtin_decl_explicit (bcode
);
1445 tree val
= force_gimple_operand_gsi (&gsi2
, ubsan_encode_value (urhs
),
1446 true, NULL_TREE
, true,
1448 g
= gimple_build_call (fn
, 2, data
, val
);
1450 gimple_set_location (g
, loc
);
1451 gsi_insert_before (&gsi2
, g
, GSI_SAME_STMT
);
1452 ubsan_create_edge (g
);
1453 *gsi
= gsi_for_stmt (stmt
);
1456 /* Determine if we can propagate given LOCATION to ubsan_data descriptor to use
1457 new style handlers. Libubsan uses heuristics to destinguish between old and
1458 new styles and relies on these properties for filename:
1460 a) Location's filename must not be NULL.
1461 b) Location's filename must not be equal to "".
1462 c) Location's filename must not be equal to "\1".
1463 d) First two bytes of filename must not contain '\xff' symbol. */
1466 ubsan_use_new_style_p (location_t loc
)
1468 if (loc
== UNKNOWN_LOCATION
)
1471 expanded_location xloc
= expand_location (loc
);
1472 if (xloc
.file
== NULL
|| strncmp (xloc
.file
, "\1", 2) == 0
1473 || xloc
.file
== '\0' || xloc
.file
[0] == '\xff'
1474 || xloc
.file
[1] == '\xff')
1480 /* Instrument float point-to-integer conversion. TYPE is an integer type of
1481 destination, EXPR is floating-point expression. */
1484 ubsan_instrument_float_cast (location_t loc
, tree type
, tree expr
)
1486 tree expr_type
= TREE_TYPE (expr
);
1487 tree t
, tt
, fn
, min
, max
;
1488 machine_mode mode
= TYPE_MODE (expr_type
);
1489 int prec
= TYPE_PRECISION (type
);
1490 bool uns_p
= TYPE_UNSIGNED (type
);
1491 if (loc
== UNKNOWN_LOCATION
)
1492 loc
= input_location
;
1494 /* Float to integer conversion first truncates toward zero, so
1495 even signed char c = 127.875f; is not problematic.
1496 Therefore, we should complain only if EXPR is unordered or smaller
1497 or equal than TYPE_MIN_VALUE - 1.0 or greater or equal than
1498 TYPE_MAX_VALUE + 1.0. */
1499 if (REAL_MODE_FORMAT (mode
)->b
== 2)
1501 /* For maximum, TYPE_MAX_VALUE might not be representable
1502 in EXPR_TYPE, e.g. if TYPE is 64-bit long long and
1503 EXPR_TYPE is IEEE single float, but TYPE_MAX_VALUE + 1.0 is
1504 either representable or infinity. */
1505 REAL_VALUE_TYPE maxval
= dconst1
;
1506 SET_REAL_EXP (&maxval
, REAL_EXP (&maxval
) + prec
- !uns_p
);
1507 real_convert (&maxval
, mode
, &maxval
);
1508 max
= build_real (expr_type
, maxval
);
1510 /* For unsigned, assume -1.0 is always representable. */
1512 min
= build_minus_one_cst (expr_type
);
1515 /* TYPE_MIN_VALUE is generally representable (or -inf),
1516 but TYPE_MIN_VALUE - 1.0 might not be. */
1517 REAL_VALUE_TYPE minval
= dconstm1
, minval2
;
1518 SET_REAL_EXP (&minval
, REAL_EXP (&minval
) + prec
- 1);
1519 real_convert (&minval
, mode
, &minval
);
1520 real_arithmetic (&minval2
, MINUS_EXPR
, &minval
, &dconst1
);
1521 real_convert (&minval2
, mode
, &minval2
);
1522 if (real_compare (EQ_EXPR
, &minval
, &minval2
)
1523 && !real_isinf (&minval
))
1525 /* If TYPE_MIN_VALUE - 1.0 is not representable and
1526 rounds to TYPE_MIN_VALUE, we need to subtract
1527 more. As REAL_MODE_FORMAT (mode)->p is the number
1528 of base digits, we want to subtract a number that
1529 will be 1 << (REAL_MODE_FORMAT (mode)->p - 1)
1530 times smaller than minval. */
1532 gcc_assert (prec
> REAL_MODE_FORMAT (mode
)->p
);
1533 SET_REAL_EXP (&minval2
,
1534 REAL_EXP (&minval2
) + prec
- 1
1535 - REAL_MODE_FORMAT (mode
)->p
+ 1);
1536 real_arithmetic (&minval2
, MINUS_EXPR
, &minval
, &minval2
);
1537 real_convert (&minval2
, mode
, &minval2
);
1539 min
= build_real (expr_type
, minval2
);
1542 else if (REAL_MODE_FORMAT (mode
)->b
== 10)
1544 /* For _Decimal128 up to 34 decimal digits, - sign,
1545 dot, e, exponent. */
1548 int p
= REAL_MODE_FORMAT (mode
)->p
;
1549 REAL_VALUE_TYPE maxval
, minval
;
1551 /* Use mpfr_snprintf rounding to compute the smallest
1552 representable decimal number greater or equal than
1553 1 << (prec - !uns_p). */
1554 mpfr_init2 (m
, prec
+ 2);
1555 mpfr_set_ui_2exp (m
, 1, prec
- !uns_p
, GMP_RNDN
);
1556 mpfr_snprintf (buf
, sizeof buf
, "%.*RUe", p
- 1, m
);
1557 decimal_real_from_string (&maxval
, buf
);
1558 max
= build_real (expr_type
, maxval
);
1560 /* For unsigned, assume -1.0 is always representable. */
1562 min
= build_minus_one_cst (expr_type
);
1565 /* Use mpfr_snprintf rounding to compute the largest
1566 representable decimal number less or equal than
1567 (-1 << (prec - 1)) - 1. */
1568 mpfr_set_si_2exp (m
, -1, prec
- 1, GMP_RNDN
);
1569 mpfr_sub_ui (m
, m
, 1, GMP_RNDN
);
1570 mpfr_snprintf (buf
, sizeof buf
, "%.*RDe", p
- 1, m
);
1571 decimal_real_from_string (&minval
, buf
);
1572 min
= build_real (expr_type
, minval
);
1579 t
= fold_build2 (UNLE_EXPR
, boolean_type_node
, expr
, min
);
1580 tt
= fold_build2 (UNGE_EXPR
, boolean_type_node
, expr
, max
);
1581 t
= fold_build2 (TRUTH_OR_EXPR
, boolean_type_node
, t
, tt
);
1582 if (integer_zerop (t
))
1585 if (flag_sanitize_undefined_trap_on_error
)
1586 fn
= build_call_expr_loc (loc
, builtin_decl_explicit (BUILT_IN_TRAP
), 0);
1589 location_t
*loc_ptr
= NULL
;
1590 unsigned num_locations
= 0;
1591 initialize_sanitizer_builtins ();
1592 /* Figure out if we can propagate location to ubsan_data and use new
1593 style handlers in libubsan. */
1594 if (ubsan_use_new_style_p (loc
))
1599 /* Create the __ubsan_handle_float_cast_overflow fn call. */
1600 tree data
= ubsan_create_data ("__ubsan_float_cast_overflow_data",
1601 num_locations
, loc_ptr
,
1602 ubsan_type_descriptor (expr_type
),
1603 ubsan_type_descriptor (type
), NULL_TREE
,
1605 enum built_in_function bcode
1606 = (flag_sanitize_recover
& SANITIZE_FLOAT_CAST
)
1607 ? BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW
1608 : BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW_ABORT
;
1609 fn
= builtin_decl_explicit (bcode
);
1610 fn
= build_call_expr_loc (loc
, fn
, 2,
1611 build_fold_addr_expr_loc (loc
, data
),
1612 ubsan_encode_value (expr
, false));
1615 return fold_build3 (COND_EXPR
, void_type_node
, t
, fn
, integer_zero_node
);
1618 /* Instrument values passed to function arguments with nonnull attribute. */
1621 instrument_nonnull_arg (gimple_stmt_iterator
*gsi
)
1623 gimple
*stmt
= gsi_stmt (*gsi
);
1625 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
1626 while for nonnull sanitization it is clear. */
1627 int save_flag_delete_null_pointer_checks
= flag_delete_null_pointer_checks
;
1628 flag_delete_null_pointer_checks
= 1;
1629 loc
[0] = gimple_location (stmt
);
1630 loc
[1] = UNKNOWN_LOCATION
;
1631 for (unsigned int i
= 0; i
< gimple_call_num_args (stmt
); i
++)
1633 tree arg
= gimple_call_arg (stmt
, i
);
1634 if (POINTER_TYPE_P (TREE_TYPE (arg
))
1635 && infer_nonnull_range_by_attribute (stmt
, arg
))
1638 if (!is_gimple_val (arg
))
1640 g
= gimple_build_assign (make_ssa_name (TREE_TYPE (arg
)), arg
);
1641 gimple_set_location (g
, loc
[0]);
1642 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1643 arg
= gimple_assign_lhs (g
);
1646 basic_block then_bb
, fallthru_bb
;
1647 *gsi
= create_cond_insert_point (gsi
, true, false, true,
1648 &then_bb
, &fallthru_bb
);
1649 g
= gimple_build_cond (EQ_EXPR
, arg
,
1650 build_zero_cst (TREE_TYPE (arg
)),
1651 NULL_TREE
, NULL_TREE
);
1652 gimple_set_location (g
, loc
[0]);
1653 gsi_insert_after (gsi
, g
, GSI_NEW_STMT
);
1655 *gsi
= gsi_after_labels (then_bb
);
1656 if (flag_sanitize_undefined_trap_on_error
)
1657 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
1660 tree data
= ubsan_create_data ("__ubsan_nonnull_arg_data",
1662 build_int_cst (integer_type_node
,
1665 data
= build_fold_addr_expr_loc (loc
[0], data
);
1666 enum built_in_function bcode
1667 = (flag_sanitize_recover
& SANITIZE_NONNULL_ATTRIBUTE
)
1668 ? BUILT_IN_UBSAN_HANDLE_NONNULL_ARG
1669 : BUILT_IN_UBSAN_HANDLE_NONNULL_ARG_ABORT
;
1670 tree fn
= builtin_decl_explicit (bcode
);
1672 g
= gimple_build_call (fn
, 1, data
);
1674 gimple_set_location (g
, loc
[0]);
1675 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1676 ubsan_create_edge (g
);
1678 *gsi
= gsi_for_stmt (stmt
);
1680 flag_delete_null_pointer_checks
= save_flag_delete_null_pointer_checks
;
1683 /* Instrument returns in functions with returns_nonnull attribute. */
1686 instrument_nonnull_return (gimple_stmt_iterator
*gsi
)
1688 greturn
*stmt
= as_a
<greturn
*> (gsi_stmt (*gsi
));
1690 tree arg
= gimple_return_retval (stmt
);
1691 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
1692 while for nonnull return sanitization it is clear. */
1693 int save_flag_delete_null_pointer_checks
= flag_delete_null_pointer_checks
;
1694 flag_delete_null_pointer_checks
= 1;
1695 loc
[0] = gimple_location (stmt
);
1696 loc
[1] = UNKNOWN_LOCATION
;
1698 && POINTER_TYPE_P (TREE_TYPE (arg
))
1699 && is_gimple_val (arg
)
1700 && infer_nonnull_range_by_attribute (stmt
, arg
))
1702 basic_block then_bb
, fallthru_bb
;
1703 *gsi
= create_cond_insert_point (gsi
, true, false, true,
1704 &then_bb
, &fallthru_bb
);
1705 gimple
*g
= gimple_build_cond (EQ_EXPR
, arg
,
1706 build_zero_cst (TREE_TYPE (arg
)),
1707 NULL_TREE
, NULL_TREE
);
1708 gimple_set_location (g
, loc
[0]);
1709 gsi_insert_after (gsi
, g
, GSI_NEW_STMT
);
1711 *gsi
= gsi_after_labels (then_bb
);
1712 if (flag_sanitize_undefined_trap_on_error
)
1713 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
1716 tree data
= ubsan_create_data ("__ubsan_nonnull_return_data",
1717 2, loc
, NULL_TREE
, NULL_TREE
);
1718 data
= build_fold_addr_expr_loc (loc
[0], data
);
1719 enum built_in_function bcode
1720 = (flag_sanitize_recover
& SANITIZE_RETURNS_NONNULL_ATTRIBUTE
)
1721 ? BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN
1722 : BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_ABORT
;
1723 tree fn
= builtin_decl_explicit (bcode
);
1725 g
= gimple_build_call (fn
, 1, data
);
1727 gimple_set_location (g
, loc
[0]);
1728 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1729 ubsan_create_edge (g
);
1730 *gsi
= gsi_for_stmt (stmt
);
1732 flag_delete_null_pointer_checks
= save_flag_delete_null_pointer_checks
;
1735 /* Instrument memory references. Here we check whether the pointer
1736 points to an out-of-bounds location. */
1739 instrument_object_size (gimple_stmt_iterator
*gsi
, bool is_lhs
)
1741 gimple
*stmt
= gsi_stmt (*gsi
);
1742 location_t loc
= gimple_location (stmt
);
1743 tree t
= is_lhs
? gimple_get_lhs (stmt
) : gimple_assign_rhs1 (stmt
);
1745 tree index
= NULL_TREE
;
1746 HOST_WIDE_INT size_in_bytes
;
1748 type
= TREE_TYPE (t
);
1749 if (VOID_TYPE_P (type
))
1752 switch (TREE_CODE (t
))
1755 if (TREE_CODE (t
) == COMPONENT_REF
1756 && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t
, 1)) != NULL_TREE
)
1758 tree repr
= DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t
, 1));
1759 t
= build3 (COMPONENT_REF
, TREE_TYPE (repr
), TREE_OPERAND (t
, 0),
1764 index
= TREE_OPERAND (t
, 1);
1776 size_in_bytes
= int_size_in_bytes (type
);
1777 if (size_in_bytes
<= 0)
1780 HOST_WIDE_INT bitsize
, bitpos
;
1783 int volatilep
= 0, reversep
, unsignedp
= 0;
1784 tree inner
= get_inner_reference (t
, &bitsize
, &bitpos
, &offset
, &mode
,
1785 &unsignedp
, &reversep
, &volatilep
, false);
1787 if (bitpos
% BITS_PER_UNIT
!= 0
1788 || bitsize
!= size_in_bytes
* BITS_PER_UNIT
)
1791 bool decl_p
= DECL_P (inner
);
1795 else if (TREE_CODE (inner
) == MEM_REF
)
1796 base
= TREE_OPERAND (inner
, 0);
1799 tree ptr
= build1 (ADDR_EXPR
, build_pointer_type (TREE_TYPE (t
)), t
);
1801 while (TREE_CODE (base
) == SSA_NAME
)
1803 gimple
*def_stmt
= SSA_NAME_DEF_STMT (base
);
1804 if (gimple_assign_ssa_name_copy_p (def_stmt
)
1805 || (gimple_assign_cast_p (def_stmt
)
1806 && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (def_stmt
))))
1807 || (is_gimple_assign (def_stmt
)
1808 && gimple_assign_rhs_code (def_stmt
) == POINTER_PLUS_EXPR
))
1810 tree rhs1
= gimple_assign_rhs1 (def_stmt
);
1811 if (TREE_CODE (rhs1
) == SSA_NAME
1812 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs1
))
1821 if (!POINTER_TYPE_P (TREE_TYPE (base
)) && !DECL_P (base
))
1825 tree base_addr
= base
;
1826 gimple
*bos_stmt
= NULL
;
1828 base_addr
= build1 (ADDR_EXPR
,
1829 build_pointer_type (TREE_TYPE (base
)), base
);
1830 unsigned HOST_WIDE_INT size
= compute_builtin_object_size (base_addr
, 0);
1831 if (size
!= (unsigned HOST_WIDE_INT
) -1)
1832 sizet
= build_int_cst (sizetype
, size
);
1835 if (LOCATION_LOCUS (loc
) == UNKNOWN_LOCATION
)
1836 loc
= input_location
;
1837 /* Generate __builtin_object_size call. */
1838 sizet
= builtin_decl_explicit (BUILT_IN_OBJECT_SIZE
);
1839 sizet
= build_call_expr_loc (loc
, sizet
, 2, base_addr
,
1841 sizet
= force_gimple_operand_gsi (gsi
, sizet
, false, NULL_TREE
, true,
1843 /* If the call above didn't end up being an integer constant, go one
1844 statement back and get the __builtin_object_size stmt. Save it,
1845 we might need it later. */
1846 if (SSA_VAR_P (sizet
))
1849 bos_stmt
= gsi_stmt (*gsi
);
1851 /* Move on to where we were. */
1858 /* Generate UBSAN_OBJECT_SIZE (ptr, ptr+sizeof(*ptr)-base, objsize, ckind)
1860 /* ptr + sizeof (*ptr) - base */
1861 t
= fold_build2 (MINUS_EXPR
, sizetype
,
1862 fold_convert (pointer_sized_int_node
, ptr
),
1863 fold_convert (pointer_sized_int_node
, base_addr
));
1864 t
= fold_build2 (PLUS_EXPR
, sizetype
, t
, TYPE_SIZE_UNIT (type
));
1866 /* Perhaps we can omit the check. */
1867 if (TREE_CODE (t
) == INTEGER_CST
1868 && TREE_CODE (sizet
) == INTEGER_CST
1869 && tree_int_cst_le (t
, sizet
))
1872 if (index
!= NULL_TREE
1873 && TREE_CODE (index
) == SSA_NAME
1874 && TREE_CODE (sizet
) == INTEGER_CST
)
1876 gimple
*def
= SSA_NAME_DEF_STMT (index
);
1877 if (is_gimple_assign (def
)
1878 && gimple_assign_rhs_code (def
) == BIT_AND_EXPR
1879 && TREE_CODE (gimple_assign_rhs2 (def
)) == INTEGER_CST
)
1881 tree cst
= gimple_assign_rhs2 (def
);
1882 tree sz
= fold_build2 (EXACT_DIV_EXPR
, sizetype
, sizet
,
1883 TYPE_SIZE_UNIT (type
));
1884 if (tree_int_cst_sgn (cst
) >= 0
1885 && tree_int_cst_lt (cst
, sz
))
1890 if (bos_stmt
&& gimple_call_builtin_p (bos_stmt
, BUILT_IN_OBJECT_SIZE
))
1891 ubsan_create_edge (bos_stmt
);
1893 /* We have to emit the check. */
1894 t
= force_gimple_operand_gsi (gsi
, t
, true, NULL_TREE
, true,
1896 ptr
= force_gimple_operand_gsi (gsi
, ptr
, true, NULL_TREE
, true,
1898 tree ckind
= build_int_cst (unsigned_char_type_node
,
1899 is_lhs
? UBSAN_STORE_OF
: UBSAN_LOAD_OF
);
1900 gimple
*g
= gimple_build_call_internal (IFN_UBSAN_OBJECT_SIZE
, 4,
1901 ptr
, t
, sizet
, ckind
);
1902 gimple_set_location (g
, loc
);
1903 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1906 /* True if we want to play UBSan games in the current function. */
1909 do_ubsan_in_current_function ()
1911 return (current_function_decl
!= NULL_TREE
1912 && !lookup_attribute ("no_sanitize_undefined",
1913 DECL_ATTRIBUTES (current_function_decl
)));
1918 const pass_data pass_data_ubsan
=
1920 GIMPLE_PASS
, /* type */
1922 OPTGROUP_NONE
, /* optinfo_flags */
1923 TV_TREE_UBSAN
, /* tv_id */
1924 ( PROP_cfg
| PROP_ssa
), /* properties_required */
1925 0, /* properties_provided */
1926 0, /* properties_destroyed */
1927 0, /* todo_flags_start */
1928 TODO_update_ssa
, /* todo_flags_finish */
1931 class pass_ubsan
: public gimple_opt_pass
1934 pass_ubsan (gcc::context
*ctxt
)
1935 : gimple_opt_pass (pass_data_ubsan
, ctxt
)
1938 /* opt_pass methods: */
1939 virtual bool gate (function
*)
1941 return flag_sanitize
& (SANITIZE_NULL
| SANITIZE_SI_OVERFLOW
1942 | SANITIZE_BOOL
| SANITIZE_ENUM
1943 | SANITIZE_ALIGNMENT
1944 | SANITIZE_NONNULL_ATTRIBUTE
1945 | SANITIZE_RETURNS_NONNULL_ATTRIBUTE
1946 | SANITIZE_OBJECT_SIZE
)
1947 && do_ubsan_in_current_function ();
1950 virtual unsigned int execute (function
*);
1952 }; // class pass_ubsan
1955 pass_ubsan::execute (function
*fun
)
1958 gimple_stmt_iterator gsi
;
1960 initialize_sanitizer_builtins ();
1962 FOR_EACH_BB_FN (bb
, fun
)
1964 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
);)
1966 gimple
*stmt
= gsi_stmt (gsi
);
1967 if (is_gimple_debug (stmt
) || gimple_clobber_p (stmt
))
1973 if ((flag_sanitize
& SANITIZE_SI_OVERFLOW
)
1974 && is_gimple_assign (stmt
))
1975 instrument_si_overflow (gsi
);
1977 if (flag_sanitize
& (SANITIZE_NULL
| SANITIZE_ALIGNMENT
))
1979 if (gimple_store_p (stmt
))
1980 instrument_null (gsi
, true);
1981 if (gimple_assign_load_p (stmt
))
1982 instrument_null (gsi
, false);
1985 if (flag_sanitize
& (SANITIZE_BOOL
| SANITIZE_ENUM
)
1986 && gimple_assign_load_p (stmt
))
1988 instrument_bool_enum_load (&gsi
);
1989 bb
= gimple_bb (stmt
);
1992 if ((flag_sanitize
& SANITIZE_NONNULL_ATTRIBUTE
)
1993 && is_gimple_call (stmt
)
1994 && !gimple_call_internal_p (stmt
))
1996 instrument_nonnull_arg (&gsi
);
1997 bb
= gimple_bb (stmt
);
2000 if ((flag_sanitize
& SANITIZE_RETURNS_NONNULL_ATTRIBUTE
)
2001 && gimple_code (stmt
) == GIMPLE_RETURN
)
2003 instrument_nonnull_return (&gsi
);
2004 bb
= gimple_bb (stmt
);
2007 if (flag_sanitize
& SANITIZE_OBJECT_SIZE
)
2009 if (gimple_store_p (stmt
))
2010 instrument_object_size (&gsi
, true);
2011 if (gimple_assign_load_p (stmt
))
2012 instrument_object_size (&gsi
, false);
2024 make_pass_ubsan (gcc::context
*ctxt
)
2026 return new pass_ubsan (ctxt
);
2029 #include "gt-ubsan.h"