1 //===-- asan_errors.h -------------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file is a part of AddressSanitizer, an address sanity checker. 10 // 11 // ASan-private header for error structures. 12 //===----------------------------------------------------------------------===// 13 #ifndef ASAN_ERRORS_H 14 #define ASAN_ERRORS_H 15 16 #include "asan_descriptions.h" 17 #include "asan_scariness_score.h" 18 #include "sanitizer_common/sanitizer_common.h" 19 20 namespace __asan { 21 22 // (*) VS2013 does not implement unrestricted unions, so we need a trivial 23 // default constructor explicitly defined for each particular error. 24 25 // None of the error classes own the stack traces mentioned in them. 26 27 struct ErrorBase { 28 ScarinessScoreBase scariness; 29 u32 tid; 30 31 ErrorBase() = default; // (*) 32 explicit ErrorBase(u32 tid_) : tid(tid_) {} 33 ErrorBase(u32 tid_, int initial_score, const char *reason) : tid(tid_) { 34 scariness.Clear(); 35 scariness.Scare(initial_score, reason); 36 } 37 }; 38 39 struct ErrorDeadlySignal : ErrorBase { 40 SignalContext signal; 41 42 ErrorDeadlySignal() = default; // (*) 43 ErrorDeadlySignal(u32 tid, const SignalContext &sig) 44 : ErrorBase(tid), 45 signal(sig) { 46 scariness.Clear(); 47 if (signal.IsStackOverflow()) { 48 scariness.Scare(10, "stack-overflow"); 49 } else if (!signal.is_memory_access) { 50 scariness.Scare(10, "signal"); 51 } else if (signal.is_true_faulting_addr && 52 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 67 struct 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 81 struct 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 99 struct 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 111 struct ErrorAllocTypeMismatch : ErrorBase { 112 const BufferedStackTrace *dealloc_stack; 113 AllocType alloc_type, dealloc_type; 114 AddressDescription addr_description; 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 addr_description(addr, 1, false) {} 124 void Print(); 125 }; 126 127 struct ErrorMallocUsableSizeNotOwned : ErrorBase { 128 const BufferedStackTrace *stack; 129 AddressDescription addr_description; 130 131 ErrorMallocUsableSizeNotOwned() = default; // (*) 132 ErrorMallocUsableSizeNotOwned(u32 tid, BufferedStackTrace *stack_, uptr addr) 133 : ErrorBase(tid, 10, "bad-malloc_usable_size"), 134 stack(stack_), 135 addr_description(addr, /*shouldLockThreadRegistry=*/false) {} 136 void Print(); 137 }; 138 139 struct ErrorSanitizerGetAllocatedSizeNotOwned : ErrorBase { 140 const BufferedStackTrace *stack; 141 AddressDescription addr_description; 142 143 ErrorSanitizerGetAllocatedSizeNotOwned() = default; // (*) 144 ErrorSanitizerGetAllocatedSizeNotOwned(u32 tid, BufferedStackTrace *stack_, 145 uptr addr) 146 : ErrorBase(tid, 10, "bad-__sanitizer_get_allocated_size"), 147 stack(stack_), 148 addr_description(addr, /*shouldLockThreadRegistry=*/false) {} 149 void Print(); 150 }; 151 152 struct ErrorCallocOverflow : ErrorBase { 153 const BufferedStackTrace *stack; 154 uptr count; 155 uptr size; 156 157 ErrorCallocOverflow() = default; // (*) 158 ErrorCallocOverflow(u32 tid, BufferedStackTrace *stack_, uptr count_, 159 uptr size_) 160 : ErrorBase(tid, 10, "calloc-overflow"), 161 stack(stack_), 162 count(count_), 163 size(size_) {} 164 void Print(); 165 }; 166 167 struct ErrorReallocArrayOverflow : ErrorBase { 168 const BufferedStackTrace *stack; 169 uptr count; 170 uptr size; 171 172 ErrorReallocArrayOverflow() = default; // (*) 173 ErrorReallocArrayOverflow(u32 tid, BufferedStackTrace *stack_, uptr count_, 174 uptr size_) 175 : ErrorBase(tid, 10, "reallocarray-overflow"), 176 stack(stack_), 177 count(count_), 178 size(size_) {} 179 void Print(); 180 }; 181 182 struct ErrorPvallocOverflow : ErrorBase { 183 const BufferedStackTrace *stack; 184 uptr size; 185 186 ErrorPvallocOverflow() = default; // (*) 187 ErrorPvallocOverflow(u32 tid, BufferedStackTrace *stack_, uptr size_) 188 : ErrorBase(tid, 10, "pvalloc-overflow"), 189 stack(stack_), 190 size(size_) {} 191 void Print(); 192 }; 193 194 struct ErrorInvalidAllocationAlignment : ErrorBase { 195 const BufferedStackTrace *stack; 196 uptr alignment; 197 198 ErrorInvalidAllocationAlignment() = default; // (*) 199 ErrorInvalidAllocationAlignment(u32 tid, BufferedStackTrace *stack_, 200 uptr alignment_) 201 : ErrorBase(tid, 10, "invalid-allocation-alignment"), 202 stack(stack_), 203 alignment(alignment_) {} 204 void Print(); 205 }; 206 207 struct ErrorInvalidAlignedAllocAlignment : ErrorBase { 208 const BufferedStackTrace *stack; 209 uptr size; 210 uptr alignment; 211 212 ErrorInvalidAlignedAllocAlignment() = default; // (*) 213 ErrorInvalidAlignedAllocAlignment(u32 tid, BufferedStackTrace *stack_, 214 uptr size_, uptr alignment_) 215 : ErrorBase(tid, 10, "invalid-aligned-alloc-alignment"), 216 stack(stack_), 217 size(size_), 218 alignment(alignment_) {} 219 void Print(); 220 }; 221 222 struct ErrorInvalidPosixMemalignAlignment : ErrorBase { 223 const BufferedStackTrace *stack; 224 uptr alignment; 225 226 ErrorInvalidPosixMemalignAlignment() = default; // (*) 227 ErrorInvalidPosixMemalignAlignment(u32 tid, BufferedStackTrace *stack_, 228 uptr alignment_) 229 : ErrorBase(tid, 10, "invalid-posix-memalign-alignment"), 230 stack(stack_), 231 alignment(alignment_) {} 232 void Print(); 233 }; 234 235 struct ErrorAllocationSizeTooBig : ErrorBase { 236 const BufferedStackTrace *stack; 237 uptr user_size; 238 uptr total_size; 239 uptr max_size; 240 241 ErrorAllocationSizeTooBig() = default; // (*) 242 ErrorAllocationSizeTooBig(u32 tid, BufferedStackTrace *stack_, 243 uptr user_size_, uptr total_size_, uptr max_size_) 244 : ErrorBase(tid, 10, "allocation-size-too-big"), 245 stack(stack_), 246 user_size(user_size_), 247 total_size(total_size_), 248 max_size(max_size_) {} 249 void Print(); 250 }; 251 252 struct ErrorRssLimitExceeded : ErrorBase { 253 const BufferedStackTrace *stack; 254 255 ErrorRssLimitExceeded() = default; // (*) 256 ErrorRssLimitExceeded(u32 tid, BufferedStackTrace *stack_) 257 : ErrorBase(tid, 10, "rss-limit-exceeded"), 258 stack(stack_) {} 259 void Print(); 260 }; 261 262 struct ErrorOutOfMemory : ErrorBase { 263 const BufferedStackTrace *stack; 264 uptr requested_size; 265 266 ErrorOutOfMemory() = default; // (*) 267 ErrorOutOfMemory(u32 tid, BufferedStackTrace *stack_, uptr requested_size_) 268 : ErrorBase(tid, 10, "out-of-memory"), 269 stack(stack_), 270 requested_size(requested_size_) {} 271 void Print(); 272 }; 273 274 struct ErrorStringFunctionMemoryRangesOverlap : ErrorBase { 275 const BufferedStackTrace *stack; 276 uptr length1, length2; 277 AddressDescription addr1_description; 278 AddressDescription addr2_description; 279 const char *function; 280 281 ErrorStringFunctionMemoryRangesOverlap() = default; // (*) 282 ErrorStringFunctionMemoryRangesOverlap(u32 tid, BufferedStackTrace *stack_, 283 uptr addr1, uptr length1_, uptr addr2, 284 uptr length2_, const char *function_) 285 : ErrorBase(tid), 286 stack(stack_), 287 length1(length1_), 288 length2(length2_), 289 addr1_description(addr1, length1, /*shouldLockThreadRegistry=*/false), 290 addr2_description(addr2, length2, /*shouldLockThreadRegistry=*/false), 291 function(function_) { 292 char bug_type[100]; 293 internal_snprintf(bug_type, sizeof(bug_type), "%s-param-overlap", function); 294 scariness.Clear(); 295 scariness.Scare(10, bug_type); 296 } 297 void Print(); 298 }; 299 300 struct ErrorStringFunctionSizeOverflow : ErrorBase { 301 const BufferedStackTrace *stack; 302 AddressDescription addr_description; 303 uptr size; 304 305 ErrorStringFunctionSizeOverflow() = default; // (*) 306 ErrorStringFunctionSizeOverflow(u32 tid, BufferedStackTrace *stack_, 307 uptr addr, uptr size_) 308 : ErrorBase(tid, 10, "negative-size-param"), 309 stack(stack_), 310 addr_description(addr, /*shouldLockThreadRegistry=*/false), 311 size(size_) {} 312 void Print(); 313 }; 314 315 struct ErrorBadParamsToAnnotateContiguousContainer : ErrorBase { 316 const BufferedStackTrace *stack; 317 uptr beg, end, old_mid, new_mid; 318 319 ErrorBadParamsToAnnotateContiguousContainer() = default; // (*) 320 // PS4: Do we want an AddressDescription for beg? 321 ErrorBadParamsToAnnotateContiguousContainer(u32 tid, 322 BufferedStackTrace *stack_, 323 uptr beg_, uptr end_, 324 uptr old_mid_, uptr new_mid_) 325 : ErrorBase(tid, 10, "bad-__sanitizer_annotate_contiguous_container"), 326 stack(stack_), 327 beg(beg_), 328 end(end_), 329 old_mid(old_mid_), 330 new_mid(new_mid_) {} 331 void Print(); 332 }; 333 334 struct ErrorBadParamsToAnnotateDoubleEndedContiguousContainer : ErrorBase { 335 const BufferedStackTrace *stack; 336 uptr storage_beg, storage_end, old_container_beg, old_container_end, 337 new_container_beg, new_container_end; 338 339 ErrorBadParamsToAnnotateDoubleEndedContiguousContainer() = default; // (*) 340 ErrorBadParamsToAnnotateDoubleEndedContiguousContainer( 341 u32 tid, BufferedStackTrace *stack_, uptr storage_beg_, uptr storage_end_, 342 uptr old_container_beg_, uptr old_container_end_, uptr new_container_beg_, 343 uptr new_container_end_) 344 : ErrorBase(tid, 10, 345 "bad-__sanitizer_annotate_double_ended_contiguous_container"), 346 stack(stack_), 347 storage_beg(storage_beg_), 348 storage_end(storage_end_), 349 old_container_beg(old_container_beg_), 350 old_container_end(old_container_end_), 351 new_container_beg(new_container_beg_), 352 new_container_end(new_container_end_) {} 353 void Print(); 354 }; 355 356 struct ErrorBadParamsToCopyContiguousContainerAnnotations : ErrorBase { 357 const BufferedStackTrace *stack; 358 uptr old_storage_beg, old_storage_end, new_storage_beg, new_storage_end; 359 360 ErrorBadParamsToCopyContiguousContainerAnnotations() = default; // (*) 361 ErrorBadParamsToCopyContiguousContainerAnnotations( 362 u32 tid, BufferedStackTrace *stack_, uptr old_storage_beg_, 363 uptr old_storage_end_, uptr new_storage_beg_, uptr new_storage_end_) 364 : ErrorBase(tid, 10, 365 "bad-__sanitizer_annotate_double_ended_contiguous_container"), 366 stack(stack_), 367 old_storage_beg(old_storage_beg_), 368 old_storage_end(old_storage_end_), 369 new_storage_beg(new_storage_beg_), 370 new_storage_end(new_storage_end_) {} 371 void Print(); 372 }; 373 374 struct ErrorODRViolation : ErrorBase { 375 __asan_global global1, global2; 376 u32 stack_id1, stack_id2; 377 378 ErrorODRViolation() = default; // (*) 379 ErrorODRViolation(u32 tid, const __asan_global *g1, u32 stack_id1_, 380 const __asan_global *g2, u32 stack_id2_) 381 : ErrorBase(tid, 10, "odr-violation"), 382 global1(*g1), 383 global2(*g2), 384 stack_id1(stack_id1_), 385 stack_id2(stack_id2_) {} 386 void Print(); 387 }; 388 389 struct ErrorInvalidPointerPair : ErrorBase { 390 uptr pc, bp, sp; 391 AddressDescription addr1_description; 392 AddressDescription addr2_description; 393 394 ErrorInvalidPointerPair() = default; // (*) 395 ErrorInvalidPointerPair(u32 tid, uptr pc_, uptr bp_, uptr sp_, uptr p1, 396 uptr p2) 397 : ErrorBase(tid, 10, "invalid-pointer-pair"), 398 pc(pc_), 399 bp(bp_), 400 sp(sp_), 401 addr1_description(p1, 1, /*shouldLockThreadRegistry=*/false), 402 addr2_description(p2, 1, /*shouldLockThreadRegistry=*/false) {} 403 void Print(); 404 }; 405 406 struct ErrorGeneric : ErrorBase { 407 AddressDescription addr_description; 408 uptr pc, bp, sp; 409 uptr access_size; 410 const char *bug_descr; 411 bool is_write; 412 u8 shadow_val; 413 414 ErrorGeneric() = default; // (*) 415 ErrorGeneric(u32 tid, uptr pc_, uptr bp_, uptr sp_, uptr addr, bool is_write_, 416 uptr access_size_); 417 void Print(); 418 }; 419 420 // clang-format off 421 #define ASAN_FOR_EACH_ERROR_KIND(macro) \ 422 macro(DeadlySignal) \ 423 macro(DoubleFree) \ 424 macro(NewDeleteTypeMismatch) \ 425 macro(FreeNotMalloced) \ 426 macro(AllocTypeMismatch) \ 427 macro(MallocUsableSizeNotOwned) \ 428 macro(SanitizerGetAllocatedSizeNotOwned) \ 429 macro(CallocOverflow) \ 430 macro(ReallocArrayOverflow) \ 431 macro(PvallocOverflow) \ 432 macro(InvalidAllocationAlignment) \ 433 macro(InvalidAlignedAllocAlignment) \ 434 macro(InvalidPosixMemalignAlignment) \ 435 macro(AllocationSizeTooBig) \ 436 macro(RssLimitExceeded) \ 437 macro(OutOfMemory) \ 438 macro(StringFunctionMemoryRangesOverlap) \ 439 macro(StringFunctionSizeOverflow) \ 440 macro(BadParamsToAnnotateContiguousContainer) \ 441 macro(BadParamsToAnnotateDoubleEndedContiguousContainer) \ 442 macro(BadParamsToCopyContiguousContainerAnnotations) \ 443 macro(ODRViolation) \ 444 macro(InvalidPointerPair) \ 445 macro(Generic) 446 // clang-format on 447 448 #define ASAN_DEFINE_ERROR_KIND(name) kErrorKind##name, 449 #define ASAN_ERROR_DESCRIPTION_MEMBER(name) Error##name name; 450 #define ASAN_ERROR_DESCRIPTION_CONSTRUCTOR(name) \ 451 ErrorDescription(Error##name const &e) : kind(kErrorKind##name) { \ 452 internal_memcpy(&name, &e, sizeof(name)); \ 453 } 454 #define ASAN_ERROR_DESCRIPTION_PRINT(name) \ 455 case kErrorKind##name: \ 456 return name.Print(); 457 458 enum ErrorKind { 459 kErrorKindInvalid = 0, 460 ASAN_FOR_EACH_ERROR_KIND(ASAN_DEFINE_ERROR_KIND) 461 }; 462 463 struct ErrorDescription { 464 ErrorKind kind; 465 // We're using a tagged union because it allows us to have a trivially 466 // copiable type and use the same structures as the public interface. 467 // 468 // We can add a wrapper around it to make it "more c++-like", but that would 469 // add a lot of code and the benefit wouldn't be that big. 470 union { 471 ErrorBase Base; 472 ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_MEMBER) 473 }; 474 475 ErrorDescription() { internal_memset(this, 0, sizeof(*this)); } 476 explicit ErrorDescription(LinkerInitialized) {} 477 ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_CONSTRUCTOR) 478 479 bool IsValid() { return kind != kErrorKindInvalid; } 480 void Print() { 481 switch (kind) { 482 ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_PRINT) 483 case kErrorKindInvalid: 484 CHECK(0); 485 } 486 CHECK(0); 487 } 488 }; 489 490 #undef ASAN_FOR_EACH_ERROR_KIND 491 #undef ASAN_DEFINE_ERROR_KIND 492 #undef ASAN_ERROR_DESCRIPTION_MEMBER 493 #undef ASAN_ERROR_DESCRIPTION_CONSTRUCTOR 494 #undef ASAN_ERROR_DESCRIPTION_PRINT 495 496 } // namespace __asan 497 498 #endif // ASAN_ERRORS_H 499