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 }
507