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