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