2014-07-29 Ed Smith-Rowland <3dw4rd@verizon.net>
[official-gcc.git] / gcc / c-family / c-ubsan.c
blobad5dd0bf92af5aa43fdad278316d91662b15c195
1 /* UndefinedBehaviorSanitizer, undefined behavior detector.
2 Copyright (C) 2013-2014 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 "tree.h"
25 #include "alloc-pool.h"
26 #include "cgraph.h"
27 #include "output.h"
28 #include "toplev.h"
29 #include "ubsan.h"
30 #include "c-family/c-common.h"
31 #include "c-family/c-ubsan.h"
32 #include "asan.h"
33 #include "internal-fn.h"
35 /* Instrument division by zero and INT_MIN / -1. If not instrumenting,
36 return NULL_TREE. */
38 tree
39 ubsan_instrument_division (location_t loc, tree op0, tree op1)
41 tree t, tt;
42 tree type = TREE_TYPE (op0);
44 /* At this point both operands should have the same type,
45 because they are already converted to RESULT_TYPE.
46 Use TYPE_MAIN_VARIANT since typedefs can confuse us. */
47 gcc_assert (TYPE_MAIN_VARIANT (TREE_TYPE (op0))
48 == TYPE_MAIN_VARIANT (TREE_TYPE (op1)));
50 if (TREE_CODE (type) == INTEGER_TYPE
51 && (flag_sanitize & SANITIZE_DIVIDE))
52 t = fold_build2 (EQ_EXPR, boolean_type_node,
53 op1, build_int_cst (type, 0));
54 else if (TREE_CODE (type) == REAL_TYPE
55 && (flag_sanitize & SANITIZE_FLOAT_DIVIDE))
56 t = fold_build2 (EQ_EXPR, boolean_type_node,
57 op1, build_real (type, dconst0));
58 else
59 return NULL_TREE;
61 /* We check INT_MIN / -1 only for signed types. */
62 if (TREE_CODE (type) == INTEGER_TYPE
63 && (flag_sanitize & SANITIZE_DIVIDE)
64 && !TYPE_UNSIGNED (type))
66 tree x;
67 tt = fold_build2 (EQ_EXPR, boolean_type_node, op1,
68 build_int_cst (type, -1));
69 x = fold_build2 (EQ_EXPR, boolean_type_node, op0,
70 TYPE_MIN_VALUE (type));
71 x = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, x, tt);
72 t = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t, x);
75 /* If the condition was folded to 0, no need to instrument
76 this expression. */
77 if (integer_zerop (t))
78 return NULL_TREE;
80 /* In case we have a SAVE_EXPR in a conditional context, we need to
81 make sure it gets evaluated before the condition. If the OP0 is
82 an instrumented array reference, mark it as having side effects so
83 it's not folded away. */
84 if (flag_sanitize & SANITIZE_BOUNDS)
86 tree xop0 = op0;
87 while (CONVERT_EXPR_P (xop0))
88 xop0 = TREE_OPERAND (xop0, 0);
89 if (TREE_CODE (xop0) == ARRAY_REF)
91 TREE_SIDE_EFFECTS (xop0) = 1;
92 TREE_SIDE_EFFECTS (op0) = 1;
95 t = fold_build2 (COMPOUND_EXPR, TREE_TYPE (t), op0, t);
96 if (flag_sanitize_undefined_trap_on_error)
97 tt = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
98 else
100 tree data = ubsan_create_data ("__ubsan_overflow_data", &loc, NULL,
101 ubsan_type_descriptor (type), NULL_TREE);
102 data = build_fold_addr_expr_loc (loc, data);
103 enum built_in_function bcode
104 = flag_sanitize_recover
105 ? BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW
106 : BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW_ABORT;
107 tt = builtin_decl_explicit (bcode);
108 tt = build_call_expr_loc (loc, tt, 3, data, ubsan_encode_value (op0),
109 ubsan_encode_value (op1));
111 t = fold_build3 (COND_EXPR, void_type_node, t, tt, void_node);
113 return t;
116 /* Instrument left and right shifts. */
118 tree
119 ubsan_instrument_shift (location_t loc, enum tree_code code,
120 tree op0, tree op1)
122 tree t, tt = NULL_TREE;
123 tree type0 = TREE_TYPE (op0);
124 tree type1 = TREE_TYPE (op1);
125 tree op1_utype = unsigned_type_for (type1);
126 HOST_WIDE_INT op0_prec = TYPE_PRECISION (type0);
127 tree uprecm1 = build_int_cst (op1_utype, op0_prec - 1);
128 tree precm1 = build_int_cst (type1, op0_prec - 1);
130 t = fold_convert_loc (loc, op1_utype, op1);
131 t = fold_build2 (GT_EXPR, boolean_type_node, t, uprecm1);
133 /* For signed x << y, in C99/C11, the following:
134 (unsigned) x >> (precm1 - y)
135 if non-zero, is undefined. */
136 if (code == LSHIFT_EXPR
137 && !TYPE_UNSIGNED (type0)
138 && flag_isoc99)
140 tree x = fold_build2 (MINUS_EXPR, integer_type_node, precm1, op1);
141 tt = fold_convert_loc (loc, unsigned_type_for (type0), op0);
142 tt = fold_build2 (RSHIFT_EXPR, TREE_TYPE (tt), tt, x);
143 tt = fold_build2 (NE_EXPR, boolean_type_node, tt,
144 build_int_cst (TREE_TYPE (tt), 0));
147 /* For signed x << y, in C++11/C++14, the following:
148 x < 0 || ((unsigned) x >> (precm1 - y))
149 if > 1, is undefined. */
150 if (code == LSHIFT_EXPR
151 && !TYPE_UNSIGNED (TREE_TYPE (op0))
152 && (cxx_dialect == cxx11 || cxx_dialect == cxx1y))
154 tree x = fold_build2 (MINUS_EXPR, integer_type_node, precm1, op1);
155 tt = fold_convert_loc (loc, unsigned_type_for (type0), op0);
156 tt = fold_build2 (RSHIFT_EXPR, TREE_TYPE (tt), tt, x);
157 tt = fold_build2 (GT_EXPR, boolean_type_node, tt,
158 build_int_cst (TREE_TYPE (tt), 1));
159 x = fold_build2 (LT_EXPR, boolean_type_node, op0,
160 build_int_cst (type0, 0));
161 tt = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, x, tt);
164 /* If the condition was folded to 0, no need to instrument
165 this expression. */
166 if (integer_zerop (t) && (tt == NULL_TREE || integer_zerop (tt)))
167 return NULL_TREE;
169 /* In case we have a SAVE_EXPR in a conditional context, we need to
170 make sure it gets evaluated before the condition. If the OP0 is
171 an instrumented array reference, mark it as having side effects so
172 it's not folded away. */
173 if (flag_sanitize & SANITIZE_BOUNDS)
175 tree xop0 = op0;
176 while (CONVERT_EXPR_P (xop0))
177 xop0 = TREE_OPERAND (xop0, 0);
178 if (TREE_CODE (xop0) == ARRAY_REF)
180 TREE_SIDE_EFFECTS (xop0) = 1;
181 TREE_SIDE_EFFECTS (op0) = 1;
184 t = fold_build2 (COMPOUND_EXPR, TREE_TYPE (t), op0, t);
185 t = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t,
186 tt ? tt : integer_zero_node);
188 if (flag_sanitize_undefined_trap_on_error)
189 tt = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
190 else
192 tree data = ubsan_create_data ("__ubsan_shift_data", &loc, NULL,
193 ubsan_type_descriptor (type0),
194 ubsan_type_descriptor (type1), NULL_TREE);
195 data = build_fold_addr_expr_loc (loc, data);
197 enum built_in_function bcode
198 = flag_sanitize_recover
199 ? BUILT_IN_UBSAN_HANDLE_SHIFT_OUT_OF_BOUNDS
200 : BUILT_IN_UBSAN_HANDLE_SHIFT_OUT_OF_BOUNDS_ABORT;
201 tt = builtin_decl_explicit (bcode);
202 tt = build_call_expr_loc (loc, tt, 3, data, ubsan_encode_value (op0),
203 ubsan_encode_value (op1));
205 t = fold_build3 (COND_EXPR, void_type_node, t, tt, void_node);
207 return t;
210 /* Instrument variable length array bound. */
212 tree
213 ubsan_instrument_vla (location_t loc, tree size)
215 tree type = TREE_TYPE (size);
216 tree t, tt;
218 t = fold_build2 (LE_EXPR, boolean_type_node, size, build_int_cst (type, 0));
219 if (flag_sanitize_undefined_trap_on_error)
220 tt = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
221 else
223 tree data = ubsan_create_data ("__ubsan_vla_data", &loc, NULL,
224 ubsan_type_descriptor (type), NULL_TREE);
225 data = build_fold_addr_expr_loc (loc, data);
226 enum built_in_function bcode
227 = flag_sanitize_recover
228 ? BUILT_IN_UBSAN_HANDLE_VLA_BOUND_NOT_POSITIVE
229 : BUILT_IN_UBSAN_HANDLE_VLA_BOUND_NOT_POSITIVE_ABORT;
230 tt = builtin_decl_explicit (bcode);
231 tt = build_call_expr_loc (loc, tt, 2, data, ubsan_encode_value (size));
233 t = fold_build3 (COND_EXPR, void_type_node, t, tt, void_node);
235 return t;
238 /* Instrument missing return in C++ functions returning non-void. */
240 tree
241 ubsan_instrument_return (location_t loc)
243 if (flag_sanitize_undefined_trap_on_error)
244 return build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
245 /* It is possible that PCH zapped table with definitions of sanitizer
246 builtins. Reinitialize them if needed. */
247 initialize_sanitizer_builtins ();
249 tree data = ubsan_create_data ("__ubsan_missing_return_data", &loc,
250 NULL, NULL_TREE);
251 tree t = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_MISSING_RETURN);
252 return build_call_expr_loc (loc, t, 1, build_fold_addr_expr_loc (loc, data));
255 /* Instrument array bounds for ARRAY_REFs. We create special builtin,
256 that gets expanded in the sanopt pass, and make an array dimension
257 of it. ARRAY is the array, *INDEX is an index to the array.
258 Return NULL_TREE if no instrumentation is emitted.
259 IGNORE_OFF_BY_ONE is true if the ARRAY_REF is inside a ADDR_EXPR. */
261 tree
262 ubsan_instrument_bounds (location_t loc, tree array, tree *index,
263 bool ignore_off_by_one)
265 tree type = TREE_TYPE (array);
266 tree domain = TYPE_DOMAIN (type);
268 if (domain == NULL_TREE || TYPE_MAX_VALUE (domain) == NULL_TREE)
269 return NULL_TREE;
271 tree bound = TYPE_MAX_VALUE (domain);
272 if (ignore_off_by_one)
273 bound = fold_build2 (PLUS_EXPR, TREE_TYPE (bound), bound,
274 build_int_cst (TREE_TYPE (bound), 1));
276 /* Detect flexible array members and suchlike. */
277 tree base = get_base_address (array);
278 if (base && (TREE_CODE (base) == INDIRECT_REF
279 || TREE_CODE (base) == MEM_REF))
281 tree next = NULL_TREE;
282 tree cref = array;
284 /* Walk all structs/unions. */
285 while (TREE_CODE (cref) == COMPONENT_REF)
287 if (TREE_CODE (TREE_TYPE (TREE_OPERAND (cref, 0))) == RECORD_TYPE)
288 for (next = DECL_CHAIN (TREE_OPERAND (cref, 1));
289 next && TREE_CODE (next) != FIELD_DECL;
290 next = DECL_CHAIN (next))
292 if (next)
293 /* Not a last element. Instrument it. */
294 break;
295 /* Ok, this is the last field of the structure/union. But the
296 aggregate containing the field must be the last field too,
297 recursively. */
298 cref = TREE_OPERAND (cref, 0);
300 if (!next)
301 /* Don't instrument this flexible array member-like array in non-strict
302 -fsanitize=bounds mode. */
303 return NULL_TREE;
306 *index = save_expr (*index);
307 /* Create a "(T *) 0" tree node to describe the array type. */
308 tree zero_with_type = build_int_cst (build_pointer_type (type), 0);
309 return build_call_expr_internal_loc (loc, IFN_UBSAN_BOUNDS,
310 void_type_node, 3, zero_with_type,
311 *index, bound);
314 /* Return true iff T is an array that was instrumented by SANITIZE_BOUNDS. */
316 bool
317 ubsan_array_ref_instrumented_p (const_tree t)
319 if (TREE_CODE (t) != ARRAY_REF)
320 return false;
322 tree op1 = TREE_OPERAND (t, 1);
323 return TREE_CODE (op1) == COMPOUND_EXPR
324 && TREE_CODE (TREE_OPERAND (op1, 0)) == CALL_EXPR
325 && CALL_EXPR_FN (TREE_OPERAND (op1, 0)) == NULL_TREE
326 && CALL_EXPR_IFN (TREE_OPERAND (op1, 0)) == IFN_UBSAN_BOUNDS;
329 /* Instrument an ARRAY_REF, if it hasn't already been instrumented.
330 IGNORE_OFF_BY_ONE is true if the ARRAY_REF is inside a ADDR_EXPR. */
332 void
333 ubsan_maybe_instrument_array_ref (tree *expr_p, bool ignore_off_by_one)
335 if (!ubsan_array_ref_instrumented_p (*expr_p)
336 && current_function_decl != NULL_TREE
337 && !lookup_attribute ("no_sanitize_undefined",
338 DECL_ATTRIBUTES (current_function_decl)))
340 tree op0 = TREE_OPERAND (*expr_p, 0);
341 tree op1 = TREE_OPERAND (*expr_p, 1);
342 tree e = ubsan_instrument_bounds (EXPR_LOCATION (*expr_p), op0, &op1,
343 ignore_off_by_one);
344 if (e != NULL_TREE)
346 tree t = copy_node (*expr_p);
347 TREE_OPERAND (t, 1) = build2 (COMPOUND_EXPR, TREE_TYPE (op1),
348 e, op1);
349 *expr_p = t;