gfortran.h (gfc_option_t): Remove warn_aliasing,
[gcc.git] / gcc / ubsan.c
1 /* UndefinedBehaviorSanitizer, undefined behavior detector.
2 Copyright (C) 2013-2014 Free Software Foundation, Inc.
3 Contributed by Marek Polacek <polacek@redhat.com>
4
5 This file is part of GCC.
6
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.
11
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.
16
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/>. */
20
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tree.h"
25 #include "stor-layout.h"
26 #include "stringpool.h"
27 #include "predict.h"
28 #include "dominance.h"
29 #include "cfg.h"
30 #include "cfganal.h"
31 #include "basic-block.h"
32 #include "hash-map.h"
33 #include "is-a.h"
34 #include "plugin-api.h"
35 #include "vec.h"
36 #include "hashtab.h"
37 #include "hash-set.h"
38 #include "machmode.h"
39 #include "tm.h"
40 #include "hard-reg-set.h"
41 #include "input.h"
42 #include "function.h"
43 #include "ipa-ref.h"
44 #include "cgraph.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"
50 #include "gimple.h"
51 #include "gimple-iterator.h"
52 #include "gimple-ssa.h"
53 #include "gimple-walk.h"
54 #include "output.h"
55 #include "tm_p.h"
56 #include "toplev.h"
57 #include "cfgloop.h"
58 #include "ubsan.h"
59 #include "c-family/c-common.h"
60 #include "rtl.h"
61 #include "expr.h"
62 #include "tree-ssanames.h"
63 #include "asan.h"
64 #include "gimplify-me.h"
65 #include "intl.h"
66 #include "realmpfr.h"
67 #include "dfp.h"
68 #include "builtins.h"
69 #include "tree-object-size.h"
70 #include "tree-eh.h"
71
72 /* Map from a tree to a VAR_DECL tree. */
73
74 struct GTY((for_user)) tree_type_map {
75 struct tree_map_base type;
76 tree decl;
77 };
78
79 struct tree_type_map_cache_hasher : ggc_cache_hasher<tree_type_map *>
80 {
81 static inline hashval_t
82 hash (tree_type_map *t)
83 {
84 return TYPE_UID (t->type.from);
85 }
86
87 static inline bool
88 equal (tree_type_map *a, tree_type_map *b)
89 {
90 return a->type.from == b->type.from;
91 }
92
93 static void
94 handle_cache_entry (tree_type_map *&m)
95 {
96 extern void gt_ggc_mx (tree_type_map *&);
97 if (m == HTAB_EMPTY_ENTRY || m == HTAB_DELETED_ENTRY)
98 return;
99 else if (ggc_marked_p (m->type.from))
100 gt_ggc_mx (m);
101 else
102 m = static_cast<tree_type_map *> (HTAB_DELETED_ENTRY);
103 }
104 };
105
106 static GTY ((cache))
107 hash_table<tree_type_map_cache_hasher> *decl_tree_for_type;
108
109 /* Lookup a VAR_DECL for TYPE, and return it if we find one. */
110
111 static tree
112 decl_for_type_lookup (tree type)
113 {
114 /* If the hash table is not initialized yet, create it now. */
115 if (decl_tree_for_type == NULL)
116 {
117 decl_tree_for_type
118 = hash_table<tree_type_map_cache_hasher>::create_ggc (10);
119 /* That also means we don't have to bother with the lookup. */
120 return NULL_TREE;
121 }
122
123 struct tree_type_map *h, in;
124 in.type.from = type;
125
126 h = decl_tree_for_type->find_with_hash (&in, TYPE_UID (type));
127 return h ? h->decl : NULL_TREE;
128 }
129
130 /* Insert a mapping TYPE->DECL in the VAR_DECL for type hashtable. */
131
132 static void
133 decl_for_type_insert (tree type, tree decl)
134 {
135 struct tree_type_map *h;
136
137 h = ggc_alloc<tree_type_map> ();
138 h->type.from = type;
139 h->decl = decl;
140 *decl_tree_for_type->find_slot_with_hash (h, TYPE_UID (type), INSERT) = h;
141 }
142
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. */
147
148 tree
149 ubsan_encode_value (tree t, bool in_expand_p)
150 {
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))
155 {
156 case BOOLEAN_TYPE:
157 case ENUMERAL_TYPE:
158 case INTEGER_TYPE:
159 return fold_build1 (NOP_EXPR, pointer_sized_int_node, t);
160 case REAL_TYPE:
161 {
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);
165 }
166 default:
167 gcc_unreachable ();
168 }
169 else
170 {
171 if (!DECL_P (t) || !TREE_ADDRESSABLE (t))
172 {
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);
177 if (in_expand_p)
178 {
179 rtx mem
180 = assign_stack_temp_for_type (TYPE_MODE (type),
181 GET_MODE_SIZE (TYPE_MODE (type)),
182 type);
183 SET_DECL_RTL (var, mem);
184 expand_assignment (var, t, false);
185 return build_fold_addr_expr (var);
186 }
187 t = build_fold_addr_expr (var);
188 return build2 (COMPOUND_EXPR, TREE_TYPE (t), tem, t);
189 }
190 else
191 return build_fold_addr_expr (t);
192 }
193 }
194
195 /* Cached ubsan_get_type_descriptor_type () return value. */
196 static GTY(()) tree ubsan_type_descriptor_type;
197
198 /* Build
199 struct __ubsan_type_descriptor
200 {
201 unsigned short __typekind;
202 unsigned short __typeinfo;
203 char __typename[];
204 }
205 type. */
206
207 static tree
208 ubsan_get_type_descriptor_type (void)
209 {
210 static const char *field_names[3]
211 = { "__typekind", "__typeinfo", "__typename" };
212 tree fields[3], ret;
213
214 if (ubsan_type_descriptor_type)
215 return ubsan_type_descriptor_type;
216
217 tree itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
218 tree flex_arr_type = build_array_type (char_type_node, itype);
219
220 ret = make_node (RECORD_TYPE);
221 for (int i = 0; i < 3; i++)
222 {
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;
228 if (i)
229 DECL_CHAIN (fields[i - 1]) = fields[i];
230 }
231 tree type_decl = build_decl (input_location, TYPE_DECL,
232 get_identifier ("__ubsan_type_descriptor"),
233 ret);
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;
239 layout_type (ret);
240 ubsan_type_descriptor_type = ret;
241 return ret;
242 }
243
244 /* Cached ubsan_get_source_location_type () return value. */
245 static GTY(()) tree ubsan_source_location_type;
246
247 /* Build
248 struct __ubsan_source_location
249 {
250 const char *__filename;
251 unsigned int __line;
252 unsigned int __column;
253 }
254 type. */
255
256 tree
257 ubsan_get_source_location_type (void)
258 {
259 static const char *field_names[3]
260 = { "__filename", "__line", "__column" };
261 tree fields[3], ret;
262 if (ubsan_source_location_type)
263 return ubsan_source_location_type;
264
265 tree const_char_type = build_qualified_type (char_type_node,
266 TYPE_QUAL_CONST);
267
268 ret = make_node (RECORD_TYPE);
269 for (int i = 0; i < 3; i++)
270 {
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;
276 if (i)
277 DECL_CHAIN (fields[i - 1]) = fields[i];
278 }
279 tree type_decl = build_decl (input_location, TYPE_DECL,
280 get_identifier ("__ubsan_source_location"),
281 ret);
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;
287 layout_type (ret);
288 ubsan_source_location_type = ret;
289 return ret;
290 }
291
292 /* Helper routine that returns a CONSTRUCTOR of __ubsan_source_location
293 type with its fields filled from a location_t LOC. */
294
295 static tree
296 ubsan_source_location (location_t loc)
297 {
298 expanded_location xloc;
299 tree type = ubsan_get_source_location_type ();
300
301 xloc = expand_location (loc);
302 tree str;
303 if (xloc.file == NULL)
304 {
305 str = build_int_cst (ptr_type_node, 0);
306 xloc.line = 0;
307 xloc.column = 0;
308 }
309 else
310 {
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);
319 }
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,
324 xloc.column));
325 TREE_CONSTANT (ctor) = 1;
326 TREE_STATIC (ctor) = 1;
327
328 return ctor;
329 }
330
331 /* This routine returns a magic number for TYPE. */
332
333 static unsigned short
334 get_ubsan_type_info_for_type (tree type)
335 {
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))
340 {
341 int prec = exact_log2 (tree_to_uhwi (TYPE_SIZE (type)));
342 gcc_assert (prec != -1);
343 return (prec << 1) | !TYPE_UNSIGNED (type);
344 }
345 else
346 return 0;
347 }
348
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. */
354
355 tree
356 ubsan_type_descriptor (tree type, enum ubsan_print_style pstyle)
357 {
358 /* See through any typedefs. */
359 type = TYPE_MAIN_VARIANT (type);
360
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,
365 renew them here. */
366 if (decl != NULL_TREE && varpool_node::get (decl))
367 return build_fold_addr_expr (decl);
368
369 tree dtype = ubsan_get_type_descriptor_type ();
370 tree type2 = type;
371 const char *tname = NULL;
372 char *pretty_name;
373 unsigned char deref_depth = 0;
374 unsigned short tkind, tinfo;
375
376 /* Get the name of the type, or the name of the pointer type. */
377 if (pstyle == UBSAN_PRINT_POINTER)
378 {
379 gcc_assert (POINTER_TYPE_P (type));
380 type2 = TREE_TYPE (type);
381
382 /* Remove any '*' operators from TYPE. */
383 while (POINTER_TYPE_P (type2))
384 deref_depth++, type2 = TREE_TYPE (type2);
385
386 if (TREE_CODE (type2) == METHOD_TYPE)
387 type2 = TYPE_METHOD_BASETYPE (type2);
388 }
389
390 /* If an array, get its type. */
391 type2 = strip_array_types (type2);
392
393 if (pstyle == UBSAN_PRINT_ARRAY)
394 {
395 while (POINTER_TYPE_P (type2))
396 deref_depth++, type2 = TREE_TYPE (type2);
397 }
398
399 if (TYPE_NAME (type2) != NULL)
400 {
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)));
405 }
406
407 if (tname == NULL)
408 /* We weren't able to determine the type name. */
409 tname = "<unknown>";
410
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)
414 {
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
421 ? "struct "
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';
429 }
430 else if (pstyle == UBSAN_PRINT_ARRAY)
431 {
432 /* Pretty print the array dimensions. */
433 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
434 tree t = 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)
439 {
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);
445 else
446 /* ??? We can't determine the variable name; print VLA unspec. */
447 pretty_name[pos++] = '*';
448 pretty_name[pos++] = ']';
449 t = TREE_TYPE (t);
450 }
451 pretty_name[pos++] = '\'';
452 pretty_name[pos] = '\0';
453
454 /* Save the tree with stripped types. */
455 type = t;
456 }
457 else
458 sprintf (pretty_name, "'%s'", tname);
459
460 switch (TREE_CODE (type))
461 {
462 case BOOLEAN_TYPE:
463 case ENUMERAL_TYPE:
464 case INTEGER_TYPE:
465 tkind = 0x0000;
466 break;
467 case REAL_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))
473 tkind = 0x0001;
474 else
475 tkind = 0xffff;
476 break;
477 default:
478 tkind = 0xffff;
479 break;
480 }
481 tinfo = get_ubsan_type_info_for_type (type);
482
483 /* Create a new VAR_DECL of type descriptor. */
484 char tmp_name[32];
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),
488 dtype);
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;
494
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,
503 tkind), NULL_TREE,
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);
510
511 /* Save the VAR_DECL into the hash table. */
512 decl_for_type_insert (type, decl);
513
514 return build_fold_addr_expr (decl);
515 }
516
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. */
522
523 tree
524 ubsan_create_data (const char *name, int loccnt, const location_t *ploc, ...)
525 {
526 va_list args;
527 tree ret, t;
528 tree fields[6];
529 vec<tree, va_gc> *saved_args = NULL;
530 size_t i = 0;
531 int j;
532
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);
536
537 /* Create the structure type. */
538 ret = make_node (RECORD_TYPE);
539 for (j = 0; j < loccnt; j++)
540 {
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;
545 if (i)
546 DECL_CHAIN (fields[i - 1]) = fields[i];
547 i++;
548 }
549
550 va_start (args, ploc);
551 for (t = va_arg (args, tree); t != NULL_TREE;
552 i++, t = va_arg (args, tree))
553 {
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,
558 td_type);
559 DECL_CONTEXT (fields[i]) = ret;
560 if (i)
561 DECL_CHAIN (fields[i - 1]) = fields[i];
562 }
563
564 for (t = va_arg (args, tree); t != NULL_TREE;
565 i++, t = va_arg (args, tree))
566 {
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,
571 TREE_TYPE (t));
572 DECL_CONTEXT (fields[i]) = ret;
573 if (i)
574 DECL_CHAIN (fields[i - 1]) = fields[i];
575 }
576 va_end (args);
577
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;
585 layout_type (ret);
586
587 /* Now, fill in the type. */
588 char tmp_name[32];
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),
592 ret);
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;
598
599 vec<constructor_elt, va_gc> *v;
600 vec_alloc (v, i);
601 tree ctor = build_constructor (ret, v);
602
603 /* If desirable, set the __ubsan_source_location element. */
604 for (j = 0; j < loccnt; j++)
605 {
606 location_t loc = LOCATION_LOCUS (ploc[j]);
607 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, ubsan_source_location (loc));
608 }
609
610 size_t nelts = vec_safe_length (saved_args);
611 for (i = 0; i < nelts; i++)
612 {
613 t = (*saved_args)[i];
614 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, t);
615 }
616
617 TREE_CONSTANT (ctor) = 1;
618 TREE_STATIC (ctor) = 1;
619 DECL_INITIAL (var) = ctor;
620 varpool_node::finalize_decl (var);
621
622 return var;
623 }
624
625 /* Instrument the __builtin_unreachable call. We just call the libubsan
626 routine instead. */
627
628 bool
629 ubsan_instrument_unreachable (gimple_stmt_iterator *gsi)
630 {
631 gimple g;
632 location_t loc = gimple_location (gsi_stmt (*gsi));
633
634 if (flag_sanitize_undefined_trap_on_error)
635 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
636 else
637 {
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);
641 tree fn
642 = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE);
643 g = gimple_build_call (fn, 1, data);
644 }
645 gimple_set_location (g, loc);
646 gsi_replace (gsi, g, false);
647 return false;
648 }
649
650 /* Return true if T is a call to a libubsan routine. */
651
652 bool
653 is_ubsan_builtin_p (tree t)
654 {
655 return TREE_CODE (t) == FUNCTION_DECL
656 && strncmp (IDENTIFIER_POINTER (DECL_NAME (t)),
657 "__builtin___ubsan_", 18) == 0;
658 }
659
660 /* Expand the UBSAN_BOUNDS special builtin function. */
661
662 bool
663 ubsan_expand_bounds_ifn (gimple_stmt_iterator *gsi)
664 {
665 gimple stmt = gsi_stmt (*gsi);
666 location_t loc = gimple_location (stmt);
667 gcc_assert (gimple_call_num_args (stmt) == 3);
668
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);
674
675 gimple_stmt_iterator gsi_orig = *gsi;
676
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,
684 true, NULL_TREE,
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);
689
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);
694 else
695 {
696 tree data
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,
709 GSI_SAME_STMT);
710 g = gimple_build_call (fn, 2, data, val);
711 }
712 gimple_set_location (g, loc);
713 gsi_insert_before (gsi, g, GSI_SAME_STMT);
714
715 /* Get rid of the UBSAN_BOUNDS call from the IR. */
716 unlink_stmt_vdef (stmt);
717 gsi_remove (&gsi_orig, true);
718
719 /* Point GSI to next logical statement. */
720 *gsi = gsi_start_bb (fallthru_bb);
721 return true;
722 }
723
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. */
728
729 bool
730 ubsan_expand_null_ifn (gimple_stmt_iterator *gsip)
731 {
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;
740 bool check_null;
741
742 basic_block cur_bb = gsi_bb (gsi);
743
744 gimple g;
745 if (!integer_zerop (align))
746 {
747 unsigned int ptralign = get_pointer_alignment (ptr) / BITS_PER_UNIT;
748 if (compare_tree_int (align, ptralign) == 1)
749 {
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);
754 }
755 }
756 check_null = (flag_sanitize & SANITIZE_NULL) != 0;
757
758 if (check_align == NULL_TREE && !check_null)
759 {
760 gsi_remove (gsip, true);
761 /* Unlink the UBSAN_NULLs vops before replacing it. */
762 unlink_stmt_vdef (stmt);
763 return true;
764 }
765
766 /* Split the original block holding the pointer dereference. */
767 edge e = split_block (cur_bb, stmt);
768
769 /* Get a hold on the 'condition block', the 'then block' and the
770 'else block'. */
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);
776
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;
781
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);
786
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;
792
793 /* Update dominance info for the newly created then_bb; note that
794 fallthru_bb's dominance info has already been updated by
795 split_block. */
796 if (dom_info_available_p (CDI_DOMINATORS))
797 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
798
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);
802 else
803 {
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);
810 tree data
811 = ubsan_create_data ("__ubsan_null_data", 1, &loc,
812 ubsan_type_descriptor (TREE_TYPE (ckind),
813 UBSAN_PRINT_POINTER),
814 NULL_TREE,
815 align,
816 fold_convert (unsigned_char_type_node, ckind),
817 NULL_TREE);
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));
822 }
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);
826
827 /* Unlink the UBSAN_NULLs vops before replacing it. */
828 unlink_stmt_vdef (stmt);
829
830 if (check_null)
831 {
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);
835
836 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
837 gsi_replace (&gsi, g, false);
838 }
839
840 if (check_align)
841 {
842 if (check_null)
843 {
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;
848
849 /* Make an edge coming from the 'cond1 block' into the 'then block';
850 this edge is unlikely taken, so set up the probability
851 accordingly. */
852 e = make_edge (cond1_bb, then_bb, EDGE_TRUE_VALUE);
853 e->probability = PROB_VERY_UNLIKELY;
854
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;
860
861 /* Update dominance info. */
862 if (dom_info_available_p (CDI_DOMINATORS))
863 {
864 set_immediate_dominator (CDI_DOMINATORS, fallthru_bb, cond1_bb);
865 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond1_bb);
866 }
867
868 gsi2 = gsi_start_bb (cond2_bb);
869 }
870
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),
875 check_align, mask);
876 gimple_set_location (g, loc);
877 if (check_null)
878 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
879 else
880 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
881
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);
886 if (check_null)
887 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
888 else
889 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
890 gsi_replace (&gsi, g, false);
891 }
892 return false;
893 }
894
895 /* Expand UBSAN_OBJECT_SIZE internal call. */
896
897 bool
898 ubsan_expand_objsize_ifn (gimple_stmt_iterator *gsi)
899 {
900 gimple stmt = gsi_stmt (*gsi);
901 location_t loc = gimple_location (stmt);
902 gcc_assert (gimple_call_num_args (stmt) == 4);
903
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;
909 gimple g;
910
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
915 object size. */;
916 else
917 {
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);
926
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);
931 else
932 {
933 tree data
934 = ubsan_create_data ("__ubsan_objsz_data", 1, &loc,
935 ubsan_type_descriptor (TREE_TYPE (ptr),
936 UBSAN_PRINT_POINTER),
937 NULL_TREE,
938 build_zero_cst (pointer_sized_int_node),
939 ckind,
940 NULL_TREE);
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);
951 }
952 gimple_set_location (g, loc);
953 gsi_insert_before (gsi, g, GSI_SAME_STMT);
954
955 /* Point GSI to next logical statement. */
956 *gsi = gsi_start_bb (fallthru_bb);
957 }
958
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);
963 }
964
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. */
967
968 static void
969 instrument_mem_ref (tree mem, tree base, gimple_stmt_iterator *iter,
970 bool is_lhs)
971 {
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)
975 {
976 align = min_align_of_type (TREE_TYPE (base));
977 if (align <= 1)
978 align = 0;
979 }
980 if (align == 0 && (flag_sanitize & SANITIZE_NULL) == 0)
981 return;
982 tree t = TREE_OPERAND (base, 0);
983 if (!POINTER_TYPE_P (TREE_TYPE (t)))
984 return;
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);
992 }
993
994 /* Perform the pointer instrumentation. */
995
996 static void
997 instrument_null (gimple_stmt_iterator gsi, bool is_lhs)
998 {
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);
1003 if (code == MEM_REF
1004 && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
1005 instrument_mem_ref (t, base, &gsi, is_lhs);
1006 }
1007
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. */
1012
1013 tree
1014 ubsan_build_overflow_builtin (tree_code code, location_t loc, tree lhstype,
1015 tree op0, tree op1)
1016 {
1017 if (flag_sanitize_undefined_trap_on_error)
1018 return build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
1019
1020 tree data = ubsan_create_data ("__ubsan_overflow_data", 1, &loc,
1021 ubsan_type_descriptor (lhstype), NULL_TREE,
1022 NULL_TREE);
1023 enum built_in_function fn_code;
1024
1025 switch (code)
1026 {
1027 case PLUS_EXPR:
1028 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1029 ? BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW
1030 : BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW_ABORT;
1031 break;
1032 case MINUS_EXPR:
1033 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1034 ? BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW
1035 : BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW_ABORT;
1036 break;
1037 case MULT_EXPR:
1038 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1039 ? BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW
1040 : BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW_ABORT;
1041 break;
1042 case NEGATE_EXPR:
1043 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1044 ? BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW
1045 : BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW_ABORT;
1046 break;
1047 default:
1048 gcc_unreachable ();
1049 }
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)
1055 : NULL_TREE);
1056 }
1057
1058 /* Perform the signed integer instrumentation. GSI is the iterator
1059 pointing at statement we are trying to instrument. */
1060
1061 static void
1062 instrument_si_overflow (gimple_stmt_iterator gsi)
1063 {
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);
1068 tree a, b;
1069 gimple g;
1070
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))
1076 return;
1077
1078 switch (code)
1079 {
1080 case MINUS_EXPR:
1081 case PLUS_EXPR:
1082 case MULT_EXPR:
1083 /* Transform
1084 i = u {+,-,*} 5;
1085 into
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);
1096 break;
1097 case NEGATE_EXPR:
1098 /* Represent i = -u;
1099 as
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);
1106 break;
1107 case ABS_EXPR:
1108 /* Transform i = ABS_EXPR<u>;
1109 into
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);
1120 update_stmt (stmt);
1121 break;
1122 default:
1123 break;
1124 }
1125 }
1126
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
1129 type values. */
1130
1131 static void
1132 instrument_bool_enum_load (gimple_stmt_iterator *gsi)
1133 {
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;
1138
1139 if (TREE_CODE (type) == BOOLEAN_TYPE && (flag_sanitize & SANITIZE_BOOL))
1140 {
1141 minv = boolean_false_node;
1142 maxv = boolean_true_node;
1143 }
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))))
1150 {
1151 minv = TYPE_MIN_VALUE (TREE_TYPE (type));
1152 maxv = TYPE_MAX_VALUE (TREE_TYPE (type));
1153 }
1154 else
1155 return;
1156
1157 int modebitsize = GET_MODE_BITSIZE (TYPE_MODE (type));
1158 HOST_WIDE_INT bitsize, bitpos;
1159 tree offset;
1160 machine_mode mode;
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);
1165
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)
1171 return;
1172
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);
1185 if (can_throw)
1186 {
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);
1193 update_stmt (stmt);
1194 *gsi = gsi_for_stmt (g);
1195 g = stmt;
1196 }
1197 else
1198 {
1199 g = gimple_build_assign (urhs, mem);
1200 gimple_set_location (g, loc);
1201 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1202 }
1203 minv = fold_convert (utype, minv);
1204 maxv = fold_convert (utype, maxv);
1205 if (!integer_zerop (minv))
1206 {
1207 g = gimple_build_assign_with_ops (MINUS_EXPR, make_ssa_name (utype),
1208 urhs, minv);
1209 gimple_set_location (g, loc);
1210 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1211 }
1212
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);
1222
1223 if (!can_throw)
1224 {
1225 gimple_assign_set_rhs_with_ops (&gsi2, NOP_EXPR, urhs);
1226 update_stmt (stmt);
1227 }
1228
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);
1232 else
1233 {
1234 tree data = ubsan_create_data ("__ubsan_invalid_value_data", 1, &loc,
1235 ubsan_type_descriptor (type), NULL_TREE,
1236 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);
1244
1245 tree val = force_gimple_operand_gsi (&gsi2, ubsan_encode_value (urhs),
1246 true, NULL_TREE, true,
1247 GSI_SAME_STMT);
1248 g = gimple_build_call (fn, 2, data, val);
1249 }
1250 gimple_set_location (g, loc);
1251 gsi_insert_before (&gsi2, g, GSI_SAME_STMT);
1252 *gsi = gsi_for_stmt (stmt);
1253 }
1254
1255 /* Instrument float point-to-integer conversion. TYPE is an integer type of
1256 destination, EXPR is floating-point expression. */
1257
1258 tree
1259 ubsan_instrument_float_cast (location_t loc, tree type, tree expr)
1260 {
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);
1266
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)
1273 {
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);
1282
1283 /* For unsigned, assume -1.0 is always representable. */
1284 if (uns_p)
1285 min = build_minus_one_cst (expr_type);
1286 else
1287 {
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))
1297 {
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. */
1304 minval2 = dconst1;
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);
1311 }
1312 min = build_real (expr_type, minval2);
1313 }
1314 }
1315 else if (REAL_MODE_FORMAT (mode)->b == 10)
1316 {
1317 /* For _Decimal128 up to 34 decimal digits, - sign,
1318 dot, e, exponent. */
1319 char buf[64];
1320 mpfr_t m;
1321 int p = REAL_MODE_FORMAT (mode)->p;
1322 REAL_VALUE_TYPE maxval, minval;
1323
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);
1332
1333 /* For unsigned, assume -1.0 is always representable. */
1334 if (uns_p)
1335 min = build_minus_one_cst (expr_type);
1336 else
1337 {
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);
1346 }
1347 mpfr_clear (m);
1348 }
1349 else
1350 return NULL_TREE;
1351
1352 if (flag_sanitize_undefined_trap_on_error)
1353 fn = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
1354 else
1355 {
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,
1360 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));
1369 }
1370
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);
1376 }
1377
1378 /* Instrument values passed to function arguments with nonnull attribute. */
1379
1380 static void
1381 instrument_nonnull_arg (gimple_stmt_iterator *gsi)
1382 {
1383 gimple stmt = gsi_stmt (*gsi);
1384 location_t loc[2];
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++)
1392 {
1393 tree arg = gimple_call_arg (stmt, i);
1394 if (POINTER_TYPE_P (TREE_TYPE (arg))
1395 && infer_nonnull_range (stmt, arg, false, true))
1396 {
1397 gimple g;
1398 if (!is_gimple_val (arg))
1399 {
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);
1404 }
1405
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);
1414
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);
1418 else
1419 {
1420 tree data = ubsan_create_data ("__ubsan_nonnull_arg_data",
1421 2, loc, NULL_TREE,
1422 build_int_cst (integer_type_node,
1423 i + 1),
1424 NULL_TREE);
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);
1431
1432 g = gimple_build_call (fn, 1, data);
1433 }
1434 gimple_set_location (g, loc[0]);
1435 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1436 }
1437 *gsi = gsi_for_stmt (stmt);
1438 }
1439 flag_delete_null_pointer_checks = save_flag_delete_null_pointer_checks;
1440 }
1441
1442 /* Instrument returns in functions with returns_nonnull attribute. */
1443
1444 static void
1445 instrument_nonnull_return (gimple_stmt_iterator *gsi)
1446 {
1447 greturn *stmt = as_a <greturn *> (gsi_stmt (*gsi));
1448 location_t loc[2];
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;
1456 if (arg
1457 && POINTER_TYPE_P (TREE_TYPE (arg))
1458 && is_gimple_val (arg)
1459 && infer_nonnull_range (stmt, arg, false, true))
1460 {
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);
1469
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);
1473 else
1474 {
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);
1483
1484 g = gimple_build_call (fn, 1, data);
1485 }
1486 gimple_set_location (g, loc[0]);
1487 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1488 *gsi = gsi_for_stmt (stmt);
1489 }
1490 flag_delete_null_pointer_checks = save_flag_delete_null_pointer_checks;
1491 }
1492
1493 /* Instrument memory references. Here we check whether the pointer
1494 points to an out-of-bounds location. */
1495
1496 static void
1497 instrument_object_size (gimple_stmt_iterator *gsi, bool is_lhs)
1498 {
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);
1502 tree type;
1503 tree index = NULL_TREE;
1504 HOST_WIDE_INT size_in_bytes;
1505
1506 type = TREE_TYPE (t);
1507 if (VOID_TYPE_P (type))
1508 return;
1509
1510 switch (TREE_CODE (t))
1511 {
1512 case COMPONENT_REF:
1513 if (TREE_CODE (t) == COMPONENT_REF
1514 && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1)) != NULL_TREE)
1515 {
1516 tree repr = DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1));
1517 t = build3 (COMPONENT_REF, TREE_TYPE (repr), TREE_OPERAND (t, 0),
1518 repr, NULL_TREE);
1519 }
1520 break;
1521 case ARRAY_REF:
1522 index = TREE_OPERAND (t, 1);
1523 break;
1524 case INDIRECT_REF:
1525 case MEM_REF:
1526 case VAR_DECL:
1527 case PARM_DECL:
1528 case RESULT_DECL:
1529 break;
1530 default:
1531 return;
1532 }
1533
1534 size_in_bytes = int_size_in_bytes (type);
1535 if (size_in_bytes <= 0)
1536 return;
1537
1538 HOST_WIDE_INT bitsize, bitpos;
1539 tree offset;
1540 machine_mode mode;
1541 int volatilep = 0, unsignedp = 0;
1542 tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset, &mode,
1543 &unsignedp, &volatilep, false);
1544
1545 if (bitpos % BITS_PER_UNIT != 0
1546 || bitsize != size_in_bytes * BITS_PER_UNIT)
1547 return;
1548
1549 bool decl_p = DECL_P (inner);
1550 tree base;
1551 if (decl_p)
1552 base = inner;
1553 else if (TREE_CODE (inner) == MEM_REF)
1554 base = TREE_OPERAND (inner, 0);
1555 else
1556 return;
1557 tree ptr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (t)), t);
1558
1559 while (TREE_CODE (base) == SSA_NAME)
1560 {
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);
1568 else
1569 break;
1570 }
1571
1572 if (!POINTER_TYPE_P (TREE_TYPE (base)) && !DECL_P (base))
1573 return;
1574
1575 tree sizet;
1576 tree base_addr = base;
1577 if (decl_p)
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);
1583 else if (optimize)
1584 {
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,
1590 integer_zero_node);
1591 sizet = force_gimple_operand_gsi (gsi, sizet, false, NULL_TREE, true,
1592 GSI_SAME_STMT);
1593 }
1594 else
1595 return;
1596
1597 /* Generate UBSAN_OBJECT_SIZE (ptr, ptr+sizeof(*ptr)-base, objsize, ckind)
1598 call. */
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));
1604
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))
1609 return;
1610
1611 if (index != NULL_TREE
1612 && TREE_CODE (index) == SSA_NAME
1613 && TREE_CODE (sizet) == INTEGER_CST)
1614 {
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)
1619 {
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))
1625 return;
1626 }
1627 }
1628
1629 /* Nope. Emit the check. */
1630 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE, true,
1631 GSI_SAME_STMT);
1632 ptr = force_gimple_operand_gsi (gsi, ptr, true, NULL_TREE, true,
1633 GSI_SAME_STMT);
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);
1640 }
1641
1642 namespace {
1643
1644 const pass_data pass_data_ubsan =
1645 {
1646 GIMPLE_PASS, /* type */
1647 "ubsan", /* name */
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 */
1655 };
1656
1657 class pass_ubsan : public gimple_opt_pass
1658 {
1659 public:
1660 pass_ubsan (gcc::context *ctxt)
1661 : gimple_opt_pass (pass_data_ubsan, ctxt)
1662 {}
1663
1664 /* opt_pass methods: */
1665 virtual bool gate (function *)
1666 {
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));
1676 }
1677
1678 virtual unsigned int execute (function *);
1679
1680 }; // class pass_ubsan
1681
1682 unsigned int
1683 pass_ubsan::execute (function *fun)
1684 {
1685 basic_block bb;
1686 gimple_stmt_iterator gsi;
1687
1688 initialize_sanitizer_builtins ();
1689
1690 FOR_EACH_BB_FN (bb, fun)
1691 {
1692 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
1693 {
1694 gimple stmt = gsi_stmt (gsi);
1695 if (is_gimple_debug (stmt) || gimple_clobber_p (stmt))
1696 {
1697 gsi_next (&gsi);
1698 continue;
1699 }
1700
1701 if ((flag_sanitize & SANITIZE_SI_OVERFLOW)
1702 && is_gimple_assign (stmt))
1703 instrument_si_overflow (gsi);
1704
1705 if (flag_sanitize & (SANITIZE_NULL | SANITIZE_ALIGNMENT))
1706 {
1707 if (gimple_store_p (stmt))
1708 instrument_null (gsi, true);
1709 if (gimple_assign_load_p (stmt))
1710 instrument_null (gsi, false);
1711 }
1712
1713 if (flag_sanitize & (SANITIZE_BOOL | SANITIZE_ENUM)
1714 && gimple_assign_load_p (stmt))
1715 {
1716 instrument_bool_enum_load (&gsi);
1717 bb = gimple_bb (stmt);
1718 }
1719
1720 if ((flag_sanitize & SANITIZE_NONNULL_ATTRIBUTE)
1721 && is_gimple_call (stmt)
1722 && !gimple_call_internal_p (stmt))
1723 {
1724 instrument_nonnull_arg (&gsi);
1725 bb = gimple_bb (stmt);
1726 }
1727
1728 if ((flag_sanitize & SANITIZE_RETURNS_NONNULL_ATTRIBUTE)
1729 && gimple_code (stmt) == GIMPLE_RETURN)
1730 {
1731 instrument_nonnull_return (&gsi);
1732 bb = gimple_bb (stmt);
1733 }
1734
1735 if (flag_sanitize & SANITIZE_OBJECT_SIZE)
1736 {
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);
1741 }
1742
1743 gsi_next (&gsi);
1744 }
1745 }
1746 return 0;
1747 }
1748
1749 } // anon namespace
1750
1751 gimple_opt_pass *
1752 make_pass_ubsan (gcc::context *ctxt)
1753 {
1754 return new pass_ubsan (ctxt);
1755 }
1756
1757 #include "gt-ubsan.h"