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