PR sanitizer/81604
[official-gcc.git] / gcc / ubsan.c
blob2580a58b6ebe0257ba1ad58efb9b78a2d1df501f
1 /* UndefinedBehaviorSanitizer, undefined behavior detector.
2 Copyright (C) 2013-2017 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
10 version.
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
15 for more details.
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/>. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "backend.h"
25 #include "rtl.h"
26 #include "c-family/c-common.h"
27 #include "gimple.h"
28 #include "cfghooks.h"
29 #include "tree-pass.h"
30 #include "memmodel.h"
31 #include "tm_p.h"
32 #include "ssa.h"
33 #include "cgraph.h"
34 #include "tree-pretty-print.h"
35 #include "stor-layout.h"
36 #include "cfganal.h"
37 #include "gimple-iterator.h"
38 #include "output.h"
39 #include "cfgloop.h"
40 #include "ubsan.h"
41 #include "expr.h"
42 #include "asan.h"
43 #include "gimplify-me.h"
44 #include "dfp.h"
45 #include "builtins.h"
46 #include "tree-object-size.h"
47 #include "tree-cfg.h"
48 #include "gimple-fold.h"
49 #include "varasm.h"
51 /* Map from a tree to a VAR_DECL tree. */
53 struct GTY((for_user)) tree_type_map {
54 struct tree_map_base type;
55 tree decl;
58 struct tree_type_map_cache_hasher : ggc_cache_ptr_hash<tree_type_map>
60 static inline hashval_t
61 hash (tree_type_map *t)
63 return TYPE_UID (t->type.from);
66 static inline bool
67 equal (tree_type_map *a, tree_type_map *b)
69 return a->type.from == b->type.from;
72 static int
73 keep_cache_entry (tree_type_map *&m)
75 return ggc_marked_p (m->type.from);
79 static GTY ((cache))
80 hash_table<tree_type_map_cache_hasher> *decl_tree_for_type;
82 /* Lookup a VAR_DECL for TYPE, and return it if we find one. */
84 static tree
85 decl_for_type_lookup (tree type)
87 /* If the hash table is not initialized yet, create it now. */
88 if (decl_tree_for_type == NULL)
90 decl_tree_for_type
91 = hash_table<tree_type_map_cache_hasher>::create_ggc (10);
92 /* That also means we don't have to bother with the lookup. */
93 return NULL_TREE;
96 struct tree_type_map *h, in;
97 in.type.from = type;
99 h = decl_tree_for_type->find_with_hash (&in, TYPE_UID (type));
100 return h ? h->decl : NULL_TREE;
103 /* Insert a mapping TYPE->DECL in the VAR_DECL for type hashtable. */
105 static void
106 decl_for_type_insert (tree type, tree decl)
108 struct tree_type_map *h;
110 h = ggc_alloc<tree_type_map> ();
111 h->type.from = type;
112 h->decl = decl;
113 *decl_tree_for_type->find_slot_with_hash (h, TYPE_UID (type), INSERT) = h;
116 /* Helper routine, which encodes a value in the pointer_sized_int_node.
117 Arguments with precision <= POINTER_SIZE are passed directly,
118 the rest is passed by reference. T is a value we are to encode.
119 PHASE determines when this function is called. */
121 tree
122 ubsan_encode_value (tree t, enum ubsan_encode_value_phase phase)
124 tree type = TREE_TYPE (t);
125 const unsigned int bitsize = GET_MODE_BITSIZE (TYPE_MODE (type));
126 if (bitsize <= POINTER_SIZE)
127 switch (TREE_CODE (type))
129 case BOOLEAN_TYPE:
130 case ENUMERAL_TYPE:
131 case INTEGER_TYPE:
132 return fold_build1 (NOP_EXPR, pointer_sized_int_node, t);
133 case REAL_TYPE:
135 tree itype = build_nonstandard_integer_type (bitsize, true);
136 t = fold_build1 (VIEW_CONVERT_EXPR, itype, t);
137 return fold_convert (pointer_sized_int_node, t);
139 default:
140 gcc_unreachable ();
142 else
144 if (!DECL_P (t) || !TREE_ADDRESSABLE (t))
146 /* The reason for this is that we don't want to pessimize
147 code by making vars unnecessarily addressable. */
148 tree var;
149 if (phase != UBSAN_ENCODE_VALUE_GENERIC)
151 var = create_tmp_var (type);
152 mark_addressable (var);
154 else
156 var = create_tmp_var_raw (type);
157 TREE_ADDRESSABLE (var) = 1;
158 DECL_CONTEXT (var) = current_function_decl;
160 if (phase == UBSAN_ENCODE_VALUE_RTL)
162 rtx mem
163 = assign_stack_temp_for_type (TYPE_MODE (type),
164 GET_MODE_SIZE (TYPE_MODE (type)),
165 type);
166 SET_DECL_RTL (var, mem);
167 expand_assignment (var, t, false);
168 return build_fold_addr_expr (var);
170 if (phase != UBSAN_ENCODE_VALUE_GENERIC)
172 tree tem = build2 (MODIFY_EXPR, void_type_node, var, t);
173 t = build_fold_addr_expr (var);
174 return build2 (COMPOUND_EXPR, TREE_TYPE (t), tem, t);
176 else
178 var = build4 (TARGET_EXPR, type, var, t, NULL_TREE, NULL_TREE);
179 return build_fold_addr_expr (var);
182 else
183 return build_fold_addr_expr (t);
187 /* Cached ubsan_get_type_descriptor_type () return value. */
188 static GTY(()) tree ubsan_type_descriptor_type;
190 /* Build
191 struct __ubsan_type_descriptor
193 unsigned short __typekind;
194 unsigned short __typeinfo;
195 char __typename[];
197 type. */
199 static tree
200 ubsan_get_type_descriptor_type (void)
202 static const char *field_names[3]
203 = { "__typekind", "__typeinfo", "__typename" };
204 tree fields[3], ret;
206 if (ubsan_type_descriptor_type)
207 return ubsan_type_descriptor_type;
209 tree itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
210 tree flex_arr_type = build_array_type (char_type_node, itype);
212 ret = make_node (RECORD_TYPE);
213 for (int i = 0; i < 3; i++)
215 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
216 get_identifier (field_names[i]),
217 (i == 2) ? flex_arr_type
218 : short_unsigned_type_node);
219 DECL_CONTEXT (fields[i]) = ret;
220 if (i)
221 DECL_CHAIN (fields[i - 1]) = fields[i];
223 tree type_decl = build_decl (input_location, TYPE_DECL,
224 get_identifier ("__ubsan_type_descriptor"),
225 ret);
226 DECL_IGNORED_P (type_decl) = 1;
227 DECL_ARTIFICIAL (type_decl) = 1;
228 TYPE_FIELDS (ret) = fields[0];
229 TYPE_NAME (ret) = type_decl;
230 TYPE_STUB_DECL (ret) = type_decl;
231 layout_type (ret);
232 ubsan_type_descriptor_type = ret;
233 return ret;
236 /* Cached ubsan_get_source_location_type () return value. */
237 static GTY(()) tree ubsan_source_location_type;
239 /* Build
240 struct __ubsan_source_location
242 const char *__filename;
243 unsigned int __line;
244 unsigned int __column;
246 type. */
248 tree
249 ubsan_get_source_location_type (void)
251 static const char *field_names[3]
252 = { "__filename", "__line", "__column" };
253 tree fields[3], ret;
254 if (ubsan_source_location_type)
255 return ubsan_source_location_type;
257 tree const_char_type = build_qualified_type (char_type_node,
258 TYPE_QUAL_CONST);
260 ret = make_node (RECORD_TYPE);
261 for (int i = 0; i < 3; i++)
263 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
264 get_identifier (field_names[i]),
265 (i == 0) ? build_pointer_type (const_char_type)
266 : unsigned_type_node);
267 DECL_CONTEXT (fields[i]) = ret;
268 if (i)
269 DECL_CHAIN (fields[i - 1]) = fields[i];
271 tree type_decl = build_decl (input_location, TYPE_DECL,
272 get_identifier ("__ubsan_source_location"),
273 ret);
274 DECL_IGNORED_P (type_decl) = 1;
275 DECL_ARTIFICIAL (type_decl) = 1;
276 TYPE_FIELDS (ret) = fields[0];
277 TYPE_NAME (ret) = type_decl;
278 TYPE_STUB_DECL (ret) = type_decl;
279 layout_type (ret);
280 ubsan_source_location_type = ret;
281 return ret;
284 /* Helper routine that returns a CONSTRUCTOR of __ubsan_source_location
285 type with its fields filled from a location_t LOC. */
287 static tree
288 ubsan_source_location (location_t loc)
290 expanded_location xloc;
291 tree type = ubsan_get_source_location_type ();
293 xloc = expand_location (loc);
294 tree str;
295 if (xloc.file == NULL)
297 str = build_int_cst (ptr_type_node, 0);
298 xloc.line = 0;
299 xloc.column = 0;
301 else
303 /* Fill in the values from LOC. */
304 size_t len = strlen (xloc.file) + 1;
305 str = build_string (len, xloc.file);
306 TREE_TYPE (str) = build_array_type_nelts (char_type_node, len);
307 TREE_READONLY (str) = 1;
308 TREE_STATIC (str) = 1;
309 str = build_fold_addr_expr (str);
311 tree ctor = build_constructor_va (type, 3, NULL_TREE, str, NULL_TREE,
312 build_int_cst (unsigned_type_node,
313 xloc.line), NULL_TREE,
314 build_int_cst (unsigned_type_node,
315 xloc.column));
316 TREE_CONSTANT (ctor) = 1;
317 TREE_STATIC (ctor) = 1;
319 return ctor;
322 /* This routine returns a magic number for TYPE. */
324 static unsigned short
325 get_ubsan_type_info_for_type (tree type)
327 if (TREE_CODE (type) == REAL_TYPE)
328 return tree_to_uhwi (TYPE_SIZE (type));
329 else if (INTEGRAL_TYPE_P (type))
331 int prec = exact_log2 (tree_to_uhwi (TYPE_SIZE (type)));
332 gcc_assert (prec != -1);
333 return (prec << 1) | !TYPE_UNSIGNED (type);
335 else
336 return 0;
339 /* Counters for internal labels. ubsan_ids[0] for Lubsan_type,
340 ubsan_ids[1] for Lubsan_data labels. */
341 static GTY(()) unsigned int ubsan_ids[2];
343 /* Helper routine that returns ADDR_EXPR of a VAR_DECL of a type
344 descriptor. It first looks into the hash table; if not found,
345 create the VAR_DECL, put it into the hash table and return the
346 ADDR_EXPR of it. TYPE describes a particular type. PSTYLE is
347 an enum controlling how we want to print the type. */
349 tree
350 ubsan_type_descriptor (tree type, enum ubsan_print_style pstyle)
352 /* See through any typedefs. */
353 type = TYPE_MAIN_VARIANT (type);
355 tree decl = decl_for_type_lookup (type);
356 /* It is possible that some of the earlier created DECLs were found
357 unused, in that case they weren't emitted and varpool_node::get
358 returns NULL node on them. But now we really need them. Thus,
359 renew them here. */
360 if (decl != NULL_TREE && varpool_node::get (decl))
361 return build_fold_addr_expr (decl);
363 tree dtype = ubsan_get_type_descriptor_type ();
364 tree type2 = type;
365 const char *tname = NULL;
366 pretty_printer pretty_name;
367 unsigned char deref_depth = 0;
368 unsigned short tkind, tinfo;
370 /* Get the name of the type, or the name of the pointer type. */
371 if (pstyle == UBSAN_PRINT_POINTER)
373 gcc_assert (POINTER_TYPE_P (type));
374 type2 = TREE_TYPE (type);
376 /* Remove any '*' operators from TYPE. */
377 while (POINTER_TYPE_P (type2))
378 deref_depth++, type2 = TREE_TYPE (type2);
380 if (TREE_CODE (type2) == METHOD_TYPE)
381 type2 = TYPE_METHOD_BASETYPE (type2);
384 /* If an array, get its type. */
385 type2 = strip_array_types (type2);
387 if (pstyle == UBSAN_PRINT_ARRAY)
389 while (POINTER_TYPE_P (type2))
390 deref_depth++, type2 = TREE_TYPE (type2);
393 if (TYPE_NAME (type2) != NULL)
395 if (TREE_CODE (TYPE_NAME (type2)) == IDENTIFIER_NODE)
396 tname = IDENTIFIER_POINTER (TYPE_NAME (type2));
397 else if (DECL_NAME (TYPE_NAME (type2)) != NULL)
398 tname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type2)));
401 if (tname == NULL)
402 /* We weren't able to determine the type name. */
403 tname = "<unknown>";
405 tree eltype = type;
406 if (pstyle == UBSAN_PRINT_POINTER)
408 pp_printf (&pretty_name, "'%s%s%s%s%s%s%s",
409 TYPE_VOLATILE (type2) ? "volatile " : "",
410 TYPE_READONLY (type2) ? "const " : "",
411 TYPE_RESTRICT (type2) ? "restrict " : "",
412 TYPE_ATOMIC (type2) ? "_Atomic " : "",
413 TREE_CODE (type2) == RECORD_TYPE
414 ? "struct "
415 : TREE_CODE (type2) == UNION_TYPE
416 ? "union " : "", tname,
417 deref_depth == 0 ? "" : " ");
418 while (deref_depth-- > 0)
419 pp_star (&pretty_name);
420 pp_quote (&pretty_name);
422 else if (pstyle == UBSAN_PRINT_ARRAY)
424 /* Pretty print the array dimensions. */
425 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
426 tree t = type;
427 pp_printf (&pretty_name, "'%s ", tname);
428 while (deref_depth-- > 0)
429 pp_star (&pretty_name);
430 while (TREE_CODE (t) == ARRAY_TYPE)
432 pp_left_bracket (&pretty_name);
433 tree dom = TYPE_DOMAIN (t);
434 if (dom != NULL_TREE
435 && TYPE_MAX_VALUE (dom) != NULL_TREE
436 && TREE_CODE (TYPE_MAX_VALUE (dom)) == INTEGER_CST)
438 if (tree_fits_uhwi_p (TYPE_MAX_VALUE (dom))
439 && tree_to_uhwi (TYPE_MAX_VALUE (dom)) + 1 != 0)
440 pp_printf (&pretty_name, HOST_WIDE_INT_PRINT_DEC,
441 tree_to_uhwi (TYPE_MAX_VALUE (dom)) + 1);
442 else
443 pp_wide_int (&pretty_name,
444 wi::add (wi::to_widest (TYPE_MAX_VALUE (dom)), 1),
445 TYPE_SIGN (TREE_TYPE (dom)));
447 else
448 /* ??? We can't determine the variable name; print VLA unspec. */
449 pp_star (&pretty_name);
450 pp_right_bracket (&pretty_name);
451 t = TREE_TYPE (t);
453 pp_quote (&pretty_name);
455 /* Save the tree with stripped types. */
456 eltype = t;
458 else
459 pp_printf (&pretty_name, "'%s'", tname);
461 switch (TREE_CODE (eltype))
463 case BOOLEAN_TYPE:
464 case ENUMERAL_TYPE:
465 case INTEGER_TYPE:
466 tkind = 0x0000;
467 break;
468 case REAL_TYPE:
469 /* FIXME: libubsan right now only supports float, double and
470 long double type formats. */
471 if (TYPE_MODE (eltype) == TYPE_MODE (float_type_node)
472 || TYPE_MODE (eltype) == TYPE_MODE (double_type_node)
473 || TYPE_MODE (eltype) == TYPE_MODE (long_double_type_node))
474 tkind = 0x0001;
475 else
476 tkind = 0xffff;
477 break;
478 default:
479 tkind = 0xffff;
480 break;
482 tinfo = get_ubsan_type_info_for_type (eltype);
484 /* Create a new VAR_DECL of type descriptor. */
485 const char *tmp = pp_formatted_text (&pretty_name);
486 size_t len = strlen (tmp) + 1;
487 tree str = build_string (len, tmp);
488 TREE_TYPE (str) = build_array_type_nelts (char_type_node, len);
489 TREE_READONLY (str) = 1;
490 TREE_STATIC (str) = 1;
492 char tmp_name[32];
493 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_type", ubsan_ids[0]++);
494 decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name),
495 dtype);
496 TREE_STATIC (decl) = 1;
497 TREE_PUBLIC (decl) = 0;
498 DECL_ARTIFICIAL (decl) = 1;
499 DECL_IGNORED_P (decl) = 1;
500 DECL_EXTERNAL (decl) = 0;
501 DECL_SIZE (decl)
502 = size_binop (PLUS_EXPR, DECL_SIZE (decl), TYPE_SIZE (TREE_TYPE (str)));
503 DECL_SIZE_UNIT (decl)
504 = size_binop (PLUS_EXPR, DECL_SIZE_UNIT (decl),
505 TYPE_SIZE_UNIT (TREE_TYPE (str)));
507 tree ctor = build_constructor_va (dtype, 3, NULL_TREE,
508 build_int_cst (short_unsigned_type_node,
509 tkind), NULL_TREE,
510 build_int_cst (short_unsigned_type_node,
511 tinfo), NULL_TREE, str);
512 TREE_CONSTANT (ctor) = 1;
513 TREE_STATIC (ctor) = 1;
514 DECL_INITIAL (decl) = ctor;
515 varpool_node::finalize_decl (decl);
517 /* Save the VAR_DECL into the hash table. */
518 decl_for_type_insert (type, decl);
520 return build_fold_addr_expr (decl);
523 /* Create a structure for the ubsan library. NAME is a name of the new
524 structure. LOCCNT is number of locations, PLOC points to array of
525 locations. The arguments in ... are of __ubsan_type_descriptor type
526 and there are at most two of them, followed by NULL_TREE, followed
527 by optional extra arguments and another NULL_TREE. */
529 tree
530 ubsan_create_data (const char *name, int loccnt, const location_t *ploc, ...)
532 va_list args;
533 tree ret, t;
534 tree fields[6];
535 vec<tree, va_gc> *saved_args = NULL;
536 size_t i = 0;
537 int j;
539 /* It is possible that PCH zapped table with definitions of sanitizer
540 builtins. Reinitialize them if needed. */
541 initialize_sanitizer_builtins ();
543 /* Firstly, create a pointer to type descriptor type. */
544 tree td_type = ubsan_get_type_descriptor_type ();
545 td_type = build_pointer_type (td_type);
547 /* Create the structure type. */
548 ret = make_node (RECORD_TYPE);
549 for (j = 0; j < loccnt; j++)
551 gcc_checking_assert (i < 2);
552 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
553 ubsan_get_source_location_type ());
554 DECL_CONTEXT (fields[i]) = ret;
555 if (i)
556 DECL_CHAIN (fields[i - 1]) = fields[i];
557 i++;
560 va_start (args, ploc);
561 for (t = va_arg (args, tree); t != NULL_TREE;
562 i++, t = va_arg (args, tree))
564 gcc_checking_assert (i < 4);
565 /* Save the tree arguments for later use. */
566 vec_safe_push (saved_args, t);
567 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
568 td_type);
569 DECL_CONTEXT (fields[i]) = ret;
570 if (i)
571 DECL_CHAIN (fields[i - 1]) = fields[i];
574 for (t = va_arg (args, tree); t != NULL_TREE;
575 i++, t = va_arg (args, tree))
577 gcc_checking_assert (i < 6);
578 /* Save the tree arguments for later use. */
579 vec_safe_push (saved_args, t);
580 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
581 TREE_TYPE (t));
582 DECL_CONTEXT (fields[i]) = ret;
583 if (i)
584 DECL_CHAIN (fields[i - 1]) = fields[i];
586 va_end (args);
588 tree type_decl = build_decl (input_location, TYPE_DECL,
589 get_identifier (name), ret);
590 DECL_IGNORED_P (type_decl) = 1;
591 DECL_ARTIFICIAL (type_decl) = 1;
592 TYPE_FIELDS (ret) = fields[0];
593 TYPE_NAME (ret) = type_decl;
594 TYPE_STUB_DECL (ret) = type_decl;
595 layout_type (ret);
597 /* Now, fill in the type. */
598 char tmp_name[32];
599 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_data", ubsan_ids[1]++);
600 tree var = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name),
601 ret);
602 TREE_STATIC (var) = 1;
603 TREE_PUBLIC (var) = 0;
604 DECL_ARTIFICIAL (var) = 1;
605 DECL_IGNORED_P (var) = 1;
606 DECL_EXTERNAL (var) = 0;
608 vec<constructor_elt, va_gc> *v;
609 vec_alloc (v, i);
610 tree ctor = build_constructor (ret, v);
612 /* If desirable, set the __ubsan_source_location element. */
613 for (j = 0; j < loccnt; j++)
615 location_t loc = LOCATION_LOCUS (ploc[j]);
616 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, ubsan_source_location (loc));
619 size_t nelts = vec_safe_length (saved_args);
620 for (i = 0; i < nelts; i++)
622 t = (*saved_args)[i];
623 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, t);
626 TREE_CONSTANT (ctor) = 1;
627 TREE_STATIC (ctor) = 1;
628 DECL_INITIAL (var) = ctor;
629 varpool_node::finalize_decl (var);
631 return var;
634 /* Instrument the __builtin_unreachable call. We just call the libubsan
635 routine instead. */
637 bool
638 ubsan_instrument_unreachable (gimple_stmt_iterator *gsi)
640 gimple *g;
641 location_t loc = gimple_location (gsi_stmt (*gsi));
643 if (flag_sanitize_undefined_trap_on_error)
644 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
645 else
647 tree data = ubsan_create_data ("__ubsan_unreachable_data", 1, &loc,
648 NULL_TREE, NULL_TREE);
649 data = build_fold_addr_expr_loc (loc, data);
650 tree fn
651 = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE);
652 g = gimple_build_call (fn, 1, data);
654 gimple_set_location (g, loc);
655 gsi_replace (gsi, g, false);
656 return false;
659 /* Return true if T is a call to a libubsan routine. */
661 bool
662 is_ubsan_builtin_p (tree t)
664 return TREE_CODE (t) == FUNCTION_DECL
665 && DECL_BUILT_IN_CLASS (t) == BUILT_IN_NORMAL
666 && strncmp (IDENTIFIER_POINTER (DECL_NAME (t)),
667 "__builtin___ubsan_", 18) == 0;
670 /* Create a callgraph edge for statement STMT. */
672 static void
673 ubsan_create_edge (gimple *stmt)
675 gcall *call_stmt = dyn_cast <gcall *> (stmt);
676 basic_block bb = gimple_bb (stmt);
677 int freq = compute_call_stmt_bb_frequency (current_function_decl, bb);
678 cgraph_node *node = cgraph_node::get (current_function_decl);
679 tree decl = gimple_call_fndecl (call_stmt);
680 if (decl)
681 node->create_edge (cgraph_node::get_create (decl), call_stmt, bb->count,
682 freq);
685 /* Expand the UBSAN_BOUNDS special builtin function. */
687 bool
688 ubsan_expand_bounds_ifn (gimple_stmt_iterator *gsi)
690 gimple *stmt = gsi_stmt (*gsi);
691 location_t loc = gimple_location (stmt);
692 gcc_assert (gimple_call_num_args (stmt) == 3);
694 /* Pick up the arguments of the UBSAN_BOUNDS call. */
695 tree type = TREE_TYPE (TREE_TYPE (gimple_call_arg (stmt, 0)));
696 tree index = gimple_call_arg (stmt, 1);
697 tree orig_index = index;
698 tree bound = gimple_call_arg (stmt, 2);
700 gimple_stmt_iterator gsi_orig = *gsi;
702 /* Create condition "if (index > bound)". */
703 basic_block then_bb, fallthru_bb;
704 gimple_stmt_iterator cond_insert_point
705 = create_cond_insert_point (gsi, false, false, true,
706 &then_bb, &fallthru_bb);
707 index = fold_convert (TREE_TYPE (bound), index);
708 index = force_gimple_operand_gsi (&cond_insert_point, index,
709 true, NULL_TREE,
710 false, GSI_NEW_STMT);
711 gimple *g = gimple_build_cond (GT_EXPR, index, bound, NULL_TREE, NULL_TREE);
712 gimple_set_location (g, loc);
713 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
715 /* Generate __ubsan_handle_out_of_bounds call. */
716 *gsi = gsi_after_labels (then_bb);
717 if (flag_sanitize_undefined_trap_on_error)
718 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
719 else
721 tree data
722 = ubsan_create_data ("__ubsan_out_of_bounds_data", 1, &loc,
723 ubsan_type_descriptor (type, UBSAN_PRINT_ARRAY),
724 ubsan_type_descriptor (TREE_TYPE (orig_index)),
725 NULL_TREE, NULL_TREE);
726 data = build_fold_addr_expr_loc (loc, data);
727 enum built_in_function bcode
728 = (flag_sanitize_recover & SANITIZE_BOUNDS)
729 ? BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS
730 : BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS_ABORT;
731 tree fn = builtin_decl_explicit (bcode);
732 tree val = ubsan_encode_value (orig_index, UBSAN_ENCODE_VALUE_GIMPLE);
733 val = force_gimple_operand_gsi (gsi, val, true, NULL_TREE, true,
734 GSI_SAME_STMT);
735 g = gimple_build_call (fn, 2, data, val);
737 gimple_set_location (g, loc);
738 gsi_insert_before (gsi, g, GSI_SAME_STMT);
740 /* Get rid of the UBSAN_BOUNDS call from the IR. */
741 unlink_stmt_vdef (stmt);
742 gsi_remove (&gsi_orig, true);
744 /* Point GSI to next logical statement. */
745 *gsi = gsi_start_bb (fallthru_bb);
746 return true;
749 /* Expand UBSAN_NULL internal call. The type is kept on the ckind
750 argument which is a constant, because the middle-end treats pointer
751 conversions as useless and therefore the type of the first argument
752 could be changed to any other pointer type. */
754 bool
755 ubsan_expand_null_ifn (gimple_stmt_iterator *gsip)
757 gimple_stmt_iterator gsi = *gsip;
758 gimple *stmt = gsi_stmt (gsi);
759 location_t loc = gimple_location (stmt);
760 gcc_assert (gimple_call_num_args (stmt) == 3);
761 tree ptr = gimple_call_arg (stmt, 0);
762 tree ckind = gimple_call_arg (stmt, 1);
763 tree align = gimple_call_arg (stmt, 2);
764 tree check_align = NULL_TREE;
765 bool check_null;
767 basic_block cur_bb = gsi_bb (gsi);
769 gimple *g;
770 if (!integer_zerop (align))
772 unsigned int ptralign = get_pointer_alignment (ptr) / BITS_PER_UNIT;
773 if (compare_tree_int (align, ptralign) == 1)
775 check_align = make_ssa_name (pointer_sized_int_node);
776 g = gimple_build_assign (check_align, NOP_EXPR, ptr);
777 gimple_set_location (g, loc);
778 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
781 check_null = sanitize_flags_p (SANITIZE_NULL);
783 if (check_align == NULL_TREE && !check_null)
785 gsi_remove (gsip, true);
786 /* Unlink the UBSAN_NULLs vops before replacing it. */
787 unlink_stmt_vdef (stmt);
788 return true;
791 /* Split the original block holding the pointer dereference. */
792 edge e = split_block (cur_bb, stmt);
794 /* Get a hold on the 'condition block', the 'then block' and the
795 'else block'. */
796 basic_block cond_bb = e->src;
797 basic_block fallthru_bb = e->dest;
798 basic_block then_bb = create_empty_bb (cond_bb);
799 add_bb_to_loop (then_bb, cond_bb->loop_father);
800 loops_state_set (LOOPS_NEED_FIXUP);
802 /* Make an edge coming from the 'cond block' into the 'then block';
803 this edge is unlikely taken, so set up the probability accordingly. */
804 e = make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
805 e->probability = profile_probability::very_unlikely ();
807 /* Connect 'then block' with the 'else block'. This is needed
808 as the ubsan routines we call in the 'then block' are not noreturn.
809 The 'then block' only has one outcoming edge. */
810 make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);
812 /* Set up the fallthrough basic block. */
813 e = find_edge (cond_bb, fallthru_bb);
814 e->flags = EDGE_FALSE_VALUE;
815 e->count = cond_bb->count;
816 e->probability = profile_probability::very_likely ();
818 /* Update dominance info for the newly created then_bb; note that
819 fallthru_bb's dominance info has already been updated by
820 split_block. */
821 if (dom_info_available_p (CDI_DOMINATORS))
822 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
824 /* Put the ubsan builtin call into the newly created BB. */
825 if (flag_sanitize_undefined_trap_on_error)
826 g = gimple_build_call (builtin_decl_implicit (BUILT_IN_TRAP), 0);
827 else
829 enum built_in_function bcode
830 = (flag_sanitize_recover & ((check_align ? SANITIZE_ALIGNMENT : 0)
831 | (check_null ? SANITIZE_NULL : 0)))
832 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
833 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT;
834 tree fn = builtin_decl_implicit (bcode);
835 tree data
836 = ubsan_create_data ("__ubsan_null_data", 1, &loc,
837 ubsan_type_descriptor (TREE_TYPE (ckind),
838 UBSAN_PRINT_POINTER),
839 NULL_TREE,
840 align,
841 fold_convert (unsigned_char_type_node, ckind),
842 NULL_TREE);
843 data = build_fold_addr_expr_loc (loc, data);
844 g = gimple_build_call (fn, 2, data,
845 check_align ? check_align
846 : build_zero_cst (pointer_sized_int_node));
848 gimple_stmt_iterator gsi2 = gsi_start_bb (then_bb);
849 gimple_set_location (g, loc);
850 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
852 /* Unlink the UBSAN_NULLs vops before replacing it. */
853 unlink_stmt_vdef (stmt);
855 if (check_null)
857 g = gimple_build_cond (EQ_EXPR, ptr, build_int_cst (TREE_TYPE (ptr), 0),
858 NULL_TREE, NULL_TREE);
859 gimple_set_location (g, loc);
861 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
862 gsi_replace (&gsi, g, false);
863 stmt = g;
866 if (check_align)
868 if (check_null)
870 /* Split the block with the condition again. */
871 e = split_block (cond_bb, stmt);
872 basic_block cond1_bb = e->src;
873 basic_block cond2_bb = e->dest;
875 /* Make an edge coming from the 'cond1 block' into the 'then block';
876 this edge is unlikely taken, so set up the probability
877 accordingly. */
878 e = make_edge (cond1_bb, then_bb, EDGE_TRUE_VALUE);
879 e->probability = profile_probability::very_unlikely ();
881 /* Set up the fallthrough basic block. */
882 e = find_edge (cond1_bb, cond2_bb);
883 e->flags = EDGE_FALSE_VALUE;
884 e->count = cond1_bb->count;
885 e->probability = profile_probability::very_likely ();
887 /* Update dominance info. */
888 if (dom_info_available_p (CDI_DOMINATORS))
890 set_immediate_dominator (CDI_DOMINATORS, fallthru_bb, cond1_bb);
891 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond1_bb);
894 gsi2 = gsi_start_bb (cond2_bb);
897 tree mask = build_int_cst (pointer_sized_int_node,
898 tree_to_uhwi (align) - 1);
899 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
900 BIT_AND_EXPR, check_align, mask);
901 gimple_set_location (g, loc);
902 if (check_null)
903 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
904 else
905 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
907 g = gimple_build_cond (NE_EXPR, gimple_assign_lhs (g),
908 build_int_cst (pointer_sized_int_node, 0),
909 NULL_TREE, NULL_TREE);
910 gimple_set_location (g, loc);
911 if (check_null)
912 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
913 else
914 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
915 gsi_replace (&gsi, g, false);
917 return false;
920 #define OBJSZ_MAX_OFFSET (1024 * 16)
922 /* Expand UBSAN_OBJECT_SIZE internal call. */
924 bool
925 ubsan_expand_objsize_ifn (gimple_stmt_iterator *gsi)
927 gimple *stmt = gsi_stmt (*gsi);
928 location_t loc = gimple_location (stmt);
929 gcc_assert (gimple_call_num_args (stmt) == 4);
931 tree ptr = gimple_call_arg (stmt, 0);
932 tree offset = gimple_call_arg (stmt, 1);
933 tree size = gimple_call_arg (stmt, 2);
934 tree ckind = gimple_call_arg (stmt, 3);
935 gimple_stmt_iterator gsi_orig = *gsi;
936 gimple *g;
938 /* See if we can discard the check. */
939 if (TREE_CODE (size) != INTEGER_CST
940 || integer_all_onesp (size))
941 /* Yes, __builtin_object_size couldn't determine the
942 object size. */;
943 else if (TREE_CODE (offset) == INTEGER_CST
944 && wi::to_widest (offset) >= -OBJSZ_MAX_OFFSET
945 && wi::to_widest (offset) <= -1)
946 /* The offset is in range [-16K, -1]. */;
947 else
949 /* if (offset > objsize) */
950 basic_block then_bb, fallthru_bb;
951 gimple_stmt_iterator cond_insert_point
952 = create_cond_insert_point (gsi, false, false, true,
953 &then_bb, &fallthru_bb);
954 g = gimple_build_cond (GT_EXPR, offset, size, NULL_TREE, NULL_TREE);
955 gimple_set_location (g, loc);
956 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
958 /* If the offset is small enough, we don't need the second
959 run-time check. */
960 if (TREE_CODE (offset) == INTEGER_CST
961 && wi::to_widest (offset) >= 0
962 && wi::to_widest (offset) <= OBJSZ_MAX_OFFSET)
963 *gsi = gsi_after_labels (then_bb);
964 else
966 /* Don't issue run-time error if (ptr > ptr + offset). That
967 may happen when computing a POINTER_PLUS_EXPR. */
968 basic_block then2_bb, fallthru2_bb;
970 gimple_stmt_iterator gsi2 = gsi_after_labels (then_bb);
971 cond_insert_point = create_cond_insert_point (&gsi2, false, false,
972 true, &then2_bb,
973 &fallthru2_bb);
974 /* Convert the pointer to an integer type. */
975 tree p = make_ssa_name (pointer_sized_int_node);
976 g = gimple_build_assign (p, NOP_EXPR, ptr);
977 gimple_set_location (g, loc);
978 gsi_insert_before (&cond_insert_point, g, GSI_NEW_STMT);
979 p = gimple_assign_lhs (g);
980 /* Compute ptr + offset. */
981 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
982 PLUS_EXPR, p, offset);
983 gimple_set_location (g, loc);
984 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
985 /* Now build the conditional and put it into the IR. */
986 g = gimple_build_cond (LE_EXPR, p, gimple_assign_lhs (g),
987 NULL_TREE, NULL_TREE);
988 gimple_set_location (g, loc);
989 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
990 *gsi = gsi_after_labels (then2_bb);
993 /* Generate __ubsan_handle_type_mismatch call. */
994 if (flag_sanitize_undefined_trap_on_error)
995 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
996 else
998 tree data
999 = ubsan_create_data ("__ubsan_objsz_data", 1, &loc,
1000 ubsan_type_descriptor (TREE_TYPE (ptr),
1001 UBSAN_PRINT_POINTER),
1002 NULL_TREE,
1003 build_zero_cst (pointer_sized_int_node),
1004 ckind,
1005 NULL_TREE);
1006 data = build_fold_addr_expr_loc (loc, data);
1007 enum built_in_function bcode
1008 = (flag_sanitize_recover & SANITIZE_OBJECT_SIZE)
1009 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
1010 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT;
1011 tree p = make_ssa_name (pointer_sized_int_node);
1012 g = gimple_build_assign (p, NOP_EXPR, ptr);
1013 gimple_set_location (g, loc);
1014 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1015 g = gimple_build_call (builtin_decl_explicit (bcode), 2, data, p);
1017 gimple_set_location (g, loc);
1018 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1020 /* Point GSI to next logical statement. */
1021 *gsi = gsi_start_bb (fallthru_bb);
1023 /* Get rid of the UBSAN_OBJECT_SIZE call from the IR. */
1024 unlink_stmt_vdef (stmt);
1025 gsi_remove (&gsi_orig, true);
1026 return true;
1029 /* Get rid of the UBSAN_OBJECT_SIZE call from the IR. */
1030 unlink_stmt_vdef (stmt);
1031 gsi_remove (gsi, true);
1032 return true;
1035 /* Expand UBSAN_PTR internal call. */
1037 bool
1038 ubsan_expand_ptr_ifn (gimple_stmt_iterator *gsip)
1040 gimple_stmt_iterator gsi = *gsip;
1041 gimple *stmt = gsi_stmt (gsi);
1042 location_t loc = gimple_location (stmt);
1043 gcc_assert (gimple_call_num_args (stmt) == 2);
1044 tree ptr = gimple_call_arg (stmt, 0);
1045 tree off = gimple_call_arg (stmt, 1);
1047 if (integer_zerop (off))
1049 gsi_remove (gsip, true);
1050 unlink_stmt_vdef (stmt);
1051 return true;
1054 basic_block cur_bb = gsi_bb (gsi);
1055 tree ptrplusoff = make_ssa_name (pointer_sized_int_node);
1056 tree ptri = make_ssa_name (pointer_sized_int_node);
1057 int pos_neg = get_range_pos_neg (off);
1059 /* Split the original block holding the pointer dereference. */
1060 edge e = split_block (cur_bb, stmt);
1062 /* Get a hold on the 'condition block', the 'then block' and the
1063 'else block'. */
1064 basic_block cond_bb = e->src;
1065 basic_block fallthru_bb = e->dest;
1066 basic_block then_bb = create_empty_bb (cond_bb);
1067 basic_block cond_pos_bb = NULL, cond_neg_bb = NULL;
1068 add_bb_to_loop (then_bb, cond_bb->loop_father);
1069 loops_state_set (LOOPS_NEED_FIXUP);
1071 /* Set up the fallthrough basic block. */
1072 e->flags = EDGE_FALSE_VALUE;
1073 if (pos_neg != 3)
1075 e->count = cond_bb->count;
1076 e->probability = profile_probability::very_likely ();
1078 /* Connect 'then block' with the 'else block'. This is needed
1079 as the ubsan routines we call in the 'then block' are not noreturn.
1080 The 'then block' only has one outcoming edge. */
1081 make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);
1083 /* Make an edge coming from the 'cond block' into the 'then block';
1084 this edge is unlikely taken, so set up the probability
1085 accordingly. */
1086 e = make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
1087 e->probability = profile_probability::very_unlikely ();
1089 else
1091 profile_count count = cond_bb->count.apply_probability (PROB_EVEN);
1092 e->count = count;
1093 e->probability = profile_probability::even ();
1095 e = split_block (fallthru_bb, (gimple *) NULL);
1096 cond_neg_bb = e->src;
1097 fallthru_bb = e->dest;
1098 e->count = count;
1099 e->probability = profile_probability::very_likely ();
1100 e->flags = EDGE_FALSE_VALUE;
1102 e = make_edge (cond_neg_bb, then_bb, EDGE_TRUE_VALUE);
1103 e->probability = profile_probability::very_unlikely ();
1105 cond_pos_bb = create_empty_bb (cond_bb);
1106 add_bb_to_loop (cond_pos_bb, cond_bb->loop_father);
1108 e = make_edge (cond_bb, cond_pos_bb, EDGE_TRUE_VALUE);
1109 e->count = count;
1110 e->probability = profile_probability::even ();
1112 e = make_edge (cond_pos_bb, then_bb, EDGE_TRUE_VALUE);
1113 e->probability = profile_probability::very_unlikely ();
1115 e = make_edge (cond_pos_bb, fallthru_bb, EDGE_FALSE_VALUE);
1116 e->count = count;
1117 e->probability = profile_probability::very_likely ();
1119 make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);
1122 gimple *g = gimple_build_assign (ptri, NOP_EXPR, ptr);
1123 gimple_set_location (g, loc);
1124 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
1125 g = gimple_build_assign (ptrplusoff, PLUS_EXPR, ptri, off);
1126 gimple_set_location (g, loc);
1127 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
1129 /* Update dominance info for the newly created then_bb; note that
1130 fallthru_bb's dominance info has already been updated by
1131 split_block. */
1132 if (dom_info_available_p (CDI_DOMINATORS))
1134 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
1135 if (pos_neg == 3)
1137 set_immediate_dominator (CDI_DOMINATORS, cond_pos_bb, cond_bb);
1138 set_immediate_dominator (CDI_DOMINATORS, fallthru_bb, cond_bb);
1142 /* Put the ubsan builtin call into the newly created BB. */
1143 if (flag_sanitize_undefined_trap_on_error)
1144 g = gimple_build_call (builtin_decl_implicit (BUILT_IN_TRAP), 0);
1145 else
1147 enum built_in_function bcode
1148 = (flag_sanitize_recover & SANITIZE_POINTER_OVERFLOW)
1149 ? BUILT_IN_UBSAN_HANDLE_POINTER_OVERFLOW
1150 : BUILT_IN_UBSAN_HANDLE_POINTER_OVERFLOW_ABORT;
1151 tree fn = builtin_decl_implicit (bcode);
1152 tree data
1153 = ubsan_create_data ("__ubsan_ptrovf_data", 1, &loc,
1154 NULL_TREE, NULL_TREE);
1155 data = build_fold_addr_expr_loc (loc, data);
1156 g = gimple_build_call (fn, 3, data, ptr, ptrplusoff);
1158 gimple_stmt_iterator gsi2 = gsi_start_bb (then_bb);
1159 gimple_set_location (g, loc);
1160 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
1162 /* Unlink the UBSAN_PTRs vops before replacing it. */
1163 unlink_stmt_vdef (stmt);
1165 if (TREE_CODE (off) == INTEGER_CST)
1166 g = gimple_build_cond (wi::neg_p (off) ? LT_EXPR : GE_EXPR, ptri,
1167 fold_build1 (NEGATE_EXPR, sizetype, off),
1168 NULL_TREE, NULL_TREE);
1169 else if (pos_neg != 3)
1170 g = gimple_build_cond (pos_neg == 1 ? LT_EXPR : GT_EXPR,
1171 ptrplusoff, ptri, NULL_TREE, NULL_TREE);
1172 else
1174 gsi2 = gsi_start_bb (cond_pos_bb);
1175 g = gimple_build_cond (LT_EXPR, ptrplusoff, ptri, NULL_TREE, NULL_TREE);
1176 gimple_set_location (g, loc);
1177 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
1179 gsi2 = gsi_start_bb (cond_neg_bb);
1180 g = gimple_build_cond (GT_EXPR, ptrplusoff, ptri, NULL_TREE, NULL_TREE);
1181 gimple_set_location (g, loc);
1182 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
1184 gimple_seq seq = NULL;
1185 tree t = gimple_build (&seq, loc, NOP_EXPR, ssizetype, off);
1186 t = gimple_build (&seq, loc, GE_EXPR, boolean_type_node,
1187 t, ssize_int (0));
1188 gsi_insert_seq_before (&gsi, seq, GSI_SAME_STMT);
1189 g = gimple_build_cond (NE_EXPR, t, boolean_false_node,
1190 NULL_TREE, NULL_TREE);
1192 gimple_set_location (g, loc);
1193 /* Replace the UBSAN_PTR with a GIMPLE_COND stmt. */
1194 gsi_replace (&gsi, g, false);
1195 return false;
1199 /* Cached __ubsan_vptr_type_cache decl. */
1200 static GTY(()) tree ubsan_vptr_type_cache_decl;
1202 /* Expand UBSAN_VPTR internal call. The type is kept on the ckind
1203 argument which is a constant, because the middle-end treats pointer
1204 conversions as useless and therefore the type of the first argument
1205 could be changed to any other pointer type. */
1207 bool
1208 ubsan_expand_vptr_ifn (gimple_stmt_iterator *gsip)
1210 gimple_stmt_iterator gsi = *gsip;
1211 gimple *stmt = gsi_stmt (gsi);
1212 location_t loc = gimple_location (stmt);
1213 gcc_assert (gimple_call_num_args (stmt) == 5);
1214 tree op = gimple_call_arg (stmt, 0);
1215 tree vptr = gimple_call_arg (stmt, 1);
1216 tree str_hash = gimple_call_arg (stmt, 2);
1217 tree ti_decl_addr = gimple_call_arg (stmt, 3);
1218 tree ckind_tree = gimple_call_arg (stmt, 4);
1219 ubsan_null_ckind ckind = (ubsan_null_ckind) tree_to_uhwi (ckind_tree);
1220 tree type = TREE_TYPE (TREE_TYPE (ckind_tree));
1221 gimple *g;
1222 basic_block fallthru_bb = NULL;
1224 if (ckind == UBSAN_DOWNCAST_POINTER)
1226 /* Guard everything with if (op != NULL) { ... }. */
1227 basic_block then_bb;
1228 gimple_stmt_iterator cond_insert_point
1229 = create_cond_insert_point (gsip, false, false, true,
1230 &then_bb, &fallthru_bb);
1231 g = gimple_build_cond (NE_EXPR, op, build_zero_cst (TREE_TYPE (op)),
1232 NULL_TREE, NULL_TREE);
1233 gimple_set_location (g, loc);
1234 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
1235 *gsip = gsi_after_labels (then_bb);
1236 gsi_remove (&gsi, false);
1237 gsi_insert_before (gsip, stmt, GSI_NEW_STMT);
1238 gsi = *gsip;
1241 tree htype = TREE_TYPE (str_hash);
1242 tree cst = wide_int_to_tree (htype,
1243 wi::uhwi (((uint64_t) 0x9ddfea08 << 32)
1244 | 0xeb382d69, 64));
1245 g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1246 vptr, str_hash);
1247 gimple_set_location (g, loc);
1248 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1249 g = gimple_build_assign (make_ssa_name (htype), MULT_EXPR,
1250 gimple_assign_lhs (g), cst);
1251 gimple_set_location (g, loc);
1252 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1253 tree t1 = gimple_assign_lhs (g);
1254 g = gimple_build_assign (make_ssa_name (htype), LSHIFT_EXPR,
1255 t1, build_int_cst (integer_type_node, 47));
1256 gimple_set_location (g, loc);
1257 tree t2 = gimple_assign_lhs (g);
1258 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1259 g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1260 vptr, t1);
1261 gimple_set_location (g, loc);
1262 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1263 g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1264 t2, gimple_assign_lhs (g));
1265 gimple_set_location (g, loc);
1266 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1267 g = gimple_build_assign (make_ssa_name (htype), MULT_EXPR,
1268 gimple_assign_lhs (g), cst);
1269 gimple_set_location (g, loc);
1270 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1271 tree t3 = gimple_assign_lhs (g);
1272 g = gimple_build_assign (make_ssa_name (htype), LSHIFT_EXPR,
1273 t3, build_int_cst (integer_type_node, 47));
1274 gimple_set_location (g, loc);
1275 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1276 g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1277 t3, gimple_assign_lhs (g));
1278 gimple_set_location (g, loc);
1279 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1280 g = gimple_build_assign (make_ssa_name (htype), MULT_EXPR,
1281 gimple_assign_lhs (g), cst);
1282 gimple_set_location (g, loc);
1283 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1284 if (!useless_type_conversion_p (pointer_sized_int_node, htype))
1286 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
1287 NOP_EXPR, gimple_assign_lhs (g));
1288 gimple_set_location (g, loc);
1289 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1291 tree hash = gimple_assign_lhs (g);
1293 if (ubsan_vptr_type_cache_decl == NULL_TREE)
1295 tree atype = build_array_type_nelts (pointer_sized_int_node, 128);
1296 tree array = build_decl (UNKNOWN_LOCATION, VAR_DECL,
1297 get_identifier ("__ubsan_vptr_type_cache"),
1298 atype);
1299 DECL_ARTIFICIAL (array) = 1;
1300 DECL_IGNORED_P (array) = 1;
1301 TREE_PUBLIC (array) = 1;
1302 TREE_STATIC (array) = 1;
1303 DECL_EXTERNAL (array) = 1;
1304 DECL_VISIBILITY (array) = VISIBILITY_DEFAULT;
1305 DECL_VISIBILITY_SPECIFIED (array) = 1;
1306 varpool_node::finalize_decl (array);
1307 ubsan_vptr_type_cache_decl = array;
1310 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
1311 BIT_AND_EXPR, hash,
1312 build_int_cst (pointer_sized_int_node, 127));
1313 gimple_set_location (g, loc);
1314 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1316 tree c = build4_loc (loc, ARRAY_REF, pointer_sized_int_node,
1317 ubsan_vptr_type_cache_decl, gimple_assign_lhs (g),
1318 NULL_TREE, NULL_TREE);
1319 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
1320 ARRAY_REF, c);
1321 gimple_set_location (g, loc);
1322 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1324 basic_block then_bb, fallthru2_bb;
1325 gimple_stmt_iterator cond_insert_point
1326 = create_cond_insert_point (gsip, false, false, true,
1327 &then_bb, &fallthru2_bb);
1328 g = gimple_build_cond (NE_EXPR, gimple_assign_lhs (g), hash,
1329 NULL_TREE, NULL_TREE);
1330 gimple_set_location (g, loc);
1331 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
1332 *gsip = gsi_after_labels (then_bb);
1333 if (fallthru_bb == NULL)
1334 fallthru_bb = fallthru2_bb;
1336 tree data
1337 = ubsan_create_data ("__ubsan_vptr_data", 1, &loc,
1338 ubsan_type_descriptor (type), NULL_TREE, ti_decl_addr,
1339 build_int_cst (unsigned_char_type_node, ckind),
1340 NULL_TREE);
1341 data = build_fold_addr_expr_loc (loc, data);
1342 enum built_in_function bcode
1343 = (flag_sanitize_recover & SANITIZE_VPTR)
1344 ? BUILT_IN_UBSAN_HANDLE_DYNAMIC_TYPE_CACHE_MISS
1345 : BUILT_IN_UBSAN_HANDLE_DYNAMIC_TYPE_CACHE_MISS_ABORT;
1347 g = gimple_build_call (builtin_decl_explicit (bcode), 3, data, op, hash);
1348 gimple_set_location (g, loc);
1349 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1351 /* Point GSI to next logical statement. */
1352 *gsip = gsi_start_bb (fallthru_bb);
1354 /* Get rid of the UBSAN_VPTR call from the IR. */
1355 unlink_stmt_vdef (stmt);
1356 gsi_remove (&gsi, true);
1357 return true;
1360 /* Instrument a memory reference. BASE is the base of MEM, IS_LHS says
1361 whether the pointer is on the left hand side of the assignment. */
1363 static void
1364 instrument_mem_ref (tree mem, tree base, gimple_stmt_iterator *iter,
1365 bool is_lhs)
1367 enum ubsan_null_ckind ikind = is_lhs ? UBSAN_STORE_OF : UBSAN_LOAD_OF;
1368 unsigned int align = 0;
1369 if (sanitize_flags_p (SANITIZE_ALIGNMENT))
1371 align = min_align_of_type (TREE_TYPE (base));
1372 if (align <= 1)
1373 align = 0;
1375 if (align == 0 && !sanitize_flags_p (SANITIZE_NULL))
1376 return;
1377 tree t = TREE_OPERAND (base, 0);
1378 if (!POINTER_TYPE_P (TREE_TYPE (t)))
1379 return;
1380 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (base)) && mem != base)
1381 ikind = UBSAN_MEMBER_ACCESS;
1382 tree kind = build_int_cst (build_pointer_type (TREE_TYPE (base)), ikind);
1383 tree alignt = build_int_cst (pointer_sized_int_node, align);
1384 gcall *g = gimple_build_call_internal (IFN_UBSAN_NULL, 3, t, kind, alignt);
1385 gimple_set_location (g, gimple_location (gsi_stmt (*iter)));
1386 gsi_insert_before (iter, g, GSI_SAME_STMT);
1389 /* Perform the pointer instrumentation. */
1391 static void
1392 instrument_null (gimple_stmt_iterator gsi, tree t, bool is_lhs)
1394 /* Handle also e.g. &s->i. */
1395 if (TREE_CODE (t) == ADDR_EXPR)
1396 t = TREE_OPERAND (t, 0);
1397 tree base = get_base_address (t);
1398 if (base != NULL_TREE
1399 && TREE_CODE (base) == MEM_REF
1400 && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
1401 instrument_mem_ref (t, base, &gsi, is_lhs);
1404 /* Instrument pointer arithmetics PTR p+ OFF. */
1406 static void
1407 instrument_pointer_overflow (gimple_stmt_iterator *gsi, tree ptr, tree off)
1409 if (TYPE_PRECISION (sizetype) != POINTER_SIZE)
1410 return;
1411 gcall *g = gimple_build_call_internal (IFN_UBSAN_PTR, 2, ptr, off);
1412 gimple_set_location (g, gimple_location (gsi_stmt (*gsi)));
1413 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1416 /* Instrument pointer arithmetics if any. */
1418 static void
1419 maybe_instrument_pointer_overflow (gimple_stmt_iterator *gsi, tree t)
1421 if (TYPE_PRECISION (sizetype) != POINTER_SIZE)
1422 return;
1424 /* Handle also e.g. &s->i. */
1425 if (TREE_CODE (t) == ADDR_EXPR)
1426 t = TREE_OPERAND (t, 0);
1428 if (!handled_component_p (t) && TREE_CODE (t) != MEM_REF)
1429 return;
1431 HOST_WIDE_INT bitsize, bitpos, bytepos;
1432 tree offset;
1433 machine_mode mode;
1434 int volatilep = 0, reversep, unsignedp = 0;
1435 tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset, &mode,
1436 &unsignedp, &reversep, &volatilep);
1437 tree moff = NULL_TREE;
1439 bool decl_p = DECL_P (inner);
1440 tree base;
1441 if (decl_p)
1443 if (DECL_REGISTER (inner))
1444 return;
1445 base = inner;
1446 /* If BASE is a fixed size automatic variable or
1447 global variable defined in the current TU and bitpos
1448 fits, don't instrument anything. */
1449 if (offset == NULL_TREE
1450 && bitpos > 0
1451 && (VAR_P (base)
1452 || TREE_CODE (base) == PARM_DECL
1453 || TREE_CODE (base) == RESULT_DECL)
1454 && DECL_SIZE (base)
1455 && TREE_CODE (DECL_SIZE (base)) == INTEGER_CST
1456 && compare_tree_int (DECL_SIZE (base), bitpos) >= 0
1457 && (!is_global_var (base) || decl_binds_to_current_def_p (base)))
1458 return;
1460 else if (TREE_CODE (inner) == MEM_REF)
1462 base = TREE_OPERAND (inner, 0);
1463 if (TREE_CODE (base) == ADDR_EXPR
1464 && DECL_P (TREE_OPERAND (base, 0))
1465 && !TREE_ADDRESSABLE (TREE_OPERAND (base, 0))
1466 && !is_global_var (TREE_OPERAND (base, 0)))
1467 return;
1468 moff = TREE_OPERAND (inner, 1);
1469 if (integer_zerop (moff))
1470 moff = NULL_TREE;
1472 else
1473 return;
1475 if (!POINTER_TYPE_P (TREE_TYPE (base)) && !DECL_P (base))
1476 return;
1477 bytepos = bitpos / BITS_PER_UNIT;
1478 if (offset == NULL_TREE && bytepos == 0 && moff == NULL_TREE)
1479 return;
1481 tree base_addr = base;
1482 if (decl_p)
1483 base_addr = build1 (ADDR_EXPR,
1484 build_pointer_type (TREE_TYPE (base)), base);
1485 t = offset;
1486 if (bytepos)
1488 if (t)
1489 t = fold_build2 (PLUS_EXPR, TREE_TYPE (t), t,
1490 build_int_cst (TREE_TYPE (t), bytepos));
1491 else
1492 t = size_int (bytepos);
1494 if (moff)
1496 if (t)
1497 t = fold_build2 (PLUS_EXPR, TREE_TYPE (t), t,
1498 fold_convert (TREE_TYPE (t), moff));
1499 else
1500 t = fold_convert (sizetype, moff);
1502 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE, true,
1503 GSI_SAME_STMT);
1504 base_addr = force_gimple_operand_gsi (gsi, base_addr, true, NULL_TREE, true,
1505 GSI_SAME_STMT);
1506 instrument_pointer_overflow (gsi, base_addr, t);
1509 /* Build an ubsan builtin call for the signed-integer-overflow
1510 sanitization. CODE says what kind of builtin are we building,
1511 LOC is a location, LHSTYPE is the type of LHS, OP0 and OP1
1512 are operands of the binary operation. */
1514 tree
1515 ubsan_build_overflow_builtin (tree_code code, location_t loc, tree lhstype,
1516 tree op0, tree op1, tree *datap)
1518 if (flag_sanitize_undefined_trap_on_error)
1519 return build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
1521 tree data;
1522 if (datap && *datap)
1523 data = *datap;
1524 else
1525 data = ubsan_create_data ("__ubsan_overflow_data", 1, &loc,
1526 ubsan_type_descriptor (lhstype), NULL_TREE,
1527 NULL_TREE);
1528 if (datap)
1529 *datap = data;
1530 enum built_in_function fn_code;
1532 switch (code)
1534 case PLUS_EXPR:
1535 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1536 ? BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW
1537 : BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW_ABORT;
1538 break;
1539 case MINUS_EXPR:
1540 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1541 ? BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW
1542 : BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW_ABORT;
1543 break;
1544 case MULT_EXPR:
1545 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1546 ? BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW
1547 : BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW_ABORT;
1548 break;
1549 case NEGATE_EXPR:
1550 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1551 ? BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW
1552 : BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW_ABORT;
1553 break;
1554 default:
1555 gcc_unreachable ();
1557 tree fn = builtin_decl_explicit (fn_code);
1558 return build_call_expr_loc (loc, fn, 2 + (code != NEGATE_EXPR),
1559 build_fold_addr_expr_loc (loc, data),
1560 ubsan_encode_value (op0, UBSAN_ENCODE_VALUE_RTL),
1562 ? ubsan_encode_value (op1,
1563 UBSAN_ENCODE_VALUE_RTL)
1564 : NULL_TREE);
1567 /* Perform the signed integer instrumentation. GSI is the iterator
1568 pointing at statement we are trying to instrument. */
1570 static void
1571 instrument_si_overflow (gimple_stmt_iterator gsi)
1573 gimple *stmt = gsi_stmt (gsi);
1574 tree_code code = gimple_assign_rhs_code (stmt);
1575 tree lhs = gimple_assign_lhs (stmt);
1576 tree lhstype = TREE_TYPE (lhs);
1577 tree lhsinner = VECTOR_TYPE_P (lhstype) ? TREE_TYPE (lhstype) : lhstype;
1578 tree a, b;
1579 gimple *g;
1581 /* If this is not a signed operation, don't instrument anything here.
1582 Also punt on bit-fields. */
1583 if (!INTEGRAL_TYPE_P (lhsinner)
1584 || TYPE_OVERFLOW_WRAPS (lhsinner)
1585 || GET_MODE_BITSIZE (TYPE_MODE (lhsinner)) != TYPE_PRECISION (lhsinner))
1586 return;
1588 switch (code)
1590 case MINUS_EXPR:
1591 case PLUS_EXPR:
1592 case MULT_EXPR:
1593 /* Transform
1594 i = u {+,-,*} 5;
1595 into
1596 i = UBSAN_CHECK_{ADD,SUB,MUL} (u, 5); */
1597 a = gimple_assign_rhs1 (stmt);
1598 b = gimple_assign_rhs2 (stmt);
1599 g = gimple_build_call_internal (code == PLUS_EXPR
1600 ? IFN_UBSAN_CHECK_ADD
1601 : code == MINUS_EXPR
1602 ? IFN_UBSAN_CHECK_SUB
1603 : IFN_UBSAN_CHECK_MUL, 2, a, b);
1604 gimple_call_set_lhs (g, lhs);
1605 gsi_replace (&gsi, g, true);
1606 break;
1607 case NEGATE_EXPR:
1608 /* Represent i = -u;
1610 i = UBSAN_CHECK_SUB (0, u); */
1611 a = build_zero_cst (lhstype);
1612 b = gimple_assign_rhs1 (stmt);
1613 g = gimple_build_call_internal (IFN_UBSAN_CHECK_SUB, 2, a, b);
1614 gimple_call_set_lhs (g, lhs);
1615 gsi_replace (&gsi, g, true);
1616 break;
1617 case ABS_EXPR:
1618 /* Transform i = ABS_EXPR<u>;
1619 into
1620 _N = UBSAN_CHECK_SUB (0, u);
1621 i = ABS_EXPR<_N>; */
1622 a = build_zero_cst (lhstype);
1623 b = gimple_assign_rhs1 (stmt);
1624 g = gimple_build_call_internal (IFN_UBSAN_CHECK_SUB, 2, a, b);
1625 a = make_ssa_name (lhstype);
1626 gimple_call_set_lhs (g, a);
1627 gimple_set_location (g, gimple_location (stmt));
1628 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
1629 gimple_assign_set_rhs1 (stmt, a);
1630 update_stmt (stmt);
1631 break;
1632 default:
1633 break;
1637 /* Instrument loads from (non-bitfield) bool and C++ enum values
1638 to check if the memory value is outside of the range of the valid
1639 type values. */
1641 static void
1642 instrument_bool_enum_load (gimple_stmt_iterator *gsi)
1644 gimple *stmt = gsi_stmt (*gsi);
1645 tree rhs = gimple_assign_rhs1 (stmt);
1646 tree type = TREE_TYPE (rhs);
1647 tree minv = NULL_TREE, maxv = NULL_TREE;
1649 if (TREE_CODE (type) == BOOLEAN_TYPE
1650 && sanitize_flags_p (SANITIZE_BOOL))
1652 minv = boolean_false_node;
1653 maxv = boolean_true_node;
1655 else if (TREE_CODE (type) == ENUMERAL_TYPE
1656 && sanitize_flags_p (SANITIZE_ENUM)
1657 && TREE_TYPE (type) != NULL_TREE
1658 && TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE
1659 && (TYPE_PRECISION (TREE_TYPE (type))
1660 < GET_MODE_PRECISION (TYPE_MODE (type))))
1662 minv = TYPE_MIN_VALUE (TREE_TYPE (type));
1663 maxv = TYPE_MAX_VALUE (TREE_TYPE (type));
1665 else
1666 return;
1668 int modebitsize = GET_MODE_BITSIZE (TYPE_MODE (type));
1669 HOST_WIDE_INT bitsize, bitpos;
1670 tree offset;
1671 machine_mode mode;
1672 int volatilep = 0, reversep, unsignedp = 0;
1673 tree base = get_inner_reference (rhs, &bitsize, &bitpos, &offset, &mode,
1674 &unsignedp, &reversep, &volatilep);
1675 tree utype = build_nonstandard_integer_type (modebitsize, 1);
1677 if ((VAR_P (base) && DECL_HARD_REGISTER (base))
1678 || (bitpos % modebitsize) != 0
1679 || bitsize != modebitsize
1680 || GET_MODE_BITSIZE (TYPE_MODE (utype)) != modebitsize
1681 || TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME)
1682 return;
1684 bool ends_bb = stmt_ends_bb_p (stmt);
1685 location_t loc = gimple_location (stmt);
1686 tree lhs = gimple_assign_lhs (stmt);
1687 tree ptype = build_pointer_type (TREE_TYPE (rhs));
1688 tree atype = reference_alias_ptr_type (rhs);
1689 gimple *g = gimple_build_assign (make_ssa_name (ptype),
1690 build_fold_addr_expr (rhs));
1691 gimple_set_location (g, loc);
1692 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1693 tree mem = build2 (MEM_REF, utype, gimple_assign_lhs (g),
1694 build_int_cst (atype, 0));
1695 tree urhs = make_ssa_name (utype);
1696 if (ends_bb)
1698 gimple_assign_set_lhs (stmt, urhs);
1699 g = gimple_build_assign (lhs, NOP_EXPR, urhs);
1700 gimple_set_location (g, loc);
1701 edge e = find_fallthru_edge (gimple_bb (stmt)->succs);
1702 gsi_insert_on_edge_immediate (e, g);
1703 gimple_assign_set_rhs_from_tree (gsi, mem);
1704 update_stmt (stmt);
1705 *gsi = gsi_for_stmt (g);
1706 g = stmt;
1708 else
1710 g = gimple_build_assign (urhs, mem);
1711 gimple_set_location (g, loc);
1712 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1714 minv = fold_convert (utype, minv);
1715 maxv = fold_convert (utype, maxv);
1716 if (!integer_zerop (minv))
1718 g = gimple_build_assign (make_ssa_name (utype), MINUS_EXPR, urhs, minv);
1719 gimple_set_location (g, loc);
1720 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1723 gimple_stmt_iterator gsi2 = *gsi;
1724 basic_block then_bb, fallthru_bb;
1725 *gsi = create_cond_insert_point (gsi, true, false, true,
1726 &then_bb, &fallthru_bb);
1727 g = gimple_build_cond (GT_EXPR, gimple_assign_lhs (g),
1728 int_const_binop (MINUS_EXPR, maxv, minv),
1729 NULL_TREE, NULL_TREE);
1730 gimple_set_location (g, loc);
1731 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1733 if (!ends_bb)
1735 gimple_assign_set_rhs_with_ops (&gsi2, NOP_EXPR, urhs);
1736 update_stmt (stmt);
1739 gsi2 = gsi_after_labels (then_bb);
1740 if (flag_sanitize_undefined_trap_on_error)
1741 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1742 else
1744 tree data = ubsan_create_data ("__ubsan_invalid_value_data", 1, &loc,
1745 ubsan_type_descriptor (type), NULL_TREE,
1746 NULL_TREE);
1747 data = build_fold_addr_expr_loc (loc, data);
1748 enum built_in_function bcode
1749 = (flag_sanitize_recover & (TREE_CODE (type) == BOOLEAN_TYPE
1750 ? SANITIZE_BOOL : SANITIZE_ENUM))
1751 ? BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE
1752 : BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE_ABORT;
1753 tree fn = builtin_decl_explicit (bcode);
1755 tree val = ubsan_encode_value (urhs, UBSAN_ENCODE_VALUE_GIMPLE);
1756 val = force_gimple_operand_gsi (&gsi2, val, true, NULL_TREE, true,
1757 GSI_SAME_STMT);
1758 g = gimple_build_call (fn, 2, data, val);
1760 gimple_set_location (g, loc);
1761 gsi_insert_before (&gsi2, g, GSI_SAME_STMT);
1762 ubsan_create_edge (g);
1763 *gsi = gsi_for_stmt (stmt);
1766 /* Determine if we can propagate given LOCATION to ubsan_data descriptor to use
1767 new style handlers. Libubsan uses heuristics to destinguish between old and
1768 new styles and relies on these properties for filename:
1770 a) Location's filename must not be NULL.
1771 b) Location's filename must not be equal to "".
1772 c) Location's filename must not be equal to "\1".
1773 d) First two bytes of filename must not contain '\xff' symbol. */
1775 static bool
1776 ubsan_use_new_style_p (location_t loc)
1778 if (loc == UNKNOWN_LOCATION)
1779 return false;
1781 expanded_location xloc = expand_location (loc);
1782 if (xloc.file == NULL || strncmp (xloc.file, "\1", 2) == 0
1783 || xloc.file[0] == '\0' || xloc.file[0] == '\xff'
1784 || xloc.file[1] == '\xff')
1785 return false;
1787 return true;
1790 /* Instrument float point-to-integer conversion. TYPE is an integer type of
1791 destination, EXPR is floating-point expression. */
1793 tree
1794 ubsan_instrument_float_cast (location_t loc, tree type, tree expr)
1796 tree expr_type = TREE_TYPE (expr);
1797 tree t, tt, fn, min, max;
1798 machine_mode mode = TYPE_MODE (expr_type);
1799 int prec = TYPE_PRECISION (type);
1800 bool uns_p = TYPE_UNSIGNED (type);
1801 if (loc == UNKNOWN_LOCATION)
1802 loc = input_location;
1804 /* Float to integer conversion first truncates toward zero, so
1805 even signed char c = 127.875f; is not problematic.
1806 Therefore, we should complain only if EXPR is unordered or smaller
1807 or equal than TYPE_MIN_VALUE - 1.0 or greater or equal than
1808 TYPE_MAX_VALUE + 1.0. */
1809 if (REAL_MODE_FORMAT (mode)->b == 2)
1811 /* For maximum, TYPE_MAX_VALUE might not be representable
1812 in EXPR_TYPE, e.g. if TYPE is 64-bit long long and
1813 EXPR_TYPE is IEEE single float, but TYPE_MAX_VALUE + 1.0 is
1814 either representable or infinity. */
1815 REAL_VALUE_TYPE maxval = dconst1;
1816 SET_REAL_EXP (&maxval, REAL_EXP (&maxval) + prec - !uns_p);
1817 real_convert (&maxval, mode, &maxval);
1818 max = build_real (expr_type, maxval);
1820 /* For unsigned, assume -1.0 is always representable. */
1821 if (uns_p)
1822 min = build_minus_one_cst (expr_type);
1823 else
1825 /* TYPE_MIN_VALUE is generally representable (or -inf),
1826 but TYPE_MIN_VALUE - 1.0 might not be. */
1827 REAL_VALUE_TYPE minval = dconstm1, minval2;
1828 SET_REAL_EXP (&minval, REAL_EXP (&minval) + prec - 1);
1829 real_convert (&minval, mode, &minval);
1830 real_arithmetic (&minval2, MINUS_EXPR, &minval, &dconst1);
1831 real_convert (&minval2, mode, &minval2);
1832 if (real_compare (EQ_EXPR, &minval, &minval2)
1833 && !real_isinf (&minval))
1835 /* If TYPE_MIN_VALUE - 1.0 is not representable and
1836 rounds to TYPE_MIN_VALUE, we need to subtract
1837 more. As REAL_MODE_FORMAT (mode)->p is the number
1838 of base digits, we want to subtract a number that
1839 will be 1 << (REAL_MODE_FORMAT (mode)->p - 1)
1840 times smaller than minval. */
1841 minval2 = dconst1;
1842 gcc_assert (prec > REAL_MODE_FORMAT (mode)->p);
1843 SET_REAL_EXP (&minval2,
1844 REAL_EXP (&minval2) + prec - 1
1845 - REAL_MODE_FORMAT (mode)->p + 1);
1846 real_arithmetic (&minval2, MINUS_EXPR, &minval, &minval2);
1847 real_convert (&minval2, mode, &minval2);
1849 min = build_real (expr_type, minval2);
1852 else if (REAL_MODE_FORMAT (mode)->b == 10)
1854 /* For _Decimal128 up to 34 decimal digits, - sign,
1855 dot, e, exponent. */
1856 char buf[64];
1857 mpfr_t m;
1858 int p = REAL_MODE_FORMAT (mode)->p;
1859 REAL_VALUE_TYPE maxval, minval;
1861 /* Use mpfr_snprintf rounding to compute the smallest
1862 representable decimal number greater or equal than
1863 1 << (prec - !uns_p). */
1864 mpfr_init2 (m, prec + 2);
1865 mpfr_set_ui_2exp (m, 1, prec - !uns_p, GMP_RNDN);
1866 mpfr_snprintf (buf, sizeof buf, "%.*RUe", p - 1, m);
1867 decimal_real_from_string (&maxval, buf);
1868 max = build_real (expr_type, maxval);
1870 /* For unsigned, assume -1.0 is always representable. */
1871 if (uns_p)
1872 min = build_minus_one_cst (expr_type);
1873 else
1875 /* Use mpfr_snprintf rounding to compute the largest
1876 representable decimal number less or equal than
1877 (-1 << (prec - 1)) - 1. */
1878 mpfr_set_si_2exp (m, -1, prec - 1, GMP_RNDN);
1879 mpfr_sub_ui (m, m, 1, GMP_RNDN);
1880 mpfr_snprintf (buf, sizeof buf, "%.*RDe", p - 1, m);
1881 decimal_real_from_string (&minval, buf);
1882 min = build_real (expr_type, minval);
1884 mpfr_clear (m);
1886 else
1887 return NULL_TREE;
1889 t = fold_build2 (UNLE_EXPR, boolean_type_node, expr, min);
1890 tt = fold_build2 (UNGE_EXPR, boolean_type_node, expr, max);
1891 t = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t, tt);
1892 if (integer_zerop (t))
1893 return NULL_TREE;
1895 if (flag_sanitize_undefined_trap_on_error)
1896 fn = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
1897 else
1899 location_t *loc_ptr = NULL;
1900 unsigned num_locations = 0;
1901 /* Figure out if we can propagate location to ubsan_data and use new
1902 style handlers in libubsan. */
1903 if (ubsan_use_new_style_p (loc))
1905 loc_ptr = &loc;
1906 num_locations = 1;
1908 /* Create the __ubsan_handle_float_cast_overflow fn call. */
1909 tree data = ubsan_create_data ("__ubsan_float_cast_overflow_data",
1910 num_locations, loc_ptr,
1911 ubsan_type_descriptor (expr_type),
1912 ubsan_type_descriptor (type), NULL_TREE,
1913 NULL_TREE);
1914 enum built_in_function bcode
1915 = (flag_sanitize_recover & SANITIZE_FLOAT_CAST)
1916 ? BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW
1917 : BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW_ABORT;
1918 fn = builtin_decl_explicit (bcode);
1919 fn = build_call_expr_loc (loc, fn, 2,
1920 build_fold_addr_expr_loc (loc, data),
1921 ubsan_encode_value (expr));
1924 return fold_build3 (COND_EXPR, void_type_node, t, fn, integer_zero_node);
1927 /* Instrument values passed to function arguments with nonnull attribute. */
1929 static void
1930 instrument_nonnull_arg (gimple_stmt_iterator *gsi)
1932 gimple *stmt = gsi_stmt (*gsi);
1933 location_t loc[2];
1934 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
1935 while for nonnull sanitization it is clear. */
1936 int save_flag_delete_null_pointer_checks = flag_delete_null_pointer_checks;
1937 flag_delete_null_pointer_checks = 1;
1938 loc[0] = gimple_location (stmt);
1939 loc[1] = UNKNOWN_LOCATION;
1940 for (unsigned int i = 0; i < gimple_call_num_args (stmt); i++)
1942 tree arg = gimple_call_arg (stmt, i);
1943 if (POINTER_TYPE_P (TREE_TYPE (arg))
1944 && infer_nonnull_range_by_attribute (stmt, arg))
1946 gimple *g;
1947 if (!is_gimple_val (arg))
1949 g = gimple_build_assign (make_ssa_name (TREE_TYPE (arg)), arg);
1950 gimple_set_location (g, loc[0]);
1951 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1952 arg = gimple_assign_lhs (g);
1955 basic_block then_bb, fallthru_bb;
1956 *gsi = create_cond_insert_point (gsi, true, false, true,
1957 &then_bb, &fallthru_bb);
1958 g = gimple_build_cond (EQ_EXPR, arg,
1959 build_zero_cst (TREE_TYPE (arg)),
1960 NULL_TREE, NULL_TREE);
1961 gimple_set_location (g, loc[0]);
1962 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1964 *gsi = gsi_after_labels (then_bb);
1965 if (flag_sanitize_undefined_trap_on_error)
1966 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1967 else
1969 tree data = ubsan_create_data ("__ubsan_nonnull_arg_data",
1970 2, loc, NULL_TREE,
1971 build_int_cst (integer_type_node,
1972 i + 1),
1973 NULL_TREE);
1974 data = build_fold_addr_expr_loc (loc[0], data);
1975 enum built_in_function bcode
1976 = (flag_sanitize_recover & SANITIZE_NONNULL_ATTRIBUTE)
1977 ? BUILT_IN_UBSAN_HANDLE_NONNULL_ARG
1978 : BUILT_IN_UBSAN_HANDLE_NONNULL_ARG_ABORT;
1979 tree fn = builtin_decl_explicit (bcode);
1981 g = gimple_build_call (fn, 1, data);
1983 gimple_set_location (g, loc[0]);
1984 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1985 ubsan_create_edge (g);
1987 *gsi = gsi_for_stmt (stmt);
1989 flag_delete_null_pointer_checks = save_flag_delete_null_pointer_checks;
1992 /* Instrument returns in functions with returns_nonnull attribute. */
1994 static void
1995 instrument_nonnull_return (gimple_stmt_iterator *gsi)
1997 greturn *stmt = as_a <greturn *> (gsi_stmt (*gsi));
1998 location_t loc[2];
1999 tree arg = gimple_return_retval (stmt);
2000 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
2001 while for nonnull return sanitization it is clear. */
2002 int save_flag_delete_null_pointer_checks = flag_delete_null_pointer_checks;
2003 flag_delete_null_pointer_checks = 1;
2004 loc[0] = gimple_location (stmt);
2005 loc[1] = UNKNOWN_LOCATION;
2006 if (arg
2007 && POINTER_TYPE_P (TREE_TYPE (arg))
2008 && is_gimple_val (arg)
2009 && infer_nonnull_range_by_attribute (stmt, arg))
2011 basic_block then_bb, fallthru_bb;
2012 *gsi = create_cond_insert_point (gsi, true, false, true,
2013 &then_bb, &fallthru_bb);
2014 gimple *g = gimple_build_cond (EQ_EXPR, arg,
2015 build_zero_cst (TREE_TYPE (arg)),
2016 NULL_TREE, NULL_TREE);
2017 gimple_set_location (g, loc[0]);
2018 gsi_insert_after (gsi, g, GSI_NEW_STMT);
2020 *gsi = gsi_after_labels (then_bb);
2021 if (flag_sanitize_undefined_trap_on_error)
2022 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
2023 else
2025 tree data = ubsan_create_data ("__ubsan_nonnull_return_data",
2026 2, loc, NULL_TREE, NULL_TREE);
2027 data = build_fold_addr_expr_loc (loc[0], data);
2028 enum built_in_function bcode
2029 = (flag_sanitize_recover & SANITIZE_RETURNS_NONNULL_ATTRIBUTE)
2030 ? BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN
2031 : BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_ABORT;
2032 tree fn = builtin_decl_explicit (bcode);
2034 g = gimple_build_call (fn, 1, data);
2036 gimple_set_location (g, loc[0]);
2037 gsi_insert_before (gsi, g, GSI_SAME_STMT);
2038 ubsan_create_edge (g);
2039 *gsi = gsi_for_stmt (stmt);
2041 flag_delete_null_pointer_checks = save_flag_delete_null_pointer_checks;
2044 /* Instrument memory references. Here we check whether the pointer
2045 points to an out-of-bounds location. */
2047 static void
2048 instrument_object_size (gimple_stmt_iterator *gsi, tree t, bool is_lhs)
2050 gimple *stmt = gsi_stmt (*gsi);
2051 location_t loc = gimple_location (stmt);
2052 tree type;
2053 tree index = NULL_TREE;
2054 HOST_WIDE_INT size_in_bytes;
2056 type = TREE_TYPE (t);
2057 if (VOID_TYPE_P (type))
2058 return;
2060 switch (TREE_CODE (t))
2062 case COMPONENT_REF:
2063 if (TREE_CODE (t) == COMPONENT_REF
2064 && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1)) != NULL_TREE)
2066 tree repr = DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1));
2067 t = build3 (COMPONENT_REF, TREE_TYPE (repr), TREE_OPERAND (t, 0),
2068 repr, TREE_OPERAND (t, 2));
2070 break;
2071 case ARRAY_REF:
2072 index = TREE_OPERAND (t, 1);
2073 break;
2074 case INDIRECT_REF:
2075 case MEM_REF:
2076 case VAR_DECL:
2077 case PARM_DECL:
2078 case RESULT_DECL:
2079 break;
2080 default:
2081 return;
2084 size_in_bytes = int_size_in_bytes (type);
2085 if (size_in_bytes <= 0)
2086 return;
2088 HOST_WIDE_INT bitsize, bitpos;
2089 tree offset;
2090 machine_mode mode;
2091 int volatilep = 0, reversep, unsignedp = 0;
2092 tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset, &mode,
2093 &unsignedp, &reversep, &volatilep);
2095 if (bitpos % BITS_PER_UNIT != 0
2096 || bitsize != size_in_bytes * BITS_PER_UNIT)
2097 return;
2099 bool decl_p = DECL_P (inner);
2100 tree base;
2101 if (decl_p)
2103 if (DECL_REGISTER (inner))
2104 return;
2105 base = inner;
2107 else if (TREE_CODE (inner) == MEM_REF)
2108 base = TREE_OPERAND (inner, 0);
2109 else
2110 return;
2111 tree ptr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (t)), t);
2113 while (TREE_CODE (base) == SSA_NAME)
2115 gimple *def_stmt = SSA_NAME_DEF_STMT (base);
2116 if (gimple_assign_ssa_name_copy_p (def_stmt)
2117 || (gimple_assign_cast_p (def_stmt)
2118 && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (def_stmt))))
2119 || (is_gimple_assign (def_stmt)
2120 && gimple_assign_rhs_code (def_stmt) == POINTER_PLUS_EXPR))
2122 tree rhs1 = gimple_assign_rhs1 (def_stmt);
2123 if (TREE_CODE (rhs1) == SSA_NAME
2124 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs1))
2125 break;
2126 else
2127 base = rhs1;
2129 else
2130 break;
2133 if (!POINTER_TYPE_P (TREE_TYPE (base)) && !DECL_P (base))
2134 return;
2136 tree sizet;
2137 tree base_addr = base;
2138 gimple *bos_stmt = NULL;
2139 if (decl_p)
2140 base_addr = build1 (ADDR_EXPR,
2141 build_pointer_type (TREE_TYPE (base)), base);
2142 unsigned HOST_WIDE_INT size;
2143 if (compute_builtin_object_size (base_addr, 0, &size))
2144 sizet = build_int_cst (sizetype, size);
2145 else if (optimize)
2147 if (LOCATION_LOCUS (loc) == UNKNOWN_LOCATION)
2148 loc = input_location;
2149 /* Generate __builtin_object_size call. */
2150 sizet = builtin_decl_explicit (BUILT_IN_OBJECT_SIZE);
2151 sizet = build_call_expr_loc (loc, sizet, 2, base_addr,
2152 integer_zero_node);
2153 sizet = force_gimple_operand_gsi (gsi, sizet, false, NULL_TREE, true,
2154 GSI_SAME_STMT);
2155 /* If the call above didn't end up being an integer constant, go one
2156 statement back and get the __builtin_object_size stmt. Save it,
2157 we might need it later. */
2158 if (SSA_VAR_P (sizet))
2160 gsi_prev (gsi);
2161 bos_stmt = gsi_stmt (*gsi);
2163 /* Move on to where we were. */
2164 gsi_next (gsi);
2167 else
2168 return;
2170 /* Generate UBSAN_OBJECT_SIZE (ptr, ptr+sizeof(*ptr)-base, objsize, ckind)
2171 call. */
2172 /* ptr + sizeof (*ptr) - base */
2173 t = fold_build2 (MINUS_EXPR, sizetype,
2174 fold_convert (pointer_sized_int_node, ptr),
2175 fold_convert (pointer_sized_int_node, base_addr));
2176 t = fold_build2 (PLUS_EXPR, sizetype, t, TYPE_SIZE_UNIT (type));
2178 /* Perhaps we can omit the check. */
2179 if (TREE_CODE (t) == INTEGER_CST
2180 && TREE_CODE (sizet) == INTEGER_CST
2181 && tree_int_cst_le (t, sizet))
2182 return;
2184 if (index != NULL_TREE
2185 && TREE_CODE (index) == SSA_NAME
2186 && TREE_CODE (sizet) == INTEGER_CST)
2188 gimple *def = SSA_NAME_DEF_STMT (index);
2189 if (is_gimple_assign (def)
2190 && gimple_assign_rhs_code (def) == BIT_AND_EXPR
2191 && TREE_CODE (gimple_assign_rhs2 (def)) == INTEGER_CST)
2193 tree cst = gimple_assign_rhs2 (def);
2194 tree sz = fold_build2 (EXACT_DIV_EXPR, sizetype, sizet,
2195 TYPE_SIZE_UNIT (type));
2196 if (tree_int_cst_sgn (cst) >= 0
2197 && tree_int_cst_lt (cst, sz))
2198 return;
2202 if (bos_stmt && gimple_call_builtin_p (bos_stmt, BUILT_IN_OBJECT_SIZE))
2203 ubsan_create_edge (bos_stmt);
2205 /* We have to emit the check. */
2206 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE, true,
2207 GSI_SAME_STMT);
2208 ptr = force_gimple_operand_gsi (gsi, ptr, true, NULL_TREE, true,
2209 GSI_SAME_STMT);
2210 tree ckind = build_int_cst (unsigned_char_type_node,
2211 is_lhs ? UBSAN_STORE_OF : UBSAN_LOAD_OF);
2212 gimple *g = gimple_build_call_internal (IFN_UBSAN_OBJECT_SIZE, 4,
2213 ptr, t, sizet, ckind);
2214 gimple_set_location (g, loc);
2215 gsi_insert_before (gsi, g, GSI_SAME_STMT);
2218 namespace {
2220 const pass_data pass_data_ubsan =
2222 GIMPLE_PASS, /* type */
2223 "ubsan", /* name */
2224 OPTGROUP_NONE, /* optinfo_flags */
2225 TV_TREE_UBSAN, /* tv_id */
2226 ( PROP_cfg | PROP_ssa ), /* properties_required */
2227 0, /* properties_provided */
2228 0, /* properties_destroyed */
2229 0, /* todo_flags_start */
2230 TODO_update_ssa, /* todo_flags_finish */
2233 class pass_ubsan : public gimple_opt_pass
2235 public:
2236 pass_ubsan (gcc::context *ctxt)
2237 : gimple_opt_pass (pass_data_ubsan, ctxt)
2240 /* opt_pass methods: */
2241 virtual bool gate (function *)
2243 return sanitize_flags_p ((SANITIZE_NULL | SANITIZE_SI_OVERFLOW
2244 | SANITIZE_BOOL | SANITIZE_ENUM
2245 | SANITIZE_ALIGNMENT
2246 | SANITIZE_NONNULL_ATTRIBUTE
2247 | SANITIZE_RETURNS_NONNULL_ATTRIBUTE
2248 | SANITIZE_OBJECT_SIZE
2249 | SANITIZE_POINTER_OVERFLOW));
2252 virtual unsigned int execute (function *);
2254 }; // class pass_ubsan
2256 unsigned int
2257 pass_ubsan::execute (function *fun)
2259 basic_block bb;
2260 gimple_stmt_iterator gsi;
2261 unsigned int ret = 0;
2263 initialize_sanitizer_builtins ();
2265 FOR_EACH_BB_FN (bb, fun)
2267 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
2269 gimple *stmt = gsi_stmt (gsi);
2270 if (is_gimple_debug (stmt) || gimple_clobber_p (stmt))
2272 gsi_next (&gsi);
2273 continue;
2276 if ((sanitize_flags_p (SANITIZE_SI_OVERFLOW, fun->decl))
2277 && is_gimple_assign (stmt))
2278 instrument_si_overflow (gsi);
2280 if (sanitize_flags_p (SANITIZE_NULL | SANITIZE_ALIGNMENT, fun->decl))
2282 if (gimple_store_p (stmt))
2283 instrument_null (gsi, gimple_get_lhs (stmt), true);
2284 if (gimple_assign_single_p (stmt))
2285 instrument_null (gsi, gimple_assign_rhs1 (stmt), false);
2286 if (is_gimple_call (stmt))
2288 unsigned args_num = gimple_call_num_args (stmt);
2289 for (unsigned i = 0; i < args_num; ++i)
2291 tree arg = gimple_call_arg (stmt, i);
2292 if (is_gimple_reg (arg) || is_gimple_min_invariant (arg))
2293 continue;
2294 instrument_null (gsi, arg, false);
2299 if (sanitize_flags_p (SANITIZE_BOOL | SANITIZE_ENUM, fun->decl)
2300 && gimple_assign_load_p (stmt))
2302 instrument_bool_enum_load (&gsi);
2303 bb = gimple_bb (stmt);
2306 if (sanitize_flags_p (SANITIZE_NONNULL_ATTRIBUTE, fun->decl)
2307 && is_gimple_call (stmt)
2308 && !gimple_call_internal_p (stmt))
2310 instrument_nonnull_arg (&gsi);
2311 bb = gimple_bb (stmt);
2314 if (sanitize_flags_p (SANITIZE_RETURNS_NONNULL_ATTRIBUTE, fun->decl)
2315 && gimple_code (stmt) == GIMPLE_RETURN)
2317 instrument_nonnull_return (&gsi);
2318 bb = gimple_bb (stmt);
2321 if (sanitize_flags_p (SANITIZE_OBJECT_SIZE, fun->decl))
2323 if (gimple_store_p (stmt))
2324 instrument_object_size (&gsi, gimple_get_lhs (stmt), true);
2325 if (gimple_assign_load_p (stmt))
2326 instrument_object_size (&gsi, gimple_assign_rhs1 (stmt),
2327 false);
2328 if (is_gimple_call (stmt))
2330 unsigned args_num = gimple_call_num_args (stmt);
2331 for (unsigned i = 0; i < args_num; ++i)
2333 tree arg = gimple_call_arg (stmt, i);
2334 if (is_gimple_reg (arg) || is_gimple_min_invariant (arg))
2335 continue;
2336 instrument_object_size (&gsi, arg, false);
2341 if (sanitize_flags_p (SANITIZE_POINTER_OVERFLOW, fun->decl))
2343 if (is_gimple_assign (stmt)
2344 && gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
2345 instrument_pointer_overflow (&gsi,
2346 gimple_assign_rhs1 (stmt),
2347 gimple_assign_rhs2 (stmt));
2348 if (gimple_store_p (stmt))
2349 maybe_instrument_pointer_overflow (&gsi,
2350 gimple_get_lhs (stmt));
2351 if (gimple_assign_single_p (stmt))
2352 maybe_instrument_pointer_overflow (&gsi,
2353 gimple_assign_rhs1 (stmt));
2354 if (is_gimple_call (stmt))
2356 unsigned args_num = gimple_call_num_args (stmt);
2357 for (unsigned i = 0; i < args_num; ++i)
2359 tree arg = gimple_call_arg (stmt, i);
2360 if (is_gimple_reg (arg))
2361 continue;
2362 maybe_instrument_pointer_overflow (&gsi, arg);
2367 gsi_next (&gsi);
2369 if (gimple_purge_dead_eh_edges (bb))
2370 ret = TODO_cleanup_cfg;
2372 return ret;
2375 } // anon namespace
2377 gimple_opt_pass *
2378 make_pass_ubsan (gcc::context *ctxt)
2380 return new pass_ubsan (ctxt);
2383 #include "gt-ubsan.h"