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"
27 #include "double-int.h"
35 #include "alloc-pool.h"
38 #include "plugin-api.h"
44 #include "hard-reg-set.h"
52 #include "c-family/c-common.h"
53 #include "c-family/c-ubsan.h"
55 #include "internal-fn.h"
56 #include "stor-layout.h"
59 /* Instrument division by zero and INT_MIN / -1. If not instrumenting,
63 ubsan_instrument_division (location_t loc
, tree op0
, tree op1
)
66 tree type
= TREE_TYPE (op0
);
68 /* At this point both operands should have the same type,
69 because they are already converted to RESULT_TYPE.
70 Use TYPE_MAIN_VARIANT since typedefs can confuse us. */
71 gcc_assert (TYPE_MAIN_VARIANT (TREE_TYPE (op0
))
72 == TYPE_MAIN_VARIANT (TREE_TYPE (op1
)));
74 if (TREE_CODE (type
) == INTEGER_TYPE
75 && (flag_sanitize
& SANITIZE_DIVIDE
))
76 t
= fold_build2 (EQ_EXPR
, boolean_type_node
,
77 op1
, build_int_cst (type
, 0));
78 else if (TREE_CODE (type
) == REAL_TYPE
79 && (flag_sanitize
& SANITIZE_FLOAT_DIVIDE
))
80 t
= fold_build2 (EQ_EXPR
, boolean_type_node
,
81 op1
, build_real (type
, dconst0
));
85 /* We check INT_MIN / -1 only for signed types. */
86 if (TREE_CODE (type
) == INTEGER_TYPE
87 && (flag_sanitize
& SANITIZE_DIVIDE
)
88 && !TYPE_UNSIGNED (type
))
91 tt
= fold_build2 (EQ_EXPR
, boolean_type_node
, op1
,
92 build_int_cst (type
, -1));
93 x
= fold_build2 (EQ_EXPR
, boolean_type_node
, op0
,
94 TYPE_MIN_VALUE (type
));
95 x
= fold_build2 (TRUTH_AND_EXPR
, boolean_type_node
, x
, tt
);
96 t
= fold_build2 (TRUTH_OR_EXPR
, boolean_type_node
, t
, x
);
99 /* If the condition was folded to 0, no need to instrument
101 if (integer_zerop (t
))
104 /* In case we have a SAVE_EXPR in a conditional context, we need to
105 make sure it gets evaluated before the condition. If the OP0 is
106 an instrumented array reference, mark it as having side effects so
107 it's not folded away. */
108 if (flag_sanitize
& SANITIZE_BOUNDS
)
111 while (CONVERT_EXPR_P (xop0
))
112 xop0
= TREE_OPERAND (xop0
, 0);
113 if (TREE_CODE (xop0
) == ARRAY_REF
)
115 TREE_SIDE_EFFECTS (xop0
) = 1;
116 TREE_SIDE_EFFECTS (op0
) = 1;
119 t
= fold_build2 (COMPOUND_EXPR
, TREE_TYPE (t
), op0
, t
);
120 if (flag_sanitize_undefined_trap_on_error
)
121 tt
= build_call_expr_loc (loc
, builtin_decl_explicit (BUILT_IN_TRAP
), 0);
124 tree data
= ubsan_create_data ("__ubsan_overflow_data", 1, &loc
,
125 ubsan_type_descriptor (type
), NULL_TREE
,
127 data
= build_fold_addr_expr_loc (loc
, data
);
128 enum built_in_function bcode
129 = (flag_sanitize_recover
& SANITIZE_DIVIDE
)
130 ? BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW
131 : BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW_ABORT
;
132 tt
= builtin_decl_explicit (bcode
);
133 tt
= build_call_expr_loc (loc
, tt
, 3, data
, ubsan_encode_value (op0
),
134 ubsan_encode_value (op1
));
136 t
= fold_build3 (COND_EXPR
, void_type_node
, t
, tt
, void_node
);
141 /* Instrument left and right shifts. */
144 ubsan_instrument_shift (location_t loc
, enum tree_code code
,
147 tree t
, tt
= NULL_TREE
;
148 tree type0
= TREE_TYPE (op0
);
149 tree type1
= TREE_TYPE (op1
);
150 tree op1_utype
= unsigned_type_for (type1
);
151 HOST_WIDE_INT op0_prec
= TYPE_PRECISION (type0
);
152 tree uprecm1
= build_int_cst (op1_utype
, op0_prec
- 1);
154 t
= fold_convert_loc (loc
, op1_utype
, op1
);
155 t
= fold_build2 (GT_EXPR
, boolean_type_node
, t
, uprecm1
);
157 /* For signed x << y, in C99/C11, the following:
158 (unsigned) x >> (uprecm1 - y)
159 if non-zero, is undefined. */
160 if (code
== LSHIFT_EXPR
161 && !TYPE_UNSIGNED (type0
)
164 tree x
= fold_build2 (MINUS_EXPR
, op1_utype
, uprecm1
,
165 fold_convert (op1_utype
, op1
));
166 tt
= fold_convert_loc (loc
, unsigned_type_for (type0
), op0
);
167 tt
= fold_build2 (RSHIFT_EXPR
, TREE_TYPE (tt
), tt
, x
);
168 tt
= fold_build2 (NE_EXPR
, boolean_type_node
, tt
,
169 build_int_cst (TREE_TYPE (tt
), 0));
172 /* For signed x << y, in C++11 and later, the following:
173 x < 0 || ((unsigned) x >> (uprecm1 - y))
174 if > 1, is undefined. */
175 if (code
== LSHIFT_EXPR
176 && !TYPE_UNSIGNED (TREE_TYPE (op0
))
177 && (cxx_dialect
>= cxx11
))
179 tree x
= fold_build2 (MINUS_EXPR
, op1_utype
, uprecm1
,
180 fold_convert (op1_utype
, op1
));
181 tt
= fold_convert_loc (loc
, unsigned_type_for (type0
), op0
);
182 tt
= fold_build2 (RSHIFT_EXPR
, TREE_TYPE (tt
), tt
, x
);
183 tt
= fold_build2 (GT_EXPR
, boolean_type_node
, tt
,
184 build_int_cst (TREE_TYPE (tt
), 1));
185 x
= fold_build2 (LT_EXPR
, boolean_type_node
, op0
,
186 build_int_cst (type0
, 0));
187 tt
= fold_build2 (TRUTH_OR_EXPR
, boolean_type_node
, x
, tt
);
190 /* If the condition was folded to 0, no need to instrument
192 if (integer_zerop (t
) && (tt
== NULL_TREE
|| integer_zerop (tt
)))
195 /* In case we have a SAVE_EXPR in a conditional context, we need to
196 make sure it gets evaluated before the condition. If the OP0 is
197 an instrumented array reference, mark it as having side effects so
198 it's not folded away. */
199 if (flag_sanitize
& SANITIZE_BOUNDS
)
202 while (CONVERT_EXPR_P (xop0
))
203 xop0
= TREE_OPERAND (xop0
, 0);
204 if (TREE_CODE (xop0
) == ARRAY_REF
)
206 TREE_SIDE_EFFECTS (xop0
) = 1;
207 TREE_SIDE_EFFECTS (op0
) = 1;
210 t
= fold_build2 (COMPOUND_EXPR
, TREE_TYPE (t
), op0
, t
);
211 t
= fold_build2 (TRUTH_OR_EXPR
, boolean_type_node
, t
,
212 tt
? tt
: integer_zero_node
);
214 if (flag_sanitize_undefined_trap_on_error
)
215 tt
= build_call_expr_loc (loc
, builtin_decl_explicit (BUILT_IN_TRAP
), 0);
218 tree data
= ubsan_create_data ("__ubsan_shift_data", 1, &loc
,
219 ubsan_type_descriptor (type0
),
220 ubsan_type_descriptor (type1
), NULL_TREE
,
222 data
= build_fold_addr_expr_loc (loc
, data
);
224 enum built_in_function bcode
225 = (flag_sanitize_recover
& SANITIZE_SHIFT
)
226 ? BUILT_IN_UBSAN_HANDLE_SHIFT_OUT_OF_BOUNDS
227 : BUILT_IN_UBSAN_HANDLE_SHIFT_OUT_OF_BOUNDS_ABORT
;
228 tt
= builtin_decl_explicit (bcode
);
229 tt
= build_call_expr_loc (loc
, tt
, 3, data
, ubsan_encode_value (op0
),
230 ubsan_encode_value (op1
));
232 t
= fold_build3 (COND_EXPR
, void_type_node
, t
, tt
, void_node
);
237 /* Instrument variable length array bound. */
240 ubsan_instrument_vla (location_t loc
, tree size
)
242 tree type
= TREE_TYPE (size
);
245 t
= fold_build2 (LE_EXPR
, boolean_type_node
, size
, build_int_cst (type
, 0));
246 if (flag_sanitize_undefined_trap_on_error
)
247 tt
= build_call_expr_loc (loc
, builtin_decl_explicit (BUILT_IN_TRAP
), 0);
250 tree data
= ubsan_create_data ("__ubsan_vla_data", 1, &loc
,
251 ubsan_type_descriptor (type
), NULL_TREE
,
253 data
= build_fold_addr_expr_loc (loc
, data
);
254 enum built_in_function bcode
255 = (flag_sanitize_recover
& SANITIZE_VLA
)
256 ? BUILT_IN_UBSAN_HANDLE_VLA_BOUND_NOT_POSITIVE
257 : BUILT_IN_UBSAN_HANDLE_VLA_BOUND_NOT_POSITIVE_ABORT
;
258 tt
= builtin_decl_explicit (bcode
);
259 tt
= build_call_expr_loc (loc
, tt
, 2, data
, ubsan_encode_value (size
));
261 t
= fold_build3 (COND_EXPR
, void_type_node
, t
, tt
, void_node
);
266 /* Instrument missing return in C++ functions returning non-void. */
269 ubsan_instrument_return (location_t loc
)
271 if (flag_sanitize_undefined_trap_on_error
)
272 return build_call_expr_loc (loc
, builtin_decl_explicit (BUILT_IN_TRAP
), 0);
273 /* It is possible that PCH zapped table with definitions of sanitizer
274 builtins. Reinitialize them if needed. */
275 initialize_sanitizer_builtins ();
277 tree data
= ubsan_create_data ("__ubsan_missing_return_data", 1, &loc
,
278 NULL_TREE
, NULL_TREE
);
279 tree t
= builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_MISSING_RETURN
);
280 return build_call_expr_loc (loc
, t
, 1, build_fold_addr_expr_loc (loc
, data
));
283 /* Instrument array bounds for ARRAY_REFs. We create special builtin,
284 that gets expanded in the sanopt pass, and make an array dimension
285 of it. ARRAY is the array, *INDEX is an index to the array.
286 Return NULL_TREE if no instrumentation is emitted.
287 IGNORE_OFF_BY_ONE is true if the ARRAY_REF is inside a ADDR_EXPR. */
290 ubsan_instrument_bounds (location_t loc
, tree array
, tree
*index
,
291 bool ignore_off_by_one
)
293 tree type
= TREE_TYPE (array
);
294 tree domain
= TYPE_DOMAIN (type
);
296 if (domain
== NULL_TREE
|| TYPE_MAX_VALUE (domain
) == NULL_TREE
)
299 tree bound
= TYPE_MAX_VALUE (domain
);
300 if (ignore_off_by_one
)
301 bound
= fold_build2 (PLUS_EXPR
, TREE_TYPE (bound
), bound
,
302 build_int_cst (TREE_TYPE (bound
), 1));
304 /* Detect flexible array members and suchlike, unless
305 -fsanitize=bounds-strict. */
306 tree base
= get_base_address (array
);
307 if ((flag_sanitize
& SANITIZE_BOUNDS_STRICT
) == 0
308 && TREE_CODE (array
) == COMPONENT_REF
309 && base
&& (TREE_CODE (base
) == INDIRECT_REF
310 || TREE_CODE (base
) == MEM_REF
))
312 tree next
= NULL_TREE
;
315 /* Walk all structs/unions. */
316 while (TREE_CODE (cref
) == COMPONENT_REF
)
318 if (TREE_CODE (TREE_TYPE (TREE_OPERAND (cref
, 0))) == RECORD_TYPE
)
319 for (next
= DECL_CHAIN (TREE_OPERAND (cref
, 1));
320 next
&& TREE_CODE (next
) != FIELD_DECL
;
321 next
= DECL_CHAIN (next
))
324 /* Not a last element. Instrument it. */
326 /* Ok, this is the last field of the structure/union. But the
327 aggregate containing the field must be the last field too,
329 cref
= TREE_OPERAND (cref
, 0);
332 /* Don't instrument this flexible array member-like array in non-strict
333 -fsanitize=bounds mode. */
337 /* Don't emit instrumentation in the most common cases. */
338 tree idx
= NULL_TREE
;
339 if (TREE_CODE (*index
) == INTEGER_CST
)
341 else if (TREE_CODE (*index
) == BIT_AND_EXPR
342 && TREE_CODE (TREE_OPERAND (*index
, 1)) == INTEGER_CST
)
343 idx
= TREE_OPERAND (*index
, 1);
345 && TREE_CODE (bound
) == INTEGER_CST
346 && tree_int_cst_sgn (idx
) >= 0
347 && tree_int_cst_le (idx
, bound
))
350 *index
= save_expr (*index
);
351 /* Create a "(T *) 0" tree node to describe the array type. */
352 tree zero_with_type
= build_int_cst (build_pointer_type (type
), 0);
353 return build_call_expr_internal_loc (loc
, IFN_UBSAN_BOUNDS
,
354 void_type_node
, 3, zero_with_type
,
358 /* Return true iff T is an array that was instrumented by SANITIZE_BOUNDS. */
361 ubsan_array_ref_instrumented_p (const_tree t
)
363 if (TREE_CODE (t
) != ARRAY_REF
)
366 tree op1
= TREE_OPERAND (t
, 1);
367 return TREE_CODE (op1
) == COMPOUND_EXPR
368 && TREE_CODE (TREE_OPERAND (op1
, 0)) == CALL_EXPR
369 && CALL_EXPR_FN (TREE_OPERAND (op1
, 0)) == NULL_TREE
370 && CALL_EXPR_IFN (TREE_OPERAND (op1
, 0)) == IFN_UBSAN_BOUNDS
;
373 /* Instrument an ARRAY_REF, if it hasn't already been instrumented.
374 IGNORE_OFF_BY_ONE is true if the ARRAY_REF is inside a ADDR_EXPR. */
377 ubsan_maybe_instrument_array_ref (tree
*expr_p
, bool ignore_off_by_one
)
379 if (!ubsan_array_ref_instrumented_p (*expr_p
)
380 && do_ubsan_in_current_function ())
382 tree op0
= TREE_OPERAND (*expr_p
, 0);
383 tree op1
= TREE_OPERAND (*expr_p
, 1);
384 tree e
= ubsan_instrument_bounds (EXPR_LOCATION (*expr_p
), op0
, &op1
,
388 tree t
= copy_node (*expr_p
);
389 TREE_OPERAND (t
, 1) = build2 (COMPOUND_EXPR
, TREE_TYPE (op1
),
397 ubsan_maybe_instrument_reference_or_call (location_t loc
, tree op
, tree ptype
,
398 enum ubsan_null_ckind ckind
)
400 if (!do_ubsan_in_current_function ())
403 tree type
= TREE_TYPE (ptype
);
405 bool instrument
= false;
406 unsigned int mina
= 0;
408 if (flag_sanitize
& SANITIZE_ALIGNMENT
)
410 mina
= min_align_of_type (type
);
414 while ((TREE_CODE (op
) == NOP_EXPR
415 || TREE_CODE (op
) == NON_LVALUE_EXPR
)
416 && TREE_CODE (TREE_TYPE (op
)) == POINTER_TYPE
)
417 op
= TREE_OPERAND (op
, 0);
418 if (TREE_CODE (op
) == NOP_EXPR
419 && TREE_CODE (TREE_TYPE (op
)) == REFERENCE_TYPE
)
421 if (mina
&& mina
> min_align_of_type (TREE_TYPE (TREE_TYPE (op
))))
426 if ((flag_sanitize
& SANITIZE_NULL
) && TREE_CODE (op
) == ADDR_EXPR
)
428 bool strict_overflow_p
= false;
429 /* tree_single_nonzero_warnv_p will not return true for non-weak
430 non-automatic decls with -fno-delete-null-pointer-checks,
431 which is disabled during -fsanitize=null. We don't want to
432 instrument those, just weak vars though. */
433 int save_flag_delete_null_pointer_checks
434 = flag_delete_null_pointer_checks
;
435 flag_delete_null_pointer_checks
= 1;
436 if (!tree_single_nonzero_warnv_p (op
, &strict_overflow_p
)
437 || strict_overflow_p
)
439 flag_delete_null_pointer_checks
440 = save_flag_delete_null_pointer_checks
;
442 else if (flag_sanitize
& SANITIZE_NULL
)
444 if (mina
&& mina
> 1)
446 if (!POINTER_TYPE_P (TREE_TYPE (op
))
447 || mina
> get_pointer_alignment (op
) / BITS_PER_UNIT
)
453 op
= save_expr (orig_op
);
454 gcc_assert (POINTER_TYPE_P (ptype
));
455 if (TREE_CODE (ptype
) == REFERENCE_TYPE
)
456 ptype
= build_pointer_type (TREE_TYPE (ptype
));
457 tree kind
= build_int_cst (ptype
, ckind
);
458 tree align
= build_int_cst (pointer_sized_int_node
, mina
);
460 = build_call_expr_internal_loc (loc
, IFN_UBSAN_NULL
, void_type_node
,
462 TREE_SIDE_EFFECTS (call
) = 1;
463 return fold_build2 (COMPOUND_EXPR
, TREE_TYPE (op
), call
, op
);
466 /* Instrument a NOP_EXPR to REFERENCE_TYPE if needed. */
469 ubsan_maybe_instrument_reference (tree stmt
)
471 tree op
= TREE_OPERAND (stmt
, 0);
472 op
= ubsan_maybe_instrument_reference_or_call (EXPR_LOCATION (stmt
), op
,
476 TREE_OPERAND (stmt
, 0) = op
;
479 /* Instrument a CALL_EXPR to a method if needed. */
482 ubsan_maybe_instrument_member_call (tree stmt
, bool is_ctor
)
484 if (call_expr_nargs (stmt
) == 0)
486 tree op
= CALL_EXPR_ARG (stmt
, 0);
487 if (op
== error_mark_node
488 || !POINTER_TYPE_P (TREE_TYPE (op
)))
490 op
= ubsan_maybe_instrument_reference_or_call (EXPR_LOCATION (stmt
), op
,
492 is_ctor
? UBSAN_CTOR_CALL
493 : UBSAN_MEMBER_CALL
);
495 CALL_EXPR_ARG (stmt
, 0) = op
;