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