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
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"
25 #include "alloc-pool.h"
30 #include "c-family/c-common.h"
31 #include "c-family/c-ubsan.h"
33 #include "internal-fn.h"
35 /* Instrument division by zero and INT_MIN / -1. If not instrumenting,
39 ubsan_instrument_division (location_t loc
, tree op0
, tree op1
)
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
));
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
))
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
77 if (integer_zerop (t
))
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
)
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);
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
);
116 /* Instrument left and right shifts. */
119 ubsan_instrument_shift (location_t loc
, enum tree_code code
,
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
)
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
166 if (integer_zerop (t
) && (tt
== NULL_TREE
|| integer_zerop (tt
)))
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
)
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);
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
);
210 /* Instrument variable length array bound. */
213 ubsan_instrument_vla (location_t loc
, tree size
)
215 tree type
= TREE_TYPE (size
);
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);
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
);
238 /* Instrument missing return in C++ functions returning non-void. */
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
,
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. */
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
)
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
;
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
))
293 /* Not a last element. Instrument it. */
295 /* Ok, this is the last field of the structure/union. But the
296 aggregate containing the field must be the last field too,
298 cref
= TREE_OPERAND (cref
, 0);
301 /* Don't instrument this flexible array member-like array in non-strict
302 -fsanitize=bounds mode. */
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
,
314 /* Return true iff T is an array that was instrumented by SANITIZE_BOUNDS. */
317 ubsan_array_ref_instrumented_p (const_tree t
)
319 if (TREE_CODE (t
) != ARRAY_REF
)
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. */
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
,
346 tree t
= copy_node (*expr_p
);
347 TREE_OPERAND (t
, 1) = build2 (COMPOUND_EXPR
, TREE_TYPE (op1
),