asan_errors.h revision 311697
1//===-- asan_errors.h -------------------------------------------*- C++ -*-===// 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// This file is a part of AddressSanitizer, an address sanity checker. 11// 12// ASan-private header for error structures. 13//===----------------------------------------------------------------------===// 14#ifndef ASAN_ERRORS_H 15#define ASAN_ERRORS_H 16 17#include "asan_descriptions.h" 18#include "asan_scariness_score.h" 19#include "sanitizer_common/sanitizer_common.h" 20 21namespace __asan { 22 23struct ErrorBase { 24 ErrorBase() = default; 25 explicit ErrorBase(u32 tid_) : tid(tid_) {} 26 ScarinessScoreBase scariness; 27 u32 tid; 28}; 29 30struct ErrorStackOverflow : ErrorBase { 31 uptr addr, pc, bp, sp; 32 // ErrorStackOverflow never owns the context. 33 void *context; 34 // VS2013 doesn't implement unrestricted unions, so we need a trivial default 35 // constructor 36 ErrorStackOverflow() = default; 37 ErrorStackOverflow(u32 tid, const SignalContext &sig) 38 : ErrorBase(tid), 39 addr(sig.addr), 40 pc(sig.pc), 41 bp(sig.bp), 42 sp(sig.sp), 43 context(sig.context) { 44 scariness.Clear(); 45 scariness.Scare(10, "stack-overflow"); 46 } 47 void Print(); 48}; 49 50struct ErrorDeadlySignal : ErrorBase { 51 uptr addr, pc, bp, sp; 52 // ErrorDeadlySignal never owns the context. 53 void *context; 54 int signo; 55 SignalContext::WriteFlag write_flag; 56 bool is_memory_access; 57 // VS2013 doesn't implement unrestricted unions, so we need a trivial default 58 // constructor 59 ErrorDeadlySignal() = default; 60 ErrorDeadlySignal(u32 tid, const SignalContext &sig, int signo_) 61 : ErrorBase(tid), 62 addr(sig.addr), 63 pc(sig.pc), 64 bp(sig.bp), 65 sp(sig.sp), 66 context(sig.context), 67 signo(signo_), 68 write_flag(sig.write_flag), 69 is_memory_access(sig.is_memory_access) { 70 scariness.Clear(); 71 if (is_memory_access) { 72 if (addr < GetPageSizeCached()) { 73 scariness.Scare(10, "null-deref"); 74 } else if (addr == pc) { 75 scariness.Scare(60, "wild-jump"); 76 } else if (write_flag == SignalContext::WRITE) { 77 scariness.Scare(30, "wild-addr-write"); 78 } else if (write_flag == SignalContext::READ) { 79 scariness.Scare(20, "wild-addr-read"); 80 } else { 81 scariness.Scare(25, "wild-addr"); 82 } 83 } else { 84 scariness.Scare(10, "signal"); 85 } 86 } 87 void Print(); 88}; 89 90struct ErrorDoubleFree : ErrorBase { 91 // ErrorDoubleFree doesn't own the stack trace. 92 const BufferedStackTrace *second_free_stack; 93 HeapAddressDescription addr_description; 94 // VS2013 doesn't implement unrestricted unions, so we need a trivial default 95 // constructor 96 ErrorDoubleFree() = default; 97 ErrorDoubleFree(u32 tid, BufferedStackTrace *stack, uptr addr) 98 : ErrorBase(tid), second_free_stack(stack) { 99 CHECK_GT(second_free_stack->size, 0); 100 GetHeapAddressInformation(addr, 1, &addr_description); 101 scariness.Clear(); 102 scariness.Scare(42, "double-free"); 103 } 104 void Print(); 105}; 106 107struct ErrorNewDeleteSizeMismatch : ErrorBase { 108 // ErrorNewDeleteSizeMismatch doesn't own the stack trace. 109 const BufferedStackTrace *free_stack; 110 HeapAddressDescription addr_description; 111 uptr delete_size; 112 // VS2013 doesn't implement unrestricted unions, so we need a trivial default 113 // constructor 114 ErrorNewDeleteSizeMismatch() = default; 115 ErrorNewDeleteSizeMismatch(u32 tid, BufferedStackTrace *stack, uptr addr, 116 uptr delete_size_) 117 : ErrorBase(tid), free_stack(stack), delete_size(delete_size_) { 118 GetHeapAddressInformation(addr, 1, &addr_description); 119 scariness.Clear(); 120 scariness.Scare(10, "new-delete-type-mismatch"); 121 } 122 void Print(); 123}; 124 125struct ErrorFreeNotMalloced : ErrorBase { 126 // ErrorFreeNotMalloced doesn't own the stack trace. 127 const BufferedStackTrace *free_stack; 128 AddressDescription addr_description; 129 // VS2013 doesn't implement unrestricted unions, so we need a trivial default 130 // constructor 131 ErrorFreeNotMalloced() = default; 132 ErrorFreeNotMalloced(u32 tid, BufferedStackTrace *stack, uptr addr) 133 : ErrorBase(tid), 134 free_stack(stack), 135 addr_description(addr, /*shouldLockThreadRegistry=*/false) { 136 scariness.Clear(); 137 scariness.Scare(40, "bad-free"); 138 } 139 void Print(); 140}; 141 142struct ErrorAllocTypeMismatch : ErrorBase { 143 // ErrorAllocTypeMismatch doesn't own the stack trace. 144 const BufferedStackTrace *dealloc_stack; 145 HeapAddressDescription addr_description; 146 AllocType alloc_type, dealloc_type; 147 // VS2013 doesn't implement unrestricted unions, so we need a trivial default 148 // constructor 149 ErrorAllocTypeMismatch() = default; 150 ErrorAllocTypeMismatch(u32 tid, BufferedStackTrace *stack, uptr addr, 151 AllocType alloc_type_, AllocType dealloc_type_) 152 : ErrorBase(tid), 153 dealloc_stack(stack), 154 alloc_type(alloc_type_), 155 dealloc_type(dealloc_type_) { 156 GetHeapAddressInformation(addr, 1, &addr_description); 157 scariness.Clear(); 158 scariness.Scare(10, "alloc-dealloc-mismatch"); 159 }; 160 void Print(); 161}; 162 163struct ErrorMallocUsableSizeNotOwned : ErrorBase { 164 // ErrorMallocUsableSizeNotOwned doesn't own the stack trace. 165 const BufferedStackTrace *stack; 166 AddressDescription addr_description; 167 // VS2013 doesn't implement unrestricted unions, so we need a trivial default 168 // constructor 169 ErrorMallocUsableSizeNotOwned() = default; 170 ErrorMallocUsableSizeNotOwned(u32 tid, BufferedStackTrace *stack_, uptr addr) 171 : ErrorBase(tid), 172 stack(stack_), 173 addr_description(addr, /*shouldLockThreadRegistry=*/false) { 174 scariness.Clear(); 175 scariness.Scare(10, "bad-malloc_usable_size"); 176 } 177 void Print(); 178}; 179 180struct ErrorSanitizerGetAllocatedSizeNotOwned : ErrorBase { 181 // ErrorSanitizerGetAllocatedSizeNotOwned doesn't own the stack trace. 182 const BufferedStackTrace *stack; 183 AddressDescription addr_description; 184 // VS2013 doesn't implement unrestricted unions, so we need a trivial default 185 // constructor 186 ErrorSanitizerGetAllocatedSizeNotOwned() = default; 187 ErrorSanitizerGetAllocatedSizeNotOwned(u32 tid, BufferedStackTrace *stack_, 188 uptr addr) 189 : ErrorBase(tid), 190 stack(stack_), 191 addr_description(addr, /*shouldLockThreadRegistry=*/false) { 192 scariness.Clear(); 193 scariness.Scare(10, "bad-__sanitizer_get_allocated_size"); 194 } 195 void Print(); 196}; 197 198struct ErrorStringFunctionMemoryRangesOverlap : ErrorBase { 199 // ErrorStringFunctionMemoryRangesOverlap doesn't own the stack trace. 200 const BufferedStackTrace *stack; 201 uptr length1, length2; 202 AddressDescription addr1_description; 203 AddressDescription addr2_description; 204 const char *function; 205 // VS2013 doesn't implement unrestricted unions, so we need a trivial default 206 // constructor 207 ErrorStringFunctionMemoryRangesOverlap() = default; 208 ErrorStringFunctionMemoryRangesOverlap(u32 tid, BufferedStackTrace *stack_, 209 uptr addr1, uptr length1_, uptr addr2, 210 uptr length2_, const char *function_) 211 : ErrorBase(tid), 212 stack(stack_), 213 length1(length1_), 214 length2(length2_), 215 addr1_description(addr1, length1, /*shouldLockThreadRegistry=*/false), 216 addr2_description(addr2, length2, /*shouldLockThreadRegistry=*/false), 217 function(function_) { 218 char bug_type[100]; 219 internal_snprintf(bug_type, sizeof(bug_type), "%s-param-overlap", function); 220 scariness.Clear(); 221 scariness.Scare(10, bug_type); 222 } 223 void Print(); 224}; 225 226struct ErrorStringFunctionSizeOverflow : ErrorBase { 227 // ErrorStringFunctionSizeOverflow doesn't own the stack trace. 228 const BufferedStackTrace *stack; 229 AddressDescription addr_description; 230 uptr size; 231 // VS2013 doesn't implement unrestricted unions, so we need a trivial default 232 // constructor 233 ErrorStringFunctionSizeOverflow() = default; 234 ErrorStringFunctionSizeOverflow(u32 tid, BufferedStackTrace *stack_, 235 uptr addr, uptr size_) 236 : ErrorBase(tid), 237 stack(stack_), 238 addr_description(addr, /*shouldLockThreadRegistry=*/false), 239 size(size_) { 240 scariness.Clear(); 241 scariness.Scare(10, "negative-size-param"); 242 } 243 void Print(); 244}; 245 246struct ErrorBadParamsToAnnotateContiguousContainer : ErrorBase { 247 // ErrorBadParamsToAnnotateContiguousContainer doesn't own the stack trace. 248 const BufferedStackTrace *stack; 249 uptr beg, end, old_mid, new_mid; 250 // VS2013 doesn't implement unrestricted unions, so we need a trivial default 251 // constructor 252 ErrorBadParamsToAnnotateContiguousContainer() = default; 253 // PS4: Do we want an AddressDescription for beg? 254 ErrorBadParamsToAnnotateContiguousContainer(u32 tid, 255 BufferedStackTrace *stack_, 256 uptr beg_, uptr end_, 257 uptr old_mid_, uptr new_mid_) 258 : ErrorBase(tid), 259 stack(stack_), 260 beg(beg_), 261 end(end_), 262 old_mid(old_mid_), 263 new_mid(new_mid_) { 264 scariness.Clear(); 265 scariness.Scare(10, "bad-__sanitizer_annotate_contiguous_container"); 266 } 267 void Print(); 268}; 269 270struct ErrorODRViolation : ErrorBase { 271 __asan_global global1, global2; 272 u32 stack_id1, stack_id2; 273 // VS2013 doesn't implement unrestricted unions, so we need a trivial default 274 // constructor 275 ErrorODRViolation() = default; 276 ErrorODRViolation(u32 tid, const __asan_global *g1, u32 stack_id1_, 277 const __asan_global *g2, u32 stack_id2_) 278 : ErrorBase(tid), 279 global1(*g1), 280 global2(*g2), 281 stack_id1(stack_id1_), 282 stack_id2(stack_id2_) { 283 scariness.Clear(); 284 scariness.Scare(10, "odr-violation"); 285 } 286 void Print(); 287}; 288 289struct ErrorInvalidPointerPair : ErrorBase { 290 uptr pc, bp, sp; 291 AddressDescription addr1_description; 292 AddressDescription addr2_description; 293 // VS2013 doesn't implement unrestricted unions, so we need a trivial default 294 // constructor 295 ErrorInvalidPointerPair() = default; 296 ErrorInvalidPointerPair(u32 tid, uptr pc_, uptr bp_, uptr sp_, uptr p1, 297 uptr p2) 298 : ErrorBase(tid), 299 pc(pc_), 300 bp(bp_), 301 sp(sp_), 302 addr1_description(p1, 1, /*shouldLockThreadRegistry=*/false), 303 addr2_description(p2, 1, /*shouldLockThreadRegistry=*/false) { 304 scariness.Clear(); 305 scariness.Scare(10, "invalid-pointer-pair"); 306 } 307 void Print(); 308}; 309 310struct ErrorGeneric : ErrorBase { 311 AddressDescription addr_description; 312 uptr pc, bp, sp; 313 uptr access_size; 314 const char *bug_descr; 315 bool is_write; 316 u8 shadow_val; 317 // VS2013 doesn't implement unrestricted unions, so we need a trivial default 318 // constructor 319 ErrorGeneric() = default; 320 ErrorGeneric(u32 tid, uptr addr, uptr pc_, uptr bp_, uptr sp_, bool is_write_, 321 uptr access_size_); 322 void Print(); 323}; 324 325// clang-format off 326#define ASAN_FOR_EACH_ERROR_KIND(macro) \ 327 macro(StackOverflow) \ 328 macro(DeadlySignal) \ 329 macro(DoubleFree) \ 330 macro(NewDeleteSizeMismatch) \ 331 macro(FreeNotMalloced) \ 332 macro(AllocTypeMismatch) \ 333 macro(MallocUsableSizeNotOwned) \ 334 macro(SanitizerGetAllocatedSizeNotOwned) \ 335 macro(StringFunctionMemoryRangesOverlap) \ 336 macro(StringFunctionSizeOverflow) \ 337 macro(BadParamsToAnnotateContiguousContainer) \ 338 macro(ODRViolation) \ 339 macro(InvalidPointerPair) \ 340 macro(Generic) 341// clang-format on 342 343#define ASAN_DEFINE_ERROR_KIND(name) kErrorKind##name, 344#define ASAN_ERROR_DESCRIPTION_MEMBER(name) Error##name name; 345#define ASAN_ERROR_DESCRIPTION_CONSTRUCTOR(name) \ 346 ErrorDescription(Error##name const &e) : kind(kErrorKind##name), name(e) {} 347#define ASAN_ERROR_DESCRIPTION_PRINT(name) \ 348 case kErrorKind##name: \ 349 return name.Print(); 350 351enum ErrorKind { 352 kErrorKindInvalid = 0, 353 ASAN_FOR_EACH_ERROR_KIND(ASAN_DEFINE_ERROR_KIND) 354}; 355 356struct ErrorDescription { 357 ErrorKind kind; 358 // We're using a tagged union because it allows us to have a trivially 359 // copiable type and use the same structures as the public interface. 360 // 361 // We can add a wrapper around it to make it "more c++-like", but that would 362 // add a lot of code and the benefit wouldn't be that big. 363 union { 364 ErrorBase Base; 365 ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_MEMBER) 366 }; 367 368 ErrorDescription() { internal_memset(this, 0, sizeof(*this)); } 369 ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_CONSTRUCTOR) 370 371 bool IsValid() { return kind != kErrorKindInvalid; } 372 void Print() { 373 switch (kind) { 374 ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_PRINT) 375 case kErrorKindInvalid: 376 CHECK(0); 377 } 378 CHECK(0); 379 } 380}; 381 382#undef ASAN_FOR_EACH_ERROR_KIND 383#undef ASAN_DEFINE_ERROR_KIND 384#undef ASAN_ERROR_DESCRIPTION_MEMBER 385#undef ASAN_ERROR_DESCRIPTION_CONSTRUCTOR 386#undef ASAN_ERROR_DESCRIPTION_PRINT 387 388} // namespace __asan 389 390#endif // ASAN_ERRORS_H 391