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"
29 #include "plugin-api.h"
31 #include "hard-reg-set.h"
38 #include "c-family/c-common.h"
39 #include "c-family/c-ubsan.h"
41 #include "internal-fn.h"
42 #include "stor-layout.h"
45 /* Instrument division by zero and INT_MIN / -1. If not instrumenting,
49 ubsan_instrument_division (location_t loc
, tree op0
, tree op1
)
52 tree type
= TREE_TYPE (op0
);
54 /* At this point both operands should have the same type,
55 because they are already converted to RESULT_TYPE.
56 Use TYPE_MAIN_VARIANT since typedefs can confuse us. */
57 gcc_assert (TYPE_MAIN_VARIANT (TREE_TYPE (op0
))
58 == TYPE_MAIN_VARIANT (TREE_TYPE (op1
)));
60 if (TREE_CODE (type
) == INTEGER_TYPE
61 && (flag_sanitize
& SANITIZE_DIVIDE
))
62 t
= fold_build2 (EQ_EXPR
, boolean_type_node
,
63 op1
, build_int_cst (type
, 0));
64 else if (TREE_CODE (type
) == REAL_TYPE
65 && (flag_sanitize
& SANITIZE_FLOAT_DIVIDE
))
66 t
= fold_build2 (EQ_EXPR
, boolean_type_node
,
67 op1
, build_real (type
, dconst0
));
71 /* We check INT_MIN / -1 only for signed types. */
72 if (TREE_CODE (type
) == INTEGER_TYPE
73 && (flag_sanitize
& SANITIZE_DIVIDE
)
74 && !TYPE_UNSIGNED (type
))
77 tt
= fold_build2 (EQ_EXPR
, boolean_type_node
, op1
,
78 build_int_cst (type
, -1));
79 x
= fold_build2 (EQ_EXPR
, boolean_type_node
, op0
,
80 TYPE_MIN_VALUE (type
));
81 x
= fold_build2 (TRUTH_AND_EXPR
, boolean_type_node
, x
, tt
);
82 t
= fold_build2 (TRUTH_OR_EXPR
, boolean_type_node
, t
, x
);
85 /* If the condition was folded to 0, no need to instrument
87 if (integer_zerop (t
))
90 /* In case we have a SAVE_EXPR in a conditional context, we need to
91 make sure it gets evaluated before the condition. If the OP0 is
92 an instrumented array reference, mark it as having side effects so
93 it's not folded away. */
94 if (flag_sanitize
& SANITIZE_BOUNDS
)
97 while (CONVERT_EXPR_P (xop0
))
98 xop0
= TREE_OPERAND (xop0
, 0);
99 if (TREE_CODE (xop0
) == ARRAY_REF
)
101 TREE_SIDE_EFFECTS (xop0
) = 1;
102 TREE_SIDE_EFFECTS (op0
) = 1;
105 t
= fold_build2 (COMPOUND_EXPR
, TREE_TYPE (t
), op0
, t
);
106 if (flag_sanitize_undefined_trap_on_error
)
107 tt
= build_call_expr_loc (loc
, builtin_decl_explicit (BUILT_IN_TRAP
), 0);
110 tree data
= ubsan_create_data ("__ubsan_overflow_data", 1, &loc
,
111 ubsan_type_descriptor (type
), NULL_TREE
,
113 data
= build_fold_addr_expr_loc (loc
, data
);
114 enum built_in_function bcode
115 = (flag_sanitize_recover
& SANITIZE_DIVIDE
)
116 ? BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW
117 : BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW_ABORT
;
118 tt
= builtin_decl_explicit (bcode
);
119 tt
= build_call_expr_loc (loc
, tt
, 3, data
, ubsan_encode_value (op0
),
120 ubsan_encode_value (op1
));
122 t
= fold_build3 (COND_EXPR
, void_type_node
, t
, tt
, void_node
);
127 /* Instrument left and right shifts. */
130 ubsan_instrument_shift (location_t loc
, enum tree_code code
,
133 tree t
, tt
= NULL_TREE
;
134 tree type0
= TREE_TYPE (op0
);
135 tree type1
= TREE_TYPE (op1
);
136 tree op1_utype
= unsigned_type_for (type1
);
137 HOST_WIDE_INT op0_prec
= TYPE_PRECISION (type0
);
138 tree uprecm1
= build_int_cst (op1_utype
, op0_prec
- 1);
140 t
= fold_convert_loc (loc
, op1_utype
, op1
);
141 t
= fold_build2 (GT_EXPR
, boolean_type_node
, t
, uprecm1
);
143 /* For signed x << y, in C99/C11, the following:
144 (unsigned) x >> (uprecm1 - y)
145 if non-zero, is undefined. */
146 if (code
== LSHIFT_EXPR
147 && !TYPE_UNSIGNED (type0
)
150 tree x
= fold_build2 (MINUS_EXPR
, op1_utype
, uprecm1
,
151 fold_convert (op1_utype
, op1
));
152 tt
= fold_convert_loc (loc
, unsigned_type_for (type0
), op0
);
153 tt
= fold_build2 (RSHIFT_EXPR
, TREE_TYPE (tt
), tt
, x
);
154 tt
= fold_build2 (NE_EXPR
, boolean_type_node
, tt
,
155 build_int_cst (TREE_TYPE (tt
), 0));
158 /* For signed x << y, in C++11 and later, the following:
159 x < 0 || ((unsigned) x >> (uprecm1 - y))
160 if > 1, is undefined. */
161 if (code
== LSHIFT_EXPR
162 && !TYPE_UNSIGNED (type0
)
163 && (cxx_dialect
>= cxx11
))
165 tree x
= fold_build2 (MINUS_EXPR
, op1_utype
, uprecm1
,
166 fold_convert (op1_utype
, op1
));
167 tt
= fold_convert_loc (loc
, unsigned_type_for (type0
), op0
);
168 tt
= fold_build2 (RSHIFT_EXPR
, TREE_TYPE (tt
), tt
, x
);
169 tt
= fold_build2 (GT_EXPR
, boolean_type_node
, tt
,
170 build_int_cst (TREE_TYPE (tt
), 1));
171 x
= fold_build2 (LT_EXPR
, boolean_type_node
, op0
,
172 build_int_cst (type0
, 0));
173 tt
= fold_build2 (TRUTH_OR_EXPR
, boolean_type_node
, x
, tt
);
176 /* If the condition was folded to 0, no need to instrument
178 if (integer_zerop (t
) && (tt
== NULL_TREE
|| integer_zerop (tt
)))
181 /* In case we have a SAVE_EXPR in a conditional context, we need to
182 make sure it gets evaluated before the condition. If the OP0 is
183 an instrumented array reference, mark it as having side effects so
184 it's not folded away. */
185 if (flag_sanitize
& SANITIZE_BOUNDS
)
188 while (CONVERT_EXPR_P (xop0
))
189 xop0
= TREE_OPERAND (xop0
, 0);
190 if (TREE_CODE (xop0
) == ARRAY_REF
)
192 TREE_SIDE_EFFECTS (xop0
) = 1;
193 TREE_SIDE_EFFECTS (op0
) = 1;
196 t
= fold_build2 (COMPOUND_EXPR
, TREE_TYPE (t
), op0
, t
);
197 t
= fold_build2 (TRUTH_OR_EXPR
, boolean_type_node
, t
,
198 tt
? tt
: integer_zero_node
);
200 if (flag_sanitize_undefined_trap_on_error
)
201 tt
= build_call_expr_loc (loc
, builtin_decl_explicit (BUILT_IN_TRAP
), 0);
204 tree data
= ubsan_create_data ("__ubsan_shift_data", 1, &loc
,
205 ubsan_type_descriptor (type0
),
206 ubsan_type_descriptor (type1
), NULL_TREE
,
208 data
= build_fold_addr_expr_loc (loc
, data
);
210 enum built_in_function bcode
211 = (flag_sanitize_recover
& SANITIZE_SHIFT
)
212 ? BUILT_IN_UBSAN_HANDLE_SHIFT_OUT_OF_BOUNDS
213 : BUILT_IN_UBSAN_HANDLE_SHIFT_OUT_OF_BOUNDS_ABORT
;
214 tt
= builtin_decl_explicit (bcode
);
215 tt
= build_call_expr_loc (loc
, tt
, 3, data
, ubsan_encode_value (op0
),
216 ubsan_encode_value (op1
));
218 t
= fold_build3 (COND_EXPR
, void_type_node
, t
, tt
, void_node
);
223 /* Instrument variable length array bound. */
226 ubsan_instrument_vla (location_t loc
, tree size
)
228 tree type
= TREE_TYPE (size
);
231 t
= fold_build2 (LE_EXPR
, boolean_type_node
, size
, build_int_cst (type
, 0));
232 if (flag_sanitize_undefined_trap_on_error
)
233 tt
= build_call_expr_loc (loc
, builtin_decl_explicit (BUILT_IN_TRAP
), 0);
236 tree data
= ubsan_create_data ("__ubsan_vla_data", 1, &loc
,
237 ubsan_type_descriptor (type
), NULL_TREE
,
239 data
= build_fold_addr_expr_loc (loc
, data
);
240 enum built_in_function bcode
241 = (flag_sanitize_recover
& SANITIZE_VLA
)
242 ? BUILT_IN_UBSAN_HANDLE_VLA_BOUND_NOT_POSITIVE
243 : BUILT_IN_UBSAN_HANDLE_VLA_BOUND_NOT_POSITIVE_ABORT
;
244 tt
= builtin_decl_explicit (bcode
);
245 tt
= build_call_expr_loc (loc
, tt
, 2, data
, ubsan_encode_value (size
));
247 t
= fold_build3 (COND_EXPR
, void_type_node
, t
, tt
, void_node
);
252 /* Instrument missing return in C++ functions returning non-void. */
255 ubsan_instrument_return (location_t loc
)
257 if (flag_sanitize_undefined_trap_on_error
)
258 return build_call_expr_loc (loc
, builtin_decl_explicit (BUILT_IN_TRAP
), 0);
259 /* It is possible that PCH zapped table with definitions of sanitizer
260 builtins. Reinitialize them if needed. */
261 initialize_sanitizer_builtins ();
263 tree data
= ubsan_create_data ("__ubsan_missing_return_data", 1, &loc
,
264 NULL_TREE
, NULL_TREE
);
265 tree t
= builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_MISSING_RETURN
);
266 return build_call_expr_loc (loc
, t
, 1, build_fold_addr_expr_loc (loc
, data
));
269 /* Instrument array bounds for ARRAY_REFs. We create special builtin,
270 that gets expanded in the sanopt pass, and make an array dimension
271 of it. ARRAY is the array, *INDEX is an index to the array.
272 Return NULL_TREE if no instrumentation is emitted.
273 IGNORE_OFF_BY_ONE is true if the ARRAY_REF is inside a ADDR_EXPR. */
276 ubsan_instrument_bounds (location_t loc
, tree array
, tree
*index
,
277 bool ignore_off_by_one
)
279 tree type
= TREE_TYPE (array
);
280 tree domain
= TYPE_DOMAIN (type
);
282 if (domain
== NULL_TREE
|| TYPE_MAX_VALUE (domain
) == NULL_TREE
)
285 tree bound
= TYPE_MAX_VALUE (domain
);
286 if (ignore_off_by_one
)
287 bound
= fold_build2 (PLUS_EXPR
, TREE_TYPE (bound
), bound
,
288 build_int_cst (TREE_TYPE (bound
), 1));
290 /* Detect flexible array members and suchlike, unless
291 -fsanitize=bounds-strict. */
292 tree base
= get_base_address (array
);
293 if ((flag_sanitize
& SANITIZE_BOUNDS_STRICT
) == 0
294 && TREE_CODE (array
) == COMPONENT_REF
295 && base
&& (TREE_CODE (base
) == INDIRECT_REF
296 || TREE_CODE (base
) == MEM_REF
))
298 tree next
= NULL_TREE
;
301 /* Walk all structs/unions. */
302 while (TREE_CODE (cref
) == COMPONENT_REF
)
304 if (TREE_CODE (TREE_TYPE (TREE_OPERAND (cref
, 0))) == RECORD_TYPE
)
305 for (next
= DECL_CHAIN (TREE_OPERAND (cref
, 1));
306 next
&& TREE_CODE (next
) != FIELD_DECL
;
307 next
= DECL_CHAIN (next
))
310 /* Not a last element. Instrument it. */
312 /* Ok, this is the last field of the structure/union. But the
313 aggregate containing the field must be the last field too,
315 cref
= TREE_OPERAND (cref
, 0);
318 /* Don't instrument this flexible array member-like array in non-strict
319 -fsanitize=bounds mode. */
323 /* Don't emit instrumentation in the most common cases. */
324 tree idx
= NULL_TREE
;
325 if (TREE_CODE (*index
) == INTEGER_CST
)
327 else if (TREE_CODE (*index
) == BIT_AND_EXPR
328 && TREE_CODE (TREE_OPERAND (*index
, 1)) == INTEGER_CST
)
329 idx
= TREE_OPERAND (*index
, 1);
331 && TREE_CODE (bound
) == INTEGER_CST
332 && tree_int_cst_sgn (idx
) >= 0
333 && tree_int_cst_le (idx
, bound
))
336 *index
= save_expr (*index
);
337 /* Create a "(T *) 0" tree node to describe the array type. */
338 tree zero_with_type
= build_int_cst (build_pointer_type (type
), 0);
339 return build_call_expr_internal_loc (loc
, IFN_UBSAN_BOUNDS
,
340 void_type_node
, 3, zero_with_type
,
344 /* Return true iff T is an array that was instrumented by SANITIZE_BOUNDS. */
347 ubsan_array_ref_instrumented_p (const_tree t
)
349 if (TREE_CODE (t
) != ARRAY_REF
)
352 tree op1
= TREE_OPERAND (t
, 1);
353 return TREE_CODE (op1
) == COMPOUND_EXPR
354 && TREE_CODE (TREE_OPERAND (op1
, 0)) == CALL_EXPR
355 && CALL_EXPR_FN (TREE_OPERAND (op1
, 0)) == NULL_TREE
356 && CALL_EXPR_IFN (TREE_OPERAND (op1
, 0)) == IFN_UBSAN_BOUNDS
;
359 /* Instrument an ARRAY_REF, if it hasn't already been instrumented.
360 IGNORE_OFF_BY_ONE is true if the ARRAY_REF is inside a ADDR_EXPR. */
363 ubsan_maybe_instrument_array_ref (tree
*expr_p
, bool ignore_off_by_one
)
365 if (!ubsan_array_ref_instrumented_p (*expr_p
)
366 && do_ubsan_in_current_function ())
368 tree op0
= TREE_OPERAND (*expr_p
, 0);
369 tree op1
= TREE_OPERAND (*expr_p
, 1);
370 tree e
= ubsan_instrument_bounds (EXPR_LOCATION (*expr_p
), op0
, &op1
,
374 tree t
= copy_node (*expr_p
);
375 TREE_OPERAND (t
, 1) = build2 (COMPOUND_EXPR
, TREE_TYPE (op1
),
383 ubsan_maybe_instrument_reference_or_call (location_t loc
, tree op
, tree ptype
,
384 enum ubsan_null_ckind ckind
)
386 if (!do_ubsan_in_current_function ())
389 tree type
= TREE_TYPE (ptype
);
391 bool instrument
= false;
392 unsigned int mina
= 0;
394 if (flag_sanitize
& SANITIZE_ALIGNMENT
)
396 mina
= min_align_of_type (type
);
400 while ((TREE_CODE (op
) == NOP_EXPR
401 || TREE_CODE (op
) == NON_LVALUE_EXPR
)
402 && TREE_CODE (TREE_TYPE (op
)) == POINTER_TYPE
)
403 op
= TREE_OPERAND (op
, 0);
404 if (TREE_CODE (op
) == NOP_EXPR
405 && TREE_CODE (TREE_TYPE (op
)) == REFERENCE_TYPE
)
407 if (mina
&& mina
> min_align_of_type (TREE_TYPE (TREE_TYPE (op
))))
412 if ((flag_sanitize
& SANITIZE_NULL
) && TREE_CODE (op
) == ADDR_EXPR
)
414 bool strict_overflow_p
= false;
415 /* tree_single_nonzero_warnv_p will not return true for non-weak
416 non-automatic decls with -fno-delete-null-pointer-checks,
417 which is disabled during -fsanitize=null. We don't want to
418 instrument those, just weak vars though. */
419 int save_flag_delete_null_pointer_checks
420 = flag_delete_null_pointer_checks
;
421 flag_delete_null_pointer_checks
= 1;
422 if (!tree_single_nonzero_warnv_p (op
, &strict_overflow_p
)
423 || strict_overflow_p
)
425 flag_delete_null_pointer_checks
426 = save_flag_delete_null_pointer_checks
;
428 else if (flag_sanitize
& SANITIZE_NULL
)
430 if (mina
&& mina
> 1)
432 if (!POINTER_TYPE_P (TREE_TYPE (op
))
433 || mina
> get_pointer_alignment (op
) / BITS_PER_UNIT
)
439 op
= save_expr (orig_op
);
440 gcc_assert (POINTER_TYPE_P (ptype
));
441 if (TREE_CODE (ptype
) == REFERENCE_TYPE
)
442 ptype
= build_pointer_type (TREE_TYPE (ptype
));
443 tree kind
= build_int_cst (ptype
, ckind
);
444 tree align
= build_int_cst (pointer_sized_int_node
, mina
);
446 = build_call_expr_internal_loc (loc
, IFN_UBSAN_NULL
, void_type_node
,
448 TREE_SIDE_EFFECTS (call
) = 1;
449 return fold_build2 (COMPOUND_EXPR
, TREE_TYPE (op
), call
, op
);
452 /* Instrument a NOP_EXPR to REFERENCE_TYPE if needed. */
455 ubsan_maybe_instrument_reference (tree stmt
)
457 tree op
= TREE_OPERAND (stmt
, 0);
458 op
= ubsan_maybe_instrument_reference_or_call (EXPR_LOCATION (stmt
), op
,
462 TREE_OPERAND (stmt
, 0) = op
;
465 /* Instrument a CALL_EXPR to a method if needed. */
468 ubsan_maybe_instrument_member_call (tree stmt
, bool is_ctor
)
470 if (call_expr_nargs (stmt
) == 0)
472 tree op
= CALL_EXPR_ARG (stmt
, 0);
473 if (op
== error_mark_node
474 || !POINTER_TYPE_P (TREE_TYPE (op
)))
476 op
= ubsan_maybe_instrument_reference_or_call (EXPR_LOCATION (stmt
), op
,
478 is_ctor
? UBSAN_CTOR_CALL
479 : UBSAN_MEMBER_CALL
);
481 CALL_EXPR_ARG (stmt
, 0) = op
;