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