ubsan_handlers_cxx.cc revision 303975
119304Speter//===-- ubsan_handlers_cxx.cc ---------------------------------------------===//
219304Speter//
319304Speter//                     The LLVM Compiler Infrastructure
419304Speter//
519304Speter// This file is distributed under the University of Illinois Open Source
619304Speter// License. See LICENSE.TXT for details.
719304Speter//
819304Speter//===----------------------------------------------------------------------===//
919304Speter//
1019304Speter// Error logging entry points for the UBSan runtime, which are only used for C++
1119304Speter// compilations. This file is permitted to use language features which require
1219304Speter// linking against a C++ ABI library.
13254225Speter//
1419304Speter//===----------------------------------------------------------------------===//
1519304Speter
1619304Speter#include "ubsan_platform.h"
1719304Speter#if CAN_SANITIZE_UB
1819304Speter#include "ubsan_handlers_cxx.h"
1919304Speter#include "ubsan_diag.h"
2019304Speter#include "ubsan_type_hash.h"
2119304Speter
2219304Speter#include "sanitizer_common/sanitizer_common.h"
2319304Speter#include "sanitizer_common/sanitizer_suppressions.h"
2419304Speter
2519304Speterusing namespace __sanitizer;
2619304Speterusing namespace __ubsan;
2719304Speter
2819304Speternamespace __ubsan {
2919304Speter  extern const char *TypeCheckKinds[];
3019304Speter}
3119304Speter
3219304Speter// Returns true if UBSan has printed an error report.
3319304Speterstatic bool HandleDynamicTypeCacheMiss(
3419304Speter    DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash,
3519304Speter    ReportOptions Opts) {
3619304Speter  if (checkDynamicType((void*)Pointer, Data->TypeInfo, Hash))
3719304Speter    // Just a cache miss. The type matches after all.
38254225Speter    return false;
3919304Speter
4019304Speter  // Check if error report should be suppressed.
4119304Speter  DynamicTypeInfo DTI = getDynamicTypeInfoFromObject((void*)Pointer);
4219304Speter  if (DTI.isValid() && IsVptrCheckSuppressed(DTI.getMostDerivedTypeName()))
4319304Speter    return false;
4419304Speter
4519304Speter  SourceLocation Loc = Data->Loc.acquire();
4619304Speter  ErrorType ET = ErrorType::DynamicTypeMismatch;
4719304Speter  if (ignoreReport(Loc, Opts, ET))
4819304Speter    return false;
4919304Speter
5019304Speter  ScopedReport R(Opts, Loc, ET);
5119304Speter
5219304Speter  Diag(Loc, DL_Error,
5319304Speter       "%0 address %1 which does not point to an object of type %2")
5419304Speter    << TypeCheckKinds[Data->TypeCheckKind] << (void*)Pointer << Data->Type;
5519304Speter
5619304Speter  // If possible, say what type it actually points to.
5719304Speter  if (!DTI.isValid())
5819304Speter    Diag(Pointer, DL_Note, "object has invalid vptr")
5919304Speter        << TypeName(DTI.getMostDerivedTypeName())
6019304Speter        << Range(Pointer, Pointer + sizeof(uptr), "invalid vptr");
61254225Speter  else if (!DTI.getOffset())
6219304Speter    Diag(Pointer, DL_Note, "object is of type %0")
6319304Speter        << TypeName(DTI.getMostDerivedTypeName())
6419304Speter        << Range(Pointer, Pointer + sizeof(uptr), "vptr for %0");
6519304Speter  else
6619304Speter    // FIXME: Find the type at the specified offset, and include that
6719304Speter    //        in the note.
6819304Speter    Diag(Pointer - DTI.getOffset(), DL_Note,
6919304Speter         "object is base class subobject at offset %0 within object of type %1")
7019304Speter        << DTI.getOffset() << TypeName(DTI.getMostDerivedTypeName())
7119304Speter        << TypeName(DTI.getSubobjectTypeName())
7219304Speter        << Range(Pointer, Pointer + sizeof(uptr),
7319304Speter                 "vptr for %2 base class of %1");
7419304Speter  return true;
7519304Speter}
7619304Speter
7719304Spetervoid __ubsan::__ubsan_handle_dynamic_type_cache_miss(
7819304Speter    DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash) {
7919304Speter  GET_REPORT_OPTIONS(false);
8019304Speter  HandleDynamicTypeCacheMiss(Data, Pointer, Hash, Opts);
8119304Speter}
8219304Spetervoid __ubsan::__ubsan_handle_dynamic_type_cache_miss_abort(
8319304Speter    DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash) {
84254225Speter  // Note: -fsanitize=vptr is always recoverable.
8519304Speter  GET_REPORT_OPTIONS(false);
8619304Speter  if (HandleDynamicTypeCacheMiss(Data, Pointer, Hash, Opts))
8719304Speter    Die();
8819304Speter}
8919304Speter
9019304Speterstatic void HandleCFIBadType(CFIBadTypeData *Data, ValueHandle Vtable,
9119304Speter                             ReportOptions Opts) {
9219304Speter  SourceLocation Loc = Data->Loc.acquire();
9319304Speter  ErrorType ET = ErrorType::CFIBadType;
9419304Speter
9519304Speter  if (ignoreReport(Loc, Opts, ET))
96254225Speter    return;
9719304Speter
9819304Speter  ScopedReport R(Opts, Loc, ET);
9919304Speter  DynamicTypeInfo DTI = getDynamicTypeInfoFromVtable((void*)Vtable);
10019304Speter
10119304Speter  static const char *TypeCheckKinds[] = {
10219304Speter    "virtual call",
10319304Speter    "non-virtual call",
10419304Speter    "base-to-derived cast",
10519304Speter    "cast to unrelated type",
10619304Speter  };
10719304Speter
10819304Speter  Diag(Loc, DL_Error, "control flow integrity check for type %0 failed during "
10919304Speter                      "%1 (vtable address %2)")
11019304Speter      << Data->Type << TypeCheckKinds[Data->TypeCheckKind] << (void *)Vtable;
111254225Speter
11219304Speter  // If possible, say what type it actually points to.
11319304Speter  if (!DTI.isValid())
11419304Speter    Diag(Vtable, DL_Note, "invalid vtable");
11519304Speter  else
11619304Speter    Diag(Vtable, DL_Note, "vtable is of type %0")
11719304Speter        << TypeName(DTI.getMostDerivedTypeName());
11819304Speter}
11919304Speter
120254225Spetervoid __ubsan::__ubsan_handle_cfi_bad_type(CFIBadTypeData *Data,
12119304Speter                                          ValueHandle Vtable) {
12219304Speter  GET_REPORT_OPTIONS(false);
123254225Speter  HandleCFIBadType(Data, Vtable, Opts);
12419304Speter}
12519304Speter
12619304Spetervoid __ubsan::__ubsan_handle_cfi_bad_type_abort(CFIBadTypeData *Data,
12719304Speter                                                ValueHandle Vtable) {
12819304Speter  GET_REPORT_OPTIONS(true);
12919304Speter  HandleCFIBadType(Data, Vtable, Opts);
13019304Speter  Die();
13119304Speter}
13219304Speter
13319304Speter#endif  // CAN_SANITIZE_UB
13419304Speter