1//===-- ubsan_handlers.cc -------------------------------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Error logging entry points for the UBSan runtime.
11//
12//===----------------------------------------------------------------------===//
13
14#include "ubsan_handlers.h"
15#include "ubsan_diag.h"
16
17#include "sanitizer_common/sanitizer_common.h"
18
19using namespace __sanitizer;
20using namespace __ubsan;
21
22namespace __ubsan {
23  const char *TypeCheckKinds[] = {
24    "load of", "store to", "reference binding to", "member access within",
25    "member call on", "constructor call on", "downcast of", "downcast of"
26  };
27}
28
29static void handleTypeMismatchImpl(TypeMismatchData *Data, ValueHandle Pointer,
30                                   Location FallbackLoc) {
31  Location Loc = Data->Loc.acquire();
32
33  // Use the SourceLocation from Data to track deduplication, even if 'invalid'
34  if (Loc.getSourceLocation().isDisabled())
35    return;
36  if (Data->Loc.isInvalid())
37    Loc = FallbackLoc;
38
39  if (!Pointer)
40    Diag(Loc, DL_Error, "%0 null pointer of type %1")
41      << TypeCheckKinds[Data->TypeCheckKind] << Data->Type;
42  else if (Data->Alignment && (Pointer & (Data->Alignment - 1)))
43    Diag(Loc, DL_Error, "%0 misaligned address %1 for type %3, "
44                        "which requires %2 byte alignment")
45      << TypeCheckKinds[Data->TypeCheckKind] << (void*)Pointer
46      << Data->Alignment << Data->Type;
47  else
48    Diag(Loc, DL_Error, "%0 address %1 with insufficient space "
49                        "for an object of type %2")
50      << TypeCheckKinds[Data->TypeCheckKind] << (void*)Pointer << Data->Type;
51  if (Pointer)
52    Diag(Pointer, DL_Note, "pointer points here");
53}
54void __ubsan::__ubsan_handle_type_mismatch(TypeMismatchData *Data,
55                                           ValueHandle Pointer) {
56  handleTypeMismatchImpl(Data, Pointer, getCallerLocation());
57}
58void __ubsan::__ubsan_handle_type_mismatch_abort(TypeMismatchData *Data,
59                                                 ValueHandle Pointer) {
60  handleTypeMismatchImpl(Data, Pointer, getCallerLocation());
61  Die();
62}
63
64/// \brief Common diagnostic emission for various forms of integer overflow.
65template<typename T> static void HandleIntegerOverflow(OverflowData *Data,
66                                                       ValueHandle LHS,
67                                                       const char *Operator,
68                                                       T RHS) {
69  SourceLocation Loc = Data->Loc.acquire();
70  if (Loc.isDisabled())
71    return;
72
73  Diag(Loc, DL_Error, "%0 integer overflow: "
74                      "%1 %2 %3 cannot be represented in type %4")
75    << (Data->Type.isSignedIntegerTy() ? "signed" : "unsigned")
76    << Value(Data->Type, LHS) << Operator << RHS << Data->Type;
77}
78
79void __ubsan::__ubsan_handle_add_overflow(OverflowData *Data,
80                                          ValueHandle LHS, ValueHandle RHS) {
81  HandleIntegerOverflow(Data, LHS, "+", Value(Data->Type, RHS));
82}
83void __ubsan::__ubsan_handle_add_overflow_abort(OverflowData *Data,
84                                                 ValueHandle LHS,
85                                                 ValueHandle RHS) {
86  __ubsan_handle_add_overflow(Data, LHS, RHS);
87  Die();
88}
89
90void __ubsan::__ubsan_handle_sub_overflow(OverflowData *Data,
91                                          ValueHandle LHS, ValueHandle RHS) {
92  HandleIntegerOverflow(Data, LHS, "-", Value(Data->Type, RHS));
93}
94void __ubsan::__ubsan_handle_sub_overflow_abort(OverflowData *Data,
95                                                 ValueHandle LHS,
96                                                 ValueHandle RHS) {
97  __ubsan_handle_sub_overflow(Data, LHS, RHS);
98  Die();
99}
100
101void __ubsan::__ubsan_handle_mul_overflow(OverflowData *Data,
102                                          ValueHandle LHS, ValueHandle RHS) {
103  HandleIntegerOverflow(Data, LHS, "*", Value(Data->Type, RHS));
104}
105void __ubsan::__ubsan_handle_mul_overflow_abort(OverflowData *Data,
106                                                 ValueHandle LHS,
107                                                 ValueHandle RHS) {
108  __ubsan_handle_mul_overflow(Data, LHS, RHS);
109  Die();
110}
111
112void __ubsan::__ubsan_handle_negate_overflow(OverflowData *Data,
113                                             ValueHandle OldVal) {
114  SourceLocation Loc = Data->Loc.acquire();
115  if (Loc.isDisabled())
116    return;
117
118  if (Data->Type.isSignedIntegerTy())
119    Diag(Loc, DL_Error,
120         "negation of %0 cannot be represented in type %1; "
121         "cast to an unsigned type to negate this value to itself")
122      << Value(Data->Type, OldVal) << Data->Type;
123  else
124    Diag(Loc, DL_Error,
125         "negation of %0 cannot be represented in type %1")
126      << Value(Data->Type, OldVal) << Data->Type;
127}
128void __ubsan::__ubsan_handle_negate_overflow_abort(OverflowData *Data,
129                                                    ValueHandle OldVal) {
130  __ubsan_handle_negate_overflow(Data, OldVal);
131  Die();
132}
133
134void __ubsan::__ubsan_handle_divrem_overflow(OverflowData *Data,
135                                             ValueHandle LHS, ValueHandle RHS) {
136  SourceLocation Loc = Data->Loc.acquire();
137  if (Loc.isDisabled())
138    return;
139
140  Value LHSVal(Data->Type, LHS);
141  Value RHSVal(Data->Type, RHS);
142  if (RHSVal.isMinusOne())
143    Diag(Loc, DL_Error,
144         "division of %0 by -1 cannot be represented in type %1")
145      << LHSVal << Data->Type;
146  else
147    Diag(Loc, DL_Error, "division by zero");
148}
149void __ubsan::__ubsan_handle_divrem_overflow_abort(OverflowData *Data,
150                                                    ValueHandle LHS,
151                                                    ValueHandle RHS) {
152  __ubsan_handle_divrem_overflow(Data, LHS, RHS);
153  Die();
154}
155
156void __ubsan::__ubsan_handle_shift_out_of_bounds(ShiftOutOfBoundsData *Data,
157                                                 ValueHandle LHS,
158                                                 ValueHandle RHS) {
159  SourceLocation Loc = Data->Loc.acquire();
160  if (Loc.isDisabled())
161    return;
162
163  Value LHSVal(Data->LHSType, LHS);
164  Value RHSVal(Data->RHSType, RHS);
165  if (RHSVal.isNegative())
166    Diag(Loc, DL_Error, "shift exponent %0 is negative") << RHSVal;
167  else if (RHSVal.getPositiveIntValue() >= Data->LHSType.getIntegerBitWidth())
168    Diag(Loc, DL_Error,
169         "shift exponent %0 is too large for %1-bit type %2")
170      << RHSVal << Data->LHSType.getIntegerBitWidth() << Data->LHSType;
171  else if (LHSVal.isNegative())
172    Diag(Loc, DL_Error, "left shift of negative value %0") << LHSVal;
173  else
174    Diag(Loc, DL_Error,
175         "left shift of %0 by %1 places cannot be represented in type %2")
176      << LHSVal << RHSVal << Data->LHSType;
177}
178void __ubsan::__ubsan_handle_shift_out_of_bounds_abort(
179                                                     ShiftOutOfBoundsData *Data,
180                                                     ValueHandle LHS,
181                                                     ValueHandle RHS) {
182  __ubsan_handle_shift_out_of_bounds(Data, LHS, RHS);
183  Die();
184}
185
186void __ubsan::__ubsan_handle_out_of_bounds(OutOfBoundsData *Data,
187                                           ValueHandle Index) {
188  SourceLocation Loc = Data->Loc.acquire();
189  if (Loc.isDisabled())
190    return;
191
192  Value IndexVal(Data->IndexType, Index);
193  Diag(Loc, DL_Error, "index %0 out of bounds for type %1")
194    << IndexVal << Data->ArrayType;
195}
196void __ubsan::__ubsan_handle_out_of_bounds_abort(OutOfBoundsData *Data,
197                                                 ValueHandle Index) {
198  __ubsan_handle_out_of_bounds(Data, Index);
199  Die();
200}
201
202void __ubsan::__ubsan_handle_builtin_unreachable(UnreachableData *Data) {
203  Diag(Data->Loc, DL_Error, "execution reached a __builtin_unreachable() call");
204  Die();
205}
206
207void __ubsan::__ubsan_handle_missing_return(UnreachableData *Data) {
208  Diag(Data->Loc, DL_Error,
209       "execution reached the end of a value-returning function "
210       "without returning a value");
211  Die();
212}
213
214void __ubsan::__ubsan_handle_vla_bound_not_positive(VLABoundData *Data,
215                                                    ValueHandle Bound) {
216  SourceLocation Loc = Data->Loc.acquire();
217  if (Loc.isDisabled())
218    return;
219
220  Diag(Loc, DL_Error, "variable length array bound evaluates to "
221                      "non-positive value %0")
222    << Value(Data->Type, Bound);
223}
224void __ubsan::__ubsan_handle_vla_bound_not_positive_abort(VLABoundData *Data,
225                                                           ValueHandle Bound) {
226  __ubsan_handle_vla_bound_not_positive(Data, Bound);
227  Die();
228}
229
230
231void __ubsan::__ubsan_handle_float_cast_overflow(FloatCastOverflowData *Data,
232                                                 ValueHandle From) {
233  // TODO: Add deduplication once a SourceLocation is generated for this check.
234  Diag(getCallerLocation(), DL_Error,
235       "value %0 is outside the range of representable values of type %2")
236    << Value(Data->FromType, From) << Data->FromType << Data->ToType;
237}
238void __ubsan::__ubsan_handle_float_cast_overflow_abort(
239                                                    FloatCastOverflowData *Data,
240                                                    ValueHandle From) {
241  Diag(getCallerLocation(), DL_Error,
242       "value %0 is outside the range of representable values of type %2")
243    << Value(Data->FromType, From) << Data->FromType << Data->ToType;
244  Die();
245}
246
247void __ubsan::__ubsan_handle_load_invalid_value(InvalidValueData *Data,
248                                                ValueHandle Val) {
249  SourceLocation Loc = Data->Loc.acquire();
250  if (Loc.isDisabled())
251    return;
252
253  Diag(Loc, DL_Error,
254       "load of value %0, which is not a valid value for type %1")
255    << Value(Data->Type, Val) << Data->Type;
256}
257void __ubsan::__ubsan_handle_load_invalid_value_abort(InvalidValueData *Data,
258                                                      ValueHandle Val) {
259  __ubsan_handle_load_invalid_value(Data, Val);
260  Die();
261}
262
263void __ubsan::__ubsan_handle_function_type_mismatch(
264    FunctionTypeMismatchData *Data,
265    ValueHandle Function) {
266  const char *FName = "(unknown)";
267
268  Location Loc = getFunctionLocation(Function, &FName);
269
270  Diag(Data->Loc, DL_Error,
271       "call to function %0 through pointer to incorrect function type %1")
272    << FName << Data->Type;
273  Diag(Loc, DL_Note, "%0 defined here") << FName;
274}
275
276void __ubsan::__ubsan_handle_function_type_mismatch_abort(
277    FunctionTypeMismatchData *Data,
278    ValueHandle Function) {
279  __ubsan_handle_function_type_mismatch(Data, Function);
280  Die();
281}
282