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