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 if (TREE_CODE (type
) == REAL_TYPE
)
306 return tree_to_uhwi (TYPE_SIZE (type
));
307 else if (INTEGRAL_TYPE_P (type
))
309 int prec
= exact_log2 (tree_to_uhwi (TYPE_SIZE (type
)));
310 gcc_assert (prec
!= -1);
311 return (prec
<< 1) | !TYPE_UNSIGNED (type
);
317 /* Counters for internal labels. ubsan_ids[0] for Lubsan_type,
318 ubsan_ids[1] for Lubsan_data labels. */
319 static GTY(()) unsigned int ubsan_ids
[2];
321 /* Helper routine that returns ADDR_EXPR of a VAR_DECL of a type
322 descriptor. It first looks into the hash table; if not found,
323 create the VAR_DECL, put it into the hash table and return the
324 ADDR_EXPR of it. TYPE describes a particular type. PSTYLE is
325 an enum controlling how we want to print the type. */
328 ubsan_type_descriptor (tree type
, enum ubsan_print_style pstyle
)
330 /* See through any typedefs. */
331 type
= TYPE_MAIN_VARIANT (type
);
333 tree decl
= decl_for_type_lookup (type
);
334 /* It is possible that some of the earlier created DECLs were found
335 unused, in that case they weren't emitted and varpool_node::get
336 returns NULL node on them. But now we really need them. Thus,
338 if (decl
!= NULL_TREE
&& varpool_node::get (decl
))
339 return build_fold_addr_expr (decl
);
341 tree dtype
= ubsan_get_type_descriptor_type ();
343 const char *tname
= NULL
;
344 pretty_printer pretty_name
;
345 unsigned char deref_depth
= 0;
346 unsigned short tkind
, tinfo
;
348 /* Get the name of the type, or the name of the pointer type. */
349 if (pstyle
== UBSAN_PRINT_POINTER
)
351 gcc_assert (POINTER_TYPE_P (type
));
352 type2
= TREE_TYPE (type
);
354 /* Remove any '*' operators from TYPE. */
355 while (POINTER_TYPE_P (type2
))
356 deref_depth
++, type2
= TREE_TYPE (type2
);
358 if (TREE_CODE (type2
) == METHOD_TYPE
)
359 type2
= TYPE_METHOD_BASETYPE (type2
);
362 /* If an array, get its type. */
363 type2
= strip_array_types (type2
);
365 if (pstyle
== UBSAN_PRINT_ARRAY
)
367 while (POINTER_TYPE_P (type2
))
368 deref_depth
++, type2
= TREE_TYPE (type2
);
371 if (TYPE_NAME (type2
) != NULL
)
373 if (TREE_CODE (TYPE_NAME (type2
)) == IDENTIFIER_NODE
)
374 tname
= IDENTIFIER_POINTER (TYPE_NAME (type2
));
375 else if (DECL_NAME (TYPE_NAME (type2
)) != NULL
)
376 tname
= IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type2
)));
380 /* We weren't able to determine the type name. */
383 if (pstyle
== UBSAN_PRINT_POINTER
)
385 pp_printf (&pretty_name
, "'%s%s%s%s%s%s%s",
386 TYPE_VOLATILE (type2
) ? "volatile " : "",
387 TYPE_READONLY (type2
) ? "const " : "",
388 TYPE_RESTRICT (type2
) ? "restrict " : "",
389 TYPE_ATOMIC (type2
) ? "_Atomic " : "",
390 TREE_CODE (type2
) == RECORD_TYPE
392 : TREE_CODE (type2
) == UNION_TYPE
393 ? "union " : "", tname
,
394 deref_depth
== 0 ? "" : " ");
395 while (deref_depth
-- > 0)
396 pp_star (&pretty_name
);
397 pp_quote (&pretty_name
);
399 else if (pstyle
== UBSAN_PRINT_ARRAY
)
401 /* Pretty print the array dimensions. */
402 gcc_assert (TREE_CODE (type
) == ARRAY_TYPE
);
404 pp_printf (&pretty_name
, "'%s ", tname
);
405 while (deref_depth
-- > 0)
406 pp_star (&pretty_name
);
407 while (TREE_CODE (t
) == ARRAY_TYPE
)
409 pp_left_bracket (&pretty_name
);
410 tree dom
= TYPE_DOMAIN (t
);
411 if (dom
&& TREE_CODE (TYPE_MAX_VALUE (dom
)) == INTEGER_CST
)
413 if (tree_fits_uhwi_p (TYPE_MAX_VALUE (dom
))
414 && tree_to_uhwi (TYPE_MAX_VALUE (dom
)) + 1 != 0)
415 pp_printf (&pretty_name
, HOST_WIDE_INT_PRINT_DEC
,
416 tree_to_uhwi (TYPE_MAX_VALUE (dom
)) + 1);
418 pp_wide_int (&pretty_name
,
419 wi::add (wi::to_widest (TYPE_MAX_VALUE (dom
)), 1),
420 TYPE_SIGN (TREE_TYPE (dom
)));
423 /* ??? We can't determine the variable name; print VLA unspec. */
424 pp_star (&pretty_name
);
425 pp_right_bracket (&pretty_name
);
428 pp_quote (&pretty_name
);
430 /* Save the tree with stripped types. */
434 pp_printf (&pretty_name
, "'%s'", tname
);
436 switch (TREE_CODE (type
))
444 /* FIXME: libubsan right now only supports float, double and
445 long double type formats. */
446 if (TYPE_MODE (type
) == TYPE_MODE (float_type_node
)
447 || TYPE_MODE (type
) == TYPE_MODE (double_type_node
)
448 || TYPE_MODE (type
) == TYPE_MODE (long_double_type_node
))
457 tinfo
= get_ubsan_type_info_for_type (type
);
459 /* Create a new VAR_DECL of type descriptor. */
460 const char *tmp
= pp_formatted_text (&pretty_name
);
461 size_t len
= strlen (tmp
) + 1;
462 tree str
= build_string (len
, tmp
);
463 TREE_TYPE (str
) = build_array_type_nelts (char_type_node
, len
);
464 TREE_READONLY (str
) = 1;
465 TREE_STATIC (str
) = 1;
468 ASM_GENERATE_INTERNAL_LABEL (tmp_name
, "Lubsan_type", ubsan_ids
[0]++);
469 decl
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
, get_identifier (tmp_name
),
471 TREE_STATIC (decl
) = 1;
472 TREE_PUBLIC (decl
) = 0;
473 DECL_ARTIFICIAL (decl
) = 1;
474 DECL_IGNORED_P (decl
) = 1;
475 DECL_EXTERNAL (decl
) = 0;
477 = size_binop (PLUS_EXPR
, DECL_SIZE (decl
), TYPE_SIZE (TREE_TYPE (str
)));
478 DECL_SIZE_UNIT (decl
)
479 = size_binop (PLUS_EXPR
, DECL_SIZE_UNIT (decl
),
480 TYPE_SIZE_UNIT (TREE_TYPE (str
)));
482 tree ctor
= build_constructor_va (dtype
, 3, NULL_TREE
,
483 build_int_cst (short_unsigned_type_node
,
485 build_int_cst (short_unsigned_type_node
,
486 tinfo
), NULL_TREE
, str
);
487 TREE_CONSTANT (ctor
) = 1;
488 TREE_STATIC (ctor
) = 1;
489 DECL_INITIAL (decl
) = ctor
;
490 varpool_node::finalize_decl (decl
);
492 /* Save the VAR_DECL into the hash table. */
493 decl_for_type_insert (type
, decl
);
495 return build_fold_addr_expr (decl
);
498 /* Create a structure for the ubsan library. NAME is a name of the new
499 structure. LOCCNT is number of locations, PLOC points to array of
500 locations. The arguments in ... are of __ubsan_type_descriptor type
501 and there are at most two of them, followed by NULL_TREE, followed
502 by optional extra arguments and another NULL_TREE. */
505 ubsan_create_data (const char *name
, int loccnt
, const location_t
*ploc
, ...)
510 vec
<tree
, va_gc
> *saved_args
= NULL
;
514 /* Firstly, create a pointer to type descriptor type. */
515 tree td_type
= ubsan_get_type_descriptor_type ();
516 td_type
= build_pointer_type (td_type
);
518 /* Create the structure type. */
519 ret
= make_node (RECORD_TYPE
);
520 for (j
= 0; j
< loccnt
; j
++)
522 gcc_checking_assert (i
< 2);
523 fields
[i
] = build_decl (UNKNOWN_LOCATION
, FIELD_DECL
, NULL_TREE
,
524 ubsan_get_source_location_type ());
525 DECL_CONTEXT (fields
[i
]) = ret
;
527 DECL_CHAIN (fields
[i
- 1]) = fields
[i
];
531 va_start (args
, ploc
);
532 for (t
= va_arg (args
, tree
); t
!= NULL_TREE
;
533 i
++, t
= va_arg (args
, tree
))
535 gcc_checking_assert (i
< 4);
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
];
545 for (t
= va_arg (args
, tree
); t
!= NULL_TREE
;
546 i
++, t
= va_arg (args
, tree
))
548 gcc_checking_assert (i
< 6);
549 /* Save the tree arguments for later use. */
550 vec_safe_push (saved_args
, t
);
551 fields
[i
] = build_decl (UNKNOWN_LOCATION
, FIELD_DECL
, NULL_TREE
,
553 DECL_CONTEXT (fields
[i
]) = ret
;
555 DECL_CHAIN (fields
[i
- 1]) = fields
[i
];
559 tree type_decl
= build_decl (input_location
, TYPE_DECL
,
560 get_identifier (name
), ret
);
561 DECL_IGNORED_P (type_decl
) = 1;
562 DECL_ARTIFICIAL (type_decl
) = 1;
563 TYPE_FIELDS (ret
) = fields
[0];
564 TYPE_NAME (ret
) = type_decl
;
565 TYPE_STUB_DECL (ret
) = type_decl
;
568 /* Now, fill in the type. */
570 ASM_GENERATE_INTERNAL_LABEL (tmp_name
, "Lubsan_data", ubsan_ids
[1]++);
571 tree var
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
, get_identifier (tmp_name
),
573 TREE_STATIC (var
) = 1;
574 TREE_PUBLIC (var
) = 0;
575 DECL_ARTIFICIAL (var
) = 1;
576 DECL_IGNORED_P (var
) = 1;
577 DECL_EXTERNAL (var
) = 0;
579 vec
<constructor_elt
, va_gc
> *v
;
581 tree ctor
= build_constructor (ret
, v
);
583 /* If desirable, set the __ubsan_source_location element. */
584 for (j
= 0; j
< loccnt
; j
++)
586 location_t loc
= LOCATION_LOCUS (ploc
[j
]);
587 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, ubsan_source_location (loc
));
590 size_t nelts
= vec_safe_length (saved_args
);
591 for (i
= 0; i
< nelts
; i
++)
593 t
= (*saved_args
)[i
];
594 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, t
);
597 TREE_CONSTANT (ctor
) = 1;
598 TREE_STATIC (ctor
) = 1;
599 DECL_INITIAL (var
) = ctor
;
600 varpool_node::finalize_decl (var
);
605 /* Instrument the __builtin_unreachable call. We just call the libubsan
609 ubsan_instrument_unreachable (gimple_stmt_iterator
*gsi
)
612 location_t loc
= gimple_location (gsi_stmt (*gsi
));
614 if (flag_sanitize_undefined_trap_on_error
)
615 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
618 tree data
= ubsan_create_data ("__ubsan_unreachable_data", 1, &loc
,
619 NULL_TREE
, NULL_TREE
);
620 data
= build_fold_addr_expr_loc (loc
, data
);
622 = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE
);
623 g
= gimple_build_call (fn
, 1, data
);
625 gimple_set_location (g
, loc
);
626 gsi_replace (gsi
, g
, false);
630 /* Return true if T is a call to a libubsan routine. */
633 is_ubsan_builtin_p (tree t
)
635 return TREE_CODE (t
) == FUNCTION_DECL
636 && DECL_BUILT_IN_CLASS (t
) == BUILT_IN_NORMAL
637 && strncmp (IDENTIFIER_POINTER (DECL_NAME (t
)),
638 "__builtin___ubsan_", 18) == 0;
641 /* Create a callgraph edge for statement STMT. */
644 ubsan_create_edge (gimple
*stmt
)
646 gcall
*call_stmt
= dyn_cast
<gcall
*> (stmt
);
647 basic_block bb
= gimple_bb (stmt
);
648 int freq
= compute_call_stmt_bb_frequency (current_function_decl
, bb
);
649 cgraph_node
*node
= cgraph_node::get (current_function_decl
);
650 tree decl
= gimple_call_fndecl (call_stmt
);
652 node
->create_edge (cgraph_node::get_create (decl
), call_stmt
, bb
->count
,
656 /* Expand the UBSAN_BOUNDS special builtin function. */
659 ubsan_expand_bounds_ifn (gimple_stmt_iterator
*gsi
)
661 gimple
*stmt
= gsi_stmt (*gsi
);
662 location_t loc
= gimple_location (stmt
);
663 gcc_assert (gimple_call_num_args (stmt
) == 3);
665 /* Pick up the arguments of the UBSAN_BOUNDS call. */
666 tree type
= TREE_TYPE (TREE_TYPE (gimple_call_arg (stmt
, 0)));
667 tree index
= gimple_call_arg (stmt
, 1);
668 tree orig_index_type
= TREE_TYPE (index
);
669 tree bound
= gimple_call_arg (stmt
, 2);
671 gimple_stmt_iterator gsi_orig
= *gsi
;
673 /* Create condition "if (index > bound)". */
674 basic_block then_bb
, fallthru_bb
;
675 gimple_stmt_iterator cond_insert_point
676 = create_cond_insert_point (gsi
, false, false, true,
677 &then_bb
, &fallthru_bb
);
678 index
= fold_convert (TREE_TYPE (bound
), index
);
679 index
= force_gimple_operand_gsi (&cond_insert_point
, index
,
681 false, GSI_NEW_STMT
);
682 gimple
*g
= gimple_build_cond (GT_EXPR
, index
, bound
, NULL_TREE
, NULL_TREE
);
683 gimple_set_location (g
, loc
);
684 gsi_insert_after (&cond_insert_point
, g
, GSI_NEW_STMT
);
686 /* Generate __ubsan_handle_out_of_bounds call. */
687 *gsi
= gsi_after_labels (then_bb
);
688 if (flag_sanitize_undefined_trap_on_error
)
689 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
693 = ubsan_create_data ("__ubsan_out_of_bounds_data", 1, &loc
,
694 ubsan_type_descriptor (type
, UBSAN_PRINT_ARRAY
),
695 ubsan_type_descriptor (orig_index_type
),
696 NULL_TREE
, NULL_TREE
);
697 data
= build_fold_addr_expr_loc (loc
, data
);
698 enum built_in_function bcode
699 = (flag_sanitize_recover
& SANITIZE_BOUNDS
)
700 ? BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS
701 : BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS_ABORT
;
702 tree fn
= builtin_decl_explicit (bcode
);
703 tree val
= force_gimple_operand_gsi (gsi
, ubsan_encode_value (index
),
704 true, NULL_TREE
, true,
706 g
= gimple_build_call (fn
, 2, data
, val
);
708 gimple_set_location (g
, loc
);
709 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
711 /* Get rid of the UBSAN_BOUNDS call from the IR. */
712 unlink_stmt_vdef (stmt
);
713 gsi_remove (&gsi_orig
, true);
715 /* Point GSI to next logical statement. */
716 *gsi
= gsi_start_bb (fallthru_bb
);
720 /* Expand UBSAN_NULL internal call. The type is kept on the ckind
721 argument which is a constant, because the middle-end treats pointer
722 conversions as useless and therefore the type of the first argument
723 could be changed to any other pointer type. */
726 ubsan_expand_null_ifn (gimple_stmt_iterator
*gsip
)
728 gimple_stmt_iterator gsi
= *gsip
;
729 gimple
*stmt
= gsi_stmt (gsi
);
730 location_t loc
= gimple_location (stmt
);
731 gcc_assert (gimple_call_num_args (stmt
) == 3);
732 tree ptr
= gimple_call_arg (stmt
, 0);
733 tree ckind
= gimple_call_arg (stmt
, 1);
734 tree align
= gimple_call_arg (stmt
, 2);
735 tree check_align
= NULL_TREE
;
738 basic_block cur_bb
= gsi_bb (gsi
);
741 if (!integer_zerop (align
))
743 unsigned int ptralign
= get_pointer_alignment (ptr
) / BITS_PER_UNIT
;
744 if (compare_tree_int (align
, ptralign
) == 1)
746 check_align
= make_ssa_name (pointer_sized_int_node
);
747 g
= gimple_build_assign (check_align
, NOP_EXPR
, ptr
);
748 gimple_set_location (g
, loc
);
749 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
752 check_null
= (flag_sanitize
& SANITIZE_NULL
) != 0;
754 if (check_align
== NULL_TREE
&& !check_null
)
756 gsi_remove (gsip
, true);
757 /* Unlink the UBSAN_NULLs vops before replacing it. */
758 unlink_stmt_vdef (stmt
);
762 /* Split the original block holding the pointer dereference. */
763 edge e
= split_block (cur_bb
, stmt
);
765 /* Get a hold on the 'condition block', the 'then block' and the
767 basic_block cond_bb
= e
->src
;
768 basic_block fallthru_bb
= e
->dest
;
769 basic_block then_bb
= create_empty_bb (cond_bb
);
770 add_bb_to_loop (then_bb
, cond_bb
->loop_father
);
771 loops_state_set (LOOPS_NEED_FIXUP
);
773 /* Make an edge coming from the 'cond block' into the 'then block';
774 this edge is unlikely taken, so set up the probability accordingly. */
775 e
= make_edge (cond_bb
, then_bb
, EDGE_TRUE_VALUE
);
776 e
->probability
= PROB_VERY_UNLIKELY
;
778 /* Connect 'then block' with the 'else block'. This is needed
779 as the ubsan routines we call in the 'then block' are not noreturn.
780 The 'then block' only has one outcoming edge. */
781 make_single_succ_edge (then_bb
, fallthru_bb
, EDGE_FALLTHRU
);
783 /* Set up the fallthrough basic block. */
784 e
= find_edge (cond_bb
, fallthru_bb
);
785 e
->flags
= EDGE_FALSE_VALUE
;
786 e
->count
= cond_bb
->count
;
787 e
->probability
= REG_BR_PROB_BASE
- PROB_VERY_UNLIKELY
;
789 /* Update dominance info for the newly created then_bb; note that
790 fallthru_bb's dominance info has already been updated by
792 if (dom_info_available_p (CDI_DOMINATORS
))
793 set_immediate_dominator (CDI_DOMINATORS
, then_bb
, cond_bb
);
795 /* Put the ubsan builtin call into the newly created BB. */
796 if (flag_sanitize_undefined_trap_on_error
)
797 g
= gimple_build_call (builtin_decl_implicit (BUILT_IN_TRAP
), 0);
800 enum built_in_function bcode
801 = (flag_sanitize_recover
& ((check_align
? SANITIZE_ALIGNMENT
: 0)
802 | (check_null
? SANITIZE_NULL
: 0)))
803 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
804 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT
;
805 tree fn
= builtin_decl_implicit (bcode
);
807 = ubsan_create_data ("__ubsan_null_data", 1, &loc
,
808 ubsan_type_descriptor (TREE_TYPE (ckind
),
809 UBSAN_PRINT_POINTER
),
812 fold_convert (unsigned_char_type_node
, ckind
),
814 data
= build_fold_addr_expr_loc (loc
, data
);
815 g
= gimple_build_call (fn
, 2, data
,
816 check_align
? check_align
817 : build_zero_cst (pointer_sized_int_node
));
819 gimple_stmt_iterator gsi2
= gsi_start_bb (then_bb
);
820 gimple_set_location (g
, loc
);
821 gsi_insert_after (&gsi2
, g
, GSI_NEW_STMT
);
823 /* Unlink the UBSAN_NULLs vops before replacing it. */
824 unlink_stmt_vdef (stmt
);
828 g
= gimple_build_cond (EQ_EXPR
, ptr
, build_int_cst (TREE_TYPE (ptr
), 0),
829 NULL_TREE
, NULL_TREE
);
830 gimple_set_location (g
, loc
);
832 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
833 gsi_replace (&gsi
, g
, false);
841 /* Split the block with the condition again. */
842 e
= split_block (cond_bb
, stmt
);
843 basic_block cond1_bb
= e
->src
;
844 basic_block cond2_bb
= e
->dest
;
846 /* Make an edge coming from the 'cond1 block' into the 'then block';
847 this edge is unlikely taken, so set up the probability
849 e
= make_edge (cond1_bb
, then_bb
, EDGE_TRUE_VALUE
);
850 e
->probability
= PROB_VERY_UNLIKELY
;
852 /* Set up the fallthrough basic block. */
853 e
= find_edge (cond1_bb
, cond2_bb
);
854 e
->flags
= EDGE_FALSE_VALUE
;
855 e
->count
= cond1_bb
->count
;
856 e
->probability
= REG_BR_PROB_BASE
- PROB_VERY_UNLIKELY
;
858 /* Update dominance info. */
859 if (dom_info_available_p (CDI_DOMINATORS
))
861 set_immediate_dominator (CDI_DOMINATORS
, fallthru_bb
, cond1_bb
);
862 set_immediate_dominator (CDI_DOMINATORS
, then_bb
, cond1_bb
);
865 gsi2
= gsi_start_bb (cond2_bb
);
868 tree mask
= build_int_cst (pointer_sized_int_node
,
869 tree_to_uhwi (align
) - 1);
870 g
= gimple_build_assign (make_ssa_name (pointer_sized_int_node
),
871 BIT_AND_EXPR
, check_align
, mask
);
872 gimple_set_location (g
, loc
);
874 gsi_insert_after (&gsi2
, g
, GSI_NEW_STMT
);
876 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
878 g
= gimple_build_cond (NE_EXPR
, gimple_assign_lhs (g
),
879 build_int_cst (pointer_sized_int_node
, 0),
880 NULL_TREE
, NULL_TREE
);
881 gimple_set_location (g
, loc
);
883 gsi_insert_after (&gsi2
, g
, GSI_NEW_STMT
);
885 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
886 gsi_replace (&gsi
, g
, false);
891 #define OBJSZ_MAX_OFFSET (1024 * 16)
893 /* Expand UBSAN_OBJECT_SIZE internal call. */
896 ubsan_expand_objsize_ifn (gimple_stmt_iterator
*gsi
)
898 gimple
*stmt
= gsi_stmt (*gsi
);
899 location_t loc
= gimple_location (stmt
);
900 gcc_assert (gimple_call_num_args (stmt
) == 4);
902 tree ptr
= gimple_call_arg (stmt
, 0);
903 tree offset
= gimple_call_arg (stmt
, 1);
904 tree size
= gimple_call_arg (stmt
, 2);
905 tree ckind
= gimple_call_arg (stmt
, 3);
906 gimple_stmt_iterator gsi_orig
= *gsi
;
909 /* See if we can discard the check. */
910 if (TREE_CODE (size
) != INTEGER_CST
911 || integer_all_onesp (size
))
912 /* Yes, __builtin_object_size couldn't determine the
914 else if (TREE_CODE (offset
) == INTEGER_CST
915 && wi::ges_p (wi::to_widest (offset
), -OBJSZ_MAX_OFFSET
)
916 && wi::les_p (wi::to_widest (offset
), -1))
917 /* The offset is in range [-16K, -1]. */;
920 /* if (offset > objsize) */
921 basic_block then_bb
, fallthru_bb
;
922 gimple_stmt_iterator cond_insert_point
923 = create_cond_insert_point (gsi
, false, false, true,
924 &then_bb
, &fallthru_bb
);
925 g
= gimple_build_cond (GT_EXPR
, offset
, size
, NULL_TREE
, NULL_TREE
);
926 gimple_set_location (g
, loc
);
927 gsi_insert_after (&cond_insert_point
, g
, GSI_NEW_STMT
);
929 /* If the offset is small enough, we don't need the second
931 if (TREE_CODE (offset
) == INTEGER_CST
932 && wi::ges_p (wi::to_widest (offset
), 0)
933 && wi::les_p (wi::to_widest (offset
), OBJSZ_MAX_OFFSET
))
934 *gsi
= gsi_after_labels (then_bb
);
937 /* Don't issue run-time error if (ptr > ptr + offset). That
938 may happen when computing a POINTER_PLUS_EXPR. */
939 basic_block then2_bb
, fallthru2_bb
;
941 gimple_stmt_iterator gsi2
= gsi_after_labels (then_bb
);
942 cond_insert_point
= create_cond_insert_point (&gsi2
, false, false,
945 /* Convert the pointer to an integer type. */
946 tree p
= make_ssa_name (pointer_sized_int_node
);
947 g
= gimple_build_assign (p
, NOP_EXPR
, ptr
);
948 gimple_set_location (g
, loc
);
949 gsi_insert_before (&cond_insert_point
, g
, GSI_NEW_STMT
);
950 p
= gimple_assign_lhs (g
);
951 /* Compute ptr + offset. */
952 g
= gimple_build_assign (make_ssa_name (pointer_sized_int_node
),
953 PLUS_EXPR
, p
, offset
);
954 gimple_set_location (g
, loc
);
955 gsi_insert_after (&cond_insert_point
, g
, GSI_NEW_STMT
);
956 /* Now build the conditional and put it into the IR. */
957 g
= gimple_build_cond (LE_EXPR
, p
, gimple_assign_lhs (g
),
958 NULL_TREE
, NULL_TREE
);
959 gimple_set_location (g
, loc
);
960 gsi_insert_after (&cond_insert_point
, g
, GSI_NEW_STMT
);
961 *gsi
= gsi_after_labels (then2_bb
);
964 /* Generate __ubsan_handle_type_mismatch call. */
965 if (flag_sanitize_undefined_trap_on_error
)
966 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
970 = ubsan_create_data ("__ubsan_objsz_data", 1, &loc
,
971 ubsan_type_descriptor (TREE_TYPE (ptr
),
972 UBSAN_PRINT_POINTER
),
974 build_zero_cst (pointer_sized_int_node
),
977 data
= build_fold_addr_expr_loc (loc
, data
);
978 enum built_in_function bcode
979 = (flag_sanitize_recover
& SANITIZE_OBJECT_SIZE
)
980 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
981 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT
;
982 tree p
= make_ssa_name (pointer_sized_int_node
);
983 g
= gimple_build_assign (p
, NOP_EXPR
, ptr
);
984 gimple_set_location (g
, loc
);
985 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
986 g
= gimple_build_call (builtin_decl_explicit (bcode
), 2, data
, p
);
988 gimple_set_location (g
, loc
);
989 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
991 /* Point GSI to next logical statement. */
992 *gsi
= gsi_start_bb (fallthru_bb
);
994 /* Get rid of the UBSAN_OBJECT_SIZE call from the IR. */
995 unlink_stmt_vdef (stmt
);
996 gsi_remove (&gsi_orig
, true);
1000 /* Get rid of the UBSAN_OBJECT_SIZE call from the IR. */
1001 unlink_stmt_vdef (stmt
);
1002 gsi_remove (gsi
, true);
1006 /* Cached __ubsan_vptr_type_cache decl. */
1007 static GTY(()) tree ubsan_vptr_type_cache_decl
;
1009 /* Expand UBSAN_VPTR internal call. The type is kept on the ckind
1010 argument which is a constant, because the middle-end treats pointer
1011 conversions as useless and therefore the type of the first argument
1012 could be changed to any other pointer type. */
1015 ubsan_expand_vptr_ifn (gimple_stmt_iterator
*gsip
)
1017 gimple_stmt_iterator gsi
= *gsip
;
1018 gimple
*stmt
= gsi_stmt (gsi
);
1019 location_t loc
= gimple_location (stmt
);
1020 gcc_assert (gimple_call_num_args (stmt
) == 5);
1021 tree op
= gimple_call_arg (stmt
, 0);
1022 tree vptr
= gimple_call_arg (stmt
, 1);
1023 tree str_hash
= gimple_call_arg (stmt
, 2);
1024 tree ti_decl_addr
= gimple_call_arg (stmt
, 3);
1025 tree ckind_tree
= gimple_call_arg (stmt
, 4);
1026 ubsan_null_ckind ckind
= (ubsan_null_ckind
) tree_to_uhwi (ckind_tree
);
1027 tree type
= TREE_TYPE (TREE_TYPE (ckind_tree
));
1029 basic_block fallthru_bb
= NULL
;
1031 if (ckind
== UBSAN_DOWNCAST_POINTER
)
1033 /* Guard everything with if (op != NULL) { ... }. */
1034 basic_block then_bb
;
1035 gimple_stmt_iterator cond_insert_point
1036 = create_cond_insert_point (gsip
, false, false, true,
1037 &then_bb
, &fallthru_bb
);
1038 g
= gimple_build_cond (NE_EXPR
, op
, build_zero_cst (TREE_TYPE (op
)),
1039 NULL_TREE
, NULL_TREE
);
1040 gimple_set_location (g
, loc
);
1041 gsi_insert_after (&cond_insert_point
, g
, GSI_NEW_STMT
);
1042 *gsip
= gsi_after_labels (then_bb
);
1043 gsi_remove (&gsi
, false);
1044 gsi_insert_before (gsip
, stmt
, GSI_NEW_STMT
);
1048 tree htype
= TREE_TYPE (str_hash
);
1049 tree cst
= wide_int_to_tree (htype
,
1050 wi::uhwi (((uint64_t) 0x9ddfea08 << 32)
1052 g
= gimple_build_assign (make_ssa_name (htype
), BIT_XOR_EXPR
,
1054 gimple_set_location (g
, loc
);
1055 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1056 g
= gimple_build_assign (make_ssa_name (htype
), MULT_EXPR
,
1057 gimple_assign_lhs (g
), cst
);
1058 gimple_set_location (g
, loc
);
1059 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1060 tree t1
= gimple_assign_lhs (g
);
1061 g
= gimple_build_assign (make_ssa_name (htype
), LSHIFT_EXPR
,
1062 t1
, build_int_cst (integer_type_node
, 47));
1063 gimple_set_location (g
, loc
);
1064 tree t2
= gimple_assign_lhs (g
);
1065 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1066 g
= gimple_build_assign (make_ssa_name (htype
), BIT_XOR_EXPR
,
1068 gimple_set_location (g
, loc
);
1069 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1070 g
= gimple_build_assign (make_ssa_name (htype
), BIT_XOR_EXPR
,
1071 t2
, gimple_assign_lhs (g
));
1072 gimple_set_location (g
, loc
);
1073 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1074 g
= gimple_build_assign (make_ssa_name (htype
), MULT_EXPR
,
1075 gimple_assign_lhs (g
), cst
);
1076 gimple_set_location (g
, loc
);
1077 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1078 tree t3
= gimple_assign_lhs (g
);
1079 g
= gimple_build_assign (make_ssa_name (htype
), LSHIFT_EXPR
,
1080 t3
, build_int_cst (integer_type_node
, 47));
1081 gimple_set_location (g
, loc
);
1082 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1083 g
= gimple_build_assign (make_ssa_name (htype
), BIT_XOR_EXPR
,
1084 t3
, gimple_assign_lhs (g
));
1085 gimple_set_location (g
, loc
);
1086 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1087 g
= gimple_build_assign (make_ssa_name (htype
), MULT_EXPR
,
1088 gimple_assign_lhs (g
), cst
);
1089 gimple_set_location (g
, loc
);
1090 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1091 if (!useless_type_conversion_p (pointer_sized_int_node
, htype
))
1093 g
= gimple_build_assign (make_ssa_name (pointer_sized_int_node
),
1094 NOP_EXPR
, gimple_assign_lhs (g
));
1095 gimple_set_location (g
, loc
);
1096 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1098 tree hash
= gimple_assign_lhs (g
);
1100 if (ubsan_vptr_type_cache_decl
== NULL_TREE
)
1102 tree atype
= build_array_type_nelts (pointer_sized_int_node
, 128);
1103 tree array
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
,
1104 get_identifier ("__ubsan_vptr_type_cache"),
1106 DECL_ARTIFICIAL (array
) = 1;
1107 DECL_IGNORED_P (array
) = 1;
1108 TREE_PUBLIC (array
) = 1;
1109 TREE_STATIC (array
) = 1;
1110 DECL_EXTERNAL (array
) = 1;
1111 DECL_VISIBILITY (array
) = VISIBILITY_DEFAULT
;
1112 DECL_VISIBILITY_SPECIFIED (array
) = 1;
1113 varpool_node::finalize_decl (array
);
1114 ubsan_vptr_type_cache_decl
= array
;
1117 g
= gimple_build_assign (make_ssa_name (pointer_sized_int_node
),
1119 build_int_cst (pointer_sized_int_node
, 127));
1120 gimple_set_location (g
, loc
);
1121 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1123 tree c
= build4_loc (loc
, ARRAY_REF
, pointer_sized_int_node
,
1124 ubsan_vptr_type_cache_decl
, gimple_assign_lhs (g
),
1125 NULL_TREE
, NULL_TREE
);
1126 g
= gimple_build_assign (make_ssa_name (pointer_sized_int_node
),
1128 gimple_set_location (g
, loc
);
1129 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1131 basic_block then_bb
, fallthru2_bb
;
1132 gimple_stmt_iterator cond_insert_point
1133 = create_cond_insert_point (gsip
, false, false, true,
1134 &then_bb
, &fallthru2_bb
);
1135 g
= gimple_build_cond (NE_EXPR
, gimple_assign_lhs (g
), hash
,
1136 NULL_TREE
, NULL_TREE
);
1137 gimple_set_location (g
, loc
);
1138 gsi_insert_after (&cond_insert_point
, g
, GSI_NEW_STMT
);
1139 *gsip
= gsi_after_labels (then_bb
);
1140 if (fallthru_bb
== NULL
)
1141 fallthru_bb
= fallthru2_bb
;
1144 = ubsan_create_data ("__ubsan_vptr_data", 1, &loc
,
1145 ubsan_type_descriptor (type
), NULL_TREE
, ti_decl_addr
,
1146 build_int_cst (unsigned_char_type_node
, ckind
),
1148 data
= build_fold_addr_expr_loc (loc
, data
);
1149 enum built_in_function bcode
1150 = (flag_sanitize_recover
& SANITIZE_VPTR
)
1151 ? BUILT_IN_UBSAN_HANDLE_DYNAMIC_TYPE_CACHE_MISS
1152 : BUILT_IN_UBSAN_HANDLE_DYNAMIC_TYPE_CACHE_MISS_ABORT
;
1154 g
= gimple_build_call (builtin_decl_explicit (bcode
), 3, data
, op
, hash
);
1155 gimple_set_location (g
, loc
);
1156 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1158 /* Point GSI to next logical statement. */
1159 *gsip
= gsi_start_bb (fallthru_bb
);
1161 /* Get rid of the UBSAN_VPTR call from the IR. */
1162 unlink_stmt_vdef (stmt
);
1163 gsi_remove (&gsi
, true);
1167 /* Instrument a memory reference. BASE is the base of MEM, IS_LHS says
1168 whether the pointer is on the left hand side of the assignment. */
1171 instrument_mem_ref (tree mem
, tree base
, gimple_stmt_iterator
*iter
,
1174 enum ubsan_null_ckind ikind
= is_lhs
? UBSAN_STORE_OF
: UBSAN_LOAD_OF
;
1175 unsigned int align
= 0;
1176 if (flag_sanitize
& SANITIZE_ALIGNMENT
)
1178 align
= min_align_of_type (TREE_TYPE (base
));
1182 if (align
== 0 && (flag_sanitize
& SANITIZE_NULL
) == 0)
1184 tree t
= TREE_OPERAND (base
, 0);
1185 if (!POINTER_TYPE_P (TREE_TYPE (t
)))
1187 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (base
)) && mem
!= base
)
1188 ikind
= UBSAN_MEMBER_ACCESS
;
1189 tree kind
= build_int_cst (build_pointer_type (TREE_TYPE (base
)), ikind
);
1190 tree alignt
= build_int_cst (pointer_sized_int_node
, align
);
1191 gcall
*g
= gimple_build_call_internal (IFN_UBSAN_NULL
, 3, t
, kind
, alignt
);
1192 gimple_set_location (g
, gimple_location (gsi_stmt (*iter
)));
1193 gsi_insert_before (iter
, g
, GSI_SAME_STMT
);
1196 /* Perform the pointer instrumentation. */
1199 instrument_null (gimple_stmt_iterator gsi
, bool is_lhs
)
1201 gimple
*stmt
= gsi_stmt (gsi
);
1202 tree t
= is_lhs
? gimple_get_lhs (stmt
) : gimple_assign_rhs1 (stmt
);
1203 tree base
= get_base_address (t
);
1204 const enum tree_code code
= TREE_CODE (base
);
1206 && TREE_CODE (TREE_OPERAND (base
, 0)) == SSA_NAME
)
1207 instrument_mem_ref (t
, base
, &gsi
, is_lhs
);
1210 /* Build an ubsan builtin call for the signed-integer-overflow
1211 sanitization. CODE says what kind of builtin are we building,
1212 LOC is a location, LHSTYPE is the type of LHS, OP0 and OP1
1213 are operands of the binary operation. */
1216 ubsan_build_overflow_builtin (tree_code code
, location_t loc
, tree lhstype
,
1219 if (flag_sanitize_undefined_trap_on_error
)
1220 return build_call_expr_loc (loc
, builtin_decl_explicit (BUILT_IN_TRAP
), 0);
1222 tree data
= ubsan_create_data ("__ubsan_overflow_data", 1, &loc
,
1223 ubsan_type_descriptor (lhstype
), NULL_TREE
,
1225 enum built_in_function fn_code
;
1230 fn_code
= (flag_sanitize_recover
& SANITIZE_SI_OVERFLOW
)
1231 ? BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW
1232 : BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW_ABORT
;
1235 fn_code
= (flag_sanitize_recover
& SANITIZE_SI_OVERFLOW
)
1236 ? BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW
1237 : BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW_ABORT
;
1240 fn_code
= (flag_sanitize_recover
& SANITIZE_SI_OVERFLOW
)
1241 ? BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW
1242 : BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW_ABORT
;
1245 fn_code
= (flag_sanitize_recover
& SANITIZE_SI_OVERFLOW
)
1246 ? BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW
1247 : BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW_ABORT
;
1252 tree fn
= builtin_decl_explicit (fn_code
);
1253 return build_call_expr_loc (loc
, fn
, 2 + (code
!= NEGATE_EXPR
),
1254 build_fold_addr_expr_loc (loc
, data
),
1255 ubsan_encode_value (op0
, true),
1256 op1
? ubsan_encode_value (op1
, true)
1260 /* Perform the signed integer instrumentation. GSI is the iterator
1261 pointing at statement we are trying to instrument. */
1264 instrument_si_overflow (gimple_stmt_iterator gsi
)
1266 gimple
*stmt
= gsi_stmt (gsi
);
1267 tree_code code
= gimple_assign_rhs_code (stmt
);
1268 tree lhs
= gimple_assign_lhs (stmt
);
1269 tree lhstype
= TREE_TYPE (lhs
);
1273 /* If this is not a signed operation, don't instrument anything here.
1274 Also punt on bit-fields. */
1275 if (!INTEGRAL_TYPE_P (lhstype
)
1276 || TYPE_OVERFLOW_WRAPS (lhstype
)
1277 || GET_MODE_BITSIZE (TYPE_MODE (lhstype
)) != TYPE_PRECISION (lhstype
))
1288 i = UBSAN_CHECK_{ADD,SUB,MUL} (u, 5); */
1289 a
= gimple_assign_rhs1 (stmt
);
1290 b
= gimple_assign_rhs2 (stmt
);
1291 g
= gimple_build_call_internal (code
== PLUS_EXPR
1292 ? IFN_UBSAN_CHECK_ADD
1293 : code
== MINUS_EXPR
1294 ? IFN_UBSAN_CHECK_SUB
1295 : IFN_UBSAN_CHECK_MUL
, 2, a
, b
);
1296 gimple_call_set_lhs (g
, lhs
);
1297 gsi_replace (&gsi
, g
, true);
1300 /* Represent i = -u;
1302 i = UBSAN_CHECK_SUB (0, u); */
1303 a
= build_int_cst (lhstype
, 0);
1304 b
= gimple_assign_rhs1 (stmt
);
1305 g
= gimple_build_call_internal (IFN_UBSAN_CHECK_SUB
, 2, a
, b
);
1306 gimple_call_set_lhs (g
, lhs
);
1307 gsi_replace (&gsi
, g
, true);
1310 /* Transform i = ABS_EXPR<u>;
1312 _N = UBSAN_CHECK_SUB (0, u);
1313 i = ABS_EXPR<_N>; */
1314 a
= build_int_cst (lhstype
, 0);
1315 b
= gimple_assign_rhs1 (stmt
);
1316 g
= gimple_build_call_internal (IFN_UBSAN_CHECK_SUB
, 2, a
, b
);
1317 a
= make_ssa_name (lhstype
);
1318 gimple_call_set_lhs (g
, a
);
1319 gimple_set_location (g
, gimple_location (stmt
));
1320 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
1321 gimple_assign_set_rhs1 (stmt
, a
);
1329 /* Instrument loads from (non-bitfield) bool and C++ enum values
1330 to check if the memory value is outside of the range of the valid
1334 instrument_bool_enum_load (gimple_stmt_iterator
*gsi
)
1336 gimple
*stmt
= gsi_stmt (*gsi
);
1337 tree rhs
= gimple_assign_rhs1 (stmt
);
1338 tree type
= TREE_TYPE (rhs
);
1339 tree minv
= NULL_TREE
, maxv
= NULL_TREE
;
1341 if (TREE_CODE (type
) == BOOLEAN_TYPE
&& (flag_sanitize
& SANITIZE_BOOL
))
1343 minv
= boolean_false_node
;
1344 maxv
= boolean_true_node
;
1346 else if (TREE_CODE (type
) == ENUMERAL_TYPE
1347 && (flag_sanitize
& SANITIZE_ENUM
)
1348 && TREE_TYPE (type
) != NULL_TREE
1349 && TREE_CODE (TREE_TYPE (type
)) == INTEGER_TYPE
1350 && (TYPE_PRECISION (TREE_TYPE (type
))
1351 < GET_MODE_PRECISION (TYPE_MODE (type
))))
1353 minv
= TYPE_MIN_VALUE (TREE_TYPE (type
));
1354 maxv
= TYPE_MAX_VALUE (TREE_TYPE (type
));
1359 int modebitsize
= GET_MODE_BITSIZE (TYPE_MODE (type
));
1360 HOST_WIDE_INT bitsize
, bitpos
;
1363 int volatilep
= 0, reversep
, unsignedp
= 0;
1364 tree base
= get_inner_reference (rhs
, &bitsize
, &bitpos
, &offset
, &mode
,
1365 &unsignedp
, &reversep
, &volatilep
, false);
1366 tree utype
= build_nonstandard_integer_type (modebitsize
, 1);
1368 if ((TREE_CODE (base
) == VAR_DECL
&& DECL_HARD_REGISTER (base
))
1369 || (bitpos
% modebitsize
) != 0
1370 || bitsize
!= modebitsize
1371 || GET_MODE_BITSIZE (TYPE_MODE (utype
)) != modebitsize
1372 || TREE_CODE (gimple_assign_lhs (stmt
)) != SSA_NAME
)
1375 bool ends_bb
= stmt_ends_bb_p (stmt
);
1376 location_t loc
= gimple_location (stmt
);
1377 tree lhs
= gimple_assign_lhs (stmt
);
1378 tree ptype
= build_pointer_type (TREE_TYPE (rhs
));
1379 tree atype
= reference_alias_ptr_type (rhs
);
1380 gimple
*g
= gimple_build_assign (make_ssa_name (ptype
),
1381 build_fold_addr_expr (rhs
));
1382 gimple_set_location (g
, loc
);
1383 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1384 tree mem
= build2 (MEM_REF
, utype
, gimple_assign_lhs (g
),
1385 build_int_cst (atype
, 0));
1386 tree urhs
= make_ssa_name (utype
);
1389 gimple_assign_set_lhs (stmt
, urhs
);
1390 g
= gimple_build_assign (lhs
, NOP_EXPR
, urhs
);
1391 gimple_set_location (g
, loc
);
1392 edge e
= find_fallthru_edge (gimple_bb (stmt
)->succs
);
1393 gsi_insert_on_edge_immediate (e
, g
);
1394 gimple_assign_set_rhs_from_tree (gsi
, mem
);
1396 *gsi
= gsi_for_stmt (g
);
1401 g
= gimple_build_assign (urhs
, mem
);
1402 gimple_set_location (g
, loc
);
1403 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1405 minv
= fold_convert (utype
, minv
);
1406 maxv
= fold_convert (utype
, maxv
);
1407 if (!integer_zerop (minv
))
1409 g
= gimple_build_assign (make_ssa_name (utype
), MINUS_EXPR
, urhs
, minv
);
1410 gimple_set_location (g
, loc
);
1411 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1414 gimple_stmt_iterator gsi2
= *gsi
;
1415 basic_block then_bb
, fallthru_bb
;
1416 *gsi
= create_cond_insert_point (gsi
, true, false, true,
1417 &then_bb
, &fallthru_bb
);
1418 g
= gimple_build_cond (GT_EXPR
, gimple_assign_lhs (g
),
1419 int_const_binop (MINUS_EXPR
, maxv
, minv
),
1420 NULL_TREE
, NULL_TREE
);
1421 gimple_set_location (g
, loc
);
1422 gsi_insert_after (gsi
, g
, GSI_NEW_STMT
);
1426 gimple_assign_set_rhs_with_ops (&gsi2
, NOP_EXPR
, urhs
);
1430 gsi2
= gsi_after_labels (then_bb
);
1431 if (flag_sanitize_undefined_trap_on_error
)
1432 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
1435 tree data
= ubsan_create_data ("__ubsan_invalid_value_data", 1, &loc
,
1436 ubsan_type_descriptor (type
), NULL_TREE
,
1438 data
= build_fold_addr_expr_loc (loc
, data
);
1439 enum built_in_function bcode
1440 = (flag_sanitize_recover
& (TREE_CODE (type
) == BOOLEAN_TYPE
1441 ? SANITIZE_BOOL
: SANITIZE_ENUM
))
1442 ? BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE
1443 : BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE_ABORT
;
1444 tree fn
= builtin_decl_explicit (bcode
);
1446 tree val
= force_gimple_operand_gsi (&gsi2
, ubsan_encode_value (urhs
),
1447 true, NULL_TREE
, true,
1449 g
= gimple_build_call (fn
, 2, data
, val
);
1451 gimple_set_location (g
, loc
);
1452 gsi_insert_before (&gsi2
, g
, GSI_SAME_STMT
);
1453 ubsan_create_edge (g
);
1454 *gsi
= gsi_for_stmt (stmt
);
1457 /* Determine if we can propagate given LOCATION to ubsan_data descriptor to use
1458 new style handlers. Libubsan uses heuristics to destinguish between old and
1459 new styles and relies on these properties for filename:
1461 a) Location's filename must not be NULL.
1462 b) Location's filename must not be equal to "".
1463 c) Location's filename must not be equal to "\1".
1464 d) First two bytes of filename must not contain '\xff' symbol. */
1467 ubsan_use_new_style_p (location_t loc
)
1469 if (loc
== UNKNOWN_LOCATION
)
1472 expanded_location xloc
= expand_location (loc
);
1473 if (xloc
.file
== NULL
|| strncmp (xloc
.file
, "\1", 2) == 0
1474 || xloc
.file
== '\0' || xloc
.file
[0] == '\xff'
1475 || xloc
.file
[1] == '\xff')
1481 /* Instrument float point-to-integer conversion. TYPE is an integer type of
1482 destination, EXPR is floating-point expression. */
1485 ubsan_instrument_float_cast (location_t loc
, tree type
, tree expr
)
1487 tree expr_type
= TREE_TYPE (expr
);
1488 tree t
, tt
, fn
, min
, max
;
1489 machine_mode mode
= TYPE_MODE (expr_type
);
1490 int prec
= TYPE_PRECISION (type
);
1491 bool uns_p
= TYPE_UNSIGNED (type
);
1492 if (loc
== UNKNOWN_LOCATION
)
1493 loc
= input_location
;
1495 /* Float to integer conversion first truncates toward zero, so
1496 even signed char c = 127.875f; is not problematic.
1497 Therefore, we should complain only if EXPR is unordered or smaller
1498 or equal than TYPE_MIN_VALUE - 1.0 or greater or equal than
1499 TYPE_MAX_VALUE + 1.0. */
1500 if (REAL_MODE_FORMAT (mode
)->b
== 2)
1502 /* For maximum, TYPE_MAX_VALUE might not be representable
1503 in EXPR_TYPE, e.g. if TYPE is 64-bit long long and
1504 EXPR_TYPE is IEEE single float, but TYPE_MAX_VALUE + 1.0 is
1505 either representable or infinity. */
1506 REAL_VALUE_TYPE maxval
= dconst1
;
1507 SET_REAL_EXP (&maxval
, REAL_EXP (&maxval
) + prec
- !uns_p
);
1508 real_convert (&maxval
, mode
, &maxval
);
1509 max
= build_real (expr_type
, maxval
);
1511 /* For unsigned, assume -1.0 is always representable. */
1513 min
= build_minus_one_cst (expr_type
);
1516 /* TYPE_MIN_VALUE is generally representable (or -inf),
1517 but TYPE_MIN_VALUE - 1.0 might not be. */
1518 REAL_VALUE_TYPE minval
= dconstm1
, minval2
;
1519 SET_REAL_EXP (&minval
, REAL_EXP (&minval
) + prec
- 1);
1520 real_convert (&minval
, mode
, &minval
);
1521 real_arithmetic (&minval2
, MINUS_EXPR
, &minval
, &dconst1
);
1522 real_convert (&minval2
, mode
, &minval2
);
1523 if (real_compare (EQ_EXPR
, &minval
, &minval2
)
1524 && !real_isinf (&minval
))
1526 /* If TYPE_MIN_VALUE - 1.0 is not representable and
1527 rounds to TYPE_MIN_VALUE, we need to subtract
1528 more. As REAL_MODE_FORMAT (mode)->p is the number
1529 of base digits, we want to subtract a number that
1530 will be 1 << (REAL_MODE_FORMAT (mode)->p - 1)
1531 times smaller than minval. */
1533 gcc_assert (prec
> REAL_MODE_FORMAT (mode
)->p
);
1534 SET_REAL_EXP (&minval2
,
1535 REAL_EXP (&minval2
) + prec
- 1
1536 - REAL_MODE_FORMAT (mode
)->p
+ 1);
1537 real_arithmetic (&minval2
, MINUS_EXPR
, &minval
, &minval2
);
1538 real_convert (&minval2
, mode
, &minval2
);
1540 min
= build_real (expr_type
, minval2
);
1543 else if (REAL_MODE_FORMAT (mode
)->b
== 10)
1545 /* For _Decimal128 up to 34 decimal digits, - sign,
1546 dot, e, exponent. */
1549 int p
= REAL_MODE_FORMAT (mode
)->p
;
1550 REAL_VALUE_TYPE maxval
, minval
;
1552 /* Use mpfr_snprintf rounding to compute the smallest
1553 representable decimal number greater or equal than
1554 1 << (prec - !uns_p). */
1555 mpfr_init2 (m
, prec
+ 2);
1556 mpfr_set_ui_2exp (m
, 1, prec
- !uns_p
, GMP_RNDN
);
1557 mpfr_snprintf (buf
, sizeof buf
, "%.*RUe", p
- 1, m
);
1558 decimal_real_from_string (&maxval
, buf
);
1559 max
= build_real (expr_type
, maxval
);
1561 /* For unsigned, assume -1.0 is always representable. */
1563 min
= build_minus_one_cst (expr_type
);
1566 /* Use mpfr_snprintf rounding to compute the largest
1567 representable decimal number less or equal than
1568 (-1 << (prec - 1)) - 1. */
1569 mpfr_set_si_2exp (m
, -1, prec
- 1, GMP_RNDN
);
1570 mpfr_sub_ui (m
, m
, 1, GMP_RNDN
);
1571 mpfr_snprintf (buf
, sizeof buf
, "%.*RDe", p
- 1, m
);
1572 decimal_real_from_string (&minval
, buf
);
1573 min
= build_real (expr_type
, minval
);
1580 t
= fold_build2 (UNLE_EXPR
, boolean_type_node
, expr
, min
);
1581 tt
= fold_build2 (UNGE_EXPR
, boolean_type_node
, expr
, max
);
1582 t
= fold_build2 (TRUTH_OR_EXPR
, boolean_type_node
, t
, tt
);
1583 if (integer_zerop (t
))
1586 if (flag_sanitize_undefined_trap_on_error
)
1587 fn
= build_call_expr_loc (loc
, builtin_decl_explicit (BUILT_IN_TRAP
), 0);
1590 location_t
*loc_ptr
= NULL
;
1591 unsigned num_locations
= 0;
1592 initialize_sanitizer_builtins ();
1593 /* Figure out if we can propagate location to ubsan_data and use new
1594 style handlers in libubsan. */
1595 if (ubsan_use_new_style_p (loc
))
1600 /* Create the __ubsan_handle_float_cast_overflow fn call. */
1601 tree data
= ubsan_create_data ("__ubsan_float_cast_overflow_data",
1602 num_locations
, loc_ptr
,
1603 ubsan_type_descriptor (expr_type
),
1604 ubsan_type_descriptor (type
), NULL_TREE
,
1606 enum built_in_function bcode
1607 = (flag_sanitize_recover
& SANITIZE_FLOAT_CAST
)
1608 ? BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW
1609 : BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW_ABORT
;
1610 fn
= builtin_decl_explicit (bcode
);
1611 fn
= build_call_expr_loc (loc
, fn
, 2,
1612 build_fold_addr_expr_loc (loc
, data
),
1613 ubsan_encode_value (expr
, false));
1616 return fold_build3 (COND_EXPR
, void_type_node
, t
, fn
, integer_zero_node
);
1619 /* Instrument values passed to function arguments with nonnull attribute. */
1622 instrument_nonnull_arg (gimple_stmt_iterator
*gsi
)
1624 gimple
*stmt
= gsi_stmt (*gsi
);
1626 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
1627 while for nonnull sanitization it is clear. */
1628 int save_flag_delete_null_pointer_checks
= flag_delete_null_pointer_checks
;
1629 flag_delete_null_pointer_checks
= 1;
1630 loc
[0] = gimple_location (stmt
);
1631 loc
[1] = UNKNOWN_LOCATION
;
1632 for (unsigned int i
= 0; i
< gimple_call_num_args (stmt
); i
++)
1634 tree arg
= gimple_call_arg (stmt
, i
);
1635 if (POINTER_TYPE_P (TREE_TYPE (arg
))
1636 && infer_nonnull_range_by_attribute (stmt
, arg
))
1639 if (!is_gimple_val (arg
))
1641 g
= gimple_build_assign (make_ssa_name (TREE_TYPE (arg
)), arg
);
1642 gimple_set_location (g
, loc
[0]);
1643 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1644 arg
= gimple_assign_lhs (g
);
1647 basic_block then_bb
, fallthru_bb
;
1648 *gsi
= create_cond_insert_point (gsi
, true, false, true,
1649 &then_bb
, &fallthru_bb
);
1650 g
= gimple_build_cond (EQ_EXPR
, arg
,
1651 build_zero_cst (TREE_TYPE (arg
)),
1652 NULL_TREE
, NULL_TREE
);
1653 gimple_set_location (g
, loc
[0]);
1654 gsi_insert_after (gsi
, g
, GSI_NEW_STMT
);
1656 *gsi
= gsi_after_labels (then_bb
);
1657 if (flag_sanitize_undefined_trap_on_error
)
1658 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
1661 tree data
= ubsan_create_data ("__ubsan_nonnull_arg_data",
1663 build_int_cst (integer_type_node
,
1666 data
= build_fold_addr_expr_loc (loc
[0], data
);
1667 enum built_in_function bcode
1668 = (flag_sanitize_recover
& SANITIZE_NONNULL_ATTRIBUTE
)
1669 ? BUILT_IN_UBSAN_HANDLE_NONNULL_ARG
1670 : BUILT_IN_UBSAN_HANDLE_NONNULL_ARG_ABORT
;
1671 tree fn
= builtin_decl_explicit (bcode
);
1673 g
= gimple_build_call (fn
, 1, data
);
1675 gimple_set_location (g
, loc
[0]);
1676 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1677 ubsan_create_edge (g
);
1679 *gsi
= gsi_for_stmt (stmt
);
1681 flag_delete_null_pointer_checks
= save_flag_delete_null_pointer_checks
;
1684 /* Instrument returns in functions with returns_nonnull attribute. */
1687 instrument_nonnull_return (gimple_stmt_iterator
*gsi
)
1689 greturn
*stmt
= as_a
<greturn
*> (gsi_stmt (*gsi
));
1691 tree arg
= gimple_return_retval (stmt
);
1692 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
1693 while for nonnull return sanitization it is clear. */
1694 int save_flag_delete_null_pointer_checks
= flag_delete_null_pointer_checks
;
1695 flag_delete_null_pointer_checks
= 1;
1696 loc
[0] = gimple_location (stmt
);
1697 loc
[1] = UNKNOWN_LOCATION
;
1699 && POINTER_TYPE_P (TREE_TYPE (arg
))
1700 && is_gimple_val (arg
)
1701 && infer_nonnull_range_by_attribute (stmt
, arg
))
1703 basic_block then_bb
, fallthru_bb
;
1704 *gsi
= create_cond_insert_point (gsi
, true, false, true,
1705 &then_bb
, &fallthru_bb
);
1706 gimple
*g
= gimple_build_cond (EQ_EXPR
, arg
,
1707 build_zero_cst (TREE_TYPE (arg
)),
1708 NULL_TREE
, NULL_TREE
);
1709 gimple_set_location (g
, loc
[0]);
1710 gsi_insert_after (gsi
, g
, GSI_NEW_STMT
);
1712 *gsi
= gsi_after_labels (then_bb
);
1713 if (flag_sanitize_undefined_trap_on_error
)
1714 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
1717 tree data
= ubsan_create_data ("__ubsan_nonnull_return_data",
1718 2, loc
, NULL_TREE
, NULL_TREE
);
1719 data
= build_fold_addr_expr_loc (loc
[0], data
);
1720 enum built_in_function bcode
1721 = (flag_sanitize_recover
& SANITIZE_RETURNS_NONNULL_ATTRIBUTE
)
1722 ? BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN
1723 : BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_ABORT
;
1724 tree fn
= builtin_decl_explicit (bcode
);
1726 g
= gimple_build_call (fn
, 1, data
);
1728 gimple_set_location (g
, loc
[0]);
1729 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1730 ubsan_create_edge (g
);
1731 *gsi
= gsi_for_stmt (stmt
);
1733 flag_delete_null_pointer_checks
= save_flag_delete_null_pointer_checks
;
1736 /* Instrument memory references. Here we check whether the pointer
1737 points to an out-of-bounds location. */
1740 instrument_object_size (gimple_stmt_iterator
*gsi
, bool is_lhs
)
1742 gimple
*stmt
= gsi_stmt (*gsi
);
1743 location_t loc
= gimple_location (stmt
);
1744 tree t
= is_lhs
? gimple_get_lhs (stmt
) : gimple_assign_rhs1 (stmt
);
1746 tree index
= NULL_TREE
;
1747 HOST_WIDE_INT size_in_bytes
;
1749 type
= TREE_TYPE (t
);
1750 if (VOID_TYPE_P (type
))
1753 switch (TREE_CODE (t
))
1756 if (TREE_CODE (t
) == COMPONENT_REF
1757 && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t
, 1)) != NULL_TREE
)
1759 tree repr
= DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t
, 1));
1760 t
= build3 (COMPONENT_REF
, TREE_TYPE (repr
), TREE_OPERAND (t
, 0),
1765 index
= TREE_OPERAND (t
, 1);
1777 size_in_bytes
= int_size_in_bytes (type
);
1778 if (size_in_bytes
<= 0)
1781 HOST_WIDE_INT bitsize
, bitpos
;
1784 int volatilep
= 0, reversep
, unsignedp
= 0;
1785 tree inner
= get_inner_reference (t
, &bitsize
, &bitpos
, &offset
, &mode
,
1786 &unsignedp
, &reversep
, &volatilep
, false);
1788 if (bitpos
% BITS_PER_UNIT
!= 0
1789 || bitsize
!= size_in_bytes
* BITS_PER_UNIT
)
1792 bool decl_p
= DECL_P (inner
);
1796 else if (TREE_CODE (inner
) == MEM_REF
)
1797 base
= TREE_OPERAND (inner
, 0);
1800 tree ptr
= build1 (ADDR_EXPR
, build_pointer_type (TREE_TYPE (t
)), t
);
1802 while (TREE_CODE (base
) == SSA_NAME
)
1804 gimple
*def_stmt
= SSA_NAME_DEF_STMT (base
);
1805 if (gimple_assign_ssa_name_copy_p (def_stmt
)
1806 || (gimple_assign_cast_p (def_stmt
)
1807 && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (def_stmt
))))
1808 || (is_gimple_assign (def_stmt
)
1809 && gimple_assign_rhs_code (def_stmt
) == POINTER_PLUS_EXPR
))
1811 tree rhs1
= gimple_assign_rhs1 (def_stmt
);
1812 if (TREE_CODE (rhs1
) == SSA_NAME
1813 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs1
))
1822 if (!POINTER_TYPE_P (TREE_TYPE (base
)) && !DECL_P (base
))
1826 tree base_addr
= base
;
1827 gimple
*bos_stmt
= NULL
;
1829 base_addr
= build1 (ADDR_EXPR
,
1830 build_pointer_type (TREE_TYPE (base
)), base
);
1831 unsigned HOST_WIDE_INT size
= compute_builtin_object_size (base_addr
, 0);
1832 if (size
!= (unsigned HOST_WIDE_INT
) -1)
1833 sizet
= build_int_cst (sizetype
, size
);
1836 if (LOCATION_LOCUS (loc
) == UNKNOWN_LOCATION
)
1837 loc
= input_location
;
1838 /* Generate __builtin_object_size call. */
1839 sizet
= builtin_decl_explicit (BUILT_IN_OBJECT_SIZE
);
1840 sizet
= build_call_expr_loc (loc
, sizet
, 2, base_addr
,
1842 sizet
= force_gimple_operand_gsi (gsi
, sizet
, false, NULL_TREE
, true,
1844 /* If the call above didn't end up being an integer constant, go one
1845 statement back and get the __builtin_object_size stmt. Save it,
1846 we might need it later. */
1847 if (SSA_VAR_P (sizet
))
1850 bos_stmt
= gsi_stmt (*gsi
);
1852 /* Move on to where we were. */
1859 /* Generate UBSAN_OBJECT_SIZE (ptr, ptr+sizeof(*ptr)-base, objsize, ckind)
1861 /* ptr + sizeof (*ptr) - base */
1862 t
= fold_build2 (MINUS_EXPR
, sizetype
,
1863 fold_convert (pointer_sized_int_node
, ptr
),
1864 fold_convert (pointer_sized_int_node
, base_addr
));
1865 t
= fold_build2 (PLUS_EXPR
, sizetype
, t
, TYPE_SIZE_UNIT (type
));
1867 /* Perhaps we can omit the check. */
1868 if (TREE_CODE (t
) == INTEGER_CST
1869 && TREE_CODE (sizet
) == INTEGER_CST
1870 && tree_int_cst_le (t
, sizet
))
1873 if (index
!= NULL_TREE
1874 && TREE_CODE (index
) == SSA_NAME
1875 && TREE_CODE (sizet
) == INTEGER_CST
)
1877 gimple
*def
= SSA_NAME_DEF_STMT (index
);
1878 if (is_gimple_assign (def
)
1879 && gimple_assign_rhs_code (def
) == BIT_AND_EXPR
1880 && TREE_CODE (gimple_assign_rhs2 (def
)) == INTEGER_CST
)
1882 tree cst
= gimple_assign_rhs2 (def
);
1883 tree sz
= fold_build2 (EXACT_DIV_EXPR
, sizetype
, sizet
,
1884 TYPE_SIZE_UNIT (type
));
1885 if (tree_int_cst_sgn (cst
) >= 0
1886 && tree_int_cst_lt (cst
, sz
))
1891 if (bos_stmt
&& gimple_call_builtin_p (bos_stmt
, BUILT_IN_OBJECT_SIZE
))
1892 ubsan_create_edge (bos_stmt
);
1894 /* We have to emit the check. */
1895 t
= force_gimple_operand_gsi (gsi
, t
, true, NULL_TREE
, true,
1897 ptr
= force_gimple_operand_gsi (gsi
, ptr
, true, NULL_TREE
, true,
1899 tree ckind
= build_int_cst (unsigned_char_type_node
,
1900 is_lhs
? UBSAN_STORE_OF
: UBSAN_LOAD_OF
);
1901 gimple
*g
= gimple_build_call_internal (IFN_UBSAN_OBJECT_SIZE
, 4,
1902 ptr
, t
, sizet
, ckind
);
1903 gimple_set_location (g
, loc
);
1904 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1907 /* True if we want to play UBSan games in the current function. */
1910 do_ubsan_in_current_function ()
1912 return (current_function_decl
!= NULL_TREE
1913 && !lookup_attribute ("no_sanitize_undefined",
1914 DECL_ATTRIBUTES (current_function_decl
)));
1919 const pass_data pass_data_ubsan
=
1921 GIMPLE_PASS
, /* type */
1923 OPTGROUP_NONE
, /* optinfo_flags */
1924 TV_TREE_UBSAN
, /* tv_id */
1925 ( PROP_cfg
| PROP_ssa
), /* properties_required */
1926 0, /* properties_provided */
1927 0, /* properties_destroyed */
1928 0, /* todo_flags_start */
1929 TODO_update_ssa
, /* todo_flags_finish */
1932 class pass_ubsan
: public gimple_opt_pass
1935 pass_ubsan (gcc::context
*ctxt
)
1936 : gimple_opt_pass (pass_data_ubsan
, ctxt
)
1939 /* opt_pass methods: */
1940 virtual bool gate (function
*)
1942 return flag_sanitize
& (SANITIZE_NULL
| SANITIZE_SI_OVERFLOW
1943 | SANITIZE_BOOL
| SANITIZE_ENUM
1944 | SANITIZE_ALIGNMENT
1945 | SANITIZE_NONNULL_ATTRIBUTE
1946 | SANITIZE_RETURNS_NONNULL_ATTRIBUTE
1947 | SANITIZE_OBJECT_SIZE
)
1948 && do_ubsan_in_current_function ();
1951 virtual unsigned int execute (function
*);
1953 }; // class pass_ubsan
1956 pass_ubsan::execute (function
*fun
)
1959 gimple_stmt_iterator gsi
;
1960 unsigned int ret
= 0;
1962 initialize_sanitizer_builtins ();
1964 FOR_EACH_BB_FN (bb
, fun
)
1966 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
);)
1968 gimple
*stmt
= gsi_stmt (gsi
);
1969 if (is_gimple_debug (stmt
) || gimple_clobber_p (stmt
))
1975 if ((flag_sanitize
& SANITIZE_SI_OVERFLOW
)
1976 && is_gimple_assign (stmt
))
1977 instrument_si_overflow (gsi
);
1979 if (flag_sanitize
& (SANITIZE_NULL
| SANITIZE_ALIGNMENT
))
1981 if (gimple_store_p (stmt
))
1982 instrument_null (gsi
, true);
1983 if (gimple_assign_load_p (stmt
))
1984 instrument_null (gsi
, false);
1987 if (flag_sanitize
& (SANITIZE_BOOL
| SANITIZE_ENUM
)
1988 && gimple_assign_load_p (stmt
))
1990 instrument_bool_enum_load (&gsi
);
1991 bb
= gimple_bb (stmt
);
1994 if ((flag_sanitize
& SANITIZE_NONNULL_ATTRIBUTE
)
1995 && is_gimple_call (stmt
)
1996 && !gimple_call_internal_p (stmt
))
1998 instrument_nonnull_arg (&gsi
);
1999 bb
= gimple_bb (stmt
);
2002 if ((flag_sanitize
& SANITIZE_RETURNS_NONNULL_ATTRIBUTE
)
2003 && gimple_code (stmt
) == GIMPLE_RETURN
)
2005 instrument_nonnull_return (&gsi
);
2006 bb
= gimple_bb (stmt
);
2009 if (flag_sanitize
& SANITIZE_OBJECT_SIZE
)
2011 if (gimple_store_p (stmt
))
2012 instrument_object_size (&gsi
, true);
2013 if (gimple_assign_load_p (stmt
))
2014 instrument_object_size (&gsi
, false);
2019 if (gimple_purge_dead_eh_edges (bb
))
2020 ret
= TODO_cleanup_cfg
;
2028 make_pass_ubsan (gcc::context
*ctxt
)
2030 return new pass_ubsan (ctxt
);
2033 #include "gt-ubsan.h"