1120586Sbms//===-- asan_errors.h -------------------------------------------*- C++ -*-===// 2120586Sbms// 3120586Sbms// This file is distributed under the University of Illinois Open Source 4120586Sbms// License. See LICENSE.TXT for details. 5120586Sbms// 6120586Sbms//===----------------------------------------------------------------------===// 7120586Sbms// 8120586Sbms// This file is a part of AddressSanitizer, an address sanity checker. 9120586Sbms// 10120586Sbms// ASan-private header for error structures. 11120586Sbms//===----------------------------------------------------------------------===// 12120586Sbms#ifndef ASAN_ERRORS_H 13120586Sbms#define ASAN_ERRORS_H 14120586Sbms 15120586Sbms#include "asan_descriptions.h" 16120586Sbms#include "asan_scariness_score.h" 17120586Sbms#include "sanitizer_common/sanitizer_common.h" 18120586Sbms 19120586Sbmsnamespace __asan { 20120586Sbms 21120586Sbms// (*) VS2013 does not implement unrestricted unions, so we need a trivial 22120586Sbms// default constructor explicitly defined for each particular error. 23120586Sbms 24120586Sbms// None of the error classes own the stack traces mentioned in them. 25120586Sbms 26120586Sbmsstruct ErrorBase { 27120586Sbms ScarinessScoreBase scariness; 28255495Sjhb u32 tid; 29131680Sru 30131681Sru ErrorBase() = default; // (*) 31120586Sbms explicit ErrorBase(u32 tid_) : tid(tid_) {} 32120586Sbms ErrorBase(u32 tid_, int initial_score, const char *reason) : tid(tid_) { 33120586Sbms scariness.Clear(); 34120586Sbms scariness.Scare(initial_score, reason); 35120586Sbms } 36120586Sbms}; 37120586Sbms 38120586Sbmsstruct ErrorDeadlySignal : ErrorBase { 39131680Sru SignalContext signal; 40131680Sru 41255495Sjhb ErrorDeadlySignal() = default; // (*) 42255495Sjhb ErrorDeadlySignal(u32 tid, const SignalContext &sig) 43131680Sru : ErrorBase(tid), 44120586Sbms signal(sig) { 45120586Sbms scariness.Clear(); 46120586Sbms if (signal.IsStackOverflow()) { 47120586Sbms scariness.Scare(10, "stack-overflow"); 48120586Sbms } else if (!signal.is_memory_access) { 49120586Sbms scariness.Scare(10, "signal"); 50255495Sjhb } else if (signal.addr < GetPageSizeCached()) { 51255495Sjhb scariness.Scare(10, "null-deref"); 52255495Sjhb } else if (signal.addr == signal.pc) { 53255495Sjhb scariness.Scare(60, "wild-jump"); 54255495Sjhb } else if (signal.write_flag == SignalContext::WRITE) { 55255495Sjhb scariness.Scare(30, "wild-addr-write"); 56255495Sjhb } else if (signal.write_flag == SignalContext::READ) { 57120586Sbms scariness.Scare(20, "wild-addr-read"); 58120586Sbms } else { 59120586Sbms scariness.Scare(25, "wild-addr"); 60120586Sbms } 61120586Sbms } 62120586Sbms void Print(); 63120586Sbms}; 64120586Sbms 65120586Sbmsstruct ErrorDoubleFree : ErrorBase { 66120586Sbms const BufferedStackTrace *second_free_stack; 67120586Sbms HeapAddressDescription addr_description; 68120586Sbms 69120586Sbms ErrorDoubleFree() = default; // (*) 70131680Sru ErrorDoubleFree(u32 tid, BufferedStackTrace *stack, uptr addr) 71131680Sru : ErrorBase(tid, 42, "double-free"), 72131680Sru second_free_stack(stack) { 73120586Sbms CHECK_GT(second_free_stack->size, 0); 74120586Sbms GetHeapAddressInformation(addr, 1, &addr_description); 75120586Sbms } 76255495Sjhb void Print(); 77255495Sjhb}; 78255495Sjhb 79255495Sjhbstruct ErrorNewDeleteTypeMismatch : ErrorBase { 80255495Sjhb const BufferedStackTrace *free_stack; 81255495Sjhb HeapAddressDescription addr_description; 82255495Sjhb uptr delete_size; 83255495Sjhb uptr delete_alignment; 84120586Sbms 85255495Sjhb ErrorNewDeleteTypeMismatch() = default; // (*) 86255495Sjhb ErrorNewDeleteTypeMismatch(u32 tid, BufferedStackTrace *stack, uptr addr, 87255495Sjhb uptr delete_size_, uptr delete_alignment_) 88255495Sjhb : ErrorBase(tid, 10, "new-delete-type-mismatch"), 89120586Sbms free_stack(stack), 90255495Sjhb delete_size(delete_size_), 91255495Sjhb delete_alignment(delete_alignment_) { 92255495Sjhb GetHeapAddressInformation(addr, 1, &addr_description); 93255495Sjhb } 94255525Sjoel void Print(); 95255495Sjhb}; 96255495Sjhb 97255495Sjhbstruct ErrorFreeNotMalloced : ErrorBase { 98255495Sjhb const BufferedStackTrace *free_stack; 99255495Sjhb AddressDescription addr_description; 100255495Sjhb 101255495Sjhb ErrorFreeNotMalloced() = default; // (*) 102255495Sjhb ErrorFreeNotMalloced(u32 tid, BufferedStackTrace *stack, uptr addr) 103255495Sjhb : ErrorBase(tid, 40, "bad-free"), 104255495Sjhb free_stack(stack), 105255495Sjhb addr_description(addr, /*shouldLockThreadRegistry=*/false) {} 106178928Salc void Print(); 107255495Sjhb}; 108255495Sjhb 109255495Sjhbstruct ErrorAllocTypeMismatch : ErrorBase { 110255495Sjhb const BufferedStackTrace *dealloc_stack; 111255495Sjhb AllocType alloc_type, dealloc_type; 112255495Sjhb AddressDescription addr_description; 113255495Sjhb 114255495Sjhb ErrorAllocTypeMismatch() = default; // (*) 115178928Salc ErrorAllocTypeMismatch(u32 tid, BufferedStackTrace *stack, uptr addr, 116255495Sjhb AllocType alloc_type_, AllocType dealloc_type_) 117255495Sjhb : ErrorBase(tid, 10, "alloc-dealloc-mismatch"), 118255495Sjhb dealloc_stack(stack), 119255495Sjhb alloc_type(alloc_type_), 120255495Sjhb dealloc_type(dealloc_type_), 121255495Sjhb addr_description(addr, 1, false) {} 122255495Sjhb void Print(); 123255495Sjhb}; 124255495Sjhb 125255495Sjhbstruct ErrorMallocUsableSizeNotOwned : ErrorBase { 126120586Sbms const BufferedStackTrace *stack; 127120586Sbms AddressDescription addr_description; 128120586Sbms 129120586Sbms ErrorMallocUsableSizeNotOwned() = default; // (*) 130120586Sbms ErrorMallocUsableSizeNotOwned(u32 tid, BufferedStackTrace *stack_, uptr addr) 131120586Sbms : ErrorBase(tid, 10, "bad-malloc_usable_size"), 132120586Sbms stack(stack_), 133120586Sbms addr_description(addr, /*shouldLockThreadRegistry=*/false) {} 134120586Sbms void Print(); 135120586Sbms}; 136120586Sbms 137120586Sbmsstruct ErrorSanitizerGetAllocatedSizeNotOwned : ErrorBase { 138131680Sru const BufferedStackTrace *stack; 139120586Sbms AddressDescription addr_description; 140120586Sbms 141178928Salc ErrorSanitizerGetAllocatedSizeNotOwned() = default; // (*) 142178928Salc ErrorSanitizerGetAllocatedSizeNotOwned(u32 tid, BufferedStackTrace *stack_, 143178928Salc uptr addr) 144178928Salc : ErrorBase(tid, 10, "bad-__sanitizer_get_allocated_size"), 145178928Salc stack(stack_), 146178928Salc addr_description(addr, /*shouldLockThreadRegistry=*/false) {} 147178928Salc void Print(); 148178928Salc}; 149120586Sbms 150120586Sbmsstruct ErrorCallocOverflow : ErrorBase { 151120586Sbms const BufferedStackTrace *stack; 152120586Sbms uptr count; 153120586Sbms uptr size; 154120586Sbms 155120586Sbms ErrorCallocOverflow() = default; // (*) 156120586Sbms ErrorCallocOverflow(u32 tid, BufferedStackTrace *stack_, uptr count_, 157120586Sbms uptr size_) 158120586Sbms : ErrorBase(tid, 10, "calloc-overflow"), 159120586Sbms stack(stack_), 160147647Shmp count(count_), 161120586Sbms 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