]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/c-family/c-ubsan.c
[PR64164] Drop copyrename, use coalescible partition as base when optimizing.
[thirdparty/gcc.git] / gcc / c-family / c-ubsan.c
CommitLineData
de5a5fa1 1/* UndefinedBehaviorSanitizer, undefined behavior detector.
5624e564 2 Copyright (C) 2013-2015 Free Software Foundation, Inc.
de5a5fa1
MP
3 Contributed by Marek Polacek <polacek@redhat.com>
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 3, or (at your option) any later
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
18along 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"
40e23961 24#include "alias.h"
de5a5fa1 25#include "tree.h"
c7131fb2 26#include "options.h"
de5a5fa1 27#include "alloc-pool.h"
c582198b
AM
28#include "tm.h"
29#include "hard-reg-set.h"
c582198b 30#include "function.h"
de5a5fa1 31#include "cgraph.h"
de5a5fa1
MP
32#include "output.h"
33#include "toplev.h"
34#include "ubsan.h"
35#include "c-family/c-common.h"
36#include "c-family/c-ubsan.h"
6525783a 37#include "asan.h"
0e37a2f3 38#include "internal-fn.h"
944fa280
JJ
39#include "stor-layout.h"
40#include "builtins.h"
dc891fe7 41#include "gimplify.h"
de5a5fa1
MP
42
43/* Instrument division by zero and INT_MIN / -1. If not instrumenting,
44 return NULL_TREE. */
45
46tree
47ubsan_instrument_division (location_t loc, tree op0, tree op1)
48{
49 tree t, tt;
50 tree type = TREE_TYPE (op0);
51
52 /* At this point both operands should have the same type,
53 because they are already converted to RESULT_TYPE.
54 Use TYPE_MAIN_VARIANT since typedefs can confuse us. */
55 gcc_assert (TYPE_MAIN_VARIANT (TREE_TYPE (op0))
56 == TYPE_MAIN_VARIANT (TREE_TYPE (op1)));
57
dc891fe7
MP
58 op0 = unshare_expr (op0);
59 op1 = unshare_expr (op1);
60
f8ed5150
MP
61 if (TREE_CODE (type) == INTEGER_TYPE
62 && (flag_sanitize & SANITIZE_DIVIDE))
63 t = fold_build2 (EQ_EXPR, boolean_type_node,
64 op1, build_int_cst (type, 0));
65 else if (TREE_CODE (type) == REAL_TYPE
66 && (flag_sanitize & SANITIZE_FLOAT_DIVIDE))
67 t = fold_build2 (EQ_EXPR, boolean_type_node,
68 op1, build_real (type, dconst0));
69 else
de5a5fa1
MP
70 return NULL_TREE;
71
de5a5fa1 72 /* We check INT_MIN / -1 only for signed types. */
f8ed5150
MP
73 if (TREE_CODE (type) == INTEGER_TYPE
74 && (flag_sanitize & SANITIZE_DIVIDE)
75 && !TYPE_UNSIGNED (type))
de5a5fa1
MP
76 {
77 tree x;
78 tt = fold_build2 (EQ_EXPR, boolean_type_node, op1,
79 build_int_cst (type, -1));
80 x = fold_build2 (EQ_EXPR, boolean_type_node, op0,
81 TYPE_MIN_VALUE (type));
82 x = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, x, tt);
83 t = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t, x);
84 }
85
b56e9788
MP
86 /* If the condition was folded to 0, no need to instrument
87 this expression. */
88 if (integer_zerop (t))
89 return NULL_TREE;
90
de5a5fa1 91 /* In case we have a SAVE_EXPR in a conditional context, we need to
0e37a2f3
MP
92 make sure it gets evaluated before the condition. If the OP0 is
93 an instrumented array reference, mark it as having side effects so
94 it's not folded away. */
95 if (flag_sanitize & SANITIZE_BOUNDS)
96 {
97 tree xop0 = op0;
98 while (CONVERT_EXPR_P (xop0))
99 xop0 = TREE_OPERAND (xop0, 0);
100 if (TREE_CODE (xop0) == ARRAY_REF)
101 {
102 TREE_SIDE_EFFECTS (xop0) = 1;
103 TREE_SIDE_EFFECTS (op0) = 1;
104 }
105 }
de5a5fa1 106 t = fold_build2 (COMPOUND_EXPR, TREE_TYPE (t), op0, t);
1c33c9b7
JJ
107 if (flag_sanitize_undefined_trap_on_error)
108 tt = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
109 else
110 {
570a11fe
JJ
111 tree data = ubsan_create_data ("__ubsan_overflow_data", 1, &loc,
112 ubsan_type_descriptor (type), NULL_TREE,
113 NULL_TREE);
1c33c9b7
JJ
114 data = build_fold_addr_expr_loc (loc, data);
115 enum built_in_function bcode
d95a2703 116 = (flag_sanitize_recover & SANITIZE_DIVIDE)
1c33c9b7
JJ
117 ? BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW
118 : BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW_ABORT;
119 tt = builtin_decl_explicit (bcode);
120 tt = build_call_expr_loc (loc, tt, 3, data, ubsan_encode_value (op0),
121 ubsan_encode_value (op1));
122 }
632f2871 123 t = fold_build3 (COND_EXPR, void_type_node, t, tt, void_node);
de5a5fa1
MP
124
125 return t;
126}
127
b906f4ca 128/* Instrument left and right shifts. */
de5a5fa1
MP
129
130tree
131ubsan_instrument_shift (location_t loc, enum tree_code code,
132 tree op0, tree op1)
133{
134 tree t, tt = NULL_TREE;
135 tree type0 = TREE_TYPE (op0);
136 tree type1 = TREE_TYPE (op1);
137 tree op1_utype = unsigned_type_for (type1);
138 HOST_WIDE_INT op0_prec = TYPE_PRECISION (type0);
139 tree uprecm1 = build_int_cst (op1_utype, op0_prec - 1);
de5a5fa1 140
dc891fe7
MP
141 op0 = unshare_expr (op0);
142 op1 = unshare_expr (op1);
143
de5a5fa1
MP
144 t = fold_convert_loc (loc, op1_utype, op1);
145 t = fold_build2 (GT_EXPR, boolean_type_node, t, uprecm1);
146
147 /* For signed x << y, in C99/C11, the following:
59d7607a 148 (unsigned) x >> (uprecm1 - y)
de5a5fa1
MP
149 if non-zero, is undefined. */
150 if (code == LSHIFT_EXPR
151 && !TYPE_UNSIGNED (type0)
152 && flag_isoc99)
153 {
541e35a6 154 tree x = fold_build2 (MINUS_EXPR, op1_utype, uprecm1,
59d7607a 155 fold_convert (op1_utype, op1));
de5a5fa1
MP
156 tt = fold_convert_loc (loc, unsigned_type_for (type0), op0);
157 tt = fold_build2 (RSHIFT_EXPR, TREE_TYPE (tt), tt, x);
158 tt = fold_build2 (NE_EXPR, boolean_type_node, tt,
159 build_int_cst (TREE_TYPE (tt), 0));
160 }
161
e4276ba5 162 /* For signed x << y, in C++11 and later, the following:
59d7607a 163 x < 0 || ((unsigned) x >> (uprecm1 - y))
de5a5fa1
MP
164 if > 1, is undefined. */
165 if (code == LSHIFT_EXPR
9677ef52 166 && !TYPE_UNSIGNED (type0)
e4276ba5 167 && (cxx_dialect >= cxx11))
de5a5fa1 168 {
6a4da643 169 tree x = fold_build2 (MINUS_EXPR, op1_utype, uprecm1,
59d7607a 170 fold_convert (op1_utype, op1));
de5a5fa1
MP
171 tt = fold_convert_loc (loc, unsigned_type_for (type0), op0);
172 tt = fold_build2 (RSHIFT_EXPR, TREE_TYPE (tt), tt, x);
173 tt = fold_build2 (GT_EXPR, boolean_type_node, tt,
174 build_int_cst (TREE_TYPE (tt), 1));
175 x = fold_build2 (LT_EXPR, boolean_type_node, op0,
176 build_int_cst (type0, 0));
177 tt = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, x, tt);
178 }
179
b56e9788
MP
180 /* If the condition was folded to 0, no need to instrument
181 this expression. */
182 if (integer_zerop (t) && (tt == NULL_TREE || integer_zerop (tt)))
183 return NULL_TREE;
184
de5a5fa1 185 /* In case we have a SAVE_EXPR in a conditional context, we need to
0e37a2f3
MP
186 make sure it gets evaluated before the condition. If the OP0 is
187 an instrumented array reference, mark it as having side effects so
188 it's not folded away. */
189 if (flag_sanitize & SANITIZE_BOUNDS)
190 {
191 tree xop0 = op0;
192 while (CONVERT_EXPR_P (xop0))
193 xop0 = TREE_OPERAND (xop0, 0);
194 if (TREE_CODE (xop0) == ARRAY_REF)
195 {
196 TREE_SIDE_EFFECTS (xop0) = 1;
197 TREE_SIDE_EFFECTS (op0) = 1;
198 }
199 }
de5a5fa1 200 t = fold_build2 (COMPOUND_EXPR, TREE_TYPE (t), op0, t);
de5a5fa1
MP
201 t = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t,
202 tt ? tt : integer_zero_node);
1c33c9b7
JJ
203
204 if (flag_sanitize_undefined_trap_on_error)
205 tt = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
206 else
207 {
570a11fe 208 tree data = ubsan_create_data ("__ubsan_shift_data", 1, &loc,
0e37a2f3 209 ubsan_type_descriptor (type0),
570a11fe
JJ
210 ubsan_type_descriptor (type1), NULL_TREE,
211 NULL_TREE);
1c33c9b7
JJ
212 data = build_fold_addr_expr_loc (loc, data);
213
214 enum built_in_function bcode
d95a2703 215 = (flag_sanitize_recover & SANITIZE_SHIFT)
1c33c9b7
JJ
216 ? BUILT_IN_UBSAN_HANDLE_SHIFT_OUT_OF_BOUNDS
217 : BUILT_IN_UBSAN_HANDLE_SHIFT_OUT_OF_BOUNDS_ABORT;
218 tt = builtin_decl_explicit (bcode);
219 tt = build_call_expr_loc (loc, tt, 3, data, ubsan_encode_value (op0),
220 ubsan_encode_value (op1));
221 }
632f2871 222 t = fold_build3 (COND_EXPR, void_type_node, t, tt, void_node);
de5a5fa1
MP
223
224 return t;
225}
b906f4ca
MP
226
227/* Instrument variable length array bound. */
228
229tree
230ubsan_instrument_vla (location_t loc, tree size)
231{
232 tree type = TREE_TYPE (size);
233 tree t, tt;
234
235 t = fold_build2 (LE_EXPR, boolean_type_node, size, build_int_cst (type, 0));
1c33c9b7
JJ
236 if (flag_sanitize_undefined_trap_on_error)
237 tt = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
238 else
239 {
570a11fe
JJ
240 tree data = ubsan_create_data ("__ubsan_vla_data", 1, &loc,
241 ubsan_type_descriptor (type), NULL_TREE,
242 NULL_TREE);
1c33c9b7
JJ
243 data = build_fold_addr_expr_loc (loc, data);
244 enum built_in_function bcode
d95a2703 245 = (flag_sanitize_recover & SANITIZE_VLA)
1c33c9b7
JJ
246 ? BUILT_IN_UBSAN_HANDLE_VLA_BOUND_NOT_POSITIVE
247 : BUILT_IN_UBSAN_HANDLE_VLA_BOUND_NOT_POSITIVE_ABORT;
248 tt = builtin_decl_explicit (bcode);
249 tt = build_call_expr_loc (loc, tt, 2, data, ubsan_encode_value (size));
250 }
632f2871 251 t = fold_build3 (COND_EXPR, void_type_node, t, tt, void_node);
b906f4ca
MP
252
253 return t;
254}
0a508bb6
JJ
255
256/* Instrument missing return in C++ functions returning non-void. */
257
258tree
259ubsan_instrument_return (location_t loc)
260{
1c33c9b7
JJ
261 if (flag_sanitize_undefined_trap_on_error)
262 return build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
6525783a
MP
263 /* It is possible that PCH zapped table with definitions of sanitizer
264 builtins. Reinitialize them if needed. */
265 initialize_sanitizer_builtins ();
266
570a11fe
JJ
267 tree data = ubsan_create_data ("__ubsan_missing_return_data", 1, &loc,
268 NULL_TREE, NULL_TREE);
0a508bb6
JJ
269 tree t = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_MISSING_RETURN);
270 return build_call_expr_loc (loc, t, 1, build_fold_addr_expr_loc (loc, data));
271}
0e37a2f3
MP
272
273/* Instrument array bounds for ARRAY_REFs. We create special builtin,
274 that gets expanded in the sanopt pass, and make an array dimension
275 of it. ARRAY is the array, *INDEX is an index to the array.
276 Return NULL_TREE if no instrumentation is emitted.
277 IGNORE_OFF_BY_ONE is true if the ARRAY_REF is inside a ADDR_EXPR. */
278
279tree
280ubsan_instrument_bounds (location_t loc, tree array, tree *index,
281 bool ignore_off_by_one)
282{
283 tree type = TREE_TYPE (array);
284 tree domain = TYPE_DOMAIN (type);
285
4d661eaa 286 if (domain == NULL_TREE || TYPE_MAX_VALUE (domain) == NULL_TREE)
0e37a2f3
MP
287 return NULL_TREE;
288
289 tree bound = TYPE_MAX_VALUE (domain);
290 if (ignore_off_by_one)
291 bound = fold_build2 (PLUS_EXPR, TREE_TYPE (bound), bound,
292 build_int_cst (TREE_TYPE (bound), 1));
293
e0f0d3b9
MP
294 /* Detect flexible array members and suchlike, unless
295 -fsanitize=bounds-strict. */
0e37a2f3 296 tree base = get_base_address (array);
e0f0d3b9
MP
297 if ((flag_sanitize & SANITIZE_BOUNDS_STRICT) == 0
298 && TREE_CODE (array) == COMPONENT_REF
22d03525 299 && base && (INDIRECT_REF_P (base) || TREE_CODE (base) == MEM_REF))
0e37a2f3
MP
300 {
301 tree next = NULL_TREE;
302 tree cref = array;
303
304 /* Walk all structs/unions. */
305 while (TREE_CODE (cref) == COMPONENT_REF)
306 {
307 if (TREE_CODE (TREE_TYPE (TREE_OPERAND (cref, 0))) == RECORD_TYPE)
308 for (next = DECL_CHAIN (TREE_OPERAND (cref, 1));
309 next && TREE_CODE (next) != FIELD_DECL;
310 next = DECL_CHAIN (next))
311 ;
312 if (next)
313 /* Not a last element. Instrument it. */
314 break;
315 /* Ok, this is the last field of the structure/union. But the
316 aggregate containing the field must be the last field too,
317 recursively. */
318 cref = TREE_OPERAND (cref, 0);
319 }
320 if (!next)
321 /* Don't instrument this flexible array member-like array in non-strict
322 -fsanitize=bounds mode. */
323 return NULL_TREE;
324 }
325
570a11fe
JJ
326 /* Don't emit instrumentation in the most common cases. */
327 tree idx = NULL_TREE;
328 if (TREE_CODE (*index) == INTEGER_CST)
329 idx = *index;
330 else if (TREE_CODE (*index) == BIT_AND_EXPR
331 && TREE_CODE (TREE_OPERAND (*index, 1)) == INTEGER_CST)
332 idx = TREE_OPERAND (*index, 1);
333 if (idx
334 && TREE_CODE (bound) == INTEGER_CST
335 && tree_int_cst_sgn (idx) >= 0
336 && tree_int_cst_le (idx, bound))
337 return NULL_TREE;
338
0e37a2f3
MP
339 *index = save_expr (*index);
340 /* Create a "(T *) 0" tree node to describe the array type. */
341 tree zero_with_type = build_int_cst (build_pointer_type (type), 0);
342 return build_call_expr_internal_loc (loc, IFN_UBSAN_BOUNDS,
343 void_type_node, 3, zero_with_type,
344 *index, bound);
345}
346
347/* Return true iff T is an array that was instrumented by SANITIZE_BOUNDS. */
348
349bool
350ubsan_array_ref_instrumented_p (const_tree t)
351{
352 if (TREE_CODE (t) != ARRAY_REF)
353 return false;
354
355 tree op1 = TREE_OPERAND (t, 1);
356 return TREE_CODE (op1) == COMPOUND_EXPR
357 && TREE_CODE (TREE_OPERAND (op1, 0)) == CALL_EXPR
358 && CALL_EXPR_FN (TREE_OPERAND (op1, 0)) == NULL_TREE
359 && CALL_EXPR_IFN (TREE_OPERAND (op1, 0)) == IFN_UBSAN_BOUNDS;
360}
361
362/* Instrument an ARRAY_REF, if it hasn't already been instrumented.
363 IGNORE_OFF_BY_ONE is true if the ARRAY_REF is inside a ADDR_EXPR. */
364
365void
366ubsan_maybe_instrument_array_ref (tree *expr_p, bool ignore_off_by_one)
367{
368 if (!ubsan_array_ref_instrumented_p (*expr_p)
f5481fc4 369 && do_ubsan_in_current_function ())
0e37a2f3
MP
370 {
371 tree op0 = TREE_OPERAND (*expr_p, 0);
372 tree op1 = TREE_OPERAND (*expr_p, 1);
373 tree e = ubsan_instrument_bounds (EXPR_LOCATION (*expr_p), op0, &op1,
374 ignore_off_by_one);
375 if (e != NULL_TREE)
376 {
377 tree t = copy_node (*expr_p);
378 TREE_OPERAND (t, 1) = build2 (COMPOUND_EXPR, TREE_TYPE (op1),
379 e, op1);
380 *expr_p = t;
381 }
382 }
383}
944fa280
JJ
384
385static tree
c39a5e99 386ubsan_maybe_instrument_reference_or_call (location_t loc, tree op, tree ptype,
944fa280
JJ
387 enum ubsan_null_ckind ckind)
388{
f5481fc4 389 if (!do_ubsan_in_current_function ())
944fa280
JJ
390 return NULL_TREE;
391
c39a5e99
JJ
392 tree type = TREE_TYPE (ptype);
393 tree orig_op = op;
394 bool instrument = false;
395 unsigned int mina = 0;
396
944fa280
JJ
397 if (flag_sanitize & SANITIZE_ALIGNMENT)
398 {
399 mina = min_align_of_type (type);
400 if (mina <= 1)
401 mina = 0;
402 }
403 while ((TREE_CODE (op) == NOP_EXPR
404 || TREE_CODE (op) == NON_LVALUE_EXPR)
405 && TREE_CODE (TREE_TYPE (op)) == POINTER_TYPE)
406 op = TREE_OPERAND (op, 0);
407 if (TREE_CODE (op) == NOP_EXPR
408 && TREE_CODE (TREE_TYPE (op)) == REFERENCE_TYPE)
409 {
410 if (mina && mina > min_align_of_type (TREE_TYPE (TREE_TYPE (op))))
411 instrument = true;
412 }
413 else
414 {
415 if ((flag_sanitize & SANITIZE_NULL) && TREE_CODE (op) == ADDR_EXPR)
416 {
417 bool strict_overflow_p = false;
418 /* tree_single_nonzero_warnv_p will not return true for non-weak
419 non-automatic decls with -fno-delete-null-pointer-checks,
420 which is disabled during -fsanitize=null. We don't want to
421 instrument those, just weak vars though. */
422 int save_flag_delete_null_pointer_checks
423 = flag_delete_null_pointer_checks;
424 flag_delete_null_pointer_checks = 1;
425 if (!tree_single_nonzero_warnv_p (op, &strict_overflow_p)
426 || strict_overflow_p)
427 instrument = true;
428 flag_delete_null_pointer_checks
429 = save_flag_delete_null_pointer_checks;
430 }
431 else if (flag_sanitize & SANITIZE_NULL)
432 instrument = true;
c39a5e99
JJ
433 if (mina && mina > 1)
434 {
435 if (!POINTER_TYPE_P (TREE_TYPE (op))
436 || mina > get_pointer_alignment (op) / BITS_PER_UNIT)
437 instrument = true;
438 }
944fa280
JJ
439 }
440 if (!instrument)
441 return NULL_TREE;
442 op = save_expr (orig_op);
c39a5e99
JJ
443 gcc_assert (POINTER_TYPE_P (ptype));
444 if (TREE_CODE (ptype) == REFERENCE_TYPE)
445 ptype = build_pointer_type (TREE_TYPE (ptype));
446 tree kind = build_int_cst (ptype, ckind);
944fa280
JJ
447 tree align = build_int_cst (pointer_sized_int_node, mina);
448 tree call
449 = build_call_expr_internal_loc (loc, IFN_UBSAN_NULL, void_type_node,
450 3, op, kind, align);
451 TREE_SIDE_EFFECTS (call) = 1;
452 return fold_build2 (COMPOUND_EXPR, TREE_TYPE (op), call, op);
453}
454
455/* Instrument a NOP_EXPR to REFERENCE_TYPE if needed. */
456
457void
458ubsan_maybe_instrument_reference (tree stmt)
459{
460 tree op = TREE_OPERAND (stmt, 0);
461 op = ubsan_maybe_instrument_reference_or_call (EXPR_LOCATION (stmt), op,
c39a5e99 462 TREE_TYPE (stmt),
944fa280
JJ
463 UBSAN_REF_BINDING);
464 if (op)
465 TREE_OPERAND (stmt, 0) = op;
466}
467
468/* Instrument a CALL_EXPR to a method if needed. */
469
470void
471ubsan_maybe_instrument_member_call (tree stmt, bool is_ctor)
472{
473 if (call_expr_nargs (stmt) == 0)
474 return;
475 tree op = CALL_EXPR_ARG (stmt, 0);
476 if (op == error_mark_node
477 || !POINTER_TYPE_P (TREE_TYPE (op)))
478 return;
479 op = ubsan_maybe_instrument_reference_or_call (EXPR_LOCATION (stmt), op,
c39a5e99 480 TREE_TYPE (op),
944fa280
JJ
481 is_ctor ? UBSAN_CTOR_CALL
482 : UBSAN_MEMBER_CALL);
483 if (op)
484 CALL_EXPR_ARG (stmt, 0) = op;
485}