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