* c-ubsan.c (ubsan_instrument_bounds): Don't skip instrumenting
[official-gcc.git] / gcc / c-family / c-ubsan.c
blobdbbdc5bf1c46b869d51dc8ba0e33ac859e4c8381
1 /* UndefinedBehaviorSanitizer, undefined behavior detector.
2 Copyright (C) 2013-2015 Free Software Foundation, Inc.
3 Contributed by Marek Polacek <polacek@redhat.com>
5 This file is part of GCC.
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.
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.
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/>. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "hash-set.h"
25 #include "machmode.h"
26 #include "vec.h"
27 #include "double-int.h"
28 #include "input.h"
29 #include "alias.h"
30 #include "symtab.h"
31 #include "options.h"
32 #include "wide-int.h"
33 #include "inchash.h"
34 #include "tree.h"
35 #include "alloc-pool.h"
36 #include "hash-map.h"
37 #include "is-a.h"
38 #include "plugin-api.h"
39 #include "vec.h"
40 #include "hashtab.h"
41 #include "hash-set.h"
42 #include "machmode.h"
43 #include "tm.h"
44 #include "hard-reg-set.h"
45 #include "input.h"
46 #include "function.h"
47 #include "ipa-ref.h"
48 #include "cgraph.h"
49 #include "output.h"
50 #include "toplev.h"
51 #include "ubsan.h"
52 #include "c-family/c-common.h"
53 #include "c-family/c-ubsan.h"
54 #include "asan.h"
55 #include "internal-fn.h"
56 #include "stor-layout.h"
57 #include "builtins.h"
59 /* Instrument division by zero and INT_MIN / -1. If not instrumenting,
60 return NULL_TREE. */
62 tree
63 ubsan_instrument_division (location_t loc, tree op0, tree op1)
65 tree t, tt;
66 tree type = TREE_TYPE (op0);
68 /* At this point both operands should have the same type,
69 because they are already converted to RESULT_TYPE.
70 Use TYPE_MAIN_VARIANT since typedefs can confuse us. */
71 gcc_assert (TYPE_MAIN_VARIANT (TREE_TYPE (op0))
72 == TYPE_MAIN_VARIANT (TREE_TYPE (op1)));
74 if (TREE_CODE (type) == INTEGER_TYPE
75 && (flag_sanitize & SANITIZE_DIVIDE))
76 t = fold_build2 (EQ_EXPR, boolean_type_node,
77 op1, build_int_cst (type, 0));
78 else if (TREE_CODE (type) == REAL_TYPE
79 && (flag_sanitize & SANITIZE_FLOAT_DIVIDE))
80 t = fold_build2 (EQ_EXPR, boolean_type_node,
81 op1, build_real (type, dconst0));
82 else
83 return NULL_TREE;
85 /* We check INT_MIN / -1 only for signed types. */
86 if (TREE_CODE (type) == INTEGER_TYPE
87 && (flag_sanitize & SANITIZE_DIVIDE)
88 && !TYPE_UNSIGNED (type))
90 tree x;
91 tt = fold_build2 (EQ_EXPR, boolean_type_node, op1,
92 build_int_cst (type, -1));
93 x = fold_build2 (EQ_EXPR, boolean_type_node, op0,
94 TYPE_MIN_VALUE (type));
95 x = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, x, tt);
96 t = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t, x);
99 /* If the condition was folded to 0, no need to instrument
100 this expression. */
101 if (integer_zerop (t))
102 return NULL_TREE;
104 /* In case we have a SAVE_EXPR in a conditional context, we need to
105 make sure it gets evaluated before the condition. If the OP0 is
106 an instrumented array reference, mark it as having side effects so
107 it's not folded away. */
108 if (flag_sanitize & SANITIZE_BOUNDS)
110 tree xop0 = op0;
111 while (CONVERT_EXPR_P (xop0))
112 xop0 = TREE_OPERAND (xop0, 0);
113 if (TREE_CODE (xop0) == ARRAY_REF)
115 TREE_SIDE_EFFECTS (xop0) = 1;
116 TREE_SIDE_EFFECTS (op0) = 1;
119 t = fold_build2 (COMPOUND_EXPR, TREE_TYPE (t), op0, t);
120 if (flag_sanitize_undefined_trap_on_error)
121 tt = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
122 else
124 tree data = ubsan_create_data ("__ubsan_overflow_data", 1, &loc,
125 ubsan_type_descriptor (type), NULL_TREE,
126 NULL_TREE);
127 data = build_fold_addr_expr_loc (loc, data);
128 enum built_in_function bcode
129 = (flag_sanitize_recover & SANITIZE_DIVIDE)
130 ? BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW
131 : BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW_ABORT;
132 tt = builtin_decl_explicit (bcode);
133 tt = build_call_expr_loc (loc, tt, 3, data, ubsan_encode_value (op0),
134 ubsan_encode_value (op1));
136 t = fold_build3 (COND_EXPR, void_type_node, t, tt, void_node);
138 return t;
141 /* Instrument left and right shifts. */
143 tree
144 ubsan_instrument_shift (location_t loc, enum tree_code code,
145 tree op0, tree op1)
147 tree t, tt = NULL_TREE;
148 tree type0 = TREE_TYPE (op0);
149 tree type1 = TREE_TYPE (op1);
150 tree op1_utype = unsigned_type_for (type1);
151 HOST_WIDE_INT op0_prec = TYPE_PRECISION (type0);
152 tree uprecm1 = build_int_cst (op1_utype, op0_prec - 1);
154 t = fold_convert_loc (loc, op1_utype, op1);
155 t = fold_build2 (GT_EXPR, boolean_type_node, t, uprecm1);
157 /* For signed x << y, in C99/C11, the following:
158 (unsigned) x >> (uprecm1 - y)
159 if non-zero, is undefined. */
160 if (code == LSHIFT_EXPR
161 && !TYPE_UNSIGNED (type0)
162 && flag_isoc99)
164 tree x = fold_build2 (MINUS_EXPR, op1_utype, uprecm1,
165 fold_convert (op1_utype, op1));
166 tt = fold_convert_loc (loc, unsigned_type_for (type0), op0);
167 tt = fold_build2 (RSHIFT_EXPR, TREE_TYPE (tt), tt, x);
168 tt = fold_build2 (NE_EXPR, boolean_type_node, tt,
169 build_int_cst (TREE_TYPE (tt), 0));
172 /* For signed x << y, in C++11 and later, the following:
173 x < 0 || ((unsigned) x >> (uprecm1 - y))
174 if > 1, is undefined. */
175 if (code == LSHIFT_EXPR
176 && !TYPE_UNSIGNED (TREE_TYPE (op0))
177 && (cxx_dialect >= cxx11))
179 tree x = fold_build2 (MINUS_EXPR, op1_utype, uprecm1,
180 fold_convert (op1_utype, op1));
181 tt = fold_convert_loc (loc, unsigned_type_for (type0), op0);
182 tt = fold_build2 (RSHIFT_EXPR, TREE_TYPE (tt), tt, x);
183 tt = fold_build2 (GT_EXPR, boolean_type_node, tt,
184 build_int_cst (TREE_TYPE (tt), 1));
185 x = fold_build2 (LT_EXPR, boolean_type_node, op0,
186 build_int_cst (type0, 0));
187 tt = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, x, tt);
190 /* If the condition was folded to 0, no need to instrument
191 this expression. */
192 if (integer_zerop (t) && (tt == NULL_TREE || integer_zerop (tt)))
193 return NULL_TREE;
195 /* In case we have a SAVE_EXPR in a conditional context, we need to
196 make sure it gets evaluated before the condition. If the OP0 is
197 an instrumented array reference, mark it as having side effects so
198 it's not folded away. */
199 if (flag_sanitize & SANITIZE_BOUNDS)
201 tree xop0 = op0;
202 while (CONVERT_EXPR_P (xop0))
203 xop0 = TREE_OPERAND (xop0, 0);
204 if (TREE_CODE (xop0) == ARRAY_REF)
206 TREE_SIDE_EFFECTS (xop0) = 1;
207 TREE_SIDE_EFFECTS (op0) = 1;
210 t = fold_build2 (COMPOUND_EXPR, TREE_TYPE (t), op0, t);
211 t = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t,
212 tt ? tt : integer_zero_node);
214 if (flag_sanitize_undefined_trap_on_error)
215 tt = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
216 else
218 tree data = ubsan_create_data ("__ubsan_shift_data", 1, &loc,
219 ubsan_type_descriptor (type0),
220 ubsan_type_descriptor (type1), NULL_TREE,
221 NULL_TREE);
222 data = build_fold_addr_expr_loc (loc, data);
224 enum built_in_function bcode
225 = (flag_sanitize_recover & SANITIZE_SHIFT)
226 ? BUILT_IN_UBSAN_HANDLE_SHIFT_OUT_OF_BOUNDS
227 : BUILT_IN_UBSAN_HANDLE_SHIFT_OUT_OF_BOUNDS_ABORT;
228 tt = builtin_decl_explicit (bcode);
229 tt = build_call_expr_loc (loc, tt, 3, data, ubsan_encode_value (op0),
230 ubsan_encode_value (op1));
232 t = fold_build3 (COND_EXPR, void_type_node, t, tt, void_node);
234 return t;
237 /* Instrument variable length array bound. */
239 tree
240 ubsan_instrument_vla (location_t loc, tree size)
242 tree type = TREE_TYPE (size);
243 tree t, tt;
245 t = fold_build2 (LE_EXPR, boolean_type_node, size, build_int_cst (type, 0));
246 if (flag_sanitize_undefined_trap_on_error)
247 tt = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
248 else
250 tree data = ubsan_create_data ("__ubsan_vla_data", 1, &loc,
251 ubsan_type_descriptor (type), NULL_TREE,
252 NULL_TREE);
253 data = build_fold_addr_expr_loc (loc, data);
254 enum built_in_function bcode
255 = (flag_sanitize_recover & SANITIZE_VLA)
256 ? BUILT_IN_UBSAN_HANDLE_VLA_BOUND_NOT_POSITIVE
257 : BUILT_IN_UBSAN_HANDLE_VLA_BOUND_NOT_POSITIVE_ABORT;
258 tt = builtin_decl_explicit (bcode);
259 tt = build_call_expr_loc (loc, tt, 2, data, ubsan_encode_value (size));
261 t = fold_build3 (COND_EXPR, void_type_node, t, tt, void_node);
263 return t;
266 /* Instrument missing return in C++ functions returning non-void. */
268 tree
269 ubsan_instrument_return (location_t loc)
271 if (flag_sanitize_undefined_trap_on_error)
272 return build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
273 /* It is possible that PCH zapped table with definitions of sanitizer
274 builtins. Reinitialize them if needed. */
275 initialize_sanitizer_builtins ();
277 tree data = ubsan_create_data ("__ubsan_missing_return_data", 1, &loc,
278 NULL_TREE, NULL_TREE);
279 tree t = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_MISSING_RETURN);
280 return build_call_expr_loc (loc, t, 1, build_fold_addr_expr_loc (loc, data));
283 /* Instrument array bounds for ARRAY_REFs. We create special builtin,
284 that gets expanded in the sanopt pass, and make an array dimension
285 of it. ARRAY is the array, *INDEX is an index to the array.
286 Return NULL_TREE if no instrumentation is emitted.
287 IGNORE_OFF_BY_ONE is true if the ARRAY_REF is inside a ADDR_EXPR. */
289 tree
290 ubsan_instrument_bounds (location_t loc, tree array, tree *index,
291 bool ignore_off_by_one)
293 tree type = TREE_TYPE (array);
294 tree domain = TYPE_DOMAIN (type);
296 if (domain == NULL_TREE || TYPE_MAX_VALUE (domain) == NULL_TREE)
297 return NULL_TREE;
299 tree bound = TYPE_MAX_VALUE (domain);
300 if (ignore_off_by_one)
301 bound = fold_build2 (PLUS_EXPR, TREE_TYPE (bound), bound,
302 build_int_cst (TREE_TYPE (bound), 1));
304 /* Detect flexible array members and suchlike, unless
305 -fsanitize=bounds-strict. */
306 tree base = get_base_address (array);
307 if ((flag_sanitize & SANITIZE_BOUNDS_STRICT) == 0
308 && TREE_CODE (array) == COMPONENT_REF
309 && base && (TREE_CODE (base) == INDIRECT_REF
310 || TREE_CODE (base) == MEM_REF))
312 tree next = NULL_TREE;
313 tree cref = array;
315 /* Walk all structs/unions. */
316 while (TREE_CODE (cref) == COMPONENT_REF)
318 if (TREE_CODE (TREE_TYPE (TREE_OPERAND (cref, 0))) == RECORD_TYPE)
319 for (next = DECL_CHAIN (TREE_OPERAND (cref, 1));
320 next && TREE_CODE (next) != FIELD_DECL;
321 next = DECL_CHAIN (next))
323 if (next)
324 /* Not a last element. Instrument it. */
325 break;
326 /* Ok, this is the last field of the structure/union. But the
327 aggregate containing the field must be the last field too,
328 recursively. */
329 cref = TREE_OPERAND (cref, 0);
331 if (!next)
332 /* Don't instrument this flexible array member-like array in non-strict
333 -fsanitize=bounds mode. */
334 return NULL_TREE;
337 /* Don't emit instrumentation in the most common cases. */
338 tree idx = NULL_TREE;
339 if (TREE_CODE (*index) == INTEGER_CST)
340 idx = *index;
341 else if (TREE_CODE (*index) == BIT_AND_EXPR
342 && TREE_CODE (TREE_OPERAND (*index, 1)) == INTEGER_CST)
343 idx = TREE_OPERAND (*index, 1);
344 if (idx
345 && TREE_CODE (bound) == INTEGER_CST
346 && tree_int_cst_sgn (idx) >= 0
347 && tree_int_cst_le (idx, bound))
348 return NULL_TREE;
350 *index = save_expr (*index);
351 /* Create a "(T *) 0" tree node to describe the array type. */
352 tree zero_with_type = build_int_cst (build_pointer_type (type), 0);
353 return build_call_expr_internal_loc (loc, IFN_UBSAN_BOUNDS,
354 void_type_node, 3, zero_with_type,
355 *index, bound);
358 /* Return true iff T is an array that was instrumented by SANITIZE_BOUNDS. */
360 bool
361 ubsan_array_ref_instrumented_p (const_tree t)
363 if (TREE_CODE (t) != ARRAY_REF)
364 return false;
366 tree op1 = TREE_OPERAND (t, 1);
367 return TREE_CODE (op1) == COMPOUND_EXPR
368 && TREE_CODE (TREE_OPERAND (op1, 0)) == CALL_EXPR
369 && CALL_EXPR_FN (TREE_OPERAND (op1, 0)) == NULL_TREE
370 && CALL_EXPR_IFN (TREE_OPERAND (op1, 0)) == IFN_UBSAN_BOUNDS;
373 /* Instrument an ARRAY_REF, if it hasn't already been instrumented.
374 IGNORE_OFF_BY_ONE is true if the ARRAY_REF is inside a ADDR_EXPR. */
376 void
377 ubsan_maybe_instrument_array_ref (tree *expr_p, bool ignore_off_by_one)
379 if (!ubsan_array_ref_instrumented_p (*expr_p)
380 && do_ubsan_in_current_function ())
382 tree op0 = TREE_OPERAND (*expr_p, 0);
383 tree op1 = TREE_OPERAND (*expr_p, 1);
384 tree e = ubsan_instrument_bounds (EXPR_LOCATION (*expr_p), op0, &op1,
385 ignore_off_by_one);
386 if (e != NULL_TREE)
388 tree t = copy_node (*expr_p);
389 TREE_OPERAND (t, 1) = build2 (COMPOUND_EXPR, TREE_TYPE (op1),
390 e, op1);
391 *expr_p = t;
396 static tree
397 ubsan_maybe_instrument_reference_or_call (location_t loc, tree op, tree ptype,
398 enum ubsan_null_ckind ckind)
400 if (!do_ubsan_in_current_function ())
401 return NULL_TREE;
403 tree type = TREE_TYPE (ptype);
404 tree orig_op = op;
405 bool instrument = false;
406 unsigned int mina = 0;
408 if (flag_sanitize & SANITIZE_ALIGNMENT)
410 mina = min_align_of_type (type);
411 if (mina <= 1)
412 mina = 0;
414 while ((TREE_CODE (op) == NOP_EXPR
415 || TREE_CODE (op) == NON_LVALUE_EXPR)
416 && TREE_CODE (TREE_TYPE (op)) == POINTER_TYPE)
417 op = TREE_OPERAND (op, 0);
418 if (TREE_CODE (op) == NOP_EXPR
419 && TREE_CODE (TREE_TYPE (op)) == REFERENCE_TYPE)
421 if (mina && mina > min_align_of_type (TREE_TYPE (TREE_TYPE (op))))
422 instrument = true;
424 else
426 if ((flag_sanitize & SANITIZE_NULL) && TREE_CODE (op) == ADDR_EXPR)
428 bool strict_overflow_p = false;
429 /* tree_single_nonzero_warnv_p will not return true for non-weak
430 non-automatic decls with -fno-delete-null-pointer-checks,
431 which is disabled during -fsanitize=null. We don't want to
432 instrument those, just weak vars though. */
433 int save_flag_delete_null_pointer_checks
434 = flag_delete_null_pointer_checks;
435 flag_delete_null_pointer_checks = 1;
436 if (!tree_single_nonzero_warnv_p (op, &strict_overflow_p)
437 || strict_overflow_p)
438 instrument = true;
439 flag_delete_null_pointer_checks
440 = save_flag_delete_null_pointer_checks;
442 else if (flag_sanitize & SANITIZE_NULL)
443 instrument = true;
444 if (mina && mina > 1)
446 if (!POINTER_TYPE_P (TREE_TYPE (op))
447 || mina > get_pointer_alignment (op) / BITS_PER_UNIT)
448 instrument = true;
451 if (!instrument)
452 return NULL_TREE;
453 op = save_expr (orig_op);
454 gcc_assert (POINTER_TYPE_P (ptype));
455 if (TREE_CODE (ptype) == REFERENCE_TYPE)
456 ptype = build_pointer_type (TREE_TYPE (ptype));
457 tree kind = build_int_cst (ptype, ckind);
458 tree align = build_int_cst (pointer_sized_int_node, mina);
459 tree call
460 = build_call_expr_internal_loc (loc, IFN_UBSAN_NULL, void_type_node,
461 3, op, kind, align);
462 TREE_SIDE_EFFECTS (call) = 1;
463 return fold_build2 (COMPOUND_EXPR, TREE_TYPE (op), call, op);
466 /* Instrument a NOP_EXPR to REFERENCE_TYPE if needed. */
468 void
469 ubsan_maybe_instrument_reference (tree stmt)
471 tree op = TREE_OPERAND (stmt, 0);
472 op = ubsan_maybe_instrument_reference_or_call (EXPR_LOCATION (stmt), op,
473 TREE_TYPE (stmt),
474 UBSAN_REF_BINDING);
475 if (op)
476 TREE_OPERAND (stmt, 0) = op;
479 /* Instrument a CALL_EXPR to a method if needed. */
481 void
482 ubsan_maybe_instrument_member_call (tree stmt, bool is_ctor)
484 if (call_expr_nargs (stmt) == 0)
485 return;
486 tree op = CALL_EXPR_ARG (stmt, 0);
487 if (op == error_mark_node
488 || !POINTER_TYPE_P (TREE_TYPE (op)))
489 return;
490 op = ubsan_maybe_instrument_reference_or_call (EXPR_LOCATION (stmt), op,
491 TREE_TYPE (op),
492 is_ctor ? UBSAN_CTOR_CALL
493 : UBSAN_MEMBER_CALL);
494 if (op)
495 CALL_EXPR_ARG (stmt, 0) = op;