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