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