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
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
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/>. */
23 #include "coretypes.h"
28 #include "alloc-pool.h"
30 #include "hard-reg-set.h"
36 #include "c-family/c-common.h"
37 #include "c-family/c-ubsan.h"
39 #include "internal-fn.h"
40 #include "stor-layout.h"
43 /* Instrument division by zero and INT_MIN / -1. If not instrumenting,
47 ubsan_instrument_division (location_t loc
, tree op0
, tree op1
)
50 tree type
= TREE_TYPE (op0
);
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
)));
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
));
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
))
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
);
83 /* If the condition was folded to 0, no need to instrument
85 if (integer_zerop (t
))
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
)
95 while (CONVERT_EXPR_P (xop0
))
96 xop0
= TREE_OPERAND (xop0
, 0);
97 if (TREE_CODE (xop0
) == ARRAY_REF
)
99 TREE_SIDE_EFFECTS (xop0
) = 1;
100 TREE_SIDE_EFFECTS (op0
) = 1;
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);
108 tree data
= ubsan_create_data ("__ubsan_overflow_data", 1, &loc
,
109 ubsan_type_descriptor (type
), 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
));
120 t
= fold_build3 (COND_EXPR
, void_type_node
, t
, tt
, void_node
);
125 /* Instrument left and right shifts. */
128 ubsan_instrument_shift (location_t loc
, enum tree_code code
,
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);
138 t
= fold_convert_loc (loc
, op1_utype
, op1
);
139 t
= fold_build2 (GT_EXPR
, boolean_type_node
, t
, uprecm1
);
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
)
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));
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
))
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
);
174 /* If the condition was folded to 0, no need to instrument
176 if (integer_zerop (t
) && (tt
== NULL_TREE
|| integer_zerop (tt
)))
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
)
186 while (CONVERT_EXPR_P (xop0
))
187 xop0
= TREE_OPERAND (xop0
, 0);
188 if (TREE_CODE (xop0
) == ARRAY_REF
)
190 TREE_SIDE_EFFECTS (xop0
) = 1;
191 TREE_SIDE_EFFECTS (op0
) = 1;
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
);
198 if (flag_sanitize_undefined_trap_on_error
)
199 tt
= build_call_expr_loc (loc
, builtin_decl_explicit (BUILT_IN_TRAP
), 0);
202 tree data
= ubsan_create_data ("__ubsan_shift_data", 1, &loc
,
203 ubsan_type_descriptor (type0
),
204 ubsan_type_descriptor (type1
), NULL_TREE
,
206 data
= build_fold_addr_expr_loc (loc
, data
);
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
));
216 t
= fold_build3 (COND_EXPR
, void_type_node
, t
, tt
, void_node
);
221 /* Instrument variable length array bound. */
224 ubsan_instrument_vla (location_t loc
, tree size
)
226 tree type
= TREE_TYPE (size
);
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);
234 tree data
= ubsan_create_data ("__ubsan_vla_data", 1, &loc
,
235 ubsan_type_descriptor (type
), 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
));
245 t
= fold_build3 (COND_EXPR
, void_type_node
, t
, tt
, void_node
);
250 /* Instrument missing return in C++ functions returning non-void. */
253 ubsan_instrument_return (location_t loc
)
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 ();
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
));
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. */
274 ubsan_instrument_bounds (location_t loc
, tree array
, tree
*index
,
275 bool ignore_off_by_one
)
277 tree type
= TREE_TYPE (array
);
278 tree domain
= TYPE_DOMAIN (type
);
280 if (domain
== NULL_TREE
|| TYPE_MAX_VALUE (domain
) == NULL_TREE
)
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));
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
))
295 tree next
= NULL_TREE
;
298 /* Walk all structs/unions. */
299 while (TREE_CODE (cref
) == COMPONENT_REF
)
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
))
307 /* Not a last element. Instrument it. */
309 /* Ok, this is the last field of the structure/union. But the
310 aggregate containing the field must be the last field too,
312 cref
= TREE_OPERAND (cref
, 0);
315 /* Don't instrument this flexible array member-like array in non-strict
316 -fsanitize=bounds mode. */
320 /* Don't emit instrumentation in the most common cases. */
321 tree idx
= NULL_TREE
;
322 if (TREE_CODE (*index
) == INTEGER_CST
)
324 else if (TREE_CODE (*index
) == BIT_AND_EXPR
325 && TREE_CODE (TREE_OPERAND (*index
, 1)) == INTEGER_CST
)
326 idx
= TREE_OPERAND (*index
, 1);
328 && TREE_CODE (bound
) == INTEGER_CST
329 && tree_int_cst_sgn (idx
) >= 0
330 && tree_int_cst_le (idx
, bound
))
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
,
341 /* Return true iff T is an array that was instrumented by SANITIZE_BOUNDS. */
344 ubsan_array_ref_instrumented_p (const_tree t
)
346 if (TREE_CODE (t
) != ARRAY_REF
)
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
;
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. */
360 ubsan_maybe_instrument_array_ref (tree
*expr_p
, bool ignore_off_by_one
)
362 if (!ubsan_array_ref_instrumented_p (*expr_p
)
363 && do_ubsan_in_current_function ())
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
,
371 tree t
= copy_node (*expr_p
);
372 TREE_OPERAND (t
, 1) = build2 (COMPOUND_EXPR
, TREE_TYPE (op1
),
380 ubsan_maybe_instrument_reference_or_call (location_t loc
, tree op
, tree ptype
,
381 enum ubsan_null_ckind ckind
)
383 if (!do_ubsan_in_current_function ())
386 tree type
= TREE_TYPE (ptype
);
388 bool instrument
= false;
389 unsigned int mina
= 0;
391 if (flag_sanitize
& SANITIZE_ALIGNMENT
)
393 mina
= min_align_of_type (type
);
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
)
404 if (mina
&& mina
> min_align_of_type (TREE_TYPE (TREE_TYPE (op
))))
409 if ((flag_sanitize
& SANITIZE_NULL
) && TREE_CODE (op
) == ADDR_EXPR
)
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
)
422 flag_delete_null_pointer_checks
423 = save_flag_delete_null_pointer_checks
;
425 else if (flag_sanitize
& SANITIZE_NULL
)
427 if (mina
&& mina
> 1)
429 if (!POINTER_TYPE_P (TREE_TYPE (op
))
430 || mina
> get_pointer_alignment (op
) / BITS_PER_UNIT
)
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
);
443 = build_call_expr_internal_loc (loc
, IFN_UBSAN_NULL
, void_type_node
,
445 TREE_SIDE_EFFECTS (call
) = 1;
446 return fold_build2 (COMPOUND_EXPR
, TREE_TYPE (op
), call
, op
);
449 /* Instrument a NOP_EXPR to REFERENCE_TYPE if needed. */
452 ubsan_maybe_instrument_reference (tree stmt
)
454 tree op
= TREE_OPERAND (stmt
, 0);
455 op
= ubsan_maybe_instrument_reference_or_call (EXPR_LOCATION (stmt
), op
,
459 TREE_OPERAND (stmt
, 0) = op
;
462 /* Instrument a CALL_EXPR to a method if needed. */
465 ubsan_maybe_instrument_member_call (tree stmt
, bool is_ctor
)
467 if (call_expr_nargs (stmt
) == 0)
469 tree op
= CALL_EXPR_ARG (stmt
, 0);
470 if (op
== error_mark_node
471 || !POINTER_TYPE_P (TREE_TYPE (op
)))
473 op
= ubsan_maybe_instrument_reference_or_call (EXPR_LOCATION (stmt
), op
,
475 is_ctor
? UBSAN_CTOR_CALL
476 : UBSAN_MEMBER_CALL
);
478 CALL_EXPR_ARG (stmt
, 0) = op
;