/ lib / ubsan / ubsan_handlers_cxx.cc
ubsan_handlers_cxx.cc
  1  //===-- ubsan_handlers_cxx.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, which are only used for C++
 11  // compilations. This file is permitted to use language features which require
 12  // linking against a C++ ABI library.
 13  //
 14  //===----------------------------------------------------------------------===//
 15  
 16  #include "ubsan_platform.h"
 17  #if CAN_SANITIZE_UB
 18  #include "ubsan_handlers_cxx.h"
 19  #include "ubsan_diag.h"
 20  #include "ubsan_type_hash.h"
 21  
 22  #include "sanitizer_common/sanitizer_common.h"
 23  #include "sanitizer_common/sanitizer_suppressions.h"
 24  
 25  using namespace __sanitizer;
 26  using namespace __ubsan;
 27  
 28  namespace __ubsan {
 29    extern const char *TypeCheckKinds[];
 30  }
 31  
 32  static void HandleDynamicTypeCacheMiss(
 33      DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash,
 34      ReportOptions Opts) {
 35    if (checkDynamicType((void*)Pointer, Data->TypeInfo, Hash))
 36      // Just a cache miss. The type matches after all.
 37      return;
 38  
 39    // Check if error report should be suppressed.
 40    DynamicTypeInfo DTI = getDynamicTypeInfoFromObject((void*)Pointer);
 41    if (DTI.isValid() && IsVptrCheckSuppressed(DTI.getMostDerivedTypeName()))
 42      return;
 43  
 44    SourceLocation Loc = Data->Loc.acquire();
 45    if (Loc.isDisabled())
 46      return;
 47  
 48    ScopedReport R(Opts, Loc, ErrorType::DynamicTypeMismatch);
 49  
 50    Diag(Loc, DL_Error,
 51         "%0 address %1 which does not point to an object of type %2")
 52      << TypeCheckKinds[Data->TypeCheckKind] << (void*)Pointer << Data->Type;
 53  
 54    // If possible, say what type it actually points to.
 55    if (!DTI.isValid())
 56      Diag(Pointer, DL_Note, "object has invalid vptr")
 57          << TypeName(DTI.getMostDerivedTypeName())
 58          << Range(Pointer, Pointer + sizeof(uptr), "invalid vptr");
 59    else if (!DTI.getOffset())
 60      Diag(Pointer, DL_Note, "object is of type %0")
 61          << TypeName(DTI.getMostDerivedTypeName())
 62          << Range(Pointer, Pointer + sizeof(uptr), "vptr for %0");
 63    else
 64      // FIXME: Find the type at the specified offset, and include that
 65      //        in the note.
 66      Diag(Pointer - DTI.getOffset(), DL_Note,
 67           "object is base class subobject at offset %0 within object of type %1")
 68          << DTI.getOffset() << TypeName(DTI.getMostDerivedTypeName())
 69          << TypeName(DTI.getSubobjectTypeName())
 70          << Range(Pointer, Pointer + sizeof(uptr),
 71                   "vptr for %2 base class of %1");
 72  }
 73  
 74  void __ubsan::__ubsan_handle_dynamic_type_cache_miss(
 75      DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash) {
 76    GET_REPORT_OPTIONS(false);
 77    HandleDynamicTypeCacheMiss(Data, Pointer, Hash, Opts);
 78  }
 79  void __ubsan::__ubsan_handle_dynamic_type_cache_miss_abort(
 80      DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash) {
 81    GET_REPORT_OPTIONS(true);
 82    HandleDynamicTypeCacheMiss(Data, Pointer, Hash, Opts);
 83  }
 84  
 85  static void HandleCFIBadType(CFIBadTypeData *Data, ValueHandle Vtable,
 86                               ReportOptions Opts) {
 87    SourceLocation Loc = Data->Loc.acquire();
 88    ScopedReport R(Opts, Loc, ErrorType::CFIBadType);
 89    DynamicTypeInfo DTI = getDynamicTypeInfoFromVtable((void*)Vtable);
 90  
 91    static const char *TypeCheckKinds[] = {
 92      "virtual call",
 93      "non-virtual call",
 94      "base-to-derived cast",
 95      "cast to unrelated type",
 96    };
 97  
 98    Diag(Loc, DL_Error, "control flow integrity check for type %0 failed during "
 99                        "%1 (vtable address %2)")
100        << Data->Type << TypeCheckKinds[Data->TypeCheckKind] << (void *)Vtable;
101  
102    // If possible, say what type it actually points to.
103    if (!DTI.isValid())
104      Diag(Vtable, DL_Note, "invalid vtable");
105    else
106      Diag(Vtable, DL_Note, "vtable is of type %0")
107          << TypeName(DTI.getMostDerivedTypeName());
108  }
109  
110  void __ubsan::__ubsan_handle_cfi_bad_type(CFIBadTypeData *Data,
111                                            ValueHandle Vtable) {
112    GET_REPORT_OPTIONS(false);
113    HandleCFIBadType(Data, Vtable, Opts);
114  }
115  
116  void __ubsan::__ubsan_handle_cfi_bad_type_abort(CFIBadTypeData *Data,
117                                                  ValueHandle Vtable) {
118    GET_REPORT_OPTIONS(true);
119    HandleCFIBadType(Data, Vtable, Opts);
120  }
121  
122  #endif  // CAN_SANITIZE_UB