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