1 /* UndefinedBehaviorSanitizer, undefined behavior detector.
2 Copyright (C) 2013-2021 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"
34 #include "tree-pretty-print.h"
35 #include "stor-layout.h"
37 #include "gimple-iterator.h"
42 #include "stringpool.h"
45 #include "gimplify-me.h"
48 #include "tree-object-size.h"
50 #include "gimple-fold.h"
53 /* Map from a tree to a VAR_DECL tree. */
55 struct GTY((for_user
)) tree_type_map
{
56 struct tree_map_base type
;
60 struct tree_type_map_cache_hasher
: ggc_cache_ptr_hash
<tree_type_map
>
62 static inline hashval_t
63 hash (tree_type_map
*t
)
65 return TYPE_UID (t
->type
.from
);
69 equal (tree_type_map
*a
, tree_type_map
*b
)
71 return a
->type
.from
== b
->type
.from
;
75 keep_cache_entry (tree_type_map
*&m
)
77 return ggc_marked_p (m
->type
.from
);
82 hash_table
<tree_type_map_cache_hasher
> *decl_tree_for_type
;
84 /* Lookup a VAR_DECL for TYPE, and return it if we find one. */
87 decl_for_type_lookup (tree type
)
89 /* If the hash table is not initialized yet, create it now. */
90 if (decl_tree_for_type
== NULL
)
93 = hash_table
<tree_type_map_cache_hasher
>::create_ggc (10);
94 /* That also means we don't have to bother with the lookup. */
98 struct tree_type_map
*h
, in
;
101 h
= decl_tree_for_type
->find_with_hash (&in
, TYPE_UID (type
));
102 return h
? h
->decl
: NULL_TREE
;
105 /* Insert a mapping TYPE->DECL in the VAR_DECL for type hashtable. */
108 decl_for_type_insert (tree type
, tree decl
)
110 struct tree_type_map
*h
;
112 h
= ggc_alloc
<tree_type_map
> ();
115 *decl_tree_for_type
->find_slot_with_hash (h
, TYPE_UID (type
), INSERT
) = h
;
118 /* Helper routine, which encodes a value in the pointer_sized_int_node.
119 Arguments with precision <= POINTER_SIZE are passed directly,
120 the rest is passed by reference. T is a value we are to encode.
121 PHASE determines when this function is called. */
124 ubsan_encode_value (tree t
, enum ubsan_encode_value_phase phase
)
126 tree type
= TREE_TYPE (t
);
127 scalar_mode mode
= SCALAR_TYPE_MODE (type
);
128 const unsigned int bitsize
= GET_MODE_BITSIZE (mode
);
129 if (bitsize
<= POINTER_SIZE
)
130 switch (TREE_CODE (type
))
135 return fold_build1 (NOP_EXPR
, pointer_sized_int_node
, t
);
138 tree itype
= build_nonstandard_integer_type (bitsize
, true);
139 t
= fold_build1 (VIEW_CONVERT_EXPR
, itype
, t
);
140 return fold_convert (pointer_sized_int_node
, t
);
147 if (!DECL_P (t
) || !TREE_ADDRESSABLE (t
))
149 /* The reason for this is that we don't want to pessimize
150 code by making vars unnecessarily addressable. */
152 if (phase
!= UBSAN_ENCODE_VALUE_GENERIC
)
154 var
= create_tmp_var (type
);
155 mark_addressable (var
);
159 var
= create_tmp_var_raw (type
);
160 TREE_ADDRESSABLE (var
) = 1;
161 DECL_CONTEXT (var
) = current_function_decl
;
163 if (phase
== UBSAN_ENCODE_VALUE_RTL
)
165 rtx mem
= assign_stack_temp_for_type (mode
, GET_MODE_SIZE (mode
),
167 SET_DECL_RTL (var
, mem
);
168 expand_assignment (var
, t
, false);
169 return build_fold_addr_expr (var
);
171 if (phase
!= UBSAN_ENCODE_VALUE_GENERIC
)
173 tree tem
= build2 (MODIFY_EXPR
, void_type_node
, var
, t
);
174 t
= build_fold_addr_expr (var
);
175 return build2 (COMPOUND_EXPR
, TREE_TYPE (t
), tem
, t
);
179 var
= build4 (TARGET_EXPR
, type
, var
, t
, NULL_TREE
, NULL_TREE
);
180 return build_fold_addr_expr (var
);
184 return build_fold_addr_expr (t
);
188 /* Cached ubsan_get_type_descriptor_type () return value. */
189 static GTY(()) tree ubsan_type_descriptor_type
;
192 struct __ubsan_type_descriptor
194 unsigned short __typekind;
195 unsigned short __typeinfo;
201 ubsan_get_type_descriptor_type (void)
203 static const char *field_names
[3]
204 = { "__typekind", "__typeinfo", "__typename" };
207 if (ubsan_type_descriptor_type
)
208 return ubsan_type_descriptor_type
;
210 tree itype
= build_range_type (sizetype
, size_zero_node
, NULL_TREE
);
211 tree flex_arr_type
= build_array_type (char_type_node
, itype
);
213 ret
= make_node (RECORD_TYPE
);
214 for (int i
= 0; i
< 3; i
++)
216 fields
[i
] = build_decl (UNKNOWN_LOCATION
, FIELD_DECL
,
217 get_identifier (field_names
[i
]),
218 (i
== 2) ? flex_arr_type
219 : short_unsigned_type_node
);
220 DECL_CONTEXT (fields
[i
]) = ret
;
222 DECL_CHAIN (fields
[i
- 1]) = fields
[i
];
224 tree type_decl
= build_decl (input_location
, TYPE_DECL
,
225 get_identifier ("__ubsan_type_descriptor"),
227 DECL_IGNORED_P (type_decl
) = 1;
228 DECL_ARTIFICIAL (type_decl
) = 1;
229 TYPE_FIELDS (ret
) = fields
[0];
230 TYPE_NAME (ret
) = type_decl
;
231 TYPE_STUB_DECL (ret
) = type_decl
;
232 TYPE_ARTIFICIAL (ret
) = 1;
234 ubsan_type_descriptor_type
= ret
;
238 /* Cached ubsan_get_source_location_type () return value. */
239 static GTY(()) tree ubsan_source_location_type
;
242 struct __ubsan_source_location
244 const char *__filename;
246 unsigned int __column;
251 ubsan_get_source_location_type (void)
253 static const char *field_names
[3]
254 = { "__filename", "__line", "__column" };
256 if (ubsan_source_location_type
)
257 return ubsan_source_location_type
;
259 tree const_char_type
= build_qualified_type (char_type_node
,
262 ret
= make_node (RECORD_TYPE
);
263 for (int i
= 0; i
< 3; i
++)
265 fields
[i
] = build_decl (UNKNOWN_LOCATION
, FIELD_DECL
,
266 get_identifier (field_names
[i
]),
267 (i
== 0) ? build_pointer_type (const_char_type
)
268 : unsigned_type_node
);
269 DECL_CONTEXT (fields
[i
]) = ret
;
271 DECL_CHAIN (fields
[i
- 1]) = fields
[i
];
273 tree type_decl
= build_decl (input_location
, TYPE_DECL
,
274 get_identifier ("__ubsan_source_location"),
276 DECL_IGNORED_P (type_decl
) = 1;
277 DECL_ARTIFICIAL (type_decl
) = 1;
278 TYPE_FIELDS (ret
) = fields
[0];
279 TYPE_NAME (ret
) = type_decl
;
280 TYPE_STUB_DECL (ret
) = type_decl
;
281 TYPE_ARTIFICIAL (ret
) = 1;
283 ubsan_source_location_type
= ret
;
287 /* Helper routine that returns a CONSTRUCTOR of __ubsan_source_location
288 type with its fields filled from a location_t LOC. */
291 ubsan_source_location (location_t loc
)
293 expanded_location xloc
;
294 tree type
= ubsan_get_source_location_type ();
296 xloc
= expand_location (loc
);
298 if (xloc
.file
== NULL
)
300 str
= build_int_cst (ptr_type_node
, 0);
306 /* Fill in the values from LOC. */
307 size_t len
= strlen (xloc
.file
) + 1;
308 str
= build_string (len
, xloc
.file
);
309 TREE_TYPE (str
) = build_array_type_nelts (char_type_node
, len
);
310 TREE_READONLY (str
) = 1;
311 TREE_STATIC (str
) = 1;
312 str
= build_fold_addr_expr (str
);
314 tree ctor
= build_constructor_va (type
, 3, NULL_TREE
, str
, NULL_TREE
,
315 build_int_cst (unsigned_type_node
,
316 xloc
.line
), NULL_TREE
,
317 build_int_cst (unsigned_type_node
,
319 TREE_CONSTANT (ctor
) = 1;
320 TREE_STATIC (ctor
) = 1;
325 /* This routine returns a magic number for TYPE. */
327 static unsigned short
328 get_ubsan_type_info_for_type (tree type
)
330 if (TREE_CODE (type
) == REAL_TYPE
)
331 return tree_to_uhwi (TYPE_SIZE (type
));
332 else if (INTEGRAL_TYPE_P (type
))
334 int prec
= exact_log2 (tree_to_uhwi (TYPE_SIZE (type
)));
335 gcc_assert (prec
!= -1);
336 return (prec
<< 1) | !TYPE_UNSIGNED (type
);
342 /* Counters for internal labels. ubsan_ids[0] for Lubsan_type,
343 ubsan_ids[1] for Lubsan_data labels. */
344 static GTY(()) unsigned int ubsan_ids
[2];
346 /* Helper routine that returns ADDR_EXPR of a VAR_DECL of a type
347 descriptor. It first looks into the hash table; if not found,
348 create the VAR_DECL, put it into the hash table and return the
349 ADDR_EXPR of it. TYPE describes a particular type. PSTYLE is
350 an enum controlling how we want to print the type. */
353 ubsan_type_descriptor (tree type
, enum ubsan_print_style pstyle
)
355 /* See through any typedefs. */
356 type
= TYPE_MAIN_VARIANT (type
);
358 tree decl
= decl_for_type_lookup (type
);
359 /* It is possible that some of the earlier created DECLs were found
360 unused, in that case they weren't emitted and varpool_node::get
361 returns NULL node on them. But now we really need them. Thus,
363 if (decl
!= NULL_TREE
&& varpool_node::get (decl
))
364 return build_fold_addr_expr (decl
);
366 tree dtype
= ubsan_get_type_descriptor_type ();
368 const char *tname
= NULL
;
369 pretty_printer pretty_name
;
370 unsigned char deref_depth
= 0;
371 unsigned short tkind
, tinfo
;
373 /* Get the name of the type, or the name of the pointer type. */
374 if (pstyle
== UBSAN_PRINT_POINTER
)
376 gcc_assert (POINTER_TYPE_P (type
));
377 type2
= TREE_TYPE (type
);
379 /* Remove any '*' operators from TYPE. */
380 while (POINTER_TYPE_P (type2
))
381 deref_depth
++, type2
= TREE_TYPE (type2
);
383 if (TREE_CODE (type2
) == METHOD_TYPE
)
384 type2
= TYPE_METHOD_BASETYPE (type2
);
387 /* If an array, get its type. */
388 type2
= strip_array_types (type2
);
390 if (pstyle
== UBSAN_PRINT_ARRAY
)
392 while (POINTER_TYPE_P (type2
))
393 deref_depth
++, type2
= TREE_TYPE (type2
);
396 if (TYPE_NAME (type2
) != NULL
)
398 if (TREE_CODE (TYPE_NAME (type2
)) == IDENTIFIER_NODE
)
399 tname
= IDENTIFIER_POINTER (TYPE_NAME (type2
));
400 else if (DECL_NAME (TYPE_NAME (type2
)) != NULL
)
401 tname
= IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type2
)));
405 /* We weren't able to determine the type name. */
408 pp_quote (&pretty_name
);
411 if (pstyle
== UBSAN_PRINT_POINTER
)
413 pp_printf (&pretty_name
, "%s%s%s%s%s%s%s",
414 TYPE_VOLATILE (type2
) ? "volatile " : "",
415 TYPE_READONLY (type2
) ? "const " : "",
416 TYPE_RESTRICT (type2
) ? "restrict " : "",
417 TYPE_ATOMIC (type2
) ? "_Atomic " : "",
418 TREE_CODE (type2
) == RECORD_TYPE
420 : TREE_CODE (type2
) == UNION_TYPE
421 ? "union " : "", tname
,
422 deref_depth
== 0 ? "" : " ");
423 while (deref_depth
-- > 0)
424 pp_star (&pretty_name
);
426 else if (pstyle
== UBSAN_PRINT_ARRAY
)
428 /* Pretty print the array dimensions. */
429 gcc_assert (TREE_CODE (type
) == ARRAY_TYPE
);
431 pp_string (&pretty_name
, tname
);
432 pp_space (&pretty_name
);
433 while (deref_depth
-- > 0)
434 pp_star (&pretty_name
);
435 while (TREE_CODE (t
) == ARRAY_TYPE
)
437 pp_left_bracket (&pretty_name
);
438 tree dom
= TYPE_DOMAIN (t
);
440 && TYPE_MAX_VALUE (dom
) != NULL_TREE
441 && TREE_CODE (TYPE_MAX_VALUE (dom
)) == INTEGER_CST
)
443 unsigned HOST_WIDE_INT m
;
444 if (tree_fits_uhwi_p (TYPE_MAX_VALUE (dom
))
445 && (m
= tree_to_uhwi (TYPE_MAX_VALUE (dom
))) + 1 != 0)
446 pp_unsigned_wide_integer (&pretty_name
, m
+ 1);
448 pp_wide_int (&pretty_name
,
449 wi::add (wi::to_widest (TYPE_MAX_VALUE (dom
)), 1),
450 TYPE_SIGN (TREE_TYPE (dom
)));
453 /* ??? We can't determine the variable name; print VLA unspec. */
454 pp_star (&pretty_name
);
455 pp_right_bracket (&pretty_name
);
459 /* Save the tree with stripped types. */
463 pp_string (&pretty_name
, tname
);
465 pp_quote (&pretty_name
);
467 switch (TREE_CODE (eltype
))
475 /* FIXME: libubsan right now only supports float, double and
476 long double type formats. */
477 if (TYPE_MODE (eltype
) == TYPE_MODE (float_type_node
)
478 || TYPE_MODE (eltype
) == TYPE_MODE (double_type_node
)
479 || TYPE_MODE (eltype
) == TYPE_MODE (long_double_type_node
))
488 tinfo
= get_ubsan_type_info_for_type (eltype
);
490 /* Create a new VAR_DECL of type descriptor. */
491 const char *tmp
= pp_formatted_text (&pretty_name
);
492 size_t len
= strlen (tmp
) + 1;
493 tree str
= build_string (len
, tmp
);
494 TREE_TYPE (str
) = build_array_type_nelts (char_type_node
, len
);
495 TREE_READONLY (str
) = 1;
496 TREE_STATIC (str
) = 1;
499 ASM_GENERATE_INTERNAL_LABEL (tmp_name
, "Lubsan_type", ubsan_ids
[0]++);
500 decl
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
, get_identifier (tmp_name
),
502 TREE_STATIC (decl
) = 1;
503 TREE_PUBLIC (decl
) = 0;
504 DECL_ARTIFICIAL (decl
) = 1;
505 DECL_IGNORED_P (decl
) = 1;
506 DECL_EXTERNAL (decl
) = 0;
508 = size_binop (PLUS_EXPR
, DECL_SIZE (decl
), TYPE_SIZE (TREE_TYPE (str
)));
509 DECL_SIZE_UNIT (decl
)
510 = size_binop (PLUS_EXPR
, DECL_SIZE_UNIT (decl
),
511 TYPE_SIZE_UNIT (TREE_TYPE (str
)));
513 tree ctor
= build_constructor_va (dtype
, 3, NULL_TREE
,
514 build_int_cst (short_unsigned_type_node
,
516 build_int_cst (short_unsigned_type_node
,
517 tinfo
), NULL_TREE
, str
);
518 TREE_CONSTANT (ctor
) = 1;
519 TREE_STATIC (ctor
) = 1;
520 DECL_INITIAL (decl
) = ctor
;
521 varpool_node::finalize_decl (decl
);
523 /* Save the VAR_DECL into the hash table. */
524 decl_for_type_insert (type
, decl
);
526 return build_fold_addr_expr (decl
);
529 /* Create a structure for the ubsan library. NAME is a name of the new
530 structure. LOCCNT is number of locations, PLOC points to array of
531 locations. The arguments in ... are of __ubsan_type_descriptor type
532 and there are at most two of them, followed by NULL_TREE, followed
533 by optional extra arguments and another NULL_TREE. */
536 ubsan_create_data (const char *name
, int loccnt
, const location_t
*ploc
, ...)
541 vec
<tree
, va_gc
> *saved_args
= NULL
;
545 /* It is possible that PCH zapped table with definitions of sanitizer
546 builtins. Reinitialize them if needed. */
547 initialize_sanitizer_builtins ();
549 /* Firstly, create a pointer to type descriptor type. */
550 tree td_type
= ubsan_get_type_descriptor_type ();
551 td_type
= build_pointer_type (td_type
);
553 /* Create the structure type. */
554 ret
= make_node (RECORD_TYPE
);
555 for (j
= 0; j
< loccnt
; j
++)
557 gcc_checking_assert (i
< 2);
558 fields
[i
] = build_decl (UNKNOWN_LOCATION
, FIELD_DECL
, NULL_TREE
,
559 ubsan_get_source_location_type ());
560 DECL_CONTEXT (fields
[i
]) = ret
;
562 DECL_CHAIN (fields
[i
- 1]) = fields
[i
];
566 va_start (args
, ploc
);
567 for (t
= va_arg (args
, tree
); t
!= NULL_TREE
;
568 i
++, t
= va_arg (args
, tree
))
570 gcc_checking_assert (i
< 4);
571 /* Save the tree arguments for later use. */
572 vec_safe_push (saved_args
, t
);
573 fields
[i
] = build_decl (UNKNOWN_LOCATION
, FIELD_DECL
, NULL_TREE
,
575 DECL_CONTEXT (fields
[i
]) = ret
;
577 DECL_CHAIN (fields
[i
- 1]) = fields
[i
];
580 for (t
= va_arg (args
, tree
); t
!= NULL_TREE
;
581 i
++, t
= va_arg (args
, tree
))
583 gcc_checking_assert (i
< 6);
584 /* Save the tree arguments for later use. */
585 vec_safe_push (saved_args
, t
);
586 fields
[i
] = build_decl (UNKNOWN_LOCATION
, FIELD_DECL
, NULL_TREE
,
588 DECL_CONTEXT (fields
[i
]) = ret
;
590 DECL_CHAIN (fields
[i
- 1]) = fields
[i
];
594 tree type_decl
= build_decl (input_location
, TYPE_DECL
,
595 get_identifier (name
), ret
);
596 DECL_IGNORED_P (type_decl
) = 1;
597 DECL_ARTIFICIAL (type_decl
) = 1;
598 TYPE_FIELDS (ret
) = fields
[0];
599 TYPE_NAME (ret
) = type_decl
;
600 TYPE_STUB_DECL (ret
) = type_decl
;
601 TYPE_ARTIFICIAL (ret
) = 1;
604 /* Now, fill in the type. */
606 ASM_GENERATE_INTERNAL_LABEL (tmp_name
, "Lubsan_data", ubsan_ids
[1]++);
607 tree var
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
, get_identifier (tmp_name
),
609 TREE_STATIC (var
) = 1;
610 TREE_PUBLIC (var
) = 0;
611 DECL_ARTIFICIAL (var
) = 1;
612 DECL_IGNORED_P (var
) = 1;
613 DECL_EXTERNAL (var
) = 0;
615 vec
<constructor_elt
, va_gc
> *v
;
617 tree ctor
= build_constructor (ret
, v
);
619 /* If desirable, set the __ubsan_source_location element. */
620 for (j
= 0; j
< loccnt
; j
++)
622 location_t loc
= LOCATION_LOCUS (ploc
[j
]);
623 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, ubsan_source_location (loc
));
626 size_t nelts
= vec_safe_length (saved_args
);
627 for (i
= 0; i
< nelts
; i
++)
629 t
= (*saved_args
)[i
];
630 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, t
);
633 TREE_CONSTANT (ctor
) = 1;
634 TREE_STATIC (ctor
) = 1;
635 DECL_INITIAL (var
) = ctor
;
636 varpool_node::finalize_decl (var
);
641 /* Instrument the __builtin_unreachable call. We just call the libubsan
645 ubsan_instrument_unreachable (gimple_stmt_iterator
*gsi
)
648 location_t loc
= gimple_location (gsi_stmt (*gsi
));
650 if (flag_sanitize_undefined_trap_on_error
)
651 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
654 tree data
= ubsan_create_data ("__ubsan_unreachable_data", 1, &loc
,
655 NULL_TREE
, NULL_TREE
);
656 data
= build_fold_addr_expr_loc (loc
, data
);
658 = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE
);
659 g
= gimple_build_call (fn
, 1, data
);
661 gimple_set_location (g
, loc
);
662 gsi_replace (gsi
, g
, false);
666 /* Return true if T is a call to a libubsan routine. */
669 is_ubsan_builtin_p (tree t
)
671 return TREE_CODE (t
) == FUNCTION_DECL
672 && fndecl_built_in_p (t
, BUILT_IN_NORMAL
)
673 && strncmp (IDENTIFIER_POINTER (DECL_NAME (t
)),
674 "__builtin___ubsan_", 18) == 0;
677 /* Create a callgraph edge for statement STMT. */
680 ubsan_create_edge (gimple
*stmt
)
682 gcall
*call_stmt
= dyn_cast
<gcall
*> (stmt
);
683 basic_block bb
= gimple_bb (stmt
);
684 cgraph_node
*node
= cgraph_node::get (current_function_decl
);
685 tree decl
= gimple_call_fndecl (call_stmt
);
687 node
->create_edge (cgraph_node::get_create (decl
), call_stmt
, bb
->count
);
690 /* Expand the UBSAN_BOUNDS special builtin function. */
693 ubsan_expand_bounds_ifn (gimple_stmt_iterator
*gsi
)
695 gimple
*stmt
= gsi_stmt (*gsi
);
696 location_t loc
= gimple_location (stmt
);
697 gcc_assert (gimple_call_num_args (stmt
) == 3);
699 /* Pick up the arguments of the UBSAN_BOUNDS call. */
700 tree type
= TREE_TYPE (TREE_TYPE (gimple_call_arg (stmt
, 0)));
701 tree index
= gimple_call_arg (stmt
, 1);
702 tree orig_index
= index
;
703 tree bound
= gimple_call_arg (stmt
, 2);
705 gimple_stmt_iterator gsi_orig
= *gsi
;
707 /* Create condition "if (index > bound)". */
708 basic_block then_bb
, fallthru_bb
;
709 gimple_stmt_iterator cond_insert_point
710 = create_cond_insert_point (gsi
, false, false, true,
711 &then_bb
, &fallthru_bb
);
712 index
= fold_convert (TREE_TYPE (bound
), index
);
713 index
= force_gimple_operand_gsi (&cond_insert_point
, index
,
715 false, GSI_NEW_STMT
);
716 gimple
*g
= gimple_build_cond (GT_EXPR
, index
, bound
, NULL_TREE
, NULL_TREE
);
717 gimple_set_location (g
, loc
);
718 gsi_insert_after (&cond_insert_point
, g
, GSI_NEW_STMT
);
720 /* Generate __ubsan_handle_out_of_bounds call. */
721 *gsi
= gsi_after_labels (then_bb
);
722 if (flag_sanitize_undefined_trap_on_error
)
723 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
727 = ubsan_create_data ("__ubsan_out_of_bounds_data", 1, &loc
,
728 ubsan_type_descriptor (type
, UBSAN_PRINT_ARRAY
),
729 ubsan_type_descriptor (TREE_TYPE (orig_index
)),
730 NULL_TREE
, NULL_TREE
);
731 data
= build_fold_addr_expr_loc (loc
, data
);
732 enum built_in_function bcode
733 = (flag_sanitize_recover
& SANITIZE_BOUNDS
)
734 ? BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS
735 : BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS_ABORT
;
736 tree fn
= builtin_decl_explicit (bcode
);
737 tree val
= ubsan_encode_value (orig_index
, UBSAN_ENCODE_VALUE_GIMPLE
);
738 val
= force_gimple_operand_gsi (gsi
, val
, true, NULL_TREE
, true,
740 g
= gimple_build_call (fn
, 2, data
, val
);
742 gimple_set_location (g
, loc
);
743 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
745 /* Get rid of the UBSAN_BOUNDS call from the IR. */
746 unlink_stmt_vdef (stmt
);
747 gsi_remove (&gsi_orig
, true);
749 /* Point GSI to next logical statement. */
750 *gsi
= gsi_start_bb (fallthru_bb
);
754 /* Expand UBSAN_NULL internal call. The type is kept on the ckind
755 argument which is a constant, because the middle-end treats pointer
756 conversions as useless and therefore the type of the first argument
757 could be changed to any other pointer type. */
760 ubsan_expand_null_ifn (gimple_stmt_iterator
*gsip
)
762 gimple_stmt_iterator gsi
= *gsip
;
763 gimple
*stmt
= gsi_stmt (gsi
);
764 location_t loc
= gimple_location (stmt
);
765 gcc_assert (gimple_call_num_args (stmt
) == 3);
766 tree ptr
= gimple_call_arg (stmt
, 0);
767 tree ckind
= gimple_call_arg (stmt
, 1);
768 tree align
= gimple_call_arg (stmt
, 2);
769 tree check_align
= NULL_TREE
;
772 basic_block cur_bb
= gsi_bb (gsi
);
775 if (!integer_zerop (align
))
777 unsigned int ptralign
= get_pointer_alignment (ptr
) / BITS_PER_UNIT
;
778 if (compare_tree_int (align
, ptralign
) == 1)
780 check_align
= make_ssa_name (pointer_sized_int_node
);
781 g
= gimple_build_assign (check_align
, NOP_EXPR
, ptr
);
782 gimple_set_location (g
, loc
);
783 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
786 check_null
= sanitize_flags_p (SANITIZE_NULL
);
788 if (check_align
== NULL_TREE
&& !check_null
)
790 gsi_remove (gsip
, true);
791 /* Unlink the UBSAN_NULLs vops before replacing it. */
792 unlink_stmt_vdef (stmt
);
796 /* Split the original block holding the pointer dereference. */
797 edge e
= split_block (cur_bb
, stmt
);
799 /* Get a hold on the 'condition block', the 'then block' and the
801 basic_block cond_bb
= e
->src
;
802 basic_block fallthru_bb
= e
->dest
;
803 basic_block then_bb
= create_empty_bb (cond_bb
);
804 add_bb_to_loop (then_bb
, cond_bb
->loop_father
);
805 loops_state_set (LOOPS_NEED_FIXUP
);
807 /* Make an edge coming from the 'cond block' into the 'then block';
808 this edge is unlikely taken, so set up the probability accordingly. */
809 e
= make_edge (cond_bb
, then_bb
, EDGE_TRUE_VALUE
);
810 e
->probability
= profile_probability::very_unlikely ();
811 then_bb
->count
= e
->count ();
813 /* Connect 'then block' with the 'else block'. This is needed
814 as the ubsan routines we call in the 'then block' are not noreturn.
815 The 'then block' only has one outcoming edge. */
816 make_single_succ_edge (then_bb
, fallthru_bb
, EDGE_FALLTHRU
);
818 /* Set up the fallthrough basic block. */
819 e
= find_edge (cond_bb
, fallthru_bb
);
820 e
->flags
= EDGE_FALSE_VALUE
;
821 e
->probability
= profile_probability::very_likely ();
823 /* Update dominance info for the newly created then_bb; note that
824 fallthru_bb's dominance info has already been updated by
826 if (dom_info_available_p (CDI_DOMINATORS
))
827 set_immediate_dominator (CDI_DOMINATORS
, then_bb
, cond_bb
);
829 /* Put the ubsan builtin call into the newly created BB. */
830 if (flag_sanitize_undefined_trap_on_error
)
831 g
= gimple_build_call (builtin_decl_implicit (BUILT_IN_TRAP
), 0);
834 enum built_in_function bcode
835 = (flag_sanitize_recover
& ((check_align
? SANITIZE_ALIGNMENT
: 0)
836 | (check_null
? SANITIZE_NULL
: 0)))
837 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_V1
838 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_V1_ABORT
;
839 tree fn
= builtin_decl_implicit (bcode
);
840 int align_log
= tree_log2 (align
);
842 = ubsan_create_data ("__ubsan_null_data", 1, &loc
,
843 ubsan_type_descriptor (TREE_TYPE (ckind
),
844 UBSAN_PRINT_POINTER
),
846 build_int_cst (unsigned_char_type_node
,
848 fold_convert (unsigned_char_type_node
, ckind
),
850 data
= build_fold_addr_expr_loc (loc
, data
);
851 g
= gimple_build_call (fn
, 2, data
,
852 check_align
? check_align
853 : build_zero_cst (pointer_sized_int_node
));
855 gimple_stmt_iterator gsi2
= gsi_start_bb (then_bb
);
856 gimple_set_location (g
, loc
);
857 gsi_insert_after (&gsi2
, g
, GSI_NEW_STMT
);
859 /* Unlink the UBSAN_NULLs vops before replacing it. */
860 unlink_stmt_vdef (stmt
);
864 g
= gimple_build_cond (EQ_EXPR
, ptr
, build_int_cst (TREE_TYPE (ptr
), 0),
865 NULL_TREE
, NULL_TREE
);
866 gimple_set_location (g
, loc
);
868 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
869 gsi_replace (&gsi
, g
, false);
877 /* Split the block with the condition again. */
878 e
= split_block (cond_bb
, stmt
);
879 basic_block cond1_bb
= e
->src
;
880 basic_block cond2_bb
= e
->dest
;
882 /* Make an edge coming from the 'cond1 block' into the 'then block';
883 this edge is unlikely taken, so set up the probability
885 e
= make_edge (cond1_bb
, then_bb
, EDGE_TRUE_VALUE
);
886 e
->probability
= profile_probability::very_unlikely ();
888 /* Set up the fallthrough basic block. */
889 e
= find_edge (cond1_bb
, cond2_bb
);
890 e
->flags
= EDGE_FALSE_VALUE
;
891 e
->probability
= profile_probability::very_likely ();
893 /* Update dominance info. */
894 if (dom_info_available_p (CDI_DOMINATORS
))
896 set_immediate_dominator (CDI_DOMINATORS
, fallthru_bb
, cond1_bb
);
897 set_immediate_dominator (CDI_DOMINATORS
, then_bb
, cond1_bb
);
900 gsi2
= gsi_start_bb (cond2_bb
);
903 tree mask
= build_int_cst (pointer_sized_int_node
,
904 tree_to_uhwi (align
) - 1);
905 g
= gimple_build_assign (make_ssa_name (pointer_sized_int_node
),
906 BIT_AND_EXPR
, check_align
, mask
);
907 gimple_set_location (g
, loc
);
909 gsi_insert_after (&gsi2
, g
, GSI_NEW_STMT
);
911 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
913 g
= gimple_build_cond (NE_EXPR
, gimple_assign_lhs (g
),
914 build_int_cst (pointer_sized_int_node
, 0),
915 NULL_TREE
, NULL_TREE
);
916 gimple_set_location (g
, loc
);
918 gsi_insert_after (&gsi2
, g
, GSI_NEW_STMT
);
920 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
921 gsi_replace (&gsi
, g
, false);
926 #define OBJSZ_MAX_OFFSET (1024 * 16)
928 /* Expand UBSAN_OBJECT_SIZE internal call. */
931 ubsan_expand_objsize_ifn (gimple_stmt_iterator
*gsi
)
933 gimple
*stmt
= gsi_stmt (*gsi
);
934 location_t loc
= gimple_location (stmt
);
935 gcc_assert (gimple_call_num_args (stmt
) == 4);
937 tree ptr
= gimple_call_arg (stmt
, 0);
938 tree offset
= gimple_call_arg (stmt
, 1);
939 tree size
= gimple_call_arg (stmt
, 2);
940 tree ckind
= gimple_call_arg (stmt
, 3);
941 gimple_stmt_iterator gsi_orig
= *gsi
;
944 /* See if we can discard the check. */
945 if (TREE_CODE (size
) != INTEGER_CST
946 || integer_all_onesp (size
))
947 /* Yes, __builtin_object_size couldn't determine the
949 else if (TREE_CODE (offset
) == INTEGER_CST
950 && wi::to_widest (offset
) >= -OBJSZ_MAX_OFFSET
951 && wi::to_widest (offset
) <= -1)
952 /* The offset is in range [-16K, -1]. */;
955 /* if (offset > objsize) */
956 basic_block then_bb
, fallthru_bb
;
957 gimple_stmt_iterator cond_insert_point
958 = create_cond_insert_point (gsi
, false, false, true,
959 &then_bb
, &fallthru_bb
);
960 g
= gimple_build_cond (GT_EXPR
, offset
, size
, NULL_TREE
, NULL_TREE
);
961 gimple_set_location (g
, loc
);
962 gsi_insert_after (&cond_insert_point
, g
, GSI_NEW_STMT
);
964 /* If the offset is small enough, we don't need the second
966 if (TREE_CODE (offset
) == INTEGER_CST
967 && wi::to_widest (offset
) >= 0
968 && wi::to_widest (offset
) <= OBJSZ_MAX_OFFSET
)
969 *gsi
= gsi_after_labels (then_bb
);
972 /* Don't issue run-time error if (ptr > ptr + offset). That
973 may happen when computing a POINTER_PLUS_EXPR. */
974 basic_block then2_bb
, fallthru2_bb
;
976 gimple_stmt_iterator gsi2
= gsi_after_labels (then_bb
);
977 cond_insert_point
= create_cond_insert_point (&gsi2
, false, false,
980 /* Convert the pointer to an integer type. */
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 (&cond_insert_point
, g
, GSI_NEW_STMT
);
985 p
= gimple_assign_lhs (g
);
986 /* Compute ptr + offset. */
987 g
= gimple_build_assign (make_ssa_name (pointer_sized_int_node
),
988 PLUS_EXPR
, p
, offset
);
989 gimple_set_location (g
, loc
);
990 gsi_insert_after (&cond_insert_point
, g
, GSI_NEW_STMT
);
991 /* Now build the conditional and put it into the IR. */
992 g
= gimple_build_cond (LE_EXPR
, p
, gimple_assign_lhs (g
),
993 NULL_TREE
, NULL_TREE
);
994 gimple_set_location (g
, loc
);
995 gsi_insert_after (&cond_insert_point
, g
, GSI_NEW_STMT
);
996 *gsi
= gsi_after_labels (then2_bb
);
999 /* Generate __ubsan_handle_type_mismatch call. */
1000 if (flag_sanitize_undefined_trap_on_error
)
1001 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
1005 = ubsan_create_data ("__ubsan_objsz_data", 1, &loc
,
1006 ubsan_type_descriptor (TREE_TYPE (ptr
),
1007 UBSAN_PRINT_POINTER
),
1009 build_zero_cst (unsigned_char_type_node
),
1012 data
= build_fold_addr_expr_loc (loc
, data
);
1013 enum built_in_function bcode
1014 = (flag_sanitize_recover
& SANITIZE_OBJECT_SIZE
)
1015 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_V1
1016 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_V1_ABORT
;
1017 tree p
= make_ssa_name (pointer_sized_int_node
);
1018 g
= gimple_build_assign (p
, NOP_EXPR
, ptr
);
1019 gimple_set_location (g
, loc
);
1020 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1021 g
= gimple_build_call (builtin_decl_explicit (bcode
), 2, data
, p
);
1023 gimple_set_location (g
, loc
);
1024 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1026 /* Point GSI to next logical statement. */
1027 *gsi
= gsi_start_bb (fallthru_bb
);
1029 /* Get rid of the UBSAN_OBJECT_SIZE call from the IR. */
1030 unlink_stmt_vdef (stmt
);
1031 gsi_remove (&gsi_orig
, true);
1035 /* Get rid of the UBSAN_OBJECT_SIZE call from the IR. */
1036 unlink_stmt_vdef (stmt
);
1037 gsi_remove (gsi
, true);
1041 /* Expand UBSAN_PTR internal call. */
1044 ubsan_expand_ptr_ifn (gimple_stmt_iterator
*gsip
)
1046 gimple_stmt_iterator gsi
= *gsip
;
1047 gimple
*stmt
= gsi_stmt (gsi
);
1048 location_t loc
= gimple_location (stmt
);
1049 gcc_assert (gimple_call_num_args (stmt
) == 2);
1050 tree ptr
= gimple_call_arg (stmt
, 0);
1051 tree off
= gimple_call_arg (stmt
, 1);
1053 if (integer_zerop (off
))
1055 gsi_remove (gsip
, true);
1056 unlink_stmt_vdef (stmt
);
1060 basic_block cur_bb
= gsi_bb (gsi
);
1061 tree ptrplusoff
= make_ssa_name (pointer_sized_int_node
);
1062 tree ptri
= make_ssa_name (pointer_sized_int_node
);
1063 int pos_neg
= get_range_pos_neg (off
);
1065 /* Split the original block holding the pointer dereference. */
1066 edge e
= split_block (cur_bb
, stmt
);
1068 /* Get a hold on the 'condition block', the 'then block' and the
1070 basic_block cond_bb
= e
->src
;
1071 basic_block fallthru_bb
= e
->dest
;
1072 basic_block then_bb
= create_empty_bb (cond_bb
);
1073 basic_block cond_pos_bb
= NULL
, cond_neg_bb
= NULL
;
1074 add_bb_to_loop (then_bb
, cond_bb
->loop_father
);
1075 loops_state_set (LOOPS_NEED_FIXUP
);
1077 /* Set up the fallthrough basic block. */
1078 e
->flags
= EDGE_FALSE_VALUE
;
1081 e
->probability
= profile_probability::very_likely ();
1083 /* Connect 'then block' with the 'else block'. This is needed
1084 as the ubsan routines we call in the 'then block' are not noreturn.
1085 The 'then block' only has one outcoming edge. */
1086 make_single_succ_edge (then_bb
, fallthru_bb
, EDGE_FALLTHRU
);
1088 /* Make an edge coming from the 'cond block' into the 'then block';
1089 this edge is unlikely taken, so set up the probability
1091 e
= make_edge (cond_bb
, then_bb
, EDGE_TRUE_VALUE
);
1092 e
->probability
= profile_probability::very_unlikely ();
1093 then_bb
->count
= e
->count ();
1097 e
->probability
= profile_probability::even ();
1099 e
= split_block (fallthru_bb
, (gimple
*) NULL
);
1100 cond_neg_bb
= e
->src
;
1101 fallthru_bb
= e
->dest
;
1102 e
->probability
= profile_probability::very_likely ();
1103 e
->flags
= EDGE_FALSE_VALUE
;
1105 e
= make_edge (cond_neg_bb
, then_bb
, EDGE_TRUE_VALUE
);
1106 e
->probability
= profile_probability::very_unlikely ();
1107 then_bb
->count
= e
->count ();
1109 cond_pos_bb
= create_empty_bb (cond_bb
);
1110 add_bb_to_loop (cond_pos_bb
, cond_bb
->loop_father
);
1112 e
= make_edge (cond_bb
, cond_pos_bb
, EDGE_TRUE_VALUE
);
1113 e
->probability
= profile_probability::even ();
1114 cond_pos_bb
->count
= e
->count ();
1116 e
= make_edge (cond_pos_bb
, then_bb
, EDGE_TRUE_VALUE
);
1117 e
->probability
= profile_probability::very_unlikely ();
1119 e
= make_edge (cond_pos_bb
, fallthru_bb
, EDGE_FALSE_VALUE
);
1120 e
->probability
= profile_probability::very_likely ();
1122 make_single_succ_edge (then_bb
, fallthru_bb
, EDGE_FALLTHRU
);
1125 gimple
*g
= gimple_build_assign (ptri
, NOP_EXPR
, ptr
);
1126 gimple_set_location (g
, loc
);
1127 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
1128 g
= gimple_build_assign (ptrplusoff
, PLUS_EXPR
, ptri
, off
);
1129 gimple_set_location (g
, loc
);
1130 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
1132 /* Update dominance info for the newly created then_bb; note that
1133 fallthru_bb's dominance info has already been updated by
1135 if (dom_info_available_p (CDI_DOMINATORS
))
1137 set_immediate_dominator (CDI_DOMINATORS
, then_bb
, cond_bb
);
1140 set_immediate_dominator (CDI_DOMINATORS
, cond_pos_bb
, cond_bb
);
1141 set_immediate_dominator (CDI_DOMINATORS
, fallthru_bb
, cond_bb
);
1145 /* Put the ubsan builtin call into the newly created BB. */
1146 if (flag_sanitize_undefined_trap_on_error
)
1147 g
= gimple_build_call (builtin_decl_implicit (BUILT_IN_TRAP
), 0);
1150 enum built_in_function bcode
1151 = (flag_sanitize_recover
& SANITIZE_POINTER_OVERFLOW
)
1152 ? BUILT_IN_UBSAN_HANDLE_POINTER_OVERFLOW
1153 : BUILT_IN_UBSAN_HANDLE_POINTER_OVERFLOW_ABORT
;
1154 tree fn
= builtin_decl_implicit (bcode
);
1156 = ubsan_create_data ("__ubsan_ptrovf_data", 1, &loc
,
1157 NULL_TREE
, NULL_TREE
);
1158 data
= build_fold_addr_expr_loc (loc
, data
);
1159 g
= gimple_build_call (fn
, 3, data
, ptr
, ptrplusoff
);
1161 gimple_stmt_iterator gsi2
= gsi_start_bb (then_bb
);
1162 gimple_set_location (g
, loc
);
1163 gsi_insert_after (&gsi2
, g
, GSI_NEW_STMT
);
1165 /* Unlink the UBSAN_PTRs vops before replacing it. */
1166 unlink_stmt_vdef (stmt
);
1168 if (TREE_CODE (off
) == INTEGER_CST
)
1169 g
= gimple_build_cond (wi::neg_p (wi::to_wide (off
)) ? LT_EXPR
: GE_EXPR
,
1170 ptri
, fold_build1 (NEGATE_EXPR
, sizetype
, off
),
1171 NULL_TREE
, NULL_TREE
);
1172 else if (pos_neg
!= 3)
1173 g
= gimple_build_cond (pos_neg
== 1 ? LT_EXPR
: GT_EXPR
,
1174 ptrplusoff
, ptri
, NULL_TREE
, NULL_TREE
);
1177 gsi2
= gsi_start_bb (cond_pos_bb
);
1178 g
= gimple_build_cond (LT_EXPR
, ptrplusoff
, ptri
, NULL_TREE
, NULL_TREE
);
1179 gimple_set_location (g
, loc
);
1180 gsi_insert_after (&gsi2
, g
, GSI_NEW_STMT
);
1182 gsi2
= gsi_start_bb (cond_neg_bb
);
1183 g
= gimple_build_cond (GT_EXPR
, ptrplusoff
, ptri
, NULL_TREE
, NULL_TREE
);
1184 gimple_set_location (g
, loc
);
1185 gsi_insert_after (&gsi2
, g
, GSI_NEW_STMT
);
1187 gimple_seq seq
= NULL
;
1188 tree t
= gimple_build (&seq
, loc
, NOP_EXPR
, ssizetype
, off
);
1189 t
= gimple_build (&seq
, loc
, GE_EXPR
, boolean_type_node
,
1191 gsi_insert_seq_before (&gsi
, seq
, GSI_SAME_STMT
);
1192 g
= gimple_build_cond (NE_EXPR
, t
, boolean_false_node
,
1193 NULL_TREE
, NULL_TREE
);
1195 gimple_set_location (g
, loc
);
1196 /* Replace the UBSAN_PTR with a GIMPLE_COND stmt. */
1197 gsi_replace (&gsi
, g
, false);
1202 /* Cached __ubsan_vptr_type_cache decl. */
1203 static GTY(()) tree ubsan_vptr_type_cache_decl
;
1205 /* Expand UBSAN_VPTR internal call. The type is kept on the ckind
1206 argument which is a constant, because the middle-end treats pointer
1207 conversions as useless and therefore the type of the first argument
1208 could be changed to any other pointer type. */
1211 ubsan_expand_vptr_ifn (gimple_stmt_iterator
*gsip
)
1213 gimple_stmt_iterator gsi
= *gsip
;
1214 gimple
*stmt
= gsi_stmt (gsi
);
1215 location_t loc
= gimple_location (stmt
);
1216 gcc_assert (gimple_call_num_args (stmt
) == 5);
1217 tree op
= gimple_call_arg (stmt
, 0);
1218 tree vptr
= gimple_call_arg (stmt
, 1);
1219 tree str_hash
= gimple_call_arg (stmt
, 2);
1220 tree ti_decl_addr
= gimple_call_arg (stmt
, 3);
1221 tree ckind_tree
= gimple_call_arg (stmt
, 4);
1222 ubsan_null_ckind ckind
= (ubsan_null_ckind
) tree_to_uhwi (ckind_tree
);
1223 tree type
= TREE_TYPE (TREE_TYPE (ckind_tree
));
1225 basic_block fallthru_bb
= NULL
;
1227 if (ckind
== UBSAN_DOWNCAST_POINTER
)
1229 /* Guard everything with if (op != NULL) { ... }. */
1230 basic_block then_bb
;
1231 gimple_stmt_iterator cond_insert_point
1232 = create_cond_insert_point (gsip
, false, false, true,
1233 &then_bb
, &fallthru_bb
);
1234 g
= gimple_build_cond (NE_EXPR
, op
, build_zero_cst (TREE_TYPE (op
)),
1235 NULL_TREE
, NULL_TREE
);
1236 gimple_set_location (g
, loc
);
1237 gsi_insert_after (&cond_insert_point
, g
, GSI_NEW_STMT
);
1238 *gsip
= gsi_after_labels (then_bb
);
1239 gsi_remove (&gsi
, false);
1240 gsi_insert_before (gsip
, stmt
, GSI_NEW_STMT
);
1244 tree htype
= TREE_TYPE (str_hash
);
1245 tree cst
= wide_int_to_tree (htype
,
1246 wi::uhwi (((uint64_t) 0x9ddfea08 << 32)
1248 g
= gimple_build_assign (make_ssa_name (htype
), BIT_XOR_EXPR
,
1250 gimple_set_location (g
, loc
);
1251 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1252 g
= gimple_build_assign (make_ssa_name (htype
), MULT_EXPR
,
1253 gimple_assign_lhs (g
), cst
);
1254 gimple_set_location (g
, loc
);
1255 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1256 tree t1
= gimple_assign_lhs (g
);
1257 g
= gimple_build_assign (make_ssa_name (htype
), LSHIFT_EXPR
,
1258 t1
, build_int_cst (integer_type_node
, 47));
1259 gimple_set_location (g
, loc
);
1260 tree t2
= gimple_assign_lhs (g
);
1261 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1262 g
= gimple_build_assign (make_ssa_name (htype
), BIT_XOR_EXPR
,
1264 gimple_set_location (g
, loc
);
1265 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1266 g
= gimple_build_assign (make_ssa_name (htype
), BIT_XOR_EXPR
,
1267 t2
, gimple_assign_lhs (g
));
1268 gimple_set_location (g
, loc
);
1269 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1270 g
= gimple_build_assign (make_ssa_name (htype
), MULT_EXPR
,
1271 gimple_assign_lhs (g
), cst
);
1272 gimple_set_location (g
, loc
);
1273 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1274 tree t3
= gimple_assign_lhs (g
);
1275 g
= gimple_build_assign (make_ssa_name (htype
), LSHIFT_EXPR
,
1276 t3
, build_int_cst (integer_type_node
, 47));
1277 gimple_set_location (g
, loc
);
1278 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1279 g
= gimple_build_assign (make_ssa_name (htype
), BIT_XOR_EXPR
,
1280 t3
, gimple_assign_lhs (g
));
1281 gimple_set_location (g
, loc
);
1282 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1283 g
= gimple_build_assign (make_ssa_name (htype
), MULT_EXPR
,
1284 gimple_assign_lhs (g
), cst
);
1285 gimple_set_location (g
, loc
);
1286 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1287 if (!useless_type_conversion_p (pointer_sized_int_node
, htype
))
1289 g
= gimple_build_assign (make_ssa_name (pointer_sized_int_node
),
1290 NOP_EXPR
, gimple_assign_lhs (g
));
1291 gimple_set_location (g
, loc
);
1292 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1294 tree hash
= gimple_assign_lhs (g
);
1296 if (ubsan_vptr_type_cache_decl
== NULL_TREE
)
1298 tree atype
= build_array_type_nelts (pointer_sized_int_node
, 128);
1299 tree array
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
,
1300 get_identifier ("__ubsan_vptr_type_cache"),
1302 DECL_ARTIFICIAL (array
) = 1;
1303 DECL_IGNORED_P (array
) = 1;
1304 TREE_PUBLIC (array
) = 1;
1305 TREE_STATIC (array
) = 1;
1306 DECL_EXTERNAL (array
) = 1;
1307 DECL_VISIBILITY (array
) = VISIBILITY_DEFAULT
;
1308 DECL_VISIBILITY_SPECIFIED (array
) = 1;
1309 varpool_node::finalize_decl (array
);
1310 ubsan_vptr_type_cache_decl
= array
;
1313 g
= gimple_build_assign (make_ssa_name (pointer_sized_int_node
),
1315 build_int_cst (pointer_sized_int_node
, 127));
1316 gimple_set_location (g
, loc
);
1317 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1319 tree c
= build4_loc (loc
, ARRAY_REF
, pointer_sized_int_node
,
1320 ubsan_vptr_type_cache_decl
, gimple_assign_lhs (g
),
1321 NULL_TREE
, NULL_TREE
);
1322 g
= gimple_build_assign (make_ssa_name (pointer_sized_int_node
),
1324 gimple_set_location (g
, loc
);
1325 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1327 basic_block then_bb
, fallthru2_bb
;
1328 gimple_stmt_iterator cond_insert_point
1329 = create_cond_insert_point (gsip
, false, false, true,
1330 &then_bb
, &fallthru2_bb
);
1331 g
= gimple_build_cond (NE_EXPR
, gimple_assign_lhs (g
), hash
,
1332 NULL_TREE
, NULL_TREE
);
1333 gimple_set_location (g
, loc
);
1334 gsi_insert_after (&cond_insert_point
, g
, GSI_NEW_STMT
);
1335 *gsip
= gsi_after_labels (then_bb
);
1336 if (fallthru_bb
== NULL
)
1337 fallthru_bb
= fallthru2_bb
;
1340 = ubsan_create_data ("__ubsan_vptr_data", 1, &loc
,
1341 ubsan_type_descriptor (type
), NULL_TREE
, ti_decl_addr
,
1342 build_int_cst (unsigned_char_type_node
, ckind
),
1344 data
= build_fold_addr_expr_loc (loc
, data
);
1345 enum built_in_function bcode
1346 = (flag_sanitize_recover
& SANITIZE_VPTR
)
1347 ? BUILT_IN_UBSAN_HANDLE_DYNAMIC_TYPE_CACHE_MISS
1348 : BUILT_IN_UBSAN_HANDLE_DYNAMIC_TYPE_CACHE_MISS_ABORT
;
1350 g
= gimple_build_call (builtin_decl_explicit (bcode
), 3, data
, op
, hash
);
1351 gimple_set_location (g
, loc
);
1352 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1354 /* Point GSI to next logical statement. */
1355 *gsip
= gsi_start_bb (fallthru_bb
);
1357 /* Get rid of the UBSAN_VPTR call from the IR. */
1358 unlink_stmt_vdef (stmt
);
1359 gsi_remove (&gsi
, true);
1363 /* Instrument a memory reference. BASE is the base of MEM, IS_LHS says
1364 whether the pointer is on the left hand side of the assignment. */
1367 instrument_mem_ref (tree mem
, tree base
, gimple_stmt_iterator
*iter
,
1370 enum ubsan_null_ckind ikind
= is_lhs
? UBSAN_STORE_OF
: UBSAN_LOAD_OF
;
1371 unsigned int align
= 0;
1372 if (sanitize_flags_p (SANITIZE_ALIGNMENT
))
1374 align
= min_align_of_type (TREE_TYPE (base
));
1378 if (align
== 0 && !sanitize_flags_p (SANITIZE_NULL
))
1380 tree t
= TREE_OPERAND (base
, 0);
1381 if (!POINTER_TYPE_P (TREE_TYPE (t
)))
1383 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (base
)) && mem
!= base
)
1384 ikind
= UBSAN_MEMBER_ACCESS
;
1385 tree kind
= build_int_cst (build_pointer_type (TREE_TYPE (base
)), ikind
);
1386 tree alignt
= build_int_cst (pointer_sized_int_node
, align
);
1387 gcall
*g
= gimple_build_call_internal (IFN_UBSAN_NULL
, 3, t
, kind
, alignt
);
1388 gimple_set_location (g
, gimple_location (gsi_stmt (*iter
)));
1389 gsi_insert_before (iter
, g
, GSI_SAME_STMT
);
1392 /* Perform the pointer instrumentation. */
1395 instrument_null (gimple_stmt_iterator gsi
, tree t
, bool is_lhs
)
1397 /* Handle also e.g. &s->i. */
1398 if (TREE_CODE (t
) == ADDR_EXPR
)
1399 t
= TREE_OPERAND (t
, 0);
1400 tree base
= get_base_address (t
);
1401 if (base
!= NULL_TREE
1402 && TREE_CODE (base
) == MEM_REF
1403 && TREE_CODE (TREE_OPERAND (base
, 0)) == SSA_NAME
)
1404 instrument_mem_ref (t
, base
, &gsi
, is_lhs
);
1407 /* Instrument pointer arithmetics PTR p+ OFF. */
1410 instrument_pointer_overflow (gimple_stmt_iterator
*gsi
, tree ptr
, tree off
)
1412 if (TYPE_PRECISION (sizetype
) != POINTER_SIZE
)
1414 gcall
*g
= gimple_build_call_internal (IFN_UBSAN_PTR
, 2, ptr
, off
);
1415 gimple_set_location (g
, gimple_location (gsi_stmt (*gsi
)));
1416 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1419 /* Instrument pointer arithmetics if any. */
1422 maybe_instrument_pointer_overflow (gimple_stmt_iterator
*gsi
, tree t
)
1424 if (TYPE_PRECISION (sizetype
) != POINTER_SIZE
)
1427 /* Handle also e.g. &s->i. */
1428 if (TREE_CODE (t
) == ADDR_EXPR
)
1429 t
= TREE_OPERAND (t
, 0);
1431 if (!handled_component_p (t
) && TREE_CODE (t
) != MEM_REF
)
1434 poly_int64 bitsize
, bitpos
, bytepos
;
1437 int volatilep
= 0, reversep
, unsignedp
= 0;
1438 tree inner
= get_inner_reference (t
, &bitsize
, &bitpos
, &offset
, &mode
,
1439 &unsignedp
, &reversep
, &volatilep
);
1440 tree moff
= NULL_TREE
;
1442 bool decl_p
= DECL_P (inner
);
1447 || TREE_CODE (inner
) == PARM_DECL
1448 || TREE_CODE (inner
) == RESULT_DECL
)
1449 && DECL_REGISTER (inner
))
1452 /* If BASE is a fixed size automatic variable or
1453 global variable defined in the current TU and bitpos
1454 fits, don't instrument anything. */
1455 poly_int64 base_size
;
1456 if (offset
== NULL_TREE
1457 && maybe_ne (bitpos
, 0)
1459 || TREE_CODE (base
) == PARM_DECL
1460 || TREE_CODE (base
) == RESULT_DECL
)
1461 && poly_int_tree_p (DECL_SIZE (base
), &base_size
)
1462 && known_ge (base_size
, bitpos
)
1463 && (!is_global_var (base
) || decl_binds_to_current_def_p (base
)))
1466 else if (TREE_CODE (inner
) == MEM_REF
)
1468 base
= TREE_OPERAND (inner
, 0);
1469 if (TREE_CODE (base
) == ADDR_EXPR
1470 && DECL_P (TREE_OPERAND (base
, 0))
1471 && !TREE_ADDRESSABLE (TREE_OPERAND (base
, 0))
1472 && !is_global_var (TREE_OPERAND (base
, 0)))
1474 moff
= TREE_OPERAND (inner
, 1);
1475 if (integer_zerop (moff
))
1481 if (!POINTER_TYPE_P (TREE_TYPE (base
)) && !DECL_P (base
))
1483 bytepos
= bits_to_bytes_round_down (bitpos
);
1484 if (offset
== NULL_TREE
&& known_eq (bytepos
, 0) && moff
== NULL_TREE
)
1487 tree base_addr
= base
;
1489 base_addr
= build1 (ADDR_EXPR
,
1490 build_pointer_type (TREE_TYPE (base
)), base
);
1492 if (maybe_ne (bytepos
, 0))
1495 t
= fold_build2 (PLUS_EXPR
, TREE_TYPE (t
), t
,
1496 build_int_cst (TREE_TYPE (t
), bytepos
));
1498 t
= size_int (bytepos
);
1503 t
= fold_build2 (PLUS_EXPR
, TREE_TYPE (t
), t
,
1504 fold_convert (TREE_TYPE (t
), moff
));
1506 t
= fold_convert (sizetype
, moff
);
1508 t
= force_gimple_operand_gsi (gsi
, t
, true, NULL_TREE
, true,
1510 base_addr
= force_gimple_operand_gsi (gsi
, base_addr
, true, NULL_TREE
, true,
1512 instrument_pointer_overflow (gsi
, base_addr
, t
);
1515 /* Build an ubsan builtin call for the signed-integer-overflow
1516 sanitization. CODE says what kind of builtin are we building,
1517 LOC is a location, LHSTYPE is the type of LHS, OP0 and OP1
1518 are operands of the binary operation. */
1521 ubsan_build_overflow_builtin (tree_code code
, location_t loc
, tree lhstype
,
1522 tree op0
, tree op1
, tree
*datap
)
1524 if (flag_sanitize_undefined_trap_on_error
)
1525 return build_call_expr_loc (loc
, builtin_decl_explicit (BUILT_IN_TRAP
), 0);
1528 if (datap
&& *datap
)
1531 data
= ubsan_create_data ("__ubsan_overflow_data", 1, &loc
,
1532 ubsan_type_descriptor (lhstype
), NULL_TREE
,
1536 enum built_in_function fn_code
;
1541 fn_code
= (flag_sanitize_recover
& SANITIZE_SI_OVERFLOW
)
1542 ? BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW
1543 : BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW_ABORT
;
1546 fn_code
= (flag_sanitize_recover
& SANITIZE_SI_OVERFLOW
)
1547 ? BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW
1548 : BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW_ABORT
;
1551 fn_code
= (flag_sanitize_recover
& SANITIZE_SI_OVERFLOW
)
1552 ? BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW
1553 : BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW_ABORT
;
1556 fn_code
= (flag_sanitize_recover
& SANITIZE_SI_OVERFLOW
)
1557 ? BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW
1558 : BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW_ABORT
;
1563 tree fn
= builtin_decl_explicit (fn_code
);
1564 return build_call_expr_loc (loc
, fn
, 2 + (code
!= NEGATE_EXPR
),
1565 build_fold_addr_expr_loc (loc
, data
),
1566 ubsan_encode_value (op0
, UBSAN_ENCODE_VALUE_RTL
),
1568 ? ubsan_encode_value (op1
,
1569 UBSAN_ENCODE_VALUE_RTL
)
1573 /* Perform the signed integer instrumentation. GSI is the iterator
1574 pointing at statement we are trying to instrument. */
1577 instrument_si_overflow (gimple_stmt_iterator gsi
)
1579 gimple
*stmt
= gsi_stmt (gsi
);
1580 tree_code code
= gimple_assign_rhs_code (stmt
);
1581 tree lhs
= gimple_assign_lhs (stmt
);
1582 tree lhstype
= TREE_TYPE (lhs
);
1583 tree lhsinner
= VECTOR_TYPE_P (lhstype
) ? TREE_TYPE (lhstype
) : lhstype
;
1587 /* If this is not a signed operation, don't instrument anything here.
1588 Also punt on bit-fields. */
1589 if (!INTEGRAL_TYPE_P (lhsinner
)
1590 || TYPE_OVERFLOW_WRAPS (lhsinner
)
1591 || maybe_ne (GET_MODE_BITSIZE (TYPE_MODE (lhsinner
)),
1592 TYPE_PRECISION (lhsinner
)))
1603 i = UBSAN_CHECK_{ADD,SUB,MUL} (u, 5); */
1604 a
= gimple_assign_rhs1 (stmt
);
1605 b
= gimple_assign_rhs2 (stmt
);
1606 g
= gimple_build_call_internal (code
== PLUS_EXPR
1607 ? IFN_UBSAN_CHECK_ADD
1608 : code
== MINUS_EXPR
1609 ? IFN_UBSAN_CHECK_SUB
1610 : IFN_UBSAN_CHECK_MUL
, 2, a
, b
);
1611 gimple_call_set_lhs (g
, lhs
);
1612 gsi_replace (&gsi
, g
, true);
1615 /* Represent i = -u;
1617 i = UBSAN_CHECK_SUB (0, u); */
1618 a
= build_zero_cst (lhstype
);
1619 b
= gimple_assign_rhs1 (stmt
);
1620 g
= gimple_build_call_internal (IFN_UBSAN_CHECK_SUB
, 2, a
, b
);
1621 gimple_call_set_lhs (g
, lhs
);
1622 gsi_replace (&gsi
, g
, true);
1625 /* Transform i = ABS_EXPR<u>;
1627 _N = UBSAN_CHECK_SUB (0, u);
1628 i = ABS_EXPR<_N>; */
1629 a
= build_zero_cst (lhstype
);
1630 b
= gimple_assign_rhs1 (stmt
);
1631 g
= gimple_build_call_internal (IFN_UBSAN_CHECK_SUB
, 2, a
, b
);
1632 a
= make_ssa_name (lhstype
);
1633 gimple_call_set_lhs (g
, a
);
1634 gimple_set_location (g
, gimple_location (stmt
));
1635 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
1636 gimple_assign_set_rhs1 (stmt
, a
);
1644 /* Instrument loads from (non-bitfield) bool and C++ enum values
1645 to check if the memory value is outside of the range of the valid
1649 instrument_bool_enum_load (gimple_stmt_iterator
*gsi
)
1651 gimple
*stmt
= gsi_stmt (*gsi
);
1652 tree rhs
= gimple_assign_rhs1 (stmt
);
1653 tree type
= TREE_TYPE (rhs
);
1654 tree minv
= NULL_TREE
, maxv
= NULL_TREE
;
1656 if (TREE_CODE (type
) == BOOLEAN_TYPE
1657 && sanitize_flags_p (SANITIZE_BOOL
))
1659 minv
= boolean_false_node
;
1660 maxv
= boolean_true_node
;
1662 else if (TREE_CODE (type
) == ENUMERAL_TYPE
1663 && sanitize_flags_p (SANITIZE_ENUM
)
1664 && TREE_TYPE (type
) != NULL_TREE
1665 && TREE_CODE (TREE_TYPE (type
)) == INTEGER_TYPE
1666 && (TYPE_PRECISION (TREE_TYPE (type
))
1667 < GET_MODE_PRECISION (SCALAR_INT_TYPE_MODE (type
))))
1669 minv
= TYPE_MIN_VALUE (TREE_TYPE (type
));
1670 maxv
= TYPE_MAX_VALUE (TREE_TYPE (type
));
1675 int modebitsize
= GET_MODE_BITSIZE (SCALAR_INT_TYPE_MODE (type
));
1676 poly_int64 bitsize
, bitpos
;
1679 int volatilep
= 0, reversep
, unsignedp
= 0;
1680 tree base
= get_inner_reference (rhs
, &bitsize
, &bitpos
, &offset
, &mode
,
1681 &unsignedp
, &reversep
, &volatilep
);
1682 tree utype
= build_nonstandard_integer_type (modebitsize
, 1);
1684 if ((VAR_P (base
) && DECL_HARD_REGISTER (base
))
1685 || !multiple_p (bitpos
, modebitsize
)
1686 || maybe_ne (bitsize
, modebitsize
)
1687 || GET_MODE_BITSIZE (SCALAR_INT_TYPE_MODE (utype
)) != modebitsize
1688 || TREE_CODE (gimple_assign_lhs (stmt
)) != SSA_NAME
)
1691 bool ends_bb
= stmt_ends_bb_p (stmt
);
1692 location_t loc
= gimple_location (stmt
);
1693 tree lhs
= gimple_assign_lhs (stmt
);
1694 tree ptype
= build_pointer_type (TREE_TYPE (rhs
));
1695 tree atype
= reference_alias_ptr_type (rhs
);
1696 gimple
*g
= gimple_build_assign (make_ssa_name (ptype
),
1697 build_fold_addr_expr (rhs
));
1698 gimple_set_location (g
, loc
);
1699 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1700 tree mem
= build2 (MEM_REF
, utype
, gimple_assign_lhs (g
),
1701 build_int_cst (atype
, 0));
1702 tree urhs
= make_ssa_name (utype
);
1705 gimple_assign_set_lhs (stmt
, urhs
);
1706 g
= gimple_build_assign (lhs
, NOP_EXPR
, urhs
);
1707 gimple_set_location (g
, loc
);
1708 edge e
= find_fallthru_edge (gimple_bb (stmt
)->succs
);
1709 gsi_insert_on_edge_immediate (e
, g
);
1710 gimple_assign_set_rhs_from_tree (gsi
, mem
);
1712 *gsi
= gsi_for_stmt (g
);
1717 g
= gimple_build_assign (urhs
, mem
);
1718 gimple_set_location (g
, loc
);
1719 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1721 minv
= fold_convert (utype
, minv
);
1722 maxv
= fold_convert (utype
, maxv
);
1723 if (!integer_zerop (minv
))
1725 g
= gimple_build_assign (make_ssa_name (utype
), MINUS_EXPR
, urhs
, minv
);
1726 gimple_set_location (g
, loc
);
1727 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1730 gimple_stmt_iterator gsi2
= *gsi
;
1731 basic_block then_bb
, fallthru_bb
;
1732 *gsi
= create_cond_insert_point (gsi
, true, false, true,
1733 &then_bb
, &fallthru_bb
);
1734 g
= gimple_build_cond (GT_EXPR
, gimple_assign_lhs (g
),
1735 int_const_binop (MINUS_EXPR
, maxv
, minv
),
1736 NULL_TREE
, NULL_TREE
);
1737 gimple_set_location (g
, loc
);
1738 gsi_insert_after (gsi
, g
, GSI_NEW_STMT
);
1742 gimple_assign_set_rhs_with_ops (&gsi2
, NOP_EXPR
, urhs
);
1746 gsi2
= gsi_after_labels (then_bb
);
1747 if (flag_sanitize_undefined_trap_on_error
)
1748 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
1751 tree data
= ubsan_create_data ("__ubsan_invalid_value_data", 1, &loc
,
1752 ubsan_type_descriptor (type
), NULL_TREE
,
1754 data
= build_fold_addr_expr_loc (loc
, data
);
1755 enum built_in_function bcode
1756 = (flag_sanitize_recover
& (TREE_CODE (type
) == BOOLEAN_TYPE
1757 ? SANITIZE_BOOL
: SANITIZE_ENUM
))
1758 ? BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE
1759 : BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE_ABORT
;
1760 tree fn
= builtin_decl_explicit (bcode
);
1762 tree val
= ubsan_encode_value (urhs
, UBSAN_ENCODE_VALUE_GIMPLE
);
1763 val
= force_gimple_operand_gsi (&gsi2
, val
, true, NULL_TREE
, true,
1765 g
= gimple_build_call (fn
, 2, data
, val
);
1767 gimple_set_location (g
, loc
);
1768 gsi_insert_before (&gsi2
, g
, GSI_SAME_STMT
);
1769 ubsan_create_edge (g
);
1770 *gsi
= gsi_for_stmt (stmt
);
1773 /* Determine if we can propagate given LOCATION to ubsan_data descriptor to use
1774 new style handlers. Libubsan uses heuristics to destinguish between old and
1775 new styles and relies on these properties for filename:
1777 a) Location's filename must not be NULL.
1778 b) Location's filename must not be equal to "".
1779 c) Location's filename must not be equal to "\1".
1780 d) First two bytes of filename must not contain '\xff' symbol. */
1783 ubsan_use_new_style_p (location_t loc
)
1785 if (loc
== UNKNOWN_LOCATION
)
1788 expanded_location xloc
= expand_location (loc
);
1789 if (xloc
.file
== NULL
|| startswith (xloc
.file
, "\1")
1790 || xloc
.file
[0] == '\0' || xloc
.file
[0] == '\xff'
1791 || xloc
.file
[1] == '\xff')
1797 /* Instrument float point-to-integer conversion. TYPE is an integer type of
1798 destination, EXPR is floating-point expression. */
1801 ubsan_instrument_float_cast (location_t loc
, tree type
, tree expr
)
1803 tree expr_type
= TREE_TYPE (expr
);
1804 tree t
, tt
, fn
, min
, max
;
1805 machine_mode mode
= TYPE_MODE (expr_type
);
1806 int prec
= TYPE_PRECISION (type
);
1807 bool uns_p
= TYPE_UNSIGNED (type
);
1808 if (loc
== UNKNOWN_LOCATION
)
1809 loc
= input_location
;
1811 /* Float to integer conversion first truncates toward zero, so
1812 even signed char c = 127.875f; is not problematic.
1813 Therefore, we should complain only if EXPR is unordered or smaller
1814 or equal than TYPE_MIN_VALUE - 1.0 or greater or equal than
1815 TYPE_MAX_VALUE + 1.0. */
1816 if (REAL_MODE_FORMAT (mode
)->b
== 2)
1818 /* For maximum, TYPE_MAX_VALUE might not be representable
1819 in EXPR_TYPE, e.g. if TYPE is 64-bit long long and
1820 EXPR_TYPE is IEEE single float, but TYPE_MAX_VALUE + 1.0 is
1821 either representable or infinity. */
1822 REAL_VALUE_TYPE maxval
= dconst1
;
1823 SET_REAL_EXP (&maxval
, REAL_EXP (&maxval
) + prec
- !uns_p
);
1824 real_convert (&maxval
, mode
, &maxval
);
1825 max
= build_real (expr_type
, maxval
);
1827 /* For unsigned, assume -1.0 is always representable. */
1829 min
= build_minus_one_cst (expr_type
);
1832 /* TYPE_MIN_VALUE is generally representable (or -inf),
1833 but TYPE_MIN_VALUE - 1.0 might not be. */
1834 REAL_VALUE_TYPE minval
= dconstm1
, minval2
;
1835 SET_REAL_EXP (&minval
, REAL_EXP (&minval
) + prec
- 1);
1836 real_convert (&minval
, mode
, &minval
);
1837 real_arithmetic (&minval2
, MINUS_EXPR
, &minval
, &dconst1
);
1838 real_convert (&minval2
, mode
, &minval2
);
1839 if (real_compare (EQ_EXPR
, &minval
, &minval2
)
1840 && !real_isinf (&minval
))
1842 /* If TYPE_MIN_VALUE - 1.0 is not representable and
1843 rounds to TYPE_MIN_VALUE, we need to subtract
1844 more. As REAL_MODE_FORMAT (mode)->p is the number
1845 of base digits, we want to subtract a number that
1846 will be 1 << (REAL_MODE_FORMAT (mode)->p - 1)
1847 times smaller than minval. */
1849 gcc_assert (prec
> REAL_MODE_FORMAT (mode
)->p
);
1850 SET_REAL_EXP (&minval2
,
1851 REAL_EXP (&minval2
) + prec
- 1
1852 - REAL_MODE_FORMAT (mode
)->p
+ 1);
1853 real_arithmetic (&minval2
, MINUS_EXPR
, &minval
, &minval2
);
1854 real_convert (&minval2
, mode
, &minval2
);
1856 min
= build_real (expr_type
, minval2
);
1859 else if (REAL_MODE_FORMAT (mode
)->b
== 10)
1861 /* For _Decimal128 up to 34 decimal digits, - sign,
1862 dot, e, exponent. */
1865 int p
= REAL_MODE_FORMAT (mode
)->p
;
1866 REAL_VALUE_TYPE maxval
, minval
;
1868 /* Use mpfr_snprintf rounding to compute the smallest
1869 representable decimal number greater or equal than
1870 1 << (prec - !uns_p). */
1871 mpfr_init2 (m
, prec
+ 2);
1872 mpfr_set_ui_2exp (m
, 1, prec
- !uns_p
, MPFR_RNDN
);
1873 mpfr_snprintf (buf
, sizeof buf
, "%.*RUe", p
- 1, m
);
1874 decimal_real_from_string (&maxval
, buf
);
1875 max
= build_real (expr_type
, maxval
);
1877 /* For unsigned, assume -1.0 is always representable. */
1879 min
= build_minus_one_cst (expr_type
);
1882 /* Use mpfr_snprintf rounding to compute the largest
1883 representable decimal number less or equal than
1884 (-1 << (prec - 1)) - 1. */
1885 mpfr_set_si_2exp (m
, -1, prec
- 1, MPFR_RNDN
);
1886 mpfr_sub_ui (m
, m
, 1, MPFR_RNDN
);
1887 mpfr_snprintf (buf
, sizeof buf
, "%.*RDe", p
- 1, m
);
1888 decimal_real_from_string (&minval
, buf
);
1889 min
= build_real (expr_type
, minval
);
1896 if (HONOR_NANS (mode
))
1898 t
= fold_build2 (UNLE_EXPR
, boolean_type_node
, expr
, min
);
1899 tt
= fold_build2 (UNGE_EXPR
, boolean_type_node
, expr
, max
);
1903 t
= fold_build2 (LE_EXPR
, boolean_type_node
, expr
, min
);
1904 tt
= fold_build2 (GE_EXPR
, boolean_type_node
, expr
, max
);
1906 t
= fold_build2 (TRUTH_OR_EXPR
, boolean_type_node
, t
, tt
);
1907 if (integer_zerop (t
))
1910 if (flag_sanitize_undefined_trap_on_error
)
1911 fn
= build_call_expr_loc (loc
, builtin_decl_explicit (BUILT_IN_TRAP
), 0);
1914 location_t
*loc_ptr
= NULL
;
1915 unsigned num_locations
= 0;
1916 /* Figure out if we can propagate location to ubsan_data and use new
1917 style handlers in libubsan. */
1918 if (ubsan_use_new_style_p (loc
))
1923 /* Create the __ubsan_handle_float_cast_overflow fn call. */
1924 tree data
= ubsan_create_data ("__ubsan_float_cast_overflow_data",
1925 num_locations
, loc_ptr
,
1926 ubsan_type_descriptor (expr_type
),
1927 ubsan_type_descriptor (type
), NULL_TREE
,
1929 enum built_in_function bcode
1930 = (flag_sanitize_recover
& SANITIZE_FLOAT_CAST
)
1931 ? BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW
1932 : BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW_ABORT
;
1933 fn
= builtin_decl_explicit (bcode
);
1934 fn
= build_call_expr_loc (loc
, fn
, 2,
1935 build_fold_addr_expr_loc (loc
, data
),
1936 ubsan_encode_value (expr
));
1939 return fold_build3 (COND_EXPR
, void_type_node
, t
, fn
, integer_zero_node
);
1942 /* Instrument values passed to function arguments with nonnull attribute. */
1945 instrument_nonnull_arg (gimple_stmt_iterator
*gsi
)
1947 gimple
*stmt
= gsi_stmt (*gsi
);
1949 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
1950 while for nonnull sanitization it is clear. */
1951 int save_flag_delete_null_pointer_checks
= flag_delete_null_pointer_checks
;
1952 flag_delete_null_pointer_checks
= 1;
1953 loc
[0] = gimple_location (stmt
);
1954 loc
[1] = UNKNOWN_LOCATION
;
1955 for (unsigned int i
= 0; i
< gimple_call_num_args (stmt
); i
++)
1957 tree arg
= gimple_call_arg (stmt
, i
);
1958 if (POINTER_TYPE_P (TREE_TYPE (arg
))
1959 && infer_nonnull_range_by_attribute (stmt
, arg
))
1962 if (!is_gimple_val (arg
))
1964 g
= gimple_build_assign (make_ssa_name (TREE_TYPE (arg
)), arg
);
1965 gimple_set_location (g
, loc
[0]);
1966 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1967 arg
= gimple_assign_lhs (g
);
1970 basic_block then_bb
, fallthru_bb
;
1971 *gsi
= create_cond_insert_point (gsi
, true, false, true,
1972 &then_bb
, &fallthru_bb
);
1973 g
= gimple_build_cond (EQ_EXPR
, arg
,
1974 build_zero_cst (TREE_TYPE (arg
)),
1975 NULL_TREE
, NULL_TREE
);
1976 gimple_set_location (g
, loc
[0]);
1977 gsi_insert_after (gsi
, g
, GSI_NEW_STMT
);
1979 *gsi
= gsi_after_labels (then_bb
);
1980 if (flag_sanitize_undefined_trap_on_error
)
1981 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
1984 tree data
= ubsan_create_data ("__ubsan_nonnull_arg_data",
1986 build_int_cst (integer_type_node
,
1989 data
= build_fold_addr_expr_loc (loc
[0], data
);
1990 enum built_in_function bcode
1991 = (flag_sanitize_recover
& SANITIZE_NONNULL_ATTRIBUTE
)
1992 ? BUILT_IN_UBSAN_HANDLE_NONNULL_ARG
1993 : BUILT_IN_UBSAN_HANDLE_NONNULL_ARG_ABORT
;
1994 tree fn
= builtin_decl_explicit (bcode
);
1996 g
= gimple_build_call (fn
, 1, data
);
1998 gimple_set_location (g
, loc
[0]);
1999 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
2000 ubsan_create_edge (g
);
2002 *gsi
= gsi_for_stmt (stmt
);
2004 flag_delete_null_pointer_checks
= save_flag_delete_null_pointer_checks
;
2007 /* Instrument returns in functions with returns_nonnull attribute. */
2010 instrument_nonnull_return (gimple_stmt_iterator
*gsi
)
2012 greturn
*stmt
= as_a
<greturn
*> (gsi_stmt (*gsi
));
2014 tree arg
= gimple_return_retval (stmt
);
2015 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
2016 while for nonnull return sanitization it is clear. */
2017 int save_flag_delete_null_pointer_checks
= flag_delete_null_pointer_checks
;
2018 flag_delete_null_pointer_checks
= 1;
2019 loc
[0] = gimple_location (stmt
);
2020 loc
[1] = UNKNOWN_LOCATION
;
2022 && POINTER_TYPE_P (TREE_TYPE (arg
))
2023 && is_gimple_val (arg
)
2024 && infer_nonnull_range_by_attribute (stmt
, arg
))
2026 basic_block then_bb
, fallthru_bb
;
2027 *gsi
= create_cond_insert_point (gsi
, true, false, true,
2028 &then_bb
, &fallthru_bb
);
2029 gimple
*g
= gimple_build_cond (EQ_EXPR
, arg
,
2030 build_zero_cst (TREE_TYPE (arg
)),
2031 NULL_TREE
, NULL_TREE
);
2032 gimple_set_location (g
, loc
[0]);
2033 gsi_insert_after (gsi
, g
, GSI_NEW_STMT
);
2035 *gsi
= gsi_after_labels (then_bb
);
2036 if (flag_sanitize_undefined_trap_on_error
)
2037 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
2040 tree data
= ubsan_create_data ("__ubsan_nonnull_return_data",
2041 1, &loc
[1], NULL_TREE
, NULL_TREE
);
2042 data
= build_fold_addr_expr_loc (loc
[0], data
);
2043 tree data2
= ubsan_create_data ("__ubsan_nonnull_return_data",
2044 1, &loc
[0], NULL_TREE
, NULL_TREE
);
2045 data2
= build_fold_addr_expr_loc (loc
[0], data2
);
2046 enum built_in_function bcode
2047 = (flag_sanitize_recover
& SANITIZE_RETURNS_NONNULL_ATTRIBUTE
)
2048 ? BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_V1
2049 : BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_V1_ABORT
;
2050 tree fn
= builtin_decl_explicit (bcode
);
2052 g
= gimple_build_call (fn
, 2, data
, data2
);
2054 gimple_set_location (g
, loc
[0]);
2055 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
2056 ubsan_create_edge (g
);
2057 *gsi
= gsi_for_stmt (stmt
);
2059 flag_delete_null_pointer_checks
= save_flag_delete_null_pointer_checks
;
2062 /* Instrument memory references. Here we check whether the pointer
2063 points to an out-of-bounds location. */
2066 instrument_object_size (gimple_stmt_iterator
*gsi
, tree t
, bool is_lhs
)
2068 gimple
*stmt
= gsi_stmt (*gsi
);
2069 location_t loc
= gimple_location (stmt
);
2071 tree index
= NULL_TREE
;
2072 HOST_WIDE_INT size_in_bytes
;
2074 type
= TREE_TYPE (t
);
2075 if (VOID_TYPE_P (type
))
2078 switch (TREE_CODE (t
))
2081 if (TREE_CODE (t
) == COMPONENT_REF
2082 && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t
, 1)) != NULL_TREE
)
2084 tree repr
= DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t
, 1));
2085 t
= build3 (COMPONENT_REF
, TREE_TYPE (repr
), TREE_OPERAND (t
, 0),
2086 repr
, TREE_OPERAND (t
, 2));
2090 index
= TREE_OPERAND (t
, 1);
2102 size_in_bytes
= int_size_in_bytes (type
);
2103 if (size_in_bytes
<= 0)
2106 poly_int64 bitsize
, bitpos
;
2109 int volatilep
= 0, reversep
, unsignedp
= 0;
2110 tree inner
= get_inner_reference (t
, &bitsize
, &bitpos
, &offset
, &mode
,
2111 &unsignedp
, &reversep
, &volatilep
);
2113 if (!multiple_p (bitpos
, BITS_PER_UNIT
)
2114 || maybe_ne (bitsize
, size_in_bytes
* BITS_PER_UNIT
))
2117 bool decl_p
= DECL_P (inner
);
2122 || TREE_CODE (inner
) == PARM_DECL
2123 || TREE_CODE (inner
) == RESULT_DECL
)
2124 && DECL_REGISTER (inner
))
2128 else if (TREE_CODE (inner
) == MEM_REF
)
2129 base
= TREE_OPERAND (inner
, 0);
2132 tree ptr
= build1 (ADDR_EXPR
, build_pointer_type (TREE_TYPE (t
)), t
);
2134 while (TREE_CODE (base
) == SSA_NAME
)
2136 gimple
*def_stmt
= SSA_NAME_DEF_STMT (base
);
2137 if (gimple_assign_ssa_name_copy_p (def_stmt
)
2138 || (gimple_assign_cast_p (def_stmt
)
2139 && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (def_stmt
))))
2140 || (is_gimple_assign (def_stmt
)
2141 && gimple_assign_rhs_code (def_stmt
) == POINTER_PLUS_EXPR
))
2143 tree rhs1
= gimple_assign_rhs1 (def_stmt
);
2144 if (TREE_CODE (rhs1
) == SSA_NAME
2145 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs1
))
2154 if (!POINTER_TYPE_P (TREE_TYPE (base
)) && !DECL_P (base
))
2158 tree base_addr
= base
;
2159 gimple
*bos_stmt
= NULL
;
2161 base_addr
= build1 (ADDR_EXPR
,
2162 build_pointer_type (TREE_TYPE (base
)), base
);
2163 if (compute_builtin_object_size (base_addr
, 0, &sizet
))
2167 if (LOCATION_LOCUS (loc
) == UNKNOWN_LOCATION
)
2168 loc
= input_location
;
2169 /* Generate __builtin_object_size call. */
2170 sizet
= builtin_decl_explicit (BUILT_IN_OBJECT_SIZE
);
2171 sizet
= build_call_expr_loc (loc
, sizet
, 2, base_addr
,
2173 sizet
= force_gimple_operand_gsi (gsi
, sizet
, false, NULL_TREE
, true,
2175 /* If the call above didn't end up being an integer constant, go one
2176 statement back and get the __builtin_object_size stmt. Save it,
2177 we might need it later. */
2178 if (SSA_VAR_P (sizet
))
2181 bos_stmt
= gsi_stmt (*gsi
);
2183 /* Move on to where we were. */
2190 /* Generate UBSAN_OBJECT_SIZE (ptr, ptr+sizeof(*ptr)-base, objsize, ckind)
2192 /* ptr + sizeof (*ptr) - base */
2193 t
= fold_build2 (MINUS_EXPR
, sizetype
,
2194 fold_convert (pointer_sized_int_node
, ptr
),
2195 fold_convert (pointer_sized_int_node
, base_addr
));
2196 t
= fold_build2 (PLUS_EXPR
, sizetype
, t
, TYPE_SIZE_UNIT (type
));
2198 /* Perhaps we can omit the check. */
2199 if (TREE_CODE (t
) == INTEGER_CST
2200 && TREE_CODE (sizet
) == INTEGER_CST
2201 && tree_int_cst_le (t
, sizet
))
2204 if (index
!= NULL_TREE
2205 && TREE_CODE (index
) == SSA_NAME
2206 && TREE_CODE (sizet
) == INTEGER_CST
)
2208 gimple
*def
= SSA_NAME_DEF_STMT (index
);
2209 if (is_gimple_assign (def
)
2210 && gimple_assign_rhs_code (def
) == BIT_AND_EXPR
2211 && TREE_CODE (gimple_assign_rhs2 (def
)) == INTEGER_CST
)
2213 tree cst
= gimple_assign_rhs2 (def
);
2214 tree sz
= fold_build2 (EXACT_DIV_EXPR
, sizetype
, sizet
,
2215 TYPE_SIZE_UNIT (type
));
2216 if (tree_int_cst_sgn (cst
) >= 0
2217 && tree_int_cst_lt (cst
, sz
))
2222 if (bos_stmt
&& gimple_call_builtin_p (bos_stmt
, BUILT_IN_OBJECT_SIZE
))
2223 ubsan_create_edge (bos_stmt
);
2225 /* We have to emit the check. */
2226 t
= force_gimple_operand_gsi (gsi
, t
, true, NULL_TREE
, true,
2228 ptr
= force_gimple_operand_gsi (gsi
, ptr
, true, NULL_TREE
, true,
2230 tree ckind
= build_int_cst (unsigned_char_type_node
,
2231 is_lhs
? UBSAN_STORE_OF
: UBSAN_LOAD_OF
);
2232 gimple
*g
= gimple_build_call_internal (IFN_UBSAN_OBJECT_SIZE
, 4,
2233 ptr
, t
, sizet
, ckind
);
2234 gimple_set_location (g
, loc
);
2235 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
2238 /* Instrument values passed to builtin functions. */
2241 instrument_builtin (gimple_stmt_iterator
*gsi
)
2243 gimple
*stmt
= gsi_stmt (*gsi
);
2244 location_t loc
= gimple_location (stmt
);
2246 enum built_in_function fcode
2247 = DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
));
2251 CASE_INT_FN (BUILT_IN_CLZ
):
2254 CASE_INT_FN (BUILT_IN_CTZ
):
2255 arg
= gimple_call_arg (stmt
, 0);
2256 if (!integer_nonzerop (arg
))
2259 if (!is_gimple_val (arg
))
2261 g
= gimple_build_assign (make_ssa_name (TREE_TYPE (arg
)), arg
);
2262 gimple_set_location (g
, loc
);
2263 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
2264 arg
= gimple_assign_lhs (g
);
2267 basic_block then_bb
, fallthru_bb
;
2268 *gsi
= create_cond_insert_point (gsi
, true, false, true,
2269 &then_bb
, &fallthru_bb
);
2270 g
= gimple_build_cond (EQ_EXPR
, arg
,
2271 build_zero_cst (TREE_TYPE (arg
)),
2272 NULL_TREE
, NULL_TREE
);
2273 gimple_set_location (g
, loc
);
2274 gsi_insert_after (gsi
, g
, GSI_NEW_STMT
);
2276 *gsi
= gsi_after_labels (then_bb
);
2277 if (flag_sanitize_undefined_trap_on_error
)
2278 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
2281 tree t
= build_int_cst (unsigned_char_type_node
, kind
);
2282 tree data
= ubsan_create_data ("__ubsan_builtin_data",
2283 1, &loc
, NULL_TREE
, t
, NULL_TREE
);
2284 data
= build_fold_addr_expr_loc (loc
, data
);
2285 enum built_in_function bcode
2286 = (flag_sanitize_recover
& SANITIZE_BUILTIN
)
2287 ? BUILT_IN_UBSAN_HANDLE_INVALID_BUILTIN
2288 : BUILT_IN_UBSAN_HANDLE_INVALID_BUILTIN_ABORT
;
2289 tree fn
= builtin_decl_explicit (bcode
);
2291 g
= gimple_build_call (fn
, 1, data
);
2293 gimple_set_location (g
, loc
);
2294 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
2295 ubsan_create_edge (g
);
2297 *gsi
= gsi_for_stmt (stmt
);
2306 const pass_data pass_data_ubsan
=
2308 GIMPLE_PASS
, /* type */
2310 OPTGROUP_NONE
, /* optinfo_flags */
2311 TV_TREE_UBSAN
, /* tv_id */
2312 ( PROP_cfg
| PROP_ssa
), /* properties_required */
2313 0, /* properties_provided */
2314 0, /* properties_destroyed */
2315 0, /* todo_flags_start */
2316 TODO_update_ssa
, /* todo_flags_finish */
2319 class pass_ubsan
: public gimple_opt_pass
2322 pass_ubsan (gcc::context
*ctxt
)
2323 : gimple_opt_pass (pass_data_ubsan
, ctxt
)
2326 /* opt_pass methods: */
2327 virtual bool gate (function
*)
2329 return sanitize_flags_p ((SANITIZE_NULL
| SANITIZE_SI_OVERFLOW
2330 | SANITIZE_BOOL
| SANITIZE_ENUM
2331 | SANITIZE_ALIGNMENT
2332 | SANITIZE_NONNULL_ATTRIBUTE
2333 | SANITIZE_RETURNS_NONNULL_ATTRIBUTE
2334 | SANITIZE_OBJECT_SIZE
2335 | SANITIZE_POINTER_OVERFLOW
2336 | SANITIZE_BUILTIN
));
2339 virtual unsigned int execute (function
*);
2341 }; // class pass_ubsan
2344 pass_ubsan::execute (function
*fun
)
2347 gimple_stmt_iterator gsi
;
2348 unsigned int ret
= 0;
2350 initialize_sanitizer_builtins ();
2352 FOR_EACH_BB_FN (bb
, fun
)
2354 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
);)
2356 gimple
*stmt
= gsi_stmt (gsi
);
2357 if (is_gimple_debug (stmt
) || gimple_clobber_p (stmt
))
2363 if ((sanitize_flags_p (SANITIZE_SI_OVERFLOW
, fun
->decl
))
2364 && is_gimple_assign (stmt
))
2365 instrument_si_overflow (gsi
);
2367 if (sanitize_flags_p (SANITIZE_NULL
| SANITIZE_ALIGNMENT
, fun
->decl
))
2369 if (gimple_store_p (stmt
))
2370 instrument_null (gsi
, gimple_get_lhs (stmt
), true);
2371 if (gimple_assign_single_p (stmt
))
2372 instrument_null (gsi
, gimple_assign_rhs1 (stmt
), false);
2373 if (is_gimple_call (stmt
))
2375 unsigned args_num
= gimple_call_num_args (stmt
);
2376 for (unsigned i
= 0; i
< args_num
; ++i
)
2378 tree arg
= gimple_call_arg (stmt
, i
);
2379 if (is_gimple_reg (arg
) || is_gimple_min_invariant (arg
))
2381 instrument_null (gsi
, arg
, false);
2386 if (sanitize_flags_p (SANITIZE_BOOL
| SANITIZE_ENUM
, fun
->decl
)
2387 && gimple_assign_load_p (stmt
))
2389 instrument_bool_enum_load (&gsi
);
2390 bb
= gimple_bb (stmt
);
2393 if (sanitize_flags_p (SANITIZE_NONNULL_ATTRIBUTE
, fun
->decl
)
2394 && is_gimple_call (stmt
)
2395 && !gimple_call_internal_p (stmt
))
2397 instrument_nonnull_arg (&gsi
);
2398 bb
= gimple_bb (stmt
);
2401 if (sanitize_flags_p (SANITIZE_BUILTIN
, fun
->decl
)
2402 && gimple_call_builtin_p (stmt
, BUILT_IN_NORMAL
))
2404 instrument_builtin (&gsi
);
2405 bb
= gimple_bb (stmt
);
2408 if (sanitize_flags_p (SANITIZE_RETURNS_NONNULL_ATTRIBUTE
, fun
->decl
)
2409 && gimple_code (stmt
) == GIMPLE_RETURN
)
2411 instrument_nonnull_return (&gsi
);
2412 bb
= gimple_bb (stmt
);
2415 if (sanitize_flags_p (SANITIZE_OBJECT_SIZE
, fun
->decl
))
2417 if (gimple_store_p (stmt
))
2418 instrument_object_size (&gsi
, gimple_get_lhs (stmt
), true);
2419 if (gimple_assign_load_p (stmt
))
2420 instrument_object_size (&gsi
, gimple_assign_rhs1 (stmt
),
2422 if (is_gimple_call (stmt
))
2424 unsigned args_num
= gimple_call_num_args (stmt
);
2425 for (unsigned i
= 0; i
< args_num
; ++i
)
2427 tree arg
= gimple_call_arg (stmt
, i
);
2428 if (is_gimple_reg (arg
) || is_gimple_min_invariant (arg
))
2430 instrument_object_size (&gsi
, arg
, false);
2435 if (sanitize_flags_p (SANITIZE_POINTER_OVERFLOW
, fun
->decl
))
2437 if (is_gimple_assign (stmt
)
2438 && gimple_assign_rhs_code (stmt
) == POINTER_PLUS_EXPR
)
2439 instrument_pointer_overflow (&gsi
,
2440 gimple_assign_rhs1 (stmt
),
2441 gimple_assign_rhs2 (stmt
));
2442 if (gimple_store_p (stmt
))
2443 maybe_instrument_pointer_overflow (&gsi
,
2444 gimple_get_lhs (stmt
));
2445 if (gimple_assign_single_p (stmt
))
2446 maybe_instrument_pointer_overflow (&gsi
,
2447 gimple_assign_rhs1 (stmt
));
2448 if (is_gimple_call (stmt
))
2450 unsigned args_num
= gimple_call_num_args (stmt
);
2451 for (unsigned i
= 0; i
< args_num
; ++i
)
2453 tree arg
= gimple_call_arg (stmt
, i
);
2454 if (is_gimple_reg (arg
))
2456 maybe_instrument_pointer_overflow (&gsi
, arg
);
2463 if (gimple_purge_dead_eh_edges (bb
))
2464 ret
= TODO_cleanup_cfg
;
2472 make_pass_ubsan (gcc::context
*ctxt
)
2474 return new pass_ubsan (ctxt
);
2477 #include "gt-ubsan.h"