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