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