]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/ubsan.c
ggcplug.c: Shuffle includes to include gcc-plugin.h earlier.
[thirdparty/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 "cgraph.h"
33 #include "tree-pass.h"
34 #include "tree-ssa-alias.h"
35 #include "tree-pretty-print.h"
36 #include "internal-fn.h"
37 #include "gimple-expr.h"
38 #include "gimple.h"
39 #include "gimple-iterator.h"
40 #include "gimple-ssa.h"
41 #include "gimple-walk.h"
42 #include "hashtab.h"
43 #include "output.h"
44 #include "tm_p.h"
45 #include "toplev.h"
46 #include "cfgloop.h"
47 #include "ubsan.h"
48 #include "c-family/c-common.h"
49 #include "rtl.h"
50 #include "expr.h"
51 #include "tree-ssanames.h"
52 #include "asan.h"
53 #include "gimplify-me.h"
54 #include "intl.h"
55 #include "realmpfr.h"
56 #include "dfp.h"
57 #include "builtins.h"
58 #include "tree-object-size.h"
59
60 /* Map from a tree to a VAR_DECL tree. */
61
62 struct GTY(()) tree_type_map {
63 struct tree_map_base type;
64 tree decl;
65 };
66
67 #define tree_type_map_eq tree_map_base_eq
68 #define tree_type_map_marked_p tree_map_base_marked_p
69
70 /* Hash from a tree in a tree_type_map. */
71
72 unsigned int
73 tree_type_map_hash (const void *item)
74 {
75 return TYPE_UID (((const struct tree_type_map *)item)->type.from);
76 }
77
78 static GTY ((if_marked ("tree_type_map_marked_p"), param_is (struct tree_type_map)))
79 htab_t decl_tree_for_type;
80
81 /* Lookup a VAR_DECL for TYPE, and return it if we find one. */
82
83 static tree
84 decl_for_type_lookup (tree type)
85 {
86 /* If the hash table is not initialized yet, create it now. */
87 if (decl_tree_for_type == NULL)
88 {
89 decl_tree_for_type = htab_create_ggc (10, tree_type_map_hash,
90 tree_type_map_eq, 0);
91 /* That also means we don't have to bother with the lookup. */
92 return NULL_TREE;
93 }
94
95 struct tree_type_map *h, in;
96 in.type.from = type;
97
98 h = (struct tree_type_map *)
99 htab_find_with_hash (decl_tree_for_type, &in, TYPE_UID (type));
100 return h ? h->decl : NULL_TREE;
101 }
102
103 /* Insert a mapping TYPE->DECL in the VAR_DECL for type hashtable. */
104
105 static void
106 decl_for_type_insert (tree type, tree decl)
107 {
108 struct tree_type_map *h;
109 void **slot;
110
111 h = ggc_alloc<tree_type_map> ();
112 h->type.from = type;
113 h->decl = decl;
114 slot = htab_find_slot_with_hash (decl_tree_for_type, h, TYPE_UID (type),
115 INSERT);
116 *(struct tree_type_map **) slot = h;
117 }
118
119 /* Helper routine, which encodes a value in the pointer_sized_int_node.
120 Arguments with precision <= POINTER_SIZE are passed directly,
121 the rest is passed by reference. T is a value we are to encode.
122 IN_EXPAND_P is true if this function is called during expansion. */
123
124 tree
125 ubsan_encode_value (tree t, bool in_expand_p)
126 {
127 tree type = TREE_TYPE (t);
128 const unsigned int bitsize = GET_MODE_BITSIZE (TYPE_MODE (type));
129 if (bitsize <= POINTER_SIZE)
130 switch (TREE_CODE (type))
131 {
132 case BOOLEAN_TYPE:
133 case ENUMERAL_TYPE:
134 case INTEGER_TYPE:
135 return fold_build1 (NOP_EXPR, pointer_sized_int_node, t);
136 case REAL_TYPE:
137 {
138 tree itype = build_nonstandard_integer_type (bitsize, true);
139 t = fold_build1 (VIEW_CONVERT_EXPR, itype, t);
140 return fold_convert (pointer_sized_int_node, t);
141 }
142 default:
143 gcc_unreachable ();
144 }
145 else
146 {
147 if (!DECL_P (t) || !TREE_ADDRESSABLE (t))
148 {
149 /* The reason for this is that we don't want to pessimize
150 code by making vars unnecessarily addressable. */
151 tree var = create_tmp_var (type, NULL);
152 tree tem = build2 (MODIFY_EXPR, void_type_node, var, t);
153 if (in_expand_p)
154 {
155 rtx mem
156 = assign_stack_temp_for_type (TYPE_MODE (type),
157 GET_MODE_SIZE (TYPE_MODE (type)),
158 type);
159 SET_DECL_RTL (var, mem);
160 expand_assignment (var, t, false);
161 return build_fold_addr_expr (var);
162 }
163 t = build_fold_addr_expr (var);
164 return build2 (COMPOUND_EXPR, TREE_TYPE (t), tem, t);
165 }
166 else
167 return build_fold_addr_expr (t);
168 }
169 }
170
171 /* Build
172 struct __ubsan_type_descriptor
173 {
174 unsigned short __typekind;
175 unsigned short __typeinfo;
176 char __typename[];
177 }
178 type. */
179
180 static tree
181 ubsan_type_descriptor_type (void)
182 {
183 static const char *field_names[3]
184 = { "__typekind", "__typeinfo", "__typename" };
185 tree fields[3], ret;
186 tree itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
187 tree flex_arr_type = build_array_type (char_type_node, itype);
188
189 ret = make_node (RECORD_TYPE);
190 for (int i = 0; i < 3; i++)
191 {
192 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
193 get_identifier (field_names[i]),
194 (i == 2) ? flex_arr_type
195 : short_unsigned_type_node);
196 DECL_CONTEXT (fields[i]) = ret;
197 if (i)
198 DECL_CHAIN (fields[i - 1]) = fields[i];
199 }
200 TYPE_FIELDS (ret) = fields[0];
201 TYPE_NAME (ret) = get_identifier ("__ubsan_type_descriptor");
202 layout_type (ret);
203 return ret;
204 }
205
206 /* Cached ubsan_get_source_location_type () return value. */
207 static GTY(()) tree ubsan_source_location_type;
208
209 /* Build
210 struct __ubsan_source_location
211 {
212 const char *__filename;
213 unsigned int __line;
214 unsigned int __column;
215 }
216 type. */
217
218 tree
219 ubsan_get_source_location_type (void)
220 {
221 static const char *field_names[3]
222 = { "__filename", "__line", "__column" };
223 tree fields[3], ret;
224 if (ubsan_source_location_type)
225 return ubsan_source_location_type;
226
227 tree const_char_type = build_qualified_type (char_type_node,
228 TYPE_QUAL_CONST);
229
230 ret = make_node (RECORD_TYPE);
231 for (int i = 0; i < 3; i++)
232 {
233 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
234 get_identifier (field_names[i]),
235 (i == 0) ? build_pointer_type (const_char_type)
236 : unsigned_type_node);
237 DECL_CONTEXT (fields[i]) = ret;
238 if (i)
239 DECL_CHAIN (fields[i - 1]) = fields[i];
240 }
241 TYPE_FIELDS (ret) = fields[0];
242 TYPE_NAME (ret) = get_identifier ("__ubsan_source_location");
243 layout_type (ret);
244 ubsan_source_location_type = ret;
245 return ret;
246 }
247
248 /* Helper routine that returns a CONSTRUCTOR of __ubsan_source_location
249 type with its fields filled from a location_t LOC. */
250
251 static tree
252 ubsan_source_location (location_t loc)
253 {
254 expanded_location xloc;
255 tree type = ubsan_get_source_location_type ();
256
257 xloc = expand_location (loc);
258 tree str;
259 if (xloc.file == NULL)
260 {
261 str = build_int_cst (ptr_type_node, 0);
262 xloc.line = 0;
263 xloc.column = 0;
264 }
265 else
266 {
267 /* Fill in the values from LOC. */
268 size_t len = strlen (xloc.file);
269 str = build_string (len + 1, xloc.file);
270 TREE_TYPE (str) = build_array_type (char_type_node,
271 build_index_type (size_int (len)));
272 TREE_READONLY (str) = 1;
273 TREE_STATIC (str) = 1;
274 str = build_fold_addr_expr (str);
275 }
276 tree ctor = build_constructor_va (type, 3, NULL_TREE, str, NULL_TREE,
277 build_int_cst (unsigned_type_node,
278 xloc.line), NULL_TREE,
279 build_int_cst (unsigned_type_node,
280 xloc.column));
281 TREE_CONSTANT (ctor) = 1;
282 TREE_STATIC (ctor) = 1;
283
284 return ctor;
285 }
286
287 /* This routine returns a magic number for TYPE. */
288
289 static unsigned short
290 get_ubsan_type_info_for_type (tree type)
291 {
292 gcc_assert (TYPE_SIZE (type) && tree_fits_uhwi_p (TYPE_SIZE (type)));
293 if (TREE_CODE (type) == REAL_TYPE)
294 return tree_to_uhwi (TYPE_SIZE (type));
295 else if (INTEGRAL_TYPE_P (type))
296 {
297 int prec = exact_log2 (tree_to_uhwi (TYPE_SIZE (type)));
298 gcc_assert (prec != -1);
299 return (prec << 1) | !TYPE_UNSIGNED (type);
300 }
301 else
302 return 0;
303 }
304
305 /* Helper routine that returns ADDR_EXPR of a VAR_DECL of a type
306 descriptor. It first looks into the hash table; if not found,
307 create the VAR_DECL, put it into the hash table and return the
308 ADDR_EXPR of it. TYPE describes a particular type. PSTYLE is
309 an enum controlling how we want to print the type. */
310
311 tree
312 ubsan_type_descriptor (tree type, enum ubsan_print_style pstyle)
313 {
314 /* See through any typedefs. */
315 type = TYPE_MAIN_VARIANT (type);
316
317 tree decl = decl_for_type_lookup (type);
318 /* It is possible that some of the earlier created DECLs were found
319 unused, in that case they weren't emitted and varpool_node::get
320 returns NULL node on them. But now we really need them. Thus,
321 renew them here. */
322 if (decl != NULL_TREE && varpool_node::get (decl))
323 return build_fold_addr_expr (decl);
324
325 tree dtype = ubsan_type_descriptor_type ();
326 tree type2 = type;
327 const char *tname = NULL;
328 char *pretty_name;
329 unsigned char deref_depth = 0;
330 unsigned short tkind, tinfo;
331
332 /* Get the name of the type, or the name of the pointer type. */
333 if (pstyle == UBSAN_PRINT_POINTER)
334 {
335 gcc_assert (POINTER_TYPE_P (type));
336 type2 = TREE_TYPE (type);
337
338 /* Remove any '*' operators from TYPE. */
339 while (POINTER_TYPE_P (type2))
340 deref_depth++, type2 = TREE_TYPE (type2);
341
342 if (TREE_CODE (type2) == METHOD_TYPE)
343 type2 = TYPE_METHOD_BASETYPE (type2);
344 }
345
346 /* If an array, get its type. */
347 type2 = strip_array_types (type2);
348
349 if (pstyle == UBSAN_PRINT_ARRAY)
350 {
351 while (POINTER_TYPE_P (type2))
352 deref_depth++, type2 = TREE_TYPE (type2);
353 }
354
355 if (TYPE_NAME (type2) != NULL)
356 {
357 if (TREE_CODE (TYPE_NAME (type2)) == IDENTIFIER_NODE)
358 tname = IDENTIFIER_POINTER (TYPE_NAME (type2));
359 else if (DECL_NAME (TYPE_NAME (type2)) != NULL)
360 tname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type2)));
361 }
362
363 if (tname == NULL)
364 /* We weren't able to determine the type name. */
365 tname = "<unknown>";
366
367 /* Decorate the type name with '', '*', "struct", or "union". */
368 pretty_name = (char *) alloca (strlen (tname) + 16 + deref_depth);
369 if (pstyle == UBSAN_PRINT_POINTER)
370 {
371 int pos = sprintf (pretty_name, "'%s%s%s%s%s%s%s",
372 TYPE_VOLATILE (type2) ? "volatile " : "",
373 TYPE_READONLY (type2) ? "const " : "",
374 TYPE_RESTRICT (type2) ? "restrict " : "",
375 TYPE_ATOMIC (type2) ? "_Atomic " : "",
376 TREE_CODE (type2) == RECORD_TYPE
377 ? "struct "
378 : TREE_CODE (type2) == UNION_TYPE
379 ? "union " : "", tname,
380 deref_depth == 0 ? "" : " ");
381 while (deref_depth-- > 0)
382 pretty_name[pos++] = '*';
383 pretty_name[pos++] = '\'';
384 pretty_name[pos] = '\0';
385 }
386 else if (pstyle == UBSAN_PRINT_ARRAY)
387 {
388 /* Pretty print the array dimensions. */
389 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
390 tree t = type;
391 int pos = sprintf (pretty_name, "'%s ", tname);
392 while (deref_depth-- > 0)
393 pretty_name[pos++] = '*';
394 while (TREE_CODE (t) == ARRAY_TYPE)
395 {
396 pretty_name[pos++] = '[';
397 tree dom = TYPE_DOMAIN (t);
398 if (dom && TREE_CODE (TYPE_MAX_VALUE (dom)) == INTEGER_CST)
399 pos += sprintf (&pretty_name[pos], HOST_WIDE_INT_PRINT_DEC,
400 tree_to_uhwi (TYPE_MAX_VALUE (dom)) + 1);
401 else
402 /* ??? We can't determine the variable name; print VLA unspec. */
403 pretty_name[pos++] = '*';
404 pretty_name[pos++] = ']';
405 t = TREE_TYPE (t);
406 }
407 pretty_name[pos++] = '\'';
408 pretty_name[pos] = '\0';
409
410 /* Save the tree with stripped types. */
411 type = t;
412 }
413 else
414 sprintf (pretty_name, "'%s'", tname);
415
416 switch (TREE_CODE (type))
417 {
418 case BOOLEAN_TYPE:
419 case ENUMERAL_TYPE:
420 case INTEGER_TYPE:
421 tkind = 0x0000;
422 break;
423 case REAL_TYPE:
424 /* FIXME: libubsan right now only supports float, double and
425 long double type formats. */
426 if (TYPE_MODE (type) == TYPE_MODE (float_type_node)
427 || TYPE_MODE (type) == TYPE_MODE (double_type_node)
428 || TYPE_MODE (type) == TYPE_MODE (long_double_type_node))
429 tkind = 0x0001;
430 else
431 tkind = 0xffff;
432 break;
433 default:
434 tkind = 0xffff;
435 break;
436 }
437 tinfo = get_ubsan_type_info_for_type (type);
438
439 /* Create a new VAR_DECL of type descriptor. */
440 char tmp_name[32];
441 static unsigned int type_var_id_num;
442 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_type", type_var_id_num++);
443 decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name),
444 dtype);
445 TREE_STATIC (decl) = 1;
446 TREE_PUBLIC (decl) = 0;
447 DECL_ARTIFICIAL (decl) = 1;
448 DECL_IGNORED_P (decl) = 1;
449 DECL_EXTERNAL (decl) = 0;
450
451 size_t len = strlen (pretty_name);
452 tree str = build_string (len + 1, pretty_name);
453 TREE_TYPE (str) = build_array_type (char_type_node,
454 build_index_type (size_int (len)));
455 TREE_READONLY (str) = 1;
456 TREE_STATIC (str) = 1;
457 tree ctor = build_constructor_va (dtype, 3, NULL_TREE,
458 build_int_cst (short_unsigned_type_node,
459 tkind), NULL_TREE,
460 build_int_cst (short_unsigned_type_node,
461 tinfo), NULL_TREE, str);
462 TREE_CONSTANT (ctor) = 1;
463 TREE_STATIC (ctor) = 1;
464 DECL_INITIAL (decl) = ctor;
465 varpool_node::finalize_decl (decl);
466
467 /* Save the VAR_DECL into the hash table. */
468 decl_for_type_insert (type, decl);
469
470 return build_fold_addr_expr (decl);
471 }
472
473 /* Create a structure for the ubsan library. NAME is a name of the new
474 structure. LOCCNT is number of locations, PLOC points to array of
475 locations. The arguments in ... are of __ubsan_type_descriptor type
476 and there are at most two of them, followed by NULL_TREE, followed
477 by optional extra arguments and another NULL_TREE. */
478
479 tree
480 ubsan_create_data (const char *name, int loccnt, const location_t *ploc, ...)
481 {
482 va_list args;
483 tree ret, t;
484 tree fields[6];
485 vec<tree, va_gc> *saved_args = NULL;
486 size_t i = 0;
487 int j;
488
489 /* Firstly, create a pointer to type descriptor type. */
490 tree td_type = ubsan_type_descriptor_type ();
491 TYPE_READONLY (td_type) = 1;
492 td_type = build_pointer_type (td_type);
493
494 /* Create the structure type. */
495 ret = make_node (RECORD_TYPE);
496 for (j = 0; j < loccnt; j++)
497 {
498 gcc_checking_assert (i < 2);
499 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
500 ubsan_get_source_location_type ());
501 DECL_CONTEXT (fields[i]) = ret;
502 if (i)
503 DECL_CHAIN (fields[i - 1]) = fields[i];
504 i++;
505 }
506
507 va_start (args, ploc);
508 for (t = va_arg (args, tree); t != NULL_TREE;
509 i++, t = va_arg (args, tree))
510 {
511 gcc_checking_assert (i < 4);
512 /* Save the tree arguments for later use. */
513 vec_safe_push (saved_args, t);
514 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
515 td_type);
516 DECL_CONTEXT (fields[i]) = ret;
517 if (i)
518 DECL_CHAIN (fields[i - 1]) = fields[i];
519 }
520
521 for (t = va_arg (args, tree); t != NULL_TREE;
522 i++, t = va_arg (args, tree))
523 {
524 gcc_checking_assert (i < 6);
525 /* Save the tree arguments for later use. */
526 vec_safe_push (saved_args, t);
527 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
528 TREE_TYPE (t));
529 DECL_CONTEXT (fields[i]) = ret;
530 if (i)
531 DECL_CHAIN (fields[i - 1]) = fields[i];
532 }
533 va_end (args);
534
535 TYPE_FIELDS (ret) = fields[0];
536 TYPE_NAME (ret) = get_identifier (name);
537 layout_type (ret);
538
539 /* Now, fill in the type. */
540 char tmp_name[32];
541 static unsigned int ubsan_var_id_num;
542 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_data", ubsan_var_id_num++);
543 tree var = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name),
544 ret);
545 TREE_STATIC (var) = 1;
546 TREE_PUBLIC (var) = 0;
547 DECL_ARTIFICIAL (var) = 1;
548 DECL_IGNORED_P (var) = 1;
549 DECL_EXTERNAL (var) = 0;
550
551 vec<constructor_elt, va_gc> *v;
552 vec_alloc (v, i);
553 tree ctor = build_constructor (ret, v);
554
555 /* If desirable, set the __ubsan_source_location element. */
556 for (j = 0; j < loccnt; j++)
557 {
558 location_t loc = LOCATION_LOCUS (ploc[j]);
559 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, ubsan_source_location (loc));
560 }
561
562 size_t nelts = vec_safe_length (saved_args);
563 for (i = 0; i < nelts; i++)
564 {
565 t = (*saved_args)[i];
566 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, t);
567 }
568
569 TREE_CONSTANT (ctor) = 1;
570 TREE_STATIC (ctor) = 1;
571 DECL_INITIAL (var) = ctor;
572 varpool_node::finalize_decl (var);
573
574 return var;
575 }
576
577 /* Instrument the __builtin_unreachable call. We just call the libubsan
578 routine instead. */
579
580 tree
581 ubsan_instrument_unreachable (location_t loc)
582 {
583 if (flag_sanitize_undefined_trap_on_error)
584 return build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
585
586 initialize_sanitizer_builtins ();
587 tree data = ubsan_create_data ("__ubsan_unreachable_data", 1, &loc, NULL_TREE,
588 NULL_TREE);
589 tree t = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE);
590 return build_call_expr_loc (loc, t, 1, build_fold_addr_expr_loc (loc, data));
591 }
592
593 /* Return true if T is a call to a libubsan routine. */
594
595 bool
596 is_ubsan_builtin_p (tree t)
597 {
598 return TREE_CODE (t) == FUNCTION_DECL
599 && strncmp (IDENTIFIER_POINTER (DECL_NAME (t)),
600 "__builtin___ubsan_", 18) == 0;
601 }
602
603 /* Expand the UBSAN_BOUNDS special builtin function. */
604
605 bool
606 ubsan_expand_bounds_ifn (gimple_stmt_iterator *gsi)
607 {
608 gimple stmt = gsi_stmt (*gsi);
609 location_t loc = gimple_location (stmt);
610 gcc_assert (gimple_call_num_args (stmt) == 3);
611
612 /* Pick up the arguments of the UBSAN_BOUNDS call. */
613 tree type = TREE_TYPE (TREE_TYPE (gimple_call_arg (stmt, 0)));
614 tree index = gimple_call_arg (stmt, 1);
615 tree orig_index_type = TREE_TYPE (index);
616 tree bound = gimple_call_arg (stmt, 2);
617
618 gimple_stmt_iterator gsi_orig = *gsi;
619
620 /* Create condition "if (index > bound)". */
621 basic_block then_bb, fallthru_bb;
622 gimple_stmt_iterator cond_insert_point
623 = create_cond_insert_point (gsi, false, false, true,
624 &then_bb, &fallthru_bb);
625 index = fold_convert (TREE_TYPE (bound), index);
626 index = force_gimple_operand_gsi (&cond_insert_point, index,
627 true, NULL_TREE,
628 false, GSI_NEW_STMT);
629 gimple g = gimple_build_cond (GT_EXPR, index, bound, NULL_TREE, NULL_TREE);
630 gimple_set_location (g, loc);
631 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
632
633 /* Generate __ubsan_handle_out_of_bounds call. */
634 *gsi = gsi_after_labels (then_bb);
635 if (flag_sanitize_undefined_trap_on_error)
636 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
637 else
638 {
639 tree data
640 = ubsan_create_data ("__ubsan_out_of_bounds_data", 1, &loc,
641 ubsan_type_descriptor (type, UBSAN_PRINT_ARRAY),
642 ubsan_type_descriptor (orig_index_type),
643 NULL_TREE, NULL_TREE);
644 data = build_fold_addr_expr_loc (loc, data);
645 enum built_in_function bcode
646 = (flag_sanitize_recover & SANITIZE_BOUNDS)
647 ? BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS
648 : BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS_ABORT;
649 tree fn = builtin_decl_explicit (bcode);
650 tree val = force_gimple_operand_gsi (gsi, ubsan_encode_value (index),
651 true, NULL_TREE, true,
652 GSI_SAME_STMT);
653 g = gimple_build_call (fn, 2, data, val);
654 }
655 gimple_set_location (g, loc);
656 gsi_insert_before (gsi, g, GSI_SAME_STMT);
657
658 /* Get rid of the UBSAN_BOUNDS call from the IR. */
659 unlink_stmt_vdef (stmt);
660 gsi_remove (&gsi_orig, true);
661
662 /* Point GSI to next logical statement. */
663 *gsi = gsi_start_bb (fallthru_bb);
664 return true;
665 }
666
667 /* Expand UBSAN_NULL internal call. The type is kept on the ckind
668 argument which is a constant, because the middle-end treats pointer
669 conversions as useless and therefore the type of the first argument
670 could be changed to any other pointer type. */
671
672 bool
673 ubsan_expand_null_ifn (gimple_stmt_iterator *gsip)
674 {
675 gimple_stmt_iterator gsi = *gsip;
676 gimple stmt = gsi_stmt (gsi);
677 location_t loc = gimple_location (stmt);
678 gcc_assert (gimple_call_num_args (stmt) == 3);
679 tree ptr = gimple_call_arg (stmt, 0);
680 tree ckind = gimple_call_arg (stmt, 1);
681 tree align = gimple_call_arg (stmt, 2);
682 tree check_align = NULL_TREE;
683 bool check_null;
684
685 basic_block cur_bb = gsi_bb (gsi);
686
687 gimple g;
688 if (!integer_zerop (align))
689 {
690 unsigned int ptralign = get_pointer_alignment (ptr) / BITS_PER_UNIT;
691 if (compare_tree_int (align, ptralign) == 1)
692 {
693 check_align = make_ssa_name (pointer_sized_int_node, NULL);
694 g = gimple_build_assign_with_ops (NOP_EXPR, check_align,
695 ptr, NULL_TREE);
696 gimple_set_location (g, loc);
697 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
698 }
699 }
700 check_null = (flag_sanitize & SANITIZE_NULL) != 0;
701
702 if (check_align == NULL_TREE && !check_null)
703 {
704 gsi_remove (gsip, true);
705 /* Unlink the UBSAN_NULLs vops before replacing it. */
706 unlink_stmt_vdef (stmt);
707 return true;
708 }
709
710 /* Split the original block holding the pointer dereference. */
711 edge e = split_block (cur_bb, stmt);
712
713 /* Get a hold on the 'condition block', the 'then block' and the
714 'else block'. */
715 basic_block cond_bb = e->src;
716 basic_block fallthru_bb = e->dest;
717 basic_block then_bb = create_empty_bb (cond_bb);
718 add_bb_to_loop (then_bb, cond_bb->loop_father);
719 loops_state_set (LOOPS_NEED_FIXUP);
720
721 /* Make an edge coming from the 'cond block' into the 'then block';
722 this edge is unlikely taken, so set up the probability accordingly. */
723 e = make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
724 e->probability = PROB_VERY_UNLIKELY;
725
726 /* Connect 'then block' with the 'else block'. This is needed
727 as the ubsan routines we call in the 'then block' are not noreturn.
728 The 'then block' only has one outcoming edge. */
729 make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);
730
731 /* Set up the fallthrough basic block. */
732 e = find_edge (cond_bb, fallthru_bb);
733 e->flags = EDGE_FALSE_VALUE;
734 e->count = cond_bb->count;
735 e->probability = REG_BR_PROB_BASE - PROB_VERY_UNLIKELY;
736
737 /* Update dominance info for the newly created then_bb; note that
738 fallthru_bb's dominance info has already been updated by
739 split_block. */
740 if (dom_info_available_p (CDI_DOMINATORS))
741 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
742
743 /* Put the ubsan builtin call into the newly created BB. */
744 if (flag_sanitize_undefined_trap_on_error)
745 g = gimple_build_call (builtin_decl_implicit (BUILT_IN_TRAP), 0);
746 else
747 {
748 enum built_in_function bcode
749 = (flag_sanitize_recover & ((check_align ? SANITIZE_ALIGNMENT : 0)
750 | (check_null ? SANITIZE_NULL : 0)))
751 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
752 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT;
753 tree fn = builtin_decl_implicit (bcode);
754 tree data
755 = ubsan_create_data ("__ubsan_null_data", 1, &loc,
756 ubsan_type_descriptor (TREE_TYPE (ckind),
757 UBSAN_PRINT_POINTER),
758 NULL_TREE,
759 align,
760 fold_convert (unsigned_char_type_node, ckind),
761 NULL_TREE);
762 data = build_fold_addr_expr_loc (loc, data);
763 g = gimple_build_call (fn, 2, data,
764 check_align ? check_align
765 : build_zero_cst (pointer_sized_int_node));
766 }
767 gimple_stmt_iterator gsi2 = gsi_start_bb (then_bb);
768 gimple_set_location (g, loc);
769 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
770
771 /* Unlink the UBSAN_NULLs vops before replacing it. */
772 unlink_stmt_vdef (stmt);
773
774 if (check_null)
775 {
776 g = gimple_build_cond (EQ_EXPR, ptr, build_int_cst (TREE_TYPE (ptr), 0),
777 NULL_TREE, NULL_TREE);
778 gimple_set_location (g, loc);
779
780 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
781 gsi_replace (&gsi, g, false);
782 }
783
784 if (check_align)
785 {
786 if (check_null)
787 {
788 /* Split the block with the condition again. */
789 e = split_block (cond_bb, stmt);
790 basic_block cond1_bb = e->src;
791 basic_block cond2_bb = e->dest;
792
793 /* Make an edge coming from the 'cond1 block' into the 'then block';
794 this edge is unlikely taken, so set up the probability
795 accordingly. */
796 e = make_edge (cond1_bb, then_bb, EDGE_TRUE_VALUE);
797 e->probability = PROB_VERY_UNLIKELY;
798
799 /* Set up the fallthrough basic block. */
800 e = find_edge (cond1_bb, cond2_bb);
801 e->flags = EDGE_FALSE_VALUE;
802 e->count = cond1_bb->count;
803 e->probability = REG_BR_PROB_BASE - PROB_VERY_UNLIKELY;
804
805 /* Update dominance info. */
806 if (dom_info_available_p (CDI_DOMINATORS))
807 {
808 set_immediate_dominator (CDI_DOMINATORS, fallthru_bb, cond1_bb);
809 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond1_bb);
810 }
811
812 gsi2 = gsi_start_bb (cond2_bb);
813 }
814
815 tree mask = build_int_cst (pointer_sized_int_node,
816 tree_to_uhwi (align) - 1);
817 g = gimple_build_assign_with_ops (BIT_AND_EXPR,
818 make_ssa_name (pointer_sized_int_node,
819 NULL),
820 check_align, mask);
821 gimple_set_location (g, loc);
822 if (check_null)
823 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
824 else
825 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
826
827 g = gimple_build_cond (NE_EXPR, gimple_assign_lhs (g),
828 build_int_cst (pointer_sized_int_node, 0),
829 NULL_TREE, NULL_TREE);
830 gimple_set_location (g, loc);
831 if (check_null)
832 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
833 else
834 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
835 gsi_replace (&gsi, g, false);
836 }
837 return false;
838 }
839
840 /* Expand UBSAN_OBJECT_SIZE internal call. */
841
842 bool
843 ubsan_expand_objsize_ifn (gimple_stmt_iterator *gsi)
844 {
845 gimple stmt = gsi_stmt (*gsi);
846 location_t loc = gimple_location (stmt);
847 gcc_assert (gimple_call_num_args (stmt) == 4);
848
849 tree ptr = gimple_call_arg (stmt, 0);
850 tree offset = gimple_call_arg (stmt, 1);
851 tree size = gimple_call_arg (stmt, 2);
852 tree ckind = gimple_call_arg (stmt, 3);
853 gimple_stmt_iterator gsi_orig = *gsi;
854 gimple g;
855
856 /* See if we can discard the check. */
857 if (TREE_CODE (size) != INTEGER_CST
858 || integer_all_onesp (size))
859 /* Yes, __builtin_object_size couldn't determine the
860 object size. */;
861 else
862 {
863 /* if (offset > objsize) */
864 basic_block then_bb, fallthru_bb;
865 gimple_stmt_iterator cond_insert_point
866 = create_cond_insert_point (gsi, false, false, true,
867 &then_bb, &fallthru_bb);
868 g = gimple_build_cond (GT_EXPR, offset, size, NULL_TREE, NULL_TREE);
869 gimple_set_location (g, loc);
870 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
871
872 /* Generate __ubsan_handle_type_mismatch call. */
873 *gsi = gsi_after_labels (then_bb);
874 if (flag_sanitize_undefined_trap_on_error)
875 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
876 else
877 {
878 tree data
879 = ubsan_create_data ("__ubsan_objsz_data", 1, &loc,
880 ubsan_type_descriptor (TREE_TYPE (ptr),
881 UBSAN_PRINT_POINTER),
882 NULL_TREE,
883 build_zero_cst (pointer_sized_int_node),
884 ckind,
885 NULL_TREE);
886 data = build_fold_addr_expr_loc (loc, data);
887 enum built_in_function bcode
888 = (flag_sanitize_recover & SANITIZE_OBJECT_SIZE)
889 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
890 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT;
891 tree p = make_ssa_name (pointer_sized_int_node, NULL);
892 g = gimple_build_assign_with_ops (NOP_EXPR, p, ptr, NULL_TREE);
893 gimple_set_location (g, loc);
894 gsi_insert_before (gsi, g, GSI_SAME_STMT);
895 g = gimple_build_call (builtin_decl_explicit (bcode), 2, data, p);
896 }
897 gimple_set_location (g, loc);
898 gsi_insert_before (gsi, g, GSI_SAME_STMT);
899
900 /* Point GSI to next logical statement. */
901 *gsi = gsi_start_bb (fallthru_bb);
902 }
903
904 /* Get rid of the UBSAN_OBJECT_SIZE call from the IR. */
905 unlink_stmt_vdef (stmt);
906 gsi_remove (&gsi_orig, true);
907 return gsi_end_p (*gsi);
908 }
909
910 /* Instrument a memory reference. BASE is the base of MEM, IS_LHS says
911 whether the pointer is on the left hand side of the assignment. */
912
913 static void
914 instrument_mem_ref (tree mem, tree base, gimple_stmt_iterator *iter,
915 bool is_lhs)
916 {
917 enum ubsan_null_ckind ikind = is_lhs ? UBSAN_STORE_OF : UBSAN_LOAD_OF;
918 unsigned int align = 0;
919 if (flag_sanitize & SANITIZE_ALIGNMENT)
920 {
921 align = min_align_of_type (TREE_TYPE (base));
922 if (align <= 1)
923 align = 0;
924 }
925 if (align == 0 && (flag_sanitize & SANITIZE_NULL) == 0)
926 return;
927 tree t = TREE_OPERAND (base, 0);
928 if (!POINTER_TYPE_P (TREE_TYPE (t)))
929 return;
930 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (TREE_TYPE (t))) && mem != base)
931 ikind = UBSAN_MEMBER_ACCESS;
932 tree kind = build_int_cst (TREE_TYPE (t), ikind);
933 tree alignt = build_int_cst (pointer_sized_int_node, align);
934 gimple g = gimple_build_call_internal (IFN_UBSAN_NULL, 3, t, kind, alignt);
935 gimple_set_location (g, gimple_location (gsi_stmt (*iter)));
936 gsi_insert_before (iter, g, GSI_SAME_STMT);
937 }
938
939 /* Perform the pointer instrumentation. */
940
941 static void
942 instrument_null (gimple_stmt_iterator gsi, bool is_lhs)
943 {
944 gimple stmt = gsi_stmt (gsi);
945 tree t = is_lhs ? gimple_get_lhs (stmt) : gimple_assign_rhs1 (stmt);
946 tree base = get_base_address (t);
947 const enum tree_code code = TREE_CODE (base);
948 if (code == MEM_REF
949 && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
950 instrument_mem_ref (t, base, &gsi, is_lhs);
951 }
952
953 /* Build an ubsan builtin call for the signed-integer-overflow
954 sanitization. CODE says what kind of builtin are we building,
955 LOC is a location, LHSTYPE is the type of LHS, OP0 and OP1
956 are operands of the binary operation. */
957
958 tree
959 ubsan_build_overflow_builtin (tree_code code, location_t loc, tree lhstype,
960 tree op0, tree op1)
961 {
962 if (flag_sanitize_undefined_trap_on_error)
963 return build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
964
965 tree data = ubsan_create_data ("__ubsan_overflow_data", 1, &loc,
966 ubsan_type_descriptor (lhstype), NULL_TREE,
967 NULL_TREE);
968 enum built_in_function fn_code;
969
970 switch (code)
971 {
972 case PLUS_EXPR:
973 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
974 ? BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW
975 : BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW_ABORT;
976 break;
977 case MINUS_EXPR:
978 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
979 ? BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW
980 : BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW_ABORT;
981 break;
982 case MULT_EXPR:
983 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
984 ? BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW
985 : BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW_ABORT;
986 break;
987 case NEGATE_EXPR:
988 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
989 ? BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW
990 : BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW_ABORT;
991 break;
992 default:
993 gcc_unreachable ();
994 }
995 tree fn = builtin_decl_explicit (fn_code);
996 return build_call_expr_loc (loc, fn, 2 + (code != NEGATE_EXPR),
997 build_fold_addr_expr_loc (loc, data),
998 ubsan_encode_value (op0, true),
999 op1 ? ubsan_encode_value (op1, true)
1000 : NULL_TREE);
1001 }
1002
1003 /* Perform the signed integer instrumentation. GSI is the iterator
1004 pointing at statement we are trying to instrument. */
1005
1006 static void
1007 instrument_si_overflow (gimple_stmt_iterator gsi)
1008 {
1009 gimple stmt = gsi_stmt (gsi);
1010 tree_code code = gimple_assign_rhs_code (stmt);
1011 tree lhs = gimple_assign_lhs (stmt);
1012 tree lhstype = TREE_TYPE (lhs);
1013 tree a, b;
1014 gimple g;
1015
1016 /* If this is not a signed operation, don't instrument anything here.
1017 Also punt on bit-fields. */
1018 if (!INTEGRAL_TYPE_P (lhstype)
1019 || TYPE_OVERFLOW_WRAPS (lhstype)
1020 || GET_MODE_BITSIZE (TYPE_MODE (lhstype)) != TYPE_PRECISION (lhstype))
1021 return;
1022
1023 switch (code)
1024 {
1025 case MINUS_EXPR:
1026 case PLUS_EXPR:
1027 case MULT_EXPR:
1028 /* Transform
1029 i = u {+,-,*} 5;
1030 into
1031 i = UBSAN_CHECK_{ADD,SUB,MUL} (u, 5); */
1032 a = gimple_assign_rhs1 (stmt);
1033 b = gimple_assign_rhs2 (stmt);
1034 g = gimple_build_call_internal (code == PLUS_EXPR
1035 ? IFN_UBSAN_CHECK_ADD
1036 : code == MINUS_EXPR
1037 ? IFN_UBSAN_CHECK_SUB
1038 : IFN_UBSAN_CHECK_MUL, 2, a, b);
1039 gimple_call_set_lhs (g, lhs);
1040 gsi_replace (&gsi, g, false);
1041 break;
1042 case NEGATE_EXPR:
1043 /* Represent i = -u;
1044 as
1045 i = UBSAN_CHECK_SUB (0, u); */
1046 a = build_int_cst (lhstype, 0);
1047 b = gimple_assign_rhs1 (stmt);
1048 g = gimple_build_call_internal (IFN_UBSAN_CHECK_SUB, 2, a, b);
1049 gimple_call_set_lhs (g, lhs);
1050 gsi_replace (&gsi, g, false);
1051 break;
1052 case ABS_EXPR:
1053 /* Transform i = ABS_EXPR<u>;
1054 into
1055 _N = UBSAN_CHECK_SUB (0, u);
1056 i = ABS_EXPR<_N>; */
1057 a = build_int_cst (lhstype, 0);
1058 b = gimple_assign_rhs1 (stmt);
1059 g = gimple_build_call_internal (IFN_UBSAN_CHECK_SUB, 2, a, b);
1060 a = make_ssa_name (lhstype, NULL);
1061 gimple_call_set_lhs (g, a);
1062 gimple_set_location (g, gimple_location (stmt));
1063 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
1064 gimple_assign_set_rhs1 (stmt, a);
1065 update_stmt (stmt);
1066 break;
1067 default:
1068 break;
1069 }
1070 }
1071
1072 /* Instrument loads from (non-bitfield) bool and C++ enum values
1073 to check if the memory value is outside of the range of the valid
1074 type values. */
1075
1076 static void
1077 instrument_bool_enum_load (gimple_stmt_iterator *gsi)
1078 {
1079 gimple stmt = gsi_stmt (*gsi);
1080 tree rhs = gimple_assign_rhs1 (stmt);
1081 tree type = TREE_TYPE (rhs);
1082 tree minv = NULL_TREE, maxv = NULL_TREE;
1083
1084 if (TREE_CODE (type) == BOOLEAN_TYPE && (flag_sanitize & SANITIZE_BOOL))
1085 {
1086 minv = boolean_false_node;
1087 maxv = boolean_true_node;
1088 }
1089 else if (TREE_CODE (type) == ENUMERAL_TYPE
1090 && (flag_sanitize & SANITIZE_ENUM)
1091 && TREE_TYPE (type) != NULL_TREE
1092 && TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE
1093 && (TYPE_PRECISION (TREE_TYPE (type))
1094 < GET_MODE_PRECISION (TYPE_MODE (type))))
1095 {
1096 minv = TYPE_MIN_VALUE (TREE_TYPE (type));
1097 maxv = TYPE_MAX_VALUE (TREE_TYPE (type));
1098 }
1099 else
1100 return;
1101
1102 int modebitsize = GET_MODE_BITSIZE (TYPE_MODE (type));
1103 HOST_WIDE_INT bitsize, bitpos;
1104 tree offset;
1105 enum machine_mode mode;
1106 int volatilep = 0, unsignedp = 0;
1107 tree base = get_inner_reference (rhs, &bitsize, &bitpos, &offset, &mode,
1108 &unsignedp, &volatilep, false);
1109 tree utype = build_nonstandard_integer_type (modebitsize, 1);
1110
1111 if ((TREE_CODE (base) == VAR_DECL && DECL_HARD_REGISTER (base))
1112 || (bitpos % modebitsize) != 0
1113 || bitsize != modebitsize
1114 || GET_MODE_BITSIZE (TYPE_MODE (utype)) != modebitsize
1115 || TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME)
1116 return;
1117
1118 location_t loc = gimple_location (stmt);
1119 tree ptype = build_pointer_type (TREE_TYPE (rhs));
1120 tree atype = reference_alias_ptr_type (rhs);
1121 gimple g = gimple_build_assign (make_ssa_name (ptype, NULL),
1122 build_fold_addr_expr (rhs));
1123 gimple_set_location (g, loc);
1124 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1125 tree mem = build2 (MEM_REF, utype, gimple_assign_lhs (g),
1126 build_int_cst (atype, 0));
1127 tree urhs = make_ssa_name (utype, NULL);
1128 g = gimple_build_assign (urhs, mem);
1129 gimple_set_location (g, loc);
1130 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1131 minv = fold_convert (utype, minv);
1132 maxv = fold_convert (utype, maxv);
1133 if (!integer_zerop (minv))
1134 {
1135 g = gimple_build_assign_with_ops (MINUS_EXPR,
1136 make_ssa_name (utype, NULL),
1137 urhs, minv);
1138 gimple_set_location (g, loc);
1139 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1140 }
1141
1142 gimple_stmt_iterator gsi2 = *gsi;
1143 basic_block then_bb, fallthru_bb;
1144 *gsi = create_cond_insert_point (gsi, true, false, true,
1145 &then_bb, &fallthru_bb);
1146 g = gimple_build_cond (GT_EXPR, gimple_assign_lhs (g),
1147 int_const_binop (MINUS_EXPR, maxv, minv),
1148 NULL_TREE, NULL_TREE);
1149 gimple_set_location (g, loc);
1150 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1151
1152 gimple_assign_set_rhs_with_ops (&gsi2, NOP_EXPR, urhs, NULL_TREE);
1153 update_stmt (stmt);
1154
1155 gsi2 = gsi_after_labels (then_bb);
1156 if (flag_sanitize_undefined_trap_on_error)
1157 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1158 else
1159 {
1160 tree data = ubsan_create_data ("__ubsan_invalid_value_data", 1, &loc,
1161 ubsan_type_descriptor (type), NULL_TREE,
1162 NULL_TREE);
1163 data = build_fold_addr_expr_loc (loc, data);
1164 enum built_in_function bcode
1165 = (flag_sanitize_recover & (TREE_CODE (type) == BOOLEAN_TYPE
1166 ? SANITIZE_BOOL : SANITIZE_ENUM))
1167 ? BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE
1168 : BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE_ABORT;
1169 tree fn = builtin_decl_explicit (bcode);
1170
1171 tree val = force_gimple_operand_gsi (&gsi2, ubsan_encode_value (urhs),
1172 true, NULL_TREE, true,
1173 GSI_SAME_STMT);
1174 g = gimple_build_call (fn, 2, data, val);
1175 }
1176 gimple_set_location (g, loc);
1177 gsi_insert_before (&gsi2, g, GSI_SAME_STMT);
1178 *gsi = gsi_for_stmt (stmt);
1179 }
1180
1181 /* Instrument float point-to-integer conversion. TYPE is an integer type of
1182 destination, EXPR is floating-point expression. */
1183
1184 tree
1185 ubsan_instrument_float_cast (location_t loc, tree type, tree expr)
1186 {
1187 tree expr_type = TREE_TYPE (expr);
1188 tree t, tt, fn, min, max;
1189 enum machine_mode mode = TYPE_MODE (expr_type);
1190 int prec = TYPE_PRECISION (type);
1191 bool uns_p = TYPE_UNSIGNED (type);
1192
1193 /* Float to integer conversion first truncates toward zero, so
1194 even signed char c = 127.875f; is not problematic.
1195 Therefore, we should complain only if EXPR is unordered or smaller
1196 or equal than TYPE_MIN_VALUE - 1.0 or greater or equal than
1197 TYPE_MAX_VALUE + 1.0. */
1198 if (REAL_MODE_FORMAT (mode)->b == 2)
1199 {
1200 /* For maximum, TYPE_MAX_VALUE might not be representable
1201 in EXPR_TYPE, e.g. if TYPE is 64-bit long long and
1202 EXPR_TYPE is IEEE single float, but TYPE_MAX_VALUE + 1.0 is
1203 either representable or infinity. */
1204 REAL_VALUE_TYPE maxval = dconst1;
1205 SET_REAL_EXP (&maxval, REAL_EXP (&maxval) + prec - !uns_p);
1206 real_convert (&maxval, mode, &maxval);
1207 max = build_real (expr_type, maxval);
1208
1209 /* For unsigned, assume -1.0 is always representable. */
1210 if (uns_p)
1211 min = build_minus_one_cst (expr_type);
1212 else
1213 {
1214 /* TYPE_MIN_VALUE is generally representable (or -inf),
1215 but TYPE_MIN_VALUE - 1.0 might not be. */
1216 REAL_VALUE_TYPE minval = dconstm1, minval2;
1217 SET_REAL_EXP (&minval, REAL_EXP (&minval) + prec - 1);
1218 real_convert (&minval, mode, &minval);
1219 real_arithmetic (&minval2, MINUS_EXPR, &minval, &dconst1);
1220 real_convert (&minval2, mode, &minval2);
1221 if (real_compare (EQ_EXPR, &minval, &minval2)
1222 && !real_isinf (&minval))
1223 {
1224 /* If TYPE_MIN_VALUE - 1.0 is not representable and
1225 rounds to TYPE_MIN_VALUE, we need to subtract
1226 more. As REAL_MODE_FORMAT (mode)->p is the number
1227 of base digits, we want to subtract a number that
1228 will be 1 << (REAL_MODE_FORMAT (mode)->p - 1)
1229 times smaller than minval. */
1230 minval2 = dconst1;
1231 gcc_assert (prec > REAL_MODE_FORMAT (mode)->p);
1232 SET_REAL_EXP (&minval2,
1233 REAL_EXP (&minval2) + prec - 1
1234 - REAL_MODE_FORMAT (mode)->p + 1);
1235 real_arithmetic (&minval2, MINUS_EXPR, &minval, &minval2);
1236 real_convert (&minval2, mode, &minval2);
1237 }
1238 min = build_real (expr_type, minval2);
1239 }
1240 }
1241 else if (REAL_MODE_FORMAT (mode)->b == 10)
1242 {
1243 /* For _Decimal128 up to 34 decimal digits, - sign,
1244 dot, e, exponent. */
1245 char buf[64];
1246 mpfr_t m;
1247 int p = REAL_MODE_FORMAT (mode)->p;
1248 REAL_VALUE_TYPE maxval, minval;
1249
1250 /* Use mpfr_snprintf rounding to compute the smallest
1251 representable decimal number greater or equal than
1252 1 << (prec - !uns_p). */
1253 mpfr_init2 (m, prec + 2);
1254 mpfr_set_ui_2exp (m, 1, prec - !uns_p, GMP_RNDN);
1255 mpfr_snprintf (buf, sizeof buf, "%.*RUe", p - 1, m);
1256 decimal_real_from_string (&maxval, buf);
1257 max = build_real (expr_type, maxval);
1258
1259 /* For unsigned, assume -1.0 is always representable. */
1260 if (uns_p)
1261 min = build_minus_one_cst (expr_type);
1262 else
1263 {
1264 /* Use mpfr_snprintf rounding to compute the largest
1265 representable decimal number less or equal than
1266 (-1 << (prec - 1)) - 1. */
1267 mpfr_set_si_2exp (m, -1, prec - 1, GMP_RNDN);
1268 mpfr_sub_ui (m, m, 1, GMP_RNDN);
1269 mpfr_snprintf (buf, sizeof buf, "%.*RDe", p - 1, m);
1270 decimal_real_from_string (&minval, buf);
1271 min = build_real (expr_type, minval);
1272 }
1273 mpfr_clear (m);
1274 }
1275 else
1276 return NULL_TREE;
1277
1278 if (flag_sanitize_undefined_trap_on_error)
1279 fn = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
1280 else
1281 {
1282 /* Create the __ubsan_handle_float_cast_overflow fn call. */
1283 tree data = ubsan_create_data ("__ubsan_float_cast_overflow_data", 0,
1284 NULL, ubsan_type_descriptor (expr_type),
1285 ubsan_type_descriptor (type), NULL_TREE,
1286 NULL_TREE);
1287 enum built_in_function bcode
1288 = (flag_sanitize_recover & SANITIZE_FLOAT_CAST)
1289 ? BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW
1290 : BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW_ABORT;
1291 fn = builtin_decl_explicit (bcode);
1292 fn = build_call_expr_loc (loc, fn, 2,
1293 build_fold_addr_expr_loc (loc, data),
1294 ubsan_encode_value (expr, false));
1295 }
1296
1297 t = fold_build2 (UNLE_EXPR, boolean_type_node, expr, min);
1298 tt = fold_build2 (UNGE_EXPR, boolean_type_node, expr, max);
1299 return fold_build3 (COND_EXPR, void_type_node,
1300 fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t, tt),
1301 fn, integer_zero_node);
1302 }
1303
1304 /* Instrument values passed to function arguments with nonnull attribute. */
1305
1306 static void
1307 instrument_nonnull_arg (gimple_stmt_iterator *gsi)
1308 {
1309 gimple stmt = gsi_stmt (*gsi);
1310 location_t loc[2];
1311 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
1312 while for nonnull sanitization it is clear. */
1313 int save_flag_delete_null_pointer_checks = flag_delete_null_pointer_checks;
1314 flag_delete_null_pointer_checks = 1;
1315 loc[0] = gimple_location (stmt);
1316 loc[1] = UNKNOWN_LOCATION;
1317 for (unsigned int i = 0; i < gimple_call_num_args (stmt); i++)
1318 {
1319 tree arg = gimple_call_arg (stmt, i);
1320 if (POINTER_TYPE_P (TREE_TYPE (arg))
1321 && infer_nonnull_range (stmt, arg, false, true))
1322 {
1323 gimple g;
1324 if (!is_gimple_val (arg))
1325 {
1326 g = gimple_build_assign (make_ssa_name (TREE_TYPE (arg), NULL),
1327 arg);
1328 gimple_set_location (g, loc[0]);
1329 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1330 arg = gimple_assign_lhs (g);
1331 }
1332
1333 basic_block then_bb, fallthru_bb;
1334 *gsi = create_cond_insert_point (gsi, true, false, true,
1335 &then_bb, &fallthru_bb);
1336 g = gimple_build_cond (EQ_EXPR, arg,
1337 build_zero_cst (TREE_TYPE (arg)),
1338 NULL_TREE, NULL_TREE);
1339 gimple_set_location (g, loc[0]);
1340 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1341
1342 *gsi = gsi_after_labels (then_bb);
1343 if (flag_sanitize_undefined_trap_on_error)
1344 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1345 else
1346 {
1347 tree data = ubsan_create_data ("__ubsan_nonnull_arg_data",
1348 2, loc, NULL_TREE,
1349 build_int_cst (integer_type_node,
1350 i + 1),
1351 NULL_TREE);
1352 data = build_fold_addr_expr_loc (loc[0], data);
1353 enum built_in_function bcode
1354 = (flag_sanitize_recover & SANITIZE_NONNULL_ATTRIBUTE)
1355 ? BUILT_IN_UBSAN_HANDLE_NONNULL_ARG
1356 : BUILT_IN_UBSAN_HANDLE_NONNULL_ARG_ABORT;
1357 tree fn = builtin_decl_explicit (bcode);
1358
1359 g = gimple_build_call (fn, 1, data);
1360 }
1361 gimple_set_location (g, loc[0]);
1362 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1363 }
1364 *gsi = gsi_for_stmt (stmt);
1365 }
1366 flag_delete_null_pointer_checks = save_flag_delete_null_pointer_checks;
1367 }
1368
1369 /* Instrument returns in functions with returns_nonnull attribute. */
1370
1371 static void
1372 instrument_nonnull_return (gimple_stmt_iterator *gsi)
1373 {
1374 gimple stmt = gsi_stmt (*gsi);
1375 location_t loc[2];
1376 tree arg = gimple_return_retval (stmt);
1377 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
1378 while for nonnull return sanitization it is clear. */
1379 int save_flag_delete_null_pointer_checks = flag_delete_null_pointer_checks;
1380 flag_delete_null_pointer_checks = 1;
1381 loc[0] = gimple_location (stmt);
1382 loc[1] = UNKNOWN_LOCATION;
1383 if (arg
1384 && POINTER_TYPE_P (TREE_TYPE (arg))
1385 && is_gimple_val (arg)
1386 && infer_nonnull_range (stmt, arg, false, true))
1387 {
1388 basic_block then_bb, fallthru_bb;
1389 *gsi = create_cond_insert_point (gsi, true, false, true,
1390 &then_bb, &fallthru_bb);
1391 gimple g = gimple_build_cond (EQ_EXPR, arg,
1392 build_zero_cst (TREE_TYPE (arg)),
1393 NULL_TREE, NULL_TREE);
1394 gimple_set_location (g, loc[0]);
1395 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1396
1397 *gsi = gsi_after_labels (then_bb);
1398 if (flag_sanitize_undefined_trap_on_error)
1399 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1400 else
1401 {
1402 tree data = ubsan_create_data ("__ubsan_nonnull_return_data",
1403 2, loc, NULL_TREE, NULL_TREE);
1404 data = build_fold_addr_expr_loc (loc[0], data);
1405 enum built_in_function bcode
1406 = (flag_sanitize_recover & SANITIZE_RETURNS_NONNULL_ATTRIBUTE)
1407 ? BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN
1408 : BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_ABORT;
1409 tree fn = builtin_decl_explicit (bcode);
1410
1411 g = gimple_build_call (fn, 1, data);
1412 }
1413 gimple_set_location (g, loc[0]);
1414 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1415 *gsi = gsi_for_stmt (stmt);
1416 }
1417 flag_delete_null_pointer_checks = save_flag_delete_null_pointer_checks;
1418 }
1419
1420 /* Instrument memory references. Here we check whether the pointer
1421 points to an out-of-bounds location. */
1422
1423 static void
1424 instrument_object_size (gimple_stmt_iterator *gsi, bool is_lhs)
1425 {
1426 gimple stmt = gsi_stmt (*gsi);
1427 location_t loc = gimple_location (stmt);
1428 tree t = is_lhs ? gimple_get_lhs (stmt) : gimple_assign_rhs1 (stmt);
1429 tree type;
1430 HOST_WIDE_INT size_in_bytes;
1431
1432 type = TREE_TYPE (t);
1433 if (VOID_TYPE_P (type))
1434 return;
1435
1436 switch (TREE_CODE (t))
1437 {
1438 case COMPONENT_REF:
1439 if (TREE_CODE (t) == COMPONENT_REF
1440 && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1)) != NULL_TREE)
1441 {
1442 tree repr = DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1));
1443 t = build3 (COMPONENT_REF, TREE_TYPE (repr), TREE_OPERAND (t, 0),
1444 repr, NULL_TREE);
1445 }
1446 break;
1447 case ARRAY_REF:
1448 case INDIRECT_REF:
1449 case MEM_REF:
1450 case VAR_DECL:
1451 case PARM_DECL:
1452 case RESULT_DECL:
1453 break;
1454 default:
1455 return;
1456 }
1457
1458 size_in_bytes = int_size_in_bytes (type);
1459 if (size_in_bytes <= 0)
1460 return;
1461
1462 HOST_WIDE_INT bitsize, bitpos;
1463 tree offset;
1464 enum machine_mode mode;
1465 int volatilep = 0, unsignedp = 0;
1466 tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset, &mode,
1467 &unsignedp, &volatilep, false);
1468
1469 if (bitpos % BITS_PER_UNIT != 0
1470 || bitsize != size_in_bytes * BITS_PER_UNIT)
1471 return;
1472
1473 bool decl_p = DECL_P (inner);
1474 tree base = decl_p ? inner : TREE_OPERAND (inner, 0);
1475 tree ptr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (t)), t);
1476
1477 while (TREE_CODE (base) == SSA_NAME)
1478 {
1479 gimple def_stmt = SSA_NAME_DEF_STMT (base);
1480 if (gimple_assign_ssa_name_copy_p (def_stmt)
1481 || (gimple_assign_cast_p (def_stmt)
1482 && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (def_stmt))))
1483 || (is_gimple_assign (def_stmt)
1484 && gimple_assign_rhs_code (def_stmt) == POINTER_PLUS_EXPR))
1485 base = gimple_assign_rhs1 (def_stmt);
1486 else
1487 break;
1488 }
1489
1490 if (!POINTER_TYPE_P (TREE_TYPE (base)) && !DECL_P (base))
1491 return;
1492
1493 tree sizet;
1494 tree base_addr = base;
1495 if (decl_p)
1496 base_addr = build1 (ADDR_EXPR,
1497 build_pointer_type (TREE_TYPE (base)), base);
1498 unsigned HOST_WIDE_INT size = compute_builtin_object_size (base_addr, 0);
1499 if (size != (unsigned HOST_WIDE_INT) -1)
1500 sizet = build_int_cst (sizetype, size);
1501 else if (optimize)
1502 {
1503 if (LOCATION_LOCUS (loc) == UNKNOWN_LOCATION)
1504 loc = input_location;
1505 /* Generate __builtin_object_size call. */
1506 sizet = builtin_decl_explicit (BUILT_IN_OBJECT_SIZE);
1507 sizet = build_call_expr_loc (loc, sizet, 2, base_addr,
1508 integer_zero_node);
1509 sizet = force_gimple_operand_gsi (gsi, sizet, false, NULL_TREE, true,
1510 GSI_SAME_STMT);
1511 }
1512 else
1513 return;
1514
1515 /* Generate UBSAN_OBJECT_SIZE (ptr, ptr+sizeof(*ptr)-base, objsize, ckind)
1516 call. */
1517 /* ptr + sizeof (*ptr) - base */
1518 t = fold_build2 (MINUS_EXPR, sizetype,
1519 fold_convert (pointer_sized_int_node, ptr),
1520 fold_convert (pointer_sized_int_node, base_addr));
1521 t = fold_build2 (PLUS_EXPR, sizetype, t, TYPE_SIZE_UNIT (type));
1522
1523 /* Perhaps we can omit the check. */
1524 if (TREE_CODE (t) == INTEGER_CST
1525 && TREE_CODE (sizet) == INTEGER_CST
1526 && tree_int_cst_le (t, sizet))
1527 return;
1528
1529 /* Nope. Emit the check. */
1530 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE, true,
1531 GSI_SAME_STMT);
1532 ptr = force_gimple_operand_gsi (gsi, ptr, true, NULL_TREE, true,
1533 GSI_SAME_STMT);
1534 tree ckind = build_int_cst (unsigned_char_type_node,
1535 is_lhs ? UBSAN_STORE_OF : UBSAN_LOAD_OF);
1536 gimple g = gimple_build_call_internal (IFN_UBSAN_OBJECT_SIZE, 4,
1537 ptr, t, sizet, ckind);
1538 gimple_set_location (g, loc);
1539 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1540 }
1541
1542 namespace {
1543
1544 const pass_data pass_data_ubsan =
1545 {
1546 GIMPLE_PASS, /* type */
1547 "ubsan", /* name */
1548 OPTGROUP_NONE, /* optinfo_flags */
1549 TV_TREE_UBSAN, /* tv_id */
1550 ( PROP_cfg | PROP_ssa ), /* properties_required */
1551 0, /* properties_provided */
1552 0, /* properties_destroyed */
1553 0, /* todo_flags_start */
1554 TODO_update_ssa, /* todo_flags_finish */
1555 };
1556
1557 class pass_ubsan : public gimple_opt_pass
1558 {
1559 public:
1560 pass_ubsan (gcc::context *ctxt)
1561 : gimple_opt_pass (pass_data_ubsan, ctxt)
1562 {}
1563
1564 /* opt_pass methods: */
1565 virtual bool gate (function *)
1566 {
1567 return flag_sanitize & (SANITIZE_NULL | SANITIZE_SI_OVERFLOW
1568 | SANITIZE_BOOL | SANITIZE_ENUM
1569 | SANITIZE_ALIGNMENT
1570 | SANITIZE_NONNULL_ATTRIBUTE
1571 | SANITIZE_RETURNS_NONNULL_ATTRIBUTE
1572 | SANITIZE_OBJECT_SIZE)
1573 && current_function_decl != NULL_TREE
1574 && !lookup_attribute ("no_sanitize_undefined",
1575 DECL_ATTRIBUTES (current_function_decl));
1576 }
1577
1578 virtual unsigned int execute (function *);
1579
1580 }; // class pass_ubsan
1581
1582 unsigned int
1583 pass_ubsan::execute (function *fun)
1584 {
1585 basic_block bb;
1586 gimple_stmt_iterator gsi;
1587
1588 initialize_sanitizer_builtins ();
1589
1590 FOR_EACH_BB_FN (bb, fun)
1591 {
1592 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
1593 {
1594 gimple stmt = gsi_stmt (gsi);
1595 if (is_gimple_debug (stmt) || gimple_clobber_p (stmt))
1596 {
1597 gsi_next (&gsi);
1598 continue;
1599 }
1600
1601 if ((flag_sanitize & SANITIZE_SI_OVERFLOW)
1602 && is_gimple_assign (stmt))
1603 instrument_si_overflow (gsi);
1604
1605 if (flag_sanitize & (SANITIZE_NULL | SANITIZE_ALIGNMENT))
1606 {
1607 if (gimple_store_p (stmt))
1608 instrument_null (gsi, true);
1609 if (gimple_assign_load_p (stmt))
1610 instrument_null (gsi, false);
1611 }
1612
1613 if (flag_sanitize & (SANITIZE_BOOL | SANITIZE_ENUM)
1614 && gimple_assign_load_p (stmt))
1615 {
1616 instrument_bool_enum_load (&gsi);
1617 bb = gimple_bb (stmt);
1618 }
1619
1620 if ((flag_sanitize & SANITIZE_NONNULL_ATTRIBUTE)
1621 && is_gimple_call (stmt)
1622 && !gimple_call_internal_p (stmt))
1623 {
1624 instrument_nonnull_arg (&gsi);
1625 bb = gimple_bb (stmt);
1626 }
1627
1628 if ((flag_sanitize & SANITIZE_RETURNS_NONNULL_ATTRIBUTE)
1629 && gimple_code (stmt) == GIMPLE_RETURN)
1630 {
1631 instrument_nonnull_return (&gsi);
1632 bb = gimple_bb (stmt);
1633 }
1634
1635 if (flag_sanitize & SANITIZE_OBJECT_SIZE)
1636 {
1637 if (gimple_store_p (stmt))
1638 instrument_object_size (&gsi, true);
1639 if (gimple_assign_load_p (stmt))
1640 instrument_object_size (&gsi, false);
1641 }
1642
1643 gsi_next (&gsi);
1644 }
1645 }
1646 return 0;
1647 }
1648
1649 } // anon namespace
1650
1651 gimple_opt_pass *
1652 make_pass_ubsan (gcc::context *ctxt)
1653 {
1654 return new pass_ubsan (ctxt);
1655 }
1656
1657 #include "gt-ubsan.h"