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