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