You've already forked linux-packaging-mono
							
							
		
			
	
	
		
			148 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			148 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
|   | //===-- ubsan_handlers_cxx.cc ---------------------------------------------===//
 | ||
|  | //
 | ||
|  | //                     The LLVM Compiler Infrastructure
 | ||
|  | //
 | ||
|  | // This file is distributed under the University of Illinois Open Source
 | ||
|  | // License. See LICENSE.TXT for details.
 | ||
|  | //
 | ||
|  | //===----------------------------------------------------------------------===//
 | ||
|  | //
 | ||
|  | // Error logging entry points for the UBSan runtime, which are only used for C++
 | ||
|  | // compilations. This file is permitted to use language features which require
 | ||
|  | // linking against a C++ ABI library.
 | ||
|  | //
 | ||
|  | //===----------------------------------------------------------------------===//
 | ||
|  | 
 | ||
|  | #include "ubsan_platform.h"
 | ||
|  | #if CAN_SANITIZE_UB
 | ||
|  | #include "ubsan_handlers.h"
 | ||
|  | #include "ubsan_handlers_cxx.h"
 | ||
|  | #include "ubsan_diag.h"
 | ||
|  | #include "ubsan_type_hash.h"
 | ||
|  | 
 | ||
|  | #include "sanitizer_common/sanitizer_common.h"
 | ||
|  | #include "sanitizer_common/sanitizer_suppressions.h"
 | ||
|  | 
 | ||
|  | using namespace __sanitizer; | ||
|  | using namespace __ubsan; | ||
|  | 
 | ||
|  | namespace __ubsan { | ||
|  |   extern const char *TypeCheckKinds[]; | ||
|  | } | ||
|  | 
 | ||
|  | // Returns true if UBSan has printed an error report.
 | ||
|  | static bool HandleDynamicTypeCacheMiss( | ||
|  |     DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash, | ||
|  |     ReportOptions Opts) { | ||
|  |   if (checkDynamicType((void*)Pointer, Data->TypeInfo, Hash)) | ||
|  |     // Just a cache miss. The type matches after all.
 | ||
|  |     return false; | ||
|  | 
 | ||
|  |   // Check if error report should be suppressed.
 | ||
|  |   DynamicTypeInfo DTI = getDynamicTypeInfoFromObject((void*)Pointer); | ||
|  |   if (DTI.isValid() && IsVptrCheckSuppressed(DTI.getMostDerivedTypeName())) | ||
|  |     return false; | ||
|  | 
 | ||
|  |   SourceLocation Loc = Data->Loc.acquire(); | ||
|  |   ErrorType ET = ErrorType::DynamicTypeMismatch; | ||
|  |   if (ignoreReport(Loc, Opts, ET)) | ||
|  |     return false; | ||
|  | 
 | ||
|  |   ScopedReport R(Opts, Loc, ET); | ||
|  | 
 | ||
|  |   Diag(Loc, DL_Error, | ||
|  |        "%0 address %1 which does not point to an object of type %2") | ||
|  |     << TypeCheckKinds[Data->TypeCheckKind] << (void*)Pointer << Data->Type; | ||
|  | 
 | ||
|  |   // If possible, say what type it actually points to.
 | ||
|  |   if (!DTI.isValid()) { | ||
|  |     if (DTI.getOffset() < -VptrMaxOffsetToTop || DTI.getOffset() > VptrMaxOffsetToTop) { | ||
|  |       Diag(Pointer, DL_Note, "object has a possibly invalid vptr: abs(offset to top) too big") | ||
|  |           << TypeName(DTI.getMostDerivedTypeName()) | ||
|  |           << Range(Pointer, Pointer + sizeof(uptr), "possibly invalid vptr"); | ||
|  |     } else { | ||
|  |       Diag(Pointer, DL_Note, "object has invalid vptr") | ||
|  |           << TypeName(DTI.getMostDerivedTypeName()) | ||
|  |           << Range(Pointer, Pointer + sizeof(uptr), "invalid vptr"); | ||
|  |     } | ||
|  |   } else if (!DTI.getOffset()) | ||
|  |     Diag(Pointer, DL_Note, "object is of type %0") | ||
|  |         << TypeName(DTI.getMostDerivedTypeName()) | ||
|  |         << Range(Pointer, Pointer + sizeof(uptr), "vptr for %0"); | ||
|  |   else | ||
|  |     // FIXME: Find the type at the specified offset, and include that
 | ||
|  |     //        in the note.
 | ||
|  |     Diag(Pointer - DTI.getOffset(), DL_Note, | ||
|  |          "object is base class subobject at offset %0 within object of type %1") | ||
|  |         << DTI.getOffset() << TypeName(DTI.getMostDerivedTypeName()) | ||
|  |         << TypeName(DTI.getSubobjectTypeName()) | ||
|  |         << Range(Pointer, Pointer + sizeof(uptr), | ||
|  |                  "vptr for %2 base class of %1"); | ||
|  |   return true; | ||
|  | } | ||
|  | 
 | ||
|  | void __ubsan::__ubsan_handle_dynamic_type_cache_miss( | ||
|  |     DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash) { | ||
|  |   GET_REPORT_OPTIONS(false); | ||
|  |   HandleDynamicTypeCacheMiss(Data, Pointer, Hash, Opts); | ||
|  | } | ||
|  | void __ubsan::__ubsan_handle_dynamic_type_cache_miss_abort( | ||
|  |     DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash) { | ||
|  |   // Note: -fsanitize=vptr is always recoverable.
 | ||
|  |   GET_REPORT_OPTIONS(false); | ||
|  |   if (HandleDynamicTypeCacheMiss(Data, Pointer, Hash, Opts)) | ||
|  |     Die(); | ||
|  | } | ||
|  | 
 | ||
|  | namespace __ubsan { | ||
|  | void __ubsan_handle_cfi_bad_type(CFICheckFailData *Data, ValueHandle Vtable, | ||
|  |                                  bool ValidVtable, ReportOptions Opts) { | ||
|  |   SourceLocation Loc = Data->Loc.acquire(); | ||
|  |   ErrorType ET = ErrorType::CFIBadType; | ||
|  | 
 | ||
|  |   if (ignoreReport(Loc, Opts, ET)) | ||
|  |     return; | ||
|  | 
 | ||
|  |   ScopedReport R(Opts, Loc, ET); | ||
|  |   DynamicTypeInfo DTI = ValidVtable | ||
|  |                             ? getDynamicTypeInfoFromVtable((void *)Vtable) | ||
|  |                             : DynamicTypeInfo(0, 0, 0); | ||
|  | 
 | ||
|  |   const char *CheckKindStr; | ||
|  |   switch (Data->CheckKind) { | ||
|  |   case CFITCK_VCall: | ||
|  |     CheckKindStr = "virtual call"; | ||
|  |     break; | ||
|  |   case CFITCK_NVCall: | ||
|  |     CheckKindStr = "non-virtual call"; | ||
|  |     break; | ||
|  |   case CFITCK_DerivedCast: | ||
|  |     CheckKindStr = "base-to-derived cast"; | ||
|  |     break; | ||
|  |   case CFITCK_UnrelatedCast: | ||
|  |     CheckKindStr = "cast to unrelated type"; | ||
|  |     break; | ||
|  |   case CFITCK_ICall: | ||
|  |     Die(); | ||
|  |   } | ||
|  | 
 | ||
|  |   Diag(Loc, DL_Error, "control flow integrity check for type %0 failed during " | ||
|  |                       "%1 (vtable address %2)") | ||
|  |       << Data->Type << CheckKindStr << (void *)Vtable; | ||
|  | 
 | ||
|  |   // If possible, say what type it actually points to.
 | ||
|  |   if (!DTI.isValid()) { | ||
|  |     const char *module = Symbolizer::GetOrInit()->GetModuleNameForPc(Vtable); | ||
|  |     if (module) | ||
|  |       Diag(Vtable, DL_Note, "invalid vtable in module %0") << module; | ||
|  |     else | ||
|  |       Diag(Vtable, DL_Note, "invalid vtable"); | ||
|  |   } else { | ||
|  |     Diag(Vtable, DL_Note, "vtable is of type %0") | ||
|  |         << TypeName(DTI.getMostDerivedTypeName()); | ||
|  |   } | ||
|  | } | ||
|  | }  // namespace __ubsan
 | ||
|  | 
 | ||
|  | #endif // CAN_SANITIZE_UB
 |