Path: blob/main/contrib/llvm-project/compiler-rt/lib/ubsan/ubsan_handlers_cxx.cpp
35233 views
//===-- ubsan_handlers_cxx.cpp --------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// Error logging entry points for the UBSan runtime, which are only used for C++9// compilations. This file is permitted to use language features which require10// linking against a C++ ABI library.11//12//===----------------------------------------------------------------------===//1314#include "ubsan_platform.h"15#if CAN_SANITIZE_UB16#include "ubsan_handlers.h"17#include "ubsan_handlers_cxx.h"18#include "ubsan_diag.h"19#include "ubsan_type_hash.h"2021#include "sanitizer_common/sanitizer_common.h"22#include "sanitizer_common/sanitizer_suppressions.h"2324using namespace __sanitizer;25using namespace __ubsan;2627namespace __ubsan {28extern const char *const TypeCheckKinds[];29}3031// Returns true if UBSan has printed an error report.32static bool HandleDynamicTypeCacheMiss(33DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash,34ReportOptions Opts) {35if (checkDynamicType((void*)Pointer, Data->TypeInfo, Hash))36// Just a cache miss. The type matches after all.37return false;3839// Check if error report should be suppressed.40DynamicTypeInfo DTI = getDynamicTypeInfoFromObject((void*)Pointer);41if (DTI.isValid() && IsVptrCheckSuppressed(DTI.getMostDerivedTypeName()))42return false;4344SourceLocation Loc = Data->Loc.acquire();45ErrorType ET = ErrorType::DynamicTypeMismatch;46if (ignoreReport(Loc, Opts, ET))47return false;4849ScopedReport R(Opts, Loc, ET);5051Diag(Loc, DL_Error, ET,52"%0 address %1 which does not point to an object of type %2")53<< TypeCheckKinds[Data->TypeCheckKind] << (void*)Pointer << Data->Type;5455// If possible, say what type it actually points to.56if (!DTI.isValid()) {57if (DTI.getOffset() < -VptrMaxOffsetToTop || DTI.getOffset() > VptrMaxOffsetToTop) {58Diag(Pointer, DL_Note, ET,59"object has a possibly invalid vptr: abs(offset to top) too big")60<< TypeName(DTI.getMostDerivedTypeName())61<< Range(Pointer, Pointer + sizeof(uptr), "possibly invalid vptr");62} else {63Diag(Pointer, DL_Note, ET, "object has invalid vptr")64<< TypeName(DTI.getMostDerivedTypeName())65<< Range(Pointer, Pointer + sizeof(uptr), "invalid vptr");66}67} else if (!DTI.getOffset())68Diag(Pointer, DL_Note, ET, "object is of type %0")69<< TypeName(DTI.getMostDerivedTypeName())70<< Range(Pointer, Pointer + sizeof(uptr), "vptr for %0");71else72// FIXME: Find the type at the specified offset, and include that73// in the note.74Diag(Pointer - DTI.getOffset(), DL_Note, ET,75"object is base class subobject at offset %0 within object of type %1")76<< DTI.getOffset() << TypeName(DTI.getMostDerivedTypeName())77<< TypeName(DTI.getSubobjectTypeName())78<< Range(Pointer, Pointer + sizeof(uptr),79"vptr for %2 base class of %1");80return true;81}8283void __ubsan::__ubsan_handle_dynamic_type_cache_miss(84DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash) {85GET_REPORT_OPTIONS(false);86HandleDynamicTypeCacheMiss(Data, Pointer, Hash, Opts);87}88void __ubsan::__ubsan_handle_dynamic_type_cache_miss_abort(89DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash) {90// Note: -fsanitize=vptr is always recoverable.91GET_REPORT_OPTIONS(false);92if (HandleDynamicTypeCacheMiss(Data, Pointer, Hash, Opts))93Die();94}9596namespace __ubsan {97void __ubsan_handle_cfi_bad_type(CFICheckFailData *Data, ValueHandle Vtable,98bool ValidVtable, ReportOptions Opts) {99SourceLocation Loc = Data->Loc.acquire();100ErrorType ET = ErrorType::CFIBadType;101102if (ignoreReport(Loc, Opts, ET))103return;104105ScopedReport R(Opts, Loc, ET);106DynamicTypeInfo DTI = ValidVtable107? getDynamicTypeInfoFromVtable((void *)Vtable)108: DynamicTypeInfo(0, 0, 0);109110const char *CheckKindStr;111switch (Data->CheckKind) {112case CFITCK_VCall:113CheckKindStr = "virtual call";114break;115case CFITCK_NVCall:116CheckKindStr = "non-virtual call";117break;118case CFITCK_DerivedCast:119CheckKindStr = "base-to-derived cast";120break;121case CFITCK_UnrelatedCast:122CheckKindStr = "cast to unrelated type";123break;124case CFITCK_VMFCall:125CheckKindStr = "virtual pointer to member function call";126break;127case CFITCK_ICall:128case CFITCK_NVMFCall:129Die();130}131132Diag(Loc, DL_Error, ET,133"control flow integrity check for type %0 failed during "134"%1 (vtable address %2)")135<< Data->Type << CheckKindStr << (void *)Vtable;136137// If possible, say what type it actually points to.138if (!DTI.isValid())139Diag(Vtable, DL_Note, ET, "invalid vtable");140else141Diag(Vtable, DL_Note, ET, "vtable is of type %0")142<< TypeName(DTI.getMostDerivedTypeName());143144// If the failure involved different DSOs for the check location and vtable,145// report the DSO names.146const char *DstModule = Symbolizer::GetOrInit()->GetModuleNameForPc(Vtable);147if (!DstModule)148DstModule = "(unknown)";149150const char *SrcModule = Symbolizer::GetOrInit()->GetModuleNameForPc(Opts.pc);151if (!SrcModule)152SrcModule = "(unknown)";153154if (internal_strcmp(SrcModule, DstModule))155Diag(Loc, DL_Note, ET, "check failed in %0, vtable located in %1")156<< SrcModule << DstModule;157}158} // namespace __ubsan159160#endif // CAN_SANITIZE_UB161162163