1 /* UndefinedBehaviorSanitizer, undefined behavior detector.
2 Copyright (C) 2013-2014 Free Software Foundation, Inc.
3 Contributed by Marek Polacek <polacek@redhat.com>
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
23 #include "coretypes.h"
25 #include "stor-layout.h"
26 #include "stringpool.h"
28 #include "dominance.h"
31 #include "basic-block.h"
34 #include "plugin-api.h"
40 #include "hard-reg-set.h"
45 #include "tree-pass.h"
46 #include "tree-ssa-alias.h"
47 #include "tree-pretty-print.h"
48 #include "internal-fn.h"
49 #include "gimple-expr.h"
51 #include "gimple-iterator.h"
52 #include "gimple-ssa.h"
53 #include "gimple-walk.h"
59 #include "c-family/c-common.h"
62 #include "tree-ssanames.h"
64 #include "gimplify-me.h"
69 #include "tree-object-size.h"
72 /* Map from a tree to a VAR_DECL tree. */
74 struct GTY((for_user
)) tree_type_map
{
75 struct tree_map_base type
;
79 struct tree_type_map_cache_hasher
: ggc_cache_hasher
<tree_type_map
*>
81 static inline hashval_t
82 hash (tree_type_map
*t
)
84 return TYPE_UID (t
->type
.from
);
88 equal (tree_type_map
*a
, tree_type_map
*b
)
90 return a
->type
.from
== b
->type
.from
;
94 handle_cache_entry (tree_type_map
*&m
)
96 extern void gt_ggc_mx (tree_type_map
*&);
97 if (m
== HTAB_EMPTY_ENTRY
|| m
== HTAB_DELETED_ENTRY
)
99 else if (ggc_marked_p (m
->type
.from
))
102 m
= static_cast<tree_type_map
*> (HTAB_DELETED_ENTRY
);
107 hash_table
<tree_type_map_cache_hasher
> *decl_tree_for_type
;
109 /* Lookup a VAR_DECL for TYPE, and return it if we find one. */
112 decl_for_type_lookup (tree type
)
114 /* If the hash table is not initialized yet, create it now. */
115 if (decl_tree_for_type
== NULL
)
118 = hash_table
<tree_type_map_cache_hasher
>::create_ggc (10);
119 /* That also means we don't have to bother with the lookup. */
123 struct tree_type_map
*h
, in
;
126 h
= decl_tree_for_type
->find_with_hash (&in
, TYPE_UID (type
));
127 return h
? h
->decl
: NULL_TREE
;
130 /* Insert a mapping TYPE->DECL in the VAR_DECL for type hashtable. */
133 decl_for_type_insert (tree type
, tree decl
)
135 struct tree_type_map
*h
;
137 h
= ggc_alloc
<tree_type_map
> ();
140 *decl_tree_for_type
->find_slot_with_hash (h
, TYPE_UID (type
), INSERT
) = h
;
143 /* Helper routine, which encodes a value in the pointer_sized_int_node.
144 Arguments with precision <= POINTER_SIZE are passed directly,
145 the rest is passed by reference. T is a value we are to encode.
146 IN_EXPAND_P is true if this function is called during expansion. */
149 ubsan_encode_value (tree t
, bool in_expand_p
)
151 tree type
= TREE_TYPE (t
);
152 const unsigned int bitsize
= GET_MODE_BITSIZE (TYPE_MODE (type
));
153 if (bitsize
<= POINTER_SIZE
)
154 switch (TREE_CODE (type
))
159 return fold_build1 (NOP_EXPR
, pointer_sized_int_node
, t
);
162 tree itype
= build_nonstandard_integer_type (bitsize
, true);
163 t
= fold_build1 (VIEW_CONVERT_EXPR
, itype
, t
);
164 return fold_convert (pointer_sized_int_node
, t
);
171 if (!DECL_P (t
) || !TREE_ADDRESSABLE (t
))
173 /* The reason for this is that we don't want to pessimize
174 code by making vars unnecessarily addressable. */
175 tree var
= create_tmp_var (type
);
176 tree tem
= build2 (MODIFY_EXPR
, void_type_node
, var
, t
);
180 = assign_stack_temp_for_type (TYPE_MODE (type
),
181 GET_MODE_SIZE (TYPE_MODE (type
)),
183 SET_DECL_RTL (var
, mem
);
184 expand_assignment (var
, t
, false);
185 return build_fold_addr_expr (var
);
187 t
= build_fold_addr_expr (var
);
188 return build2 (COMPOUND_EXPR
, TREE_TYPE (t
), tem
, t
);
191 return build_fold_addr_expr (t
);
195 /* Cached ubsan_get_type_descriptor_type () return value. */
196 static GTY(()) tree ubsan_type_descriptor_type
;
199 struct __ubsan_type_descriptor
201 unsigned short __typekind;
202 unsigned short __typeinfo;
208 ubsan_get_type_descriptor_type (void)
210 static const char *field_names
[3]
211 = { "__typekind", "__typeinfo", "__typename" };
214 if (ubsan_type_descriptor_type
)
215 return ubsan_type_descriptor_type
;
217 tree itype
= build_range_type (sizetype
, size_zero_node
, NULL_TREE
);
218 tree flex_arr_type
= build_array_type (char_type_node
, itype
);
220 ret
= make_node (RECORD_TYPE
);
221 for (int i
= 0; i
< 3; i
++)
223 fields
[i
] = build_decl (UNKNOWN_LOCATION
, FIELD_DECL
,
224 get_identifier (field_names
[i
]),
225 (i
== 2) ? flex_arr_type
226 : short_unsigned_type_node
);
227 DECL_CONTEXT (fields
[i
]) = ret
;
229 DECL_CHAIN (fields
[i
- 1]) = fields
[i
];
231 tree type_decl
= build_decl (input_location
, TYPE_DECL
,
232 get_identifier ("__ubsan_type_descriptor"),
234 DECL_IGNORED_P (type_decl
) = 1;
235 DECL_ARTIFICIAL (type_decl
) = 1;
236 TYPE_FIELDS (ret
) = fields
[0];
237 TYPE_NAME (ret
) = type_decl
;
238 TYPE_STUB_DECL (ret
) = type_decl
;
240 ubsan_type_descriptor_type
= ret
;
244 /* Cached ubsan_get_source_location_type () return value. */
245 static GTY(()) tree ubsan_source_location_type
;
248 struct __ubsan_source_location
250 const char *__filename;
252 unsigned int __column;
257 ubsan_get_source_location_type (void)
259 static const char *field_names
[3]
260 = { "__filename", "__line", "__column" };
262 if (ubsan_source_location_type
)
263 return ubsan_source_location_type
;
265 tree const_char_type
= build_qualified_type (char_type_node
,
268 ret
= make_node (RECORD_TYPE
);
269 for (int i
= 0; i
< 3; i
++)
271 fields
[i
] = build_decl (UNKNOWN_LOCATION
, FIELD_DECL
,
272 get_identifier (field_names
[i
]),
273 (i
== 0) ? build_pointer_type (const_char_type
)
274 : unsigned_type_node
);
275 DECL_CONTEXT (fields
[i
]) = ret
;
277 DECL_CHAIN (fields
[i
- 1]) = fields
[i
];
279 tree type_decl
= build_decl (input_location
, TYPE_DECL
,
280 get_identifier ("__ubsan_source_location"),
282 DECL_IGNORED_P (type_decl
) = 1;
283 DECL_ARTIFICIAL (type_decl
) = 1;
284 TYPE_FIELDS (ret
) = fields
[0];
285 TYPE_NAME (ret
) = type_decl
;
286 TYPE_STUB_DECL (ret
) = type_decl
;
288 ubsan_source_location_type
= ret
;
292 /* Helper routine that returns a CONSTRUCTOR of __ubsan_source_location
293 type with its fields filled from a location_t LOC. */
296 ubsan_source_location (location_t loc
)
298 expanded_location xloc
;
299 tree type
= ubsan_get_source_location_type ();
301 xloc
= expand_location (loc
);
303 if (xloc
.file
== NULL
)
305 str
= build_int_cst (ptr_type_node
, 0);
311 /* Fill in the values from LOC. */
312 size_t len
= strlen (xloc
.file
);
313 str
= build_string (len
+ 1, xloc
.file
);
314 TREE_TYPE (str
) = build_array_type (char_type_node
,
315 build_index_type (size_int (len
)));
316 TREE_READONLY (str
) = 1;
317 TREE_STATIC (str
) = 1;
318 str
= build_fold_addr_expr (str
);
320 tree ctor
= build_constructor_va (type
, 3, NULL_TREE
, str
, NULL_TREE
,
321 build_int_cst (unsigned_type_node
,
322 xloc
.line
), NULL_TREE
,
323 build_int_cst (unsigned_type_node
,
325 TREE_CONSTANT (ctor
) = 1;
326 TREE_STATIC (ctor
) = 1;
331 /* This routine returns a magic number for TYPE. */
333 static unsigned short
334 get_ubsan_type_info_for_type (tree type
)
336 gcc_assert (TYPE_SIZE (type
) && tree_fits_uhwi_p (TYPE_SIZE (type
)));
337 if (TREE_CODE (type
) == REAL_TYPE
)
338 return tree_to_uhwi (TYPE_SIZE (type
));
339 else if (INTEGRAL_TYPE_P (type
))
341 int prec
= exact_log2 (tree_to_uhwi (TYPE_SIZE (type
)));
342 gcc_assert (prec
!= -1);
343 return (prec
<< 1) | !TYPE_UNSIGNED (type
);
349 /* Helper routine that returns ADDR_EXPR of a VAR_DECL of a type
350 descriptor. It first looks into the hash table; if not found,
351 create the VAR_DECL, put it into the hash table and return the
352 ADDR_EXPR of it. TYPE describes a particular type. PSTYLE is
353 an enum controlling how we want to print the type. */
356 ubsan_type_descriptor (tree type
, enum ubsan_print_style pstyle
)
358 /* See through any typedefs. */
359 type
= TYPE_MAIN_VARIANT (type
);
361 tree decl
= decl_for_type_lookup (type
);
362 /* It is possible that some of the earlier created DECLs were found
363 unused, in that case they weren't emitted and varpool_node::get
364 returns NULL node on them. But now we really need them. Thus,
366 if (decl
!= NULL_TREE
&& varpool_node::get (decl
))
367 return build_fold_addr_expr (decl
);
369 tree dtype
= ubsan_get_type_descriptor_type ();
371 const char *tname
= NULL
;
373 unsigned char deref_depth
= 0;
374 unsigned short tkind
, tinfo
;
376 /* Get the name of the type, or the name of the pointer type. */
377 if (pstyle
== UBSAN_PRINT_POINTER
)
379 gcc_assert (POINTER_TYPE_P (type
));
380 type2
= TREE_TYPE (type
);
382 /* Remove any '*' operators from TYPE. */
383 while (POINTER_TYPE_P (type2
))
384 deref_depth
++, type2
= TREE_TYPE (type2
);
386 if (TREE_CODE (type2
) == METHOD_TYPE
)
387 type2
= TYPE_METHOD_BASETYPE (type2
);
390 /* If an array, get its type. */
391 type2
= strip_array_types (type2
);
393 if (pstyle
== UBSAN_PRINT_ARRAY
)
395 while (POINTER_TYPE_P (type2
))
396 deref_depth
++, type2
= TREE_TYPE (type2
);
399 if (TYPE_NAME (type2
) != NULL
)
401 if (TREE_CODE (TYPE_NAME (type2
)) == IDENTIFIER_NODE
)
402 tname
= IDENTIFIER_POINTER (TYPE_NAME (type2
));
403 else if (DECL_NAME (TYPE_NAME (type2
)) != NULL
)
404 tname
= IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type2
)));
408 /* We weren't able to determine the type name. */
411 /* Decorate the type name with '', '*', "struct", or "union". */
412 pretty_name
= (char *) alloca (strlen (tname
) + 16 + deref_depth
);
413 if (pstyle
== UBSAN_PRINT_POINTER
)
415 int pos
= sprintf (pretty_name
, "'%s%s%s%s%s%s%s",
416 TYPE_VOLATILE (type2
) ? "volatile " : "",
417 TYPE_READONLY (type2
) ? "const " : "",
418 TYPE_RESTRICT (type2
) ? "restrict " : "",
419 TYPE_ATOMIC (type2
) ? "_Atomic " : "",
420 TREE_CODE (type2
) == RECORD_TYPE
422 : TREE_CODE (type2
) == UNION_TYPE
423 ? "union " : "", tname
,
424 deref_depth
== 0 ? "" : " ");
425 while (deref_depth
-- > 0)
426 pretty_name
[pos
++] = '*';
427 pretty_name
[pos
++] = '\'';
428 pretty_name
[pos
] = '\0';
430 else if (pstyle
== UBSAN_PRINT_ARRAY
)
432 /* Pretty print the array dimensions. */
433 gcc_assert (TREE_CODE (type
) == ARRAY_TYPE
);
435 int pos
= sprintf (pretty_name
, "'%s ", tname
);
436 while (deref_depth
-- > 0)
437 pretty_name
[pos
++] = '*';
438 while (TREE_CODE (t
) == ARRAY_TYPE
)
440 pretty_name
[pos
++] = '[';
441 tree dom
= TYPE_DOMAIN (t
);
442 if (dom
&& TREE_CODE (TYPE_MAX_VALUE (dom
)) == INTEGER_CST
)
443 pos
+= sprintf (&pretty_name
[pos
], HOST_WIDE_INT_PRINT_DEC
,
444 tree_to_uhwi (TYPE_MAX_VALUE (dom
)) + 1);
446 /* ??? We can't determine the variable name; print VLA unspec. */
447 pretty_name
[pos
++] = '*';
448 pretty_name
[pos
++] = ']';
451 pretty_name
[pos
++] = '\'';
452 pretty_name
[pos
] = '\0';
454 /* Save the tree with stripped types. */
458 sprintf (pretty_name
, "'%s'", tname
);
460 switch (TREE_CODE (type
))
468 /* FIXME: libubsan right now only supports float, double and
469 long double type formats. */
470 if (TYPE_MODE (type
) == TYPE_MODE (float_type_node
)
471 || TYPE_MODE (type
) == TYPE_MODE (double_type_node
)
472 || TYPE_MODE (type
) == TYPE_MODE (long_double_type_node
))
481 tinfo
= get_ubsan_type_info_for_type (type
);
483 /* Create a new VAR_DECL of type descriptor. */
485 static unsigned int type_var_id_num
;
486 ASM_GENERATE_INTERNAL_LABEL (tmp_name
, "Lubsan_type", type_var_id_num
++);
487 decl
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
, get_identifier (tmp_name
),
489 TREE_STATIC (decl
) = 1;
490 TREE_PUBLIC (decl
) = 0;
491 DECL_ARTIFICIAL (decl
) = 1;
492 DECL_IGNORED_P (decl
) = 1;
493 DECL_EXTERNAL (decl
) = 0;
495 size_t len
= strlen (pretty_name
);
496 tree str
= build_string (len
+ 1, pretty_name
);
497 TREE_TYPE (str
) = build_array_type (char_type_node
,
498 build_index_type (size_int (len
)));
499 TREE_READONLY (str
) = 1;
500 TREE_STATIC (str
) = 1;
501 tree ctor
= build_constructor_va (dtype
, 3, NULL_TREE
,
502 build_int_cst (short_unsigned_type_node
,
504 build_int_cst (short_unsigned_type_node
,
505 tinfo
), NULL_TREE
, str
);
506 TREE_CONSTANT (ctor
) = 1;
507 TREE_STATIC (ctor
) = 1;
508 DECL_INITIAL (decl
) = ctor
;
509 varpool_node::finalize_decl (decl
);
511 /* Save the VAR_DECL into the hash table. */
512 decl_for_type_insert (type
, decl
);
514 return build_fold_addr_expr (decl
);
517 /* Create a structure for the ubsan library. NAME is a name of the new
518 structure. LOCCNT is number of locations, PLOC points to array of
519 locations. The arguments in ... are of __ubsan_type_descriptor type
520 and there are at most two of them, followed by NULL_TREE, followed
521 by optional extra arguments and another NULL_TREE. */
524 ubsan_create_data (const char *name
, int loccnt
, const location_t
*ploc
, ...)
529 vec
<tree
, va_gc
> *saved_args
= NULL
;
533 /* Firstly, create a pointer to type descriptor type. */
534 tree td_type
= ubsan_get_type_descriptor_type ();
535 td_type
= build_pointer_type (td_type
);
537 /* Create the structure type. */
538 ret
= make_node (RECORD_TYPE
);
539 for (j
= 0; j
< loccnt
; j
++)
541 gcc_checking_assert (i
< 2);
542 fields
[i
] = build_decl (UNKNOWN_LOCATION
, FIELD_DECL
, NULL_TREE
,
543 ubsan_get_source_location_type ());
544 DECL_CONTEXT (fields
[i
]) = ret
;
546 DECL_CHAIN (fields
[i
- 1]) = fields
[i
];
550 va_start (args
, ploc
);
551 for (t
= va_arg (args
, tree
); t
!= NULL_TREE
;
552 i
++, t
= va_arg (args
, tree
))
554 gcc_checking_assert (i
< 4);
555 /* Save the tree arguments for later use. */
556 vec_safe_push (saved_args
, t
);
557 fields
[i
] = build_decl (UNKNOWN_LOCATION
, FIELD_DECL
, NULL_TREE
,
559 DECL_CONTEXT (fields
[i
]) = ret
;
561 DECL_CHAIN (fields
[i
- 1]) = fields
[i
];
564 for (t
= va_arg (args
, tree
); t
!= NULL_TREE
;
565 i
++, t
= va_arg (args
, tree
))
567 gcc_checking_assert (i
< 6);
568 /* Save the tree arguments for later use. */
569 vec_safe_push (saved_args
, t
);
570 fields
[i
] = build_decl (UNKNOWN_LOCATION
, FIELD_DECL
, NULL_TREE
,
572 DECL_CONTEXT (fields
[i
]) = ret
;
574 DECL_CHAIN (fields
[i
- 1]) = fields
[i
];
578 tree type_decl
= build_decl (input_location
, TYPE_DECL
,
579 get_identifier (name
), ret
);
580 DECL_IGNORED_P (type_decl
) = 1;
581 DECL_ARTIFICIAL (type_decl
) = 1;
582 TYPE_FIELDS (ret
) = fields
[0];
583 TYPE_NAME (ret
) = type_decl
;
584 TYPE_STUB_DECL (ret
) = type_decl
;
587 /* Now, fill in the type. */
589 static unsigned int ubsan_var_id_num
;
590 ASM_GENERATE_INTERNAL_LABEL (tmp_name
, "Lubsan_data", ubsan_var_id_num
++);
591 tree var
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
, get_identifier (tmp_name
),
593 TREE_STATIC (var
) = 1;
594 TREE_PUBLIC (var
) = 0;
595 DECL_ARTIFICIAL (var
) = 1;
596 DECL_IGNORED_P (var
) = 1;
597 DECL_EXTERNAL (var
) = 0;
599 vec
<constructor_elt
, va_gc
> *v
;
601 tree ctor
= build_constructor (ret
, v
);
603 /* If desirable, set the __ubsan_source_location element. */
604 for (j
= 0; j
< loccnt
; j
++)
606 location_t loc
= LOCATION_LOCUS (ploc
[j
]);
607 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, ubsan_source_location (loc
));
610 size_t nelts
= vec_safe_length (saved_args
);
611 for (i
= 0; i
< nelts
; i
++)
613 t
= (*saved_args
)[i
];
614 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, t
);
617 TREE_CONSTANT (ctor
) = 1;
618 TREE_STATIC (ctor
) = 1;
619 DECL_INITIAL (var
) = ctor
;
620 varpool_node::finalize_decl (var
);
625 /* Instrument the __builtin_unreachable call. We just call the libubsan
629 ubsan_instrument_unreachable (gimple_stmt_iterator
*gsi
)
632 location_t loc
= gimple_location (gsi_stmt (*gsi
));
634 if (flag_sanitize_undefined_trap_on_error
)
635 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
638 tree data
= ubsan_create_data ("__ubsan_unreachable_data", 1, &loc
,
639 NULL_TREE
, NULL_TREE
);
640 data
= build_fold_addr_expr_loc (loc
, data
);
642 = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE
);
643 g
= gimple_build_call (fn
, 1, data
);
645 gimple_set_location (g
, loc
);
646 gsi_replace (gsi
, g
, false);
650 /* Return true if T is a call to a libubsan routine. */
653 is_ubsan_builtin_p (tree t
)
655 return TREE_CODE (t
) == FUNCTION_DECL
656 && strncmp (IDENTIFIER_POINTER (DECL_NAME (t
)),
657 "__builtin___ubsan_", 18) == 0;
660 /* Expand the UBSAN_BOUNDS special builtin function. */
663 ubsan_expand_bounds_ifn (gimple_stmt_iterator
*gsi
)
665 gimple stmt
= gsi_stmt (*gsi
);
666 location_t loc
= gimple_location (stmt
);
667 gcc_assert (gimple_call_num_args (stmt
) == 3);
669 /* Pick up the arguments of the UBSAN_BOUNDS call. */
670 tree type
= TREE_TYPE (TREE_TYPE (gimple_call_arg (stmt
, 0)));
671 tree index
= gimple_call_arg (stmt
, 1);
672 tree orig_index_type
= TREE_TYPE (index
);
673 tree bound
= gimple_call_arg (stmt
, 2);
675 gimple_stmt_iterator gsi_orig
= *gsi
;
677 /* Create condition "if (index > bound)". */
678 basic_block then_bb
, fallthru_bb
;
679 gimple_stmt_iterator cond_insert_point
680 = create_cond_insert_point (gsi
, false, false, true,
681 &then_bb
, &fallthru_bb
);
682 index
= fold_convert (TREE_TYPE (bound
), index
);
683 index
= force_gimple_operand_gsi (&cond_insert_point
, index
,
685 false, GSI_NEW_STMT
);
686 gimple g
= gimple_build_cond (GT_EXPR
, index
, bound
, NULL_TREE
, NULL_TREE
);
687 gimple_set_location (g
, loc
);
688 gsi_insert_after (&cond_insert_point
, g
, GSI_NEW_STMT
);
690 /* Generate __ubsan_handle_out_of_bounds call. */
691 *gsi
= gsi_after_labels (then_bb
);
692 if (flag_sanitize_undefined_trap_on_error
)
693 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
697 = ubsan_create_data ("__ubsan_out_of_bounds_data", 1, &loc
,
698 ubsan_type_descriptor (type
, UBSAN_PRINT_ARRAY
),
699 ubsan_type_descriptor (orig_index_type
),
700 NULL_TREE
, NULL_TREE
);
701 data
= build_fold_addr_expr_loc (loc
, data
);
702 enum built_in_function bcode
703 = (flag_sanitize_recover
& SANITIZE_BOUNDS
)
704 ? BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS
705 : BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS_ABORT
;
706 tree fn
= builtin_decl_explicit (bcode
);
707 tree val
= force_gimple_operand_gsi (gsi
, ubsan_encode_value (index
),
708 true, NULL_TREE
, true,
710 g
= gimple_build_call (fn
, 2, data
, val
);
712 gimple_set_location (g
, loc
);
713 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
715 /* Get rid of the UBSAN_BOUNDS call from the IR. */
716 unlink_stmt_vdef (stmt
);
717 gsi_remove (&gsi_orig
, true);
719 /* Point GSI to next logical statement. */
720 *gsi
= gsi_start_bb (fallthru_bb
);
724 /* Expand UBSAN_NULL internal call. The type is kept on the ckind
725 argument which is a constant, because the middle-end treats pointer
726 conversions as useless and therefore the type of the first argument
727 could be changed to any other pointer type. */
730 ubsan_expand_null_ifn (gimple_stmt_iterator
*gsip
)
732 gimple_stmt_iterator gsi
= *gsip
;
733 gimple stmt
= gsi_stmt (gsi
);
734 location_t loc
= gimple_location (stmt
);
735 gcc_assert (gimple_call_num_args (stmt
) == 3);
736 tree ptr
= gimple_call_arg (stmt
, 0);
737 tree ckind
= gimple_call_arg (stmt
, 1);
738 tree align
= gimple_call_arg (stmt
, 2);
739 tree check_align
= NULL_TREE
;
742 basic_block cur_bb
= gsi_bb (gsi
);
745 if (!integer_zerop (align
))
747 unsigned int ptralign
= get_pointer_alignment (ptr
) / BITS_PER_UNIT
;
748 if (compare_tree_int (align
, ptralign
) == 1)
750 check_align
= make_ssa_name (pointer_sized_int_node
);
751 g
= gimple_build_assign_with_ops (NOP_EXPR
, check_align
, ptr
);
752 gimple_set_location (g
, loc
);
753 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
756 check_null
= (flag_sanitize
& SANITIZE_NULL
) != 0;
758 if (check_align
== NULL_TREE
&& !check_null
)
760 gsi_remove (gsip
, true);
761 /* Unlink the UBSAN_NULLs vops before replacing it. */
762 unlink_stmt_vdef (stmt
);
766 /* Split the original block holding the pointer dereference. */
767 edge e
= split_block (cur_bb
, stmt
);
769 /* Get a hold on the 'condition block', the 'then block' and the
771 basic_block cond_bb
= e
->src
;
772 basic_block fallthru_bb
= e
->dest
;
773 basic_block then_bb
= create_empty_bb (cond_bb
);
774 add_bb_to_loop (then_bb
, cond_bb
->loop_father
);
775 loops_state_set (LOOPS_NEED_FIXUP
);
777 /* Make an edge coming from the 'cond block' into the 'then block';
778 this edge is unlikely taken, so set up the probability accordingly. */
779 e
= make_edge (cond_bb
, then_bb
, EDGE_TRUE_VALUE
);
780 e
->probability
= PROB_VERY_UNLIKELY
;
782 /* Connect 'then block' with the 'else block'. This is needed
783 as the ubsan routines we call in the 'then block' are not noreturn.
784 The 'then block' only has one outcoming edge. */
785 make_single_succ_edge (then_bb
, fallthru_bb
, EDGE_FALLTHRU
);
787 /* Set up the fallthrough basic block. */
788 e
= find_edge (cond_bb
, fallthru_bb
);
789 e
->flags
= EDGE_FALSE_VALUE
;
790 e
->count
= cond_bb
->count
;
791 e
->probability
= REG_BR_PROB_BASE
- PROB_VERY_UNLIKELY
;
793 /* Update dominance info for the newly created then_bb; note that
794 fallthru_bb's dominance info has already been updated by
796 if (dom_info_available_p (CDI_DOMINATORS
))
797 set_immediate_dominator (CDI_DOMINATORS
, then_bb
, cond_bb
);
799 /* Put the ubsan builtin call into the newly created BB. */
800 if (flag_sanitize_undefined_trap_on_error
)
801 g
= gimple_build_call (builtin_decl_implicit (BUILT_IN_TRAP
), 0);
804 enum built_in_function bcode
805 = (flag_sanitize_recover
& ((check_align
? SANITIZE_ALIGNMENT
: 0)
806 | (check_null
? SANITIZE_NULL
: 0)))
807 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
808 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT
;
809 tree fn
= builtin_decl_implicit (bcode
);
811 = ubsan_create_data ("__ubsan_null_data", 1, &loc
,
812 ubsan_type_descriptor (TREE_TYPE (ckind
),
813 UBSAN_PRINT_POINTER
),
816 fold_convert (unsigned_char_type_node
, ckind
),
818 data
= build_fold_addr_expr_loc (loc
, data
);
819 g
= gimple_build_call (fn
, 2, data
,
820 check_align
? check_align
821 : build_zero_cst (pointer_sized_int_node
));
823 gimple_stmt_iterator gsi2
= gsi_start_bb (then_bb
);
824 gimple_set_location (g
, loc
);
825 gsi_insert_after (&gsi2
, g
, GSI_NEW_STMT
);
827 /* Unlink the UBSAN_NULLs vops before replacing it. */
828 unlink_stmt_vdef (stmt
);
832 g
= gimple_build_cond (EQ_EXPR
, ptr
, build_int_cst (TREE_TYPE (ptr
), 0),
833 NULL_TREE
, NULL_TREE
);
834 gimple_set_location (g
, loc
);
836 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
837 gsi_replace (&gsi
, g
, false);
844 /* Split the block with the condition again. */
845 e
= split_block (cond_bb
, stmt
);
846 basic_block cond1_bb
= e
->src
;
847 basic_block cond2_bb
= e
->dest
;
849 /* Make an edge coming from the 'cond1 block' into the 'then block';
850 this edge is unlikely taken, so set up the probability
852 e
= make_edge (cond1_bb
, then_bb
, EDGE_TRUE_VALUE
);
853 e
->probability
= PROB_VERY_UNLIKELY
;
855 /* Set up the fallthrough basic block. */
856 e
= find_edge (cond1_bb
, cond2_bb
);
857 e
->flags
= EDGE_FALSE_VALUE
;
858 e
->count
= cond1_bb
->count
;
859 e
->probability
= REG_BR_PROB_BASE
- PROB_VERY_UNLIKELY
;
861 /* Update dominance info. */
862 if (dom_info_available_p (CDI_DOMINATORS
))
864 set_immediate_dominator (CDI_DOMINATORS
, fallthru_bb
, cond1_bb
);
865 set_immediate_dominator (CDI_DOMINATORS
, then_bb
, cond1_bb
);
868 gsi2
= gsi_start_bb (cond2_bb
);
871 tree mask
= build_int_cst (pointer_sized_int_node
,
872 tree_to_uhwi (align
) - 1);
873 g
= gimple_build_assign_with_ops (BIT_AND_EXPR
,
874 make_ssa_name (pointer_sized_int_node
),
876 gimple_set_location (g
, loc
);
878 gsi_insert_after (&gsi2
, g
, GSI_NEW_STMT
);
880 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
882 g
= gimple_build_cond (NE_EXPR
, gimple_assign_lhs (g
),
883 build_int_cst (pointer_sized_int_node
, 0),
884 NULL_TREE
, NULL_TREE
);
885 gimple_set_location (g
, loc
);
887 gsi_insert_after (&gsi2
, g
, GSI_NEW_STMT
);
889 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
890 gsi_replace (&gsi
, g
, false);
895 /* Expand UBSAN_OBJECT_SIZE internal call. */
898 ubsan_expand_objsize_ifn (gimple_stmt_iterator
*gsi
)
900 gimple stmt
= gsi_stmt (*gsi
);
901 location_t loc
= gimple_location (stmt
);
902 gcc_assert (gimple_call_num_args (stmt
) == 4);
904 tree ptr
= gimple_call_arg (stmt
, 0);
905 tree offset
= gimple_call_arg (stmt
, 1);
906 tree size
= gimple_call_arg (stmt
, 2);
907 tree ckind
= gimple_call_arg (stmt
, 3);
908 gimple_stmt_iterator gsi_orig
= *gsi
;
911 /* See if we can discard the check. */
912 if (TREE_CODE (size
) != INTEGER_CST
913 || integer_all_onesp (size
))
914 /* Yes, __builtin_object_size couldn't determine the
918 /* if (offset > objsize) */
919 basic_block then_bb
, fallthru_bb
;
920 gimple_stmt_iterator cond_insert_point
921 = create_cond_insert_point (gsi
, false, false, true,
922 &then_bb
, &fallthru_bb
);
923 g
= gimple_build_cond (GT_EXPR
, offset
, size
, NULL_TREE
, NULL_TREE
);
924 gimple_set_location (g
, loc
);
925 gsi_insert_after (&cond_insert_point
, g
, GSI_NEW_STMT
);
927 /* Generate __ubsan_handle_type_mismatch call. */
928 *gsi
= gsi_after_labels (then_bb
);
929 if (flag_sanitize_undefined_trap_on_error
)
930 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
934 = ubsan_create_data ("__ubsan_objsz_data", 1, &loc
,
935 ubsan_type_descriptor (TREE_TYPE (ptr
),
936 UBSAN_PRINT_POINTER
),
938 build_zero_cst (pointer_sized_int_node
),
941 data
= build_fold_addr_expr_loc (loc
, data
);
942 enum built_in_function bcode
943 = (flag_sanitize_recover
& SANITIZE_OBJECT_SIZE
)
944 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
945 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT
;
946 tree p
= make_ssa_name (pointer_sized_int_node
);
947 g
= gimple_build_assign_with_ops (NOP_EXPR
, p
, ptr
);
948 gimple_set_location (g
, loc
);
949 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
950 g
= gimple_build_call (builtin_decl_explicit (bcode
), 2, data
, p
);
952 gimple_set_location (g
, loc
);
953 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
955 /* Point GSI to next logical statement. */
956 *gsi
= gsi_start_bb (fallthru_bb
);
959 /* Get rid of the UBSAN_OBJECT_SIZE call from the IR. */
960 unlink_stmt_vdef (stmt
);
961 gsi_remove (&gsi_orig
, true);
962 return gsi_end_p (*gsi
);
965 /* Instrument a memory reference. BASE is the base of MEM, IS_LHS says
966 whether the pointer is on the left hand side of the assignment. */
969 instrument_mem_ref (tree mem
, tree base
, gimple_stmt_iterator
*iter
,
972 enum ubsan_null_ckind ikind
= is_lhs
? UBSAN_STORE_OF
: UBSAN_LOAD_OF
;
973 unsigned int align
= 0;
974 if (flag_sanitize
& SANITIZE_ALIGNMENT
)
976 align
= min_align_of_type (TREE_TYPE (base
));
980 if (align
== 0 && (flag_sanitize
& SANITIZE_NULL
) == 0)
982 tree t
= TREE_OPERAND (base
, 0);
983 if (!POINTER_TYPE_P (TREE_TYPE (t
)))
985 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (TREE_TYPE (t
))) && mem
!= base
)
986 ikind
= UBSAN_MEMBER_ACCESS
;
987 tree kind
= build_int_cst (TREE_TYPE (t
), ikind
);
988 tree alignt
= build_int_cst (pointer_sized_int_node
, align
);
989 gcall
*g
= gimple_build_call_internal (IFN_UBSAN_NULL
, 3, t
, kind
, alignt
);
990 gimple_set_location (g
, gimple_location (gsi_stmt (*iter
)));
991 gsi_insert_before (iter
, g
, GSI_SAME_STMT
);
994 /* Perform the pointer instrumentation. */
997 instrument_null (gimple_stmt_iterator gsi
, bool is_lhs
)
999 gimple stmt
= gsi_stmt (gsi
);
1000 tree t
= is_lhs
? gimple_get_lhs (stmt
) : gimple_assign_rhs1 (stmt
);
1001 tree base
= get_base_address (t
);
1002 const enum tree_code code
= TREE_CODE (base
);
1004 && TREE_CODE (TREE_OPERAND (base
, 0)) == SSA_NAME
)
1005 instrument_mem_ref (t
, base
, &gsi
, is_lhs
);
1008 /* Build an ubsan builtin call for the signed-integer-overflow
1009 sanitization. CODE says what kind of builtin are we building,
1010 LOC is a location, LHSTYPE is the type of LHS, OP0 and OP1
1011 are operands of the binary operation. */
1014 ubsan_build_overflow_builtin (tree_code code
, location_t loc
, tree lhstype
,
1017 if (flag_sanitize_undefined_trap_on_error
)
1018 return build_call_expr_loc (loc
, builtin_decl_explicit (BUILT_IN_TRAP
), 0);
1020 tree data
= ubsan_create_data ("__ubsan_overflow_data", 1, &loc
,
1021 ubsan_type_descriptor (lhstype
), NULL_TREE
,
1023 enum built_in_function fn_code
;
1028 fn_code
= (flag_sanitize_recover
& SANITIZE_SI_OVERFLOW
)
1029 ? BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW
1030 : BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW_ABORT
;
1033 fn_code
= (flag_sanitize_recover
& SANITIZE_SI_OVERFLOW
)
1034 ? BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW
1035 : BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW_ABORT
;
1038 fn_code
= (flag_sanitize_recover
& SANITIZE_SI_OVERFLOW
)
1039 ? BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW
1040 : BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW_ABORT
;
1043 fn_code
= (flag_sanitize_recover
& SANITIZE_SI_OVERFLOW
)
1044 ? BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW
1045 : BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW_ABORT
;
1050 tree fn
= builtin_decl_explicit (fn_code
);
1051 return build_call_expr_loc (loc
, fn
, 2 + (code
!= NEGATE_EXPR
),
1052 build_fold_addr_expr_loc (loc
, data
),
1053 ubsan_encode_value (op0
, true),
1054 op1
? ubsan_encode_value (op1
, true)
1058 /* Perform the signed integer instrumentation. GSI is the iterator
1059 pointing at statement we are trying to instrument. */
1062 instrument_si_overflow (gimple_stmt_iterator gsi
)
1064 gimple stmt
= gsi_stmt (gsi
);
1065 tree_code code
= gimple_assign_rhs_code (stmt
);
1066 tree lhs
= gimple_assign_lhs (stmt
);
1067 tree lhstype
= TREE_TYPE (lhs
);
1071 /* If this is not a signed operation, don't instrument anything here.
1072 Also punt on bit-fields. */
1073 if (!INTEGRAL_TYPE_P (lhstype
)
1074 || TYPE_OVERFLOW_WRAPS (lhstype
)
1075 || GET_MODE_BITSIZE (TYPE_MODE (lhstype
)) != TYPE_PRECISION (lhstype
))
1086 i = UBSAN_CHECK_{ADD,SUB,MUL} (u, 5); */
1087 a
= gimple_assign_rhs1 (stmt
);
1088 b
= gimple_assign_rhs2 (stmt
);
1089 g
= gimple_build_call_internal (code
== PLUS_EXPR
1090 ? IFN_UBSAN_CHECK_ADD
1091 : code
== MINUS_EXPR
1092 ? IFN_UBSAN_CHECK_SUB
1093 : IFN_UBSAN_CHECK_MUL
, 2, a
, b
);
1094 gimple_call_set_lhs (g
, lhs
);
1095 gsi_replace (&gsi
, g
, false);
1098 /* Represent i = -u;
1100 i = UBSAN_CHECK_SUB (0, u); */
1101 a
= build_int_cst (lhstype
, 0);
1102 b
= gimple_assign_rhs1 (stmt
);
1103 g
= gimple_build_call_internal (IFN_UBSAN_CHECK_SUB
, 2, a
, b
);
1104 gimple_call_set_lhs (g
, lhs
);
1105 gsi_replace (&gsi
, g
, false);
1108 /* Transform i = ABS_EXPR<u>;
1110 _N = UBSAN_CHECK_SUB (0, u);
1111 i = ABS_EXPR<_N>; */
1112 a
= build_int_cst (lhstype
, 0);
1113 b
= gimple_assign_rhs1 (stmt
);
1114 g
= gimple_build_call_internal (IFN_UBSAN_CHECK_SUB
, 2, a
, b
);
1115 a
= make_ssa_name (lhstype
);
1116 gimple_call_set_lhs (g
, a
);
1117 gimple_set_location (g
, gimple_location (stmt
));
1118 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
1119 gimple_assign_set_rhs1 (stmt
, a
);
1127 /* Instrument loads from (non-bitfield) bool and C++ enum values
1128 to check if the memory value is outside of the range of the valid
1132 instrument_bool_enum_load (gimple_stmt_iterator
*gsi
)
1134 gimple stmt
= gsi_stmt (*gsi
);
1135 tree rhs
= gimple_assign_rhs1 (stmt
);
1136 tree type
= TREE_TYPE (rhs
);
1137 tree minv
= NULL_TREE
, maxv
= NULL_TREE
;
1139 if (TREE_CODE (type
) == BOOLEAN_TYPE
&& (flag_sanitize
& SANITIZE_BOOL
))
1141 minv
= boolean_false_node
;
1142 maxv
= boolean_true_node
;
1144 else if (TREE_CODE (type
) == ENUMERAL_TYPE
1145 && (flag_sanitize
& SANITIZE_ENUM
)
1146 && TREE_TYPE (type
) != NULL_TREE
1147 && TREE_CODE (TREE_TYPE (type
)) == INTEGER_TYPE
1148 && (TYPE_PRECISION (TREE_TYPE (type
))
1149 < GET_MODE_PRECISION (TYPE_MODE (type
))))
1151 minv
= TYPE_MIN_VALUE (TREE_TYPE (type
));
1152 maxv
= TYPE_MAX_VALUE (TREE_TYPE (type
));
1157 int modebitsize
= GET_MODE_BITSIZE (TYPE_MODE (type
));
1158 HOST_WIDE_INT bitsize
, bitpos
;
1161 int volatilep
= 0, unsignedp
= 0;
1162 tree base
= get_inner_reference (rhs
, &bitsize
, &bitpos
, &offset
, &mode
,
1163 &unsignedp
, &volatilep
, false);
1164 tree utype
= build_nonstandard_integer_type (modebitsize
, 1);
1166 if ((TREE_CODE (base
) == VAR_DECL
&& DECL_HARD_REGISTER (base
))
1167 || (bitpos
% modebitsize
) != 0
1168 || bitsize
!= modebitsize
1169 || GET_MODE_BITSIZE (TYPE_MODE (utype
)) != modebitsize
1170 || TREE_CODE (gimple_assign_lhs (stmt
)) != SSA_NAME
)
1173 bool can_throw
= stmt_could_throw_p (stmt
);
1174 location_t loc
= gimple_location (stmt
);
1175 tree lhs
= gimple_assign_lhs (stmt
);
1176 tree ptype
= build_pointer_type (TREE_TYPE (rhs
));
1177 tree atype
= reference_alias_ptr_type (rhs
);
1178 gimple g
= gimple_build_assign (make_ssa_name (ptype
),
1179 build_fold_addr_expr (rhs
));
1180 gimple_set_location (g
, loc
);
1181 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1182 tree mem
= build2 (MEM_REF
, utype
, gimple_assign_lhs (g
),
1183 build_int_cst (atype
, 0));
1184 tree urhs
= make_ssa_name (utype
);
1187 gimple_assign_set_lhs (stmt
, urhs
);
1188 g
= gimple_build_assign_with_ops (NOP_EXPR
, lhs
, urhs
);
1189 gimple_set_location (g
, loc
);
1190 edge e
= find_fallthru_edge (gimple_bb (stmt
)->succs
);
1191 gsi_insert_on_edge_immediate (e
, g
);
1192 gimple_assign_set_rhs_from_tree (gsi
, mem
);
1194 *gsi
= gsi_for_stmt (g
);
1199 g
= gimple_build_assign (urhs
, mem
);
1200 gimple_set_location (g
, loc
);
1201 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1203 minv
= fold_convert (utype
, minv
);
1204 maxv
= fold_convert (utype
, maxv
);
1205 if (!integer_zerop (minv
))
1207 g
= gimple_build_assign_with_ops (MINUS_EXPR
, make_ssa_name (utype
),
1209 gimple_set_location (g
, loc
);
1210 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1213 gimple_stmt_iterator gsi2
= *gsi
;
1214 basic_block then_bb
, fallthru_bb
;
1215 *gsi
= create_cond_insert_point (gsi
, true, false, true,
1216 &then_bb
, &fallthru_bb
);
1217 g
= gimple_build_cond (GT_EXPR
, gimple_assign_lhs (g
),
1218 int_const_binop (MINUS_EXPR
, maxv
, minv
),
1219 NULL_TREE
, NULL_TREE
);
1220 gimple_set_location (g
, loc
);
1221 gsi_insert_after (gsi
, g
, GSI_NEW_STMT
);
1225 gimple_assign_set_rhs_with_ops (&gsi2
, NOP_EXPR
, urhs
);
1229 gsi2
= gsi_after_labels (then_bb
);
1230 if (flag_sanitize_undefined_trap_on_error
)
1231 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
1234 tree data
= ubsan_create_data ("__ubsan_invalid_value_data", 1, &loc
,
1235 ubsan_type_descriptor (type
), NULL_TREE
,
1237 data
= build_fold_addr_expr_loc (loc
, data
);
1238 enum built_in_function bcode
1239 = (flag_sanitize_recover
& (TREE_CODE (type
) == BOOLEAN_TYPE
1240 ? SANITIZE_BOOL
: SANITIZE_ENUM
))
1241 ? BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE
1242 : BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE_ABORT
;
1243 tree fn
= builtin_decl_explicit (bcode
);
1245 tree val
= force_gimple_operand_gsi (&gsi2
, ubsan_encode_value (urhs
),
1246 true, NULL_TREE
, true,
1248 g
= gimple_build_call (fn
, 2, data
, val
);
1250 gimple_set_location (g
, loc
);
1251 gsi_insert_before (&gsi2
, g
, GSI_SAME_STMT
);
1252 *gsi
= gsi_for_stmt (stmt
);
1255 /* Instrument float point-to-integer conversion. TYPE is an integer type of
1256 destination, EXPR is floating-point expression. */
1259 ubsan_instrument_float_cast (location_t loc
, tree type
, tree expr
)
1261 tree expr_type
= TREE_TYPE (expr
);
1262 tree t
, tt
, fn
, min
, max
;
1263 machine_mode mode
= TYPE_MODE (expr_type
);
1264 int prec
= TYPE_PRECISION (type
);
1265 bool uns_p
= TYPE_UNSIGNED (type
);
1267 /* Float to integer conversion first truncates toward zero, so
1268 even signed char c = 127.875f; is not problematic.
1269 Therefore, we should complain only if EXPR is unordered or smaller
1270 or equal than TYPE_MIN_VALUE - 1.0 or greater or equal than
1271 TYPE_MAX_VALUE + 1.0. */
1272 if (REAL_MODE_FORMAT (mode
)->b
== 2)
1274 /* For maximum, TYPE_MAX_VALUE might not be representable
1275 in EXPR_TYPE, e.g. if TYPE is 64-bit long long and
1276 EXPR_TYPE is IEEE single float, but TYPE_MAX_VALUE + 1.0 is
1277 either representable or infinity. */
1278 REAL_VALUE_TYPE maxval
= dconst1
;
1279 SET_REAL_EXP (&maxval
, REAL_EXP (&maxval
) + prec
- !uns_p
);
1280 real_convert (&maxval
, mode
, &maxval
);
1281 max
= build_real (expr_type
, maxval
);
1283 /* For unsigned, assume -1.0 is always representable. */
1285 min
= build_minus_one_cst (expr_type
);
1288 /* TYPE_MIN_VALUE is generally representable (or -inf),
1289 but TYPE_MIN_VALUE - 1.0 might not be. */
1290 REAL_VALUE_TYPE minval
= dconstm1
, minval2
;
1291 SET_REAL_EXP (&minval
, REAL_EXP (&minval
) + prec
- 1);
1292 real_convert (&minval
, mode
, &minval
);
1293 real_arithmetic (&minval2
, MINUS_EXPR
, &minval
, &dconst1
);
1294 real_convert (&minval2
, mode
, &minval2
);
1295 if (real_compare (EQ_EXPR
, &minval
, &minval2
)
1296 && !real_isinf (&minval
))
1298 /* If TYPE_MIN_VALUE - 1.0 is not representable and
1299 rounds to TYPE_MIN_VALUE, we need to subtract
1300 more. As REAL_MODE_FORMAT (mode)->p is the number
1301 of base digits, we want to subtract a number that
1302 will be 1 << (REAL_MODE_FORMAT (mode)->p - 1)
1303 times smaller than minval. */
1305 gcc_assert (prec
> REAL_MODE_FORMAT (mode
)->p
);
1306 SET_REAL_EXP (&minval2
,
1307 REAL_EXP (&minval2
) + prec
- 1
1308 - REAL_MODE_FORMAT (mode
)->p
+ 1);
1309 real_arithmetic (&minval2
, MINUS_EXPR
, &minval
, &minval2
);
1310 real_convert (&minval2
, mode
, &minval2
);
1312 min
= build_real (expr_type
, minval2
);
1315 else if (REAL_MODE_FORMAT (mode
)->b
== 10)
1317 /* For _Decimal128 up to 34 decimal digits, - sign,
1318 dot, e, exponent. */
1321 int p
= REAL_MODE_FORMAT (mode
)->p
;
1322 REAL_VALUE_TYPE maxval
, minval
;
1324 /* Use mpfr_snprintf rounding to compute the smallest
1325 representable decimal number greater or equal than
1326 1 << (prec - !uns_p). */
1327 mpfr_init2 (m
, prec
+ 2);
1328 mpfr_set_ui_2exp (m
, 1, prec
- !uns_p
, GMP_RNDN
);
1329 mpfr_snprintf (buf
, sizeof buf
, "%.*RUe", p
- 1, m
);
1330 decimal_real_from_string (&maxval
, buf
);
1331 max
= build_real (expr_type
, maxval
);
1333 /* For unsigned, assume -1.0 is always representable. */
1335 min
= build_minus_one_cst (expr_type
);
1338 /* Use mpfr_snprintf rounding to compute the largest
1339 representable decimal number less or equal than
1340 (-1 << (prec - 1)) - 1. */
1341 mpfr_set_si_2exp (m
, -1, prec
- 1, GMP_RNDN
);
1342 mpfr_sub_ui (m
, m
, 1, GMP_RNDN
);
1343 mpfr_snprintf (buf
, sizeof buf
, "%.*RDe", p
- 1, m
);
1344 decimal_real_from_string (&minval
, buf
);
1345 min
= build_real (expr_type
, minval
);
1352 if (flag_sanitize_undefined_trap_on_error
)
1353 fn
= build_call_expr_loc (loc
, builtin_decl_explicit (BUILT_IN_TRAP
), 0);
1356 /* Create the __ubsan_handle_float_cast_overflow fn call. */
1357 tree data
= ubsan_create_data ("__ubsan_float_cast_overflow_data", 0,
1358 NULL
, ubsan_type_descriptor (expr_type
),
1359 ubsan_type_descriptor (type
), NULL_TREE
,
1361 enum built_in_function bcode
1362 = (flag_sanitize_recover
& SANITIZE_FLOAT_CAST
)
1363 ? BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW
1364 : BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW_ABORT
;
1365 fn
= builtin_decl_explicit (bcode
);
1366 fn
= build_call_expr_loc (loc
, fn
, 2,
1367 build_fold_addr_expr_loc (loc
, data
),
1368 ubsan_encode_value (expr
, false));
1371 t
= fold_build2 (UNLE_EXPR
, boolean_type_node
, expr
, min
);
1372 tt
= fold_build2 (UNGE_EXPR
, boolean_type_node
, expr
, max
);
1373 return fold_build3 (COND_EXPR
, void_type_node
,
1374 fold_build2 (TRUTH_OR_EXPR
, boolean_type_node
, t
, tt
),
1375 fn
, integer_zero_node
);
1378 /* Instrument values passed to function arguments with nonnull attribute. */
1381 instrument_nonnull_arg (gimple_stmt_iterator
*gsi
)
1383 gimple stmt
= gsi_stmt (*gsi
);
1385 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
1386 while for nonnull sanitization it is clear. */
1387 int save_flag_delete_null_pointer_checks
= flag_delete_null_pointer_checks
;
1388 flag_delete_null_pointer_checks
= 1;
1389 loc
[0] = gimple_location (stmt
);
1390 loc
[1] = UNKNOWN_LOCATION
;
1391 for (unsigned int i
= 0; i
< gimple_call_num_args (stmt
); i
++)
1393 tree arg
= gimple_call_arg (stmt
, i
);
1394 if (POINTER_TYPE_P (TREE_TYPE (arg
))
1395 && infer_nonnull_range (stmt
, arg
, false, true))
1398 if (!is_gimple_val (arg
))
1400 g
= gimple_build_assign (make_ssa_name (TREE_TYPE (arg
)), arg
);
1401 gimple_set_location (g
, loc
[0]);
1402 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1403 arg
= gimple_assign_lhs (g
);
1406 basic_block then_bb
, fallthru_bb
;
1407 *gsi
= create_cond_insert_point (gsi
, true, false, true,
1408 &then_bb
, &fallthru_bb
);
1409 g
= gimple_build_cond (EQ_EXPR
, arg
,
1410 build_zero_cst (TREE_TYPE (arg
)),
1411 NULL_TREE
, NULL_TREE
);
1412 gimple_set_location (g
, loc
[0]);
1413 gsi_insert_after (gsi
, g
, GSI_NEW_STMT
);
1415 *gsi
= gsi_after_labels (then_bb
);
1416 if (flag_sanitize_undefined_trap_on_error
)
1417 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
1420 tree data
= ubsan_create_data ("__ubsan_nonnull_arg_data",
1422 build_int_cst (integer_type_node
,
1425 data
= build_fold_addr_expr_loc (loc
[0], data
);
1426 enum built_in_function bcode
1427 = (flag_sanitize_recover
& SANITIZE_NONNULL_ATTRIBUTE
)
1428 ? BUILT_IN_UBSAN_HANDLE_NONNULL_ARG
1429 : BUILT_IN_UBSAN_HANDLE_NONNULL_ARG_ABORT
;
1430 tree fn
= builtin_decl_explicit (bcode
);
1432 g
= gimple_build_call (fn
, 1, data
);
1434 gimple_set_location (g
, loc
[0]);
1435 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1437 *gsi
= gsi_for_stmt (stmt
);
1439 flag_delete_null_pointer_checks
= save_flag_delete_null_pointer_checks
;
1442 /* Instrument returns in functions with returns_nonnull attribute. */
1445 instrument_nonnull_return (gimple_stmt_iterator
*gsi
)
1447 greturn
*stmt
= as_a
<greturn
*> (gsi_stmt (*gsi
));
1449 tree arg
= gimple_return_retval (stmt
);
1450 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
1451 while for nonnull return sanitization it is clear. */
1452 int save_flag_delete_null_pointer_checks
= flag_delete_null_pointer_checks
;
1453 flag_delete_null_pointer_checks
= 1;
1454 loc
[0] = gimple_location (stmt
);
1455 loc
[1] = UNKNOWN_LOCATION
;
1457 && POINTER_TYPE_P (TREE_TYPE (arg
))
1458 && is_gimple_val (arg
)
1459 && infer_nonnull_range (stmt
, arg
, false, true))
1461 basic_block then_bb
, fallthru_bb
;
1462 *gsi
= create_cond_insert_point (gsi
, true, false, true,
1463 &then_bb
, &fallthru_bb
);
1464 gimple g
= gimple_build_cond (EQ_EXPR
, arg
,
1465 build_zero_cst (TREE_TYPE (arg
)),
1466 NULL_TREE
, NULL_TREE
);
1467 gimple_set_location (g
, loc
[0]);
1468 gsi_insert_after (gsi
, g
, GSI_NEW_STMT
);
1470 *gsi
= gsi_after_labels (then_bb
);
1471 if (flag_sanitize_undefined_trap_on_error
)
1472 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
1475 tree data
= ubsan_create_data ("__ubsan_nonnull_return_data",
1476 2, loc
, NULL_TREE
, NULL_TREE
);
1477 data
= build_fold_addr_expr_loc (loc
[0], data
);
1478 enum built_in_function bcode
1479 = (flag_sanitize_recover
& SANITIZE_RETURNS_NONNULL_ATTRIBUTE
)
1480 ? BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN
1481 : BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_ABORT
;
1482 tree fn
= builtin_decl_explicit (bcode
);
1484 g
= gimple_build_call (fn
, 1, data
);
1486 gimple_set_location (g
, loc
[0]);
1487 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1488 *gsi
= gsi_for_stmt (stmt
);
1490 flag_delete_null_pointer_checks
= save_flag_delete_null_pointer_checks
;
1493 /* Instrument memory references. Here we check whether the pointer
1494 points to an out-of-bounds location. */
1497 instrument_object_size (gimple_stmt_iterator
*gsi
, bool is_lhs
)
1499 gimple stmt
= gsi_stmt (*gsi
);
1500 location_t loc
= gimple_location (stmt
);
1501 tree t
= is_lhs
? gimple_get_lhs (stmt
) : gimple_assign_rhs1 (stmt
);
1503 tree index
= NULL_TREE
;
1504 HOST_WIDE_INT size_in_bytes
;
1506 type
= TREE_TYPE (t
);
1507 if (VOID_TYPE_P (type
))
1510 switch (TREE_CODE (t
))
1513 if (TREE_CODE (t
) == COMPONENT_REF
1514 && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t
, 1)) != NULL_TREE
)
1516 tree repr
= DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t
, 1));
1517 t
= build3 (COMPONENT_REF
, TREE_TYPE (repr
), TREE_OPERAND (t
, 0),
1522 index
= TREE_OPERAND (t
, 1);
1534 size_in_bytes
= int_size_in_bytes (type
);
1535 if (size_in_bytes
<= 0)
1538 HOST_WIDE_INT bitsize
, bitpos
;
1541 int volatilep
= 0, unsignedp
= 0;
1542 tree inner
= get_inner_reference (t
, &bitsize
, &bitpos
, &offset
, &mode
,
1543 &unsignedp
, &volatilep
, false);
1545 if (bitpos
% BITS_PER_UNIT
!= 0
1546 || bitsize
!= size_in_bytes
* BITS_PER_UNIT
)
1549 bool decl_p
= DECL_P (inner
);
1553 else if (TREE_CODE (inner
) == MEM_REF
)
1554 base
= TREE_OPERAND (inner
, 0);
1557 tree ptr
= build1 (ADDR_EXPR
, build_pointer_type (TREE_TYPE (t
)), t
);
1559 while (TREE_CODE (base
) == SSA_NAME
)
1561 gimple def_stmt
= SSA_NAME_DEF_STMT (base
);
1562 if (gimple_assign_ssa_name_copy_p (def_stmt
)
1563 || (gimple_assign_cast_p (def_stmt
)
1564 && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (def_stmt
))))
1565 || (is_gimple_assign (def_stmt
)
1566 && gimple_assign_rhs_code (def_stmt
) == POINTER_PLUS_EXPR
))
1567 base
= gimple_assign_rhs1 (def_stmt
);
1572 if (!POINTER_TYPE_P (TREE_TYPE (base
)) && !DECL_P (base
))
1576 tree base_addr
= base
;
1578 base_addr
= build1 (ADDR_EXPR
,
1579 build_pointer_type (TREE_TYPE (base
)), base
);
1580 unsigned HOST_WIDE_INT size
= compute_builtin_object_size (base_addr
, 0);
1581 if (size
!= (unsigned HOST_WIDE_INT
) -1)
1582 sizet
= build_int_cst (sizetype
, size
);
1585 if (LOCATION_LOCUS (loc
) == UNKNOWN_LOCATION
)
1586 loc
= input_location
;
1587 /* Generate __builtin_object_size call. */
1588 sizet
= builtin_decl_explicit (BUILT_IN_OBJECT_SIZE
);
1589 sizet
= build_call_expr_loc (loc
, sizet
, 2, base_addr
,
1591 sizet
= force_gimple_operand_gsi (gsi
, sizet
, false, NULL_TREE
, true,
1597 /* Generate UBSAN_OBJECT_SIZE (ptr, ptr+sizeof(*ptr)-base, objsize, ckind)
1599 /* ptr + sizeof (*ptr) - base */
1600 t
= fold_build2 (MINUS_EXPR
, sizetype
,
1601 fold_convert (pointer_sized_int_node
, ptr
),
1602 fold_convert (pointer_sized_int_node
, base_addr
));
1603 t
= fold_build2 (PLUS_EXPR
, sizetype
, t
, TYPE_SIZE_UNIT (type
));
1605 /* Perhaps we can omit the check. */
1606 if (TREE_CODE (t
) == INTEGER_CST
1607 && TREE_CODE (sizet
) == INTEGER_CST
1608 && tree_int_cst_le (t
, sizet
))
1611 if (index
!= NULL_TREE
1612 && TREE_CODE (index
) == SSA_NAME
1613 && TREE_CODE (sizet
) == INTEGER_CST
)
1615 gimple def
= SSA_NAME_DEF_STMT (index
);
1616 if (is_gimple_assign (def
)
1617 && gimple_assign_rhs_code (def
) == BIT_AND_EXPR
1618 && TREE_CODE (gimple_assign_rhs2 (def
)) == INTEGER_CST
)
1620 tree cst
= gimple_assign_rhs2 (def
);
1621 tree sz
= fold_build2 (EXACT_DIV_EXPR
, sizetype
, sizet
,
1622 TYPE_SIZE_UNIT (type
));
1623 if (tree_int_cst_sgn (cst
) >= 0
1624 && tree_int_cst_lt (cst
, sz
))
1629 /* Nope. Emit the check. */
1630 t
= force_gimple_operand_gsi (gsi
, t
, true, NULL_TREE
, true,
1632 ptr
= force_gimple_operand_gsi (gsi
, ptr
, true, NULL_TREE
, true,
1634 tree ckind
= build_int_cst (unsigned_char_type_node
,
1635 is_lhs
? UBSAN_STORE_OF
: UBSAN_LOAD_OF
);
1636 gimple g
= gimple_build_call_internal (IFN_UBSAN_OBJECT_SIZE
, 4,
1637 ptr
, t
, sizet
, ckind
);
1638 gimple_set_location (g
, loc
);
1639 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1644 const pass_data pass_data_ubsan
=
1646 GIMPLE_PASS
, /* type */
1648 OPTGROUP_NONE
, /* optinfo_flags */
1649 TV_TREE_UBSAN
, /* tv_id */
1650 ( PROP_cfg
| PROP_ssa
), /* properties_required */
1651 0, /* properties_provided */
1652 0, /* properties_destroyed */
1653 0, /* todo_flags_start */
1654 TODO_update_ssa
, /* todo_flags_finish */
1657 class pass_ubsan
: public gimple_opt_pass
1660 pass_ubsan (gcc::context
*ctxt
)
1661 : gimple_opt_pass (pass_data_ubsan
, ctxt
)
1664 /* opt_pass methods: */
1665 virtual bool gate (function
*)
1667 return flag_sanitize
& (SANITIZE_NULL
| SANITIZE_SI_OVERFLOW
1668 | SANITIZE_BOOL
| SANITIZE_ENUM
1669 | SANITIZE_ALIGNMENT
1670 | SANITIZE_NONNULL_ATTRIBUTE
1671 | SANITIZE_RETURNS_NONNULL_ATTRIBUTE
1672 | SANITIZE_OBJECT_SIZE
)
1673 && current_function_decl
!= NULL_TREE
1674 && !lookup_attribute ("no_sanitize_undefined",
1675 DECL_ATTRIBUTES (current_function_decl
));
1678 virtual unsigned int execute (function
*);
1680 }; // class pass_ubsan
1683 pass_ubsan::execute (function
*fun
)
1686 gimple_stmt_iterator gsi
;
1688 initialize_sanitizer_builtins ();
1690 FOR_EACH_BB_FN (bb
, fun
)
1692 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
);)
1694 gimple stmt
= gsi_stmt (gsi
);
1695 if (is_gimple_debug (stmt
) || gimple_clobber_p (stmt
))
1701 if ((flag_sanitize
& SANITIZE_SI_OVERFLOW
)
1702 && is_gimple_assign (stmt
))
1703 instrument_si_overflow (gsi
);
1705 if (flag_sanitize
& (SANITIZE_NULL
| SANITIZE_ALIGNMENT
))
1707 if (gimple_store_p (stmt
))
1708 instrument_null (gsi
, true);
1709 if (gimple_assign_load_p (stmt
))
1710 instrument_null (gsi
, false);
1713 if (flag_sanitize
& (SANITIZE_BOOL
| SANITIZE_ENUM
)
1714 && gimple_assign_load_p (stmt
))
1716 instrument_bool_enum_load (&gsi
);
1717 bb
= gimple_bb (stmt
);
1720 if ((flag_sanitize
& SANITIZE_NONNULL_ATTRIBUTE
)
1721 && is_gimple_call (stmt
)
1722 && !gimple_call_internal_p (stmt
))
1724 instrument_nonnull_arg (&gsi
);
1725 bb
= gimple_bb (stmt
);
1728 if ((flag_sanitize
& SANITIZE_RETURNS_NONNULL_ATTRIBUTE
)
1729 && gimple_code (stmt
) == GIMPLE_RETURN
)
1731 instrument_nonnull_return (&gsi
);
1732 bb
= gimple_bb (stmt
);
1735 if (flag_sanitize
& SANITIZE_OBJECT_SIZE
)
1737 if (gimple_store_p (stmt
))
1738 instrument_object_size (&gsi
, true);
1739 if (gimple_assign_load_p (stmt
))
1740 instrument_object_size (&gsi
, false);
1752 make_pass_ubsan (gcc::context
*ctxt
)
1754 return new pass_ubsan (ctxt
);
1757 #include "gt-ubsan.h"