1 //===-- asan_errors.h -------------------------------------------*- C++ -*-===// 2 // 3 // This file is distributed under the University of Illinois Open Source 4 // License. See LICENSE.TXT for details. 5 // 6 //===----------------------------------------------------------------------===// 7 // 8 // This file is a part of AddressSanitizer, an address sanity checker. 9 // 10 // ASan-private header for error structures. 11 //===----------------------------------------------------------------------===// 12 #ifndef ASAN_ERRORS_H 13 #define ASAN_ERRORS_H 14 15 #include "asan_descriptions.h" 16 #include "asan_scariness_score.h" 17 #include "sanitizer_common/sanitizer_common.h" 18 19 namespace __asan { 20 21 struct ErrorBase { 22 ErrorBase() = default; ErrorBaseErrorBase23 explicit ErrorBase(u32 tid_) : tid(tid_) {} 24 ScarinessScoreBase scariness; 25 u32 tid; 26 }; 27 28 struct ErrorDeadlySignal : ErrorBase { 29 SignalContext signal; 30 // VS2013 doesn't implement unrestricted unions, so we need a trivial default 31 // constructor 32 ErrorDeadlySignal() = default; ErrorDeadlySignalErrorDeadlySignal33 ErrorDeadlySignal(u32 tid, const SignalContext &sig) 34 : ErrorBase(tid), signal(sig) { 35 scariness.Clear(); 36 if (signal.IsStackOverflow()) { 37 scariness.Scare(10, "stack-overflow"); 38 } else if (!signal.is_memory_access) { 39 scariness.Scare(10, "signal"); 40 } else if (signal.addr < GetPageSizeCached()) { 41 scariness.Scare(10, "null-deref"); 42 } else if (signal.addr == signal.pc) { 43 scariness.Scare(60, "wild-jump"); 44 } else if (signal.write_flag == SignalContext::WRITE) { 45 scariness.Scare(30, "wild-addr-write"); 46 } else if (signal.write_flag == SignalContext::READ) { 47 scariness.Scare(20, "wild-addr-read"); 48 } else { 49 scariness.Scare(25, "wild-addr"); 50 } 51 } 52 void Print(); 53 }; 54 55 struct ErrorDoubleFree : ErrorBase { 56 // ErrorDoubleFree doesn't own the stack trace. 57 const BufferedStackTrace *second_free_stack; 58 HeapAddressDescription addr_description; 59 // VS2013 doesn't implement unrestricted unions, so we need a trivial default 60 // constructor 61 ErrorDoubleFree() = default; ErrorDoubleFreeErrorDoubleFree62 ErrorDoubleFree(u32 tid, BufferedStackTrace *stack, uptr addr) 63 : ErrorBase(tid), second_free_stack(stack) { 64 CHECK_GT(second_free_stack->size, 0); 65 GetHeapAddressInformation(addr, 1, &addr_description); 66 scariness.Clear(); 67 scariness.Scare(42, "double-free"); 68 } 69 void Print(); 70 }; 71 72 struct ErrorNewDeleteSizeMismatch : ErrorBase { 73 // ErrorNewDeleteSizeMismatch doesn't own the stack trace. 74 const BufferedStackTrace *free_stack; 75 HeapAddressDescription addr_description; 76 uptr delete_size; 77 // VS2013 doesn't implement unrestricted unions, so we need a trivial default 78 // constructor 79 ErrorNewDeleteSizeMismatch() = default; ErrorNewDeleteSizeMismatchErrorNewDeleteSizeMismatch80 ErrorNewDeleteSizeMismatch(u32 tid, BufferedStackTrace *stack, uptr addr, 81 uptr delete_size_) 82 : ErrorBase(tid), free_stack(stack), delete_size(delete_size_) { 83 GetHeapAddressInformation(addr, 1, &addr_description); 84 scariness.Clear(); 85 scariness.Scare(10, "new-delete-type-mismatch"); 86 } 87 void Print(); 88 }; 89 90 struct ErrorFreeNotMalloced : ErrorBase { 91 // ErrorFreeNotMalloced doesn't own the stack trace. 92 const BufferedStackTrace *free_stack; 93 AddressDescription addr_description; 94 // VS2013 doesn't implement unrestricted unions, so we need a trivial default 95 // constructor 96 ErrorFreeNotMalloced() = default; ErrorFreeNotMallocedErrorFreeNotMalloced97 ErrorFreeNotMalloced(u32 tid, BufferedStackTrace *stack, uptr addr) 98 : ErrorBase(tid), 99 free_stack(stack), 100 addr_description(addr, /*shouldLockThreadRegistry=*/false) { 101 scariness.Clear(); 102 scariness.Scare(40, "bad-free"); 103 } 104 void Print(); 105 }; 106 107 struct ErrorAllocTypeMismatch : ErrorBase { 108 // ErrorAllocTypeMismatch doesn't own the stack trace. 109 const BufferedStackTrace *dealloc_stack; 110 HeapAddressDescription addr_description; 111 AllocType alloc_type, dealloc_type; 112 // VS2013 doesn't implement unrestricted unions, so we need a trivial default 113 // constructor 114 ErrorAllocTypeMismatch() = default; ErrorAllocTypeMismatchErrorAllocTypeMismatch115 ErrorAllocTypeMismatch(u32 tid, BufferedStackTrace *stack, uptr addr, 116 AllocType alloc_type_, AllocType dealloc_type_) 117 : ErrorBase(tid), 118 dealloc_stack(stack), 119 alloc_type(alloc_type_), 120 dealloc_type(dealloc_type_) { 121 GetHeapAddressInformation(addr, 1, &addr_description); 122 scariness.Clear(); 123 scariness.Scare(10, "alloc-dealloc-mismatch"); 124 }; 125 void Print(); 126 }; 127 128 struct ErrorMallocUsableSizeNotOwned : ErrorBase { 129 // ErrorMallocUsableSizeNotOwned doesn't own the stack trace. 130 const BufferedStackTrace *stack; 131 AddressDescription addr_description; 132 // VS2013 doesn't implement unrestricted unions, so we need a trivial default 133 // constructor 134 ErrorMallocUsableSizeNotOwned() = default; ErrorMallocUsableSizeNotOwnedErrorMallocUsableSizeNotOwned135 ErrorMallocUsableSizeNotOwned(u32 tid, BufferedStackTrace *stack_, uptr addr) 136 : ErrorBase(tid), 137 stack(stack_), 138 addr_description(addr, /*shouldLockThreadRegistry=*/false) { 139 scariness.Clear(); 140 scariness.Scare(10, "bad-malloc_usable_size"); 141 } 142 void Print(); 143 }; 144 145 struct ErrorSanitizerGetAllocatedSizeNotOwned : ErrorBase { 146 // ErrorSanitizerGetAllocatedSizeNotOwned doesn't own the stack trace. 147 const BufferedStackTrace *stack; 148 AddressDescription addr_description; 149 // VS2013 doesn't implement unrestricted unions, so we need a trivial default 150 // constructor 151 ErrorSanitizerGetAllocatedSizeNotOwned() = default; ErrorSanitizerGetAllocatedSizeNotOwnedErrorSanitizerGetAllocatedSizeNotOwned152 ErrorSanitizerGetAllocatedSizeNotOwned(u32 tid, BufferedStackTrace *stack_, 153 uptr addr) 154 : ErrorBase(tid), 155 stack(stack_), 156 addr_description(addr, /*shouldLockThreadRegistry=*/false) { 157 scariness.Clear(); 158 scariness.Scare(10, "bad-__sanitizer_get_allocated_size"); 159 } 160 void Print(); 161 }; 162 163 struct ErrorStringFunctionMemoryRangesOverlap : ErrorBase { 164 // ErrorStringFunctionMemoryRangesOverlap doesn't own the stack trace. 165 const BufferedStackTrace *stack; 166 uptr length1, length2; 167 AddressDescription addr1_description; 168 AddressDescription addr2_description; 169 const char *function; 170 // VS2013 doesn't implement unrestricted unions, so we need a trivial default 171 // constructor 172 ErrorStringFunctionMemoryRangesOverlap() = default; ErrorStringFunctionMemoryRangesOverlapErrorStringFunctionMemoryRangesOverlap173 ErrorStringFunctionMemoryRangesOverlap(u32 tid, BufferedStackTrace *stack_, 174 uptr addr1, uptr length1_, uptr addr2, 175 uptr length2_, const char *function_) 176 : ErrorBase(tid), 177 stack(stack_), 178 length1(length1_), 179 length2(length2_), 180 addr1_description(addr1, length1, /*shouldLockThreadRegistry=*/false), 181 addr2_description(addr2, length2, /*shouldLockThreadRegistry=*/false), 182 function(function_) { 183 char bug_type[100]; 184 internal_snprintf(bug_type, sizeof(bug_type), "%s-param-overlap", function); 185 scariness.Clear(); 186 scariness.Scare(10, bug_type); 187 } 188 void Print(); 189 }; 190 191 struct ErrorStringFunctionSizeOverflow : ErrorBase { 192 // ErrorStringFunctionSizeOverflow doesn't own the stack trace. 193 const BufferedStackTrace *stack; 194 AddressDescription addr_description; 195 uptr size; 196 // VS2013 doesn't implement unrestricted unions, so we need a trivial default 197 // constructor 198 ErrorStringFunctionSizeOverflow() = default; ErrorStringFunctionSizeOverflowErrorStringFunctionSizeOverflow199 ErrorStringFunctionSizeOverflow(u32 tid, BufferedStackTrace *stack_, 200 uptr addr, uptr size_) 201 : ErrorBase(tid), 202 stack(stack_), 203 addr_description(addr, /*shouldLockThreadRegistry=*/false), 204 size(size_) { 205 scariness.Clear(); 206 scariness.Scare(10, "negative-size-param"); 207 } 208 void Print(); 209 }; 210 211 struct ErrorBadParamsToAnnotateContiguousContainer : ErrorBase { 212 // ErrorBadParamsToAnnotateContiguousContainer doesn't own the stack trace. 213 const BufferedStackTrace *stack; 214 uptr beg, end, old_mid, new_mid; 215 // VS2013 doesn't implement unrestricted unions, so we need a trivial default 216 // constructor 217 ErrorBadParamsToAnnotateContiguousContainer() = default; 218 // PS4: Do we want an AddressDescription for beg? ErrorBadParamsToAnnotateContiguousContainerErrorBadParamsToAnnotateContiguousContainer219 ErrorBadParamsToAnnotateContiguousContainer(u32 tid, 220 BufferedStackTrace *stack_, 221 uptr beg_, uptr end_, 222 uptr old_mid_, uptr new_mid_) 223 : ErrorBase(tid), 224 stack(stack_), 225 beg(beg_), 226 end(end_), 227 old_mid(old_mid_), 228 new_mid(new_mid_) { 229 scariness.Clear(); 230 scariness.Scare(10, "bad-__sanitizer_annotate_contiguous_container"); 231 } 232 void Print(); 233 }; 234 235 struct ErrorODRViolation : ErrorBase { 236 __asan_global global1, global2; 237 u32 stack_id1, stack_id2; 238 // VS2013 doesn't implement unrestricted unions, so we need a trivial default 239 // constructor 240 ErrorODRViolation() = default; ErrorODRViolationErrorODRViolation241 ErrorODRViolation(u32 tid, const __asan_global *g1, u32 stack_id1_, 242 const __asan_global *g2, u32 stack_id2_) 243 : ErrorBase(tid), 244 global1(*g1), 245 global2(*g2), 246 stack_id1(stack_id1_), 247 stack_id2(stack_id2_) { 248 scariness.Clear(); 249 scariness.Scare(10, "odr-violation"); 250 } 251 void Print(); 252 }; 253 254 struct ErrorInvalidPointerPair : ErrorBase { 255 uptr pc, bp, sp; 256 AddressDescription addr1_description; 257 AddressDescription addr2_description; 258 // VS2013 doesn't implement unrestricted unions, so we need a trivial default 259 // constructor 260 ErrorInvalidPointerPair() = default; ErrorInvalidPointerPairErrorInvalidPointerPair261 ErrorInvalidPointerPair(u32 tid, uptr pc_, uptr bp_, uptr sp_, uptr p1, 262 uptr p2) 263 : ErrorBase(tid), 264 pc(pc_), 265 bp(bp_), 266 sp(sp_), 267 addr1_description(p1, 1, /*shouldLockThreadRegistry=*/false), 268 addr2_description(p2, 1, /*shouldLockThreadRegistry=*/false) { 269 scariness.Clear(); 270 scariness.Scare(10, "invalid-pointer-pair"); 271 } 272 void Print(); 273 }; 274 275 struct ErrorGeneric : ErrorBase { 276 AddressDescription addr_description; 277 uptr pc, bp, sp; 278 uptr access_size; 279 const char *bug_descr; 280 bool is_write; 281 u8 shadow_val; 282 // VS2013 doesn't implement unrestricted unions, so we need a trivial default 283 // constructor 284 ErrorGeneric() = default; 285 ErrorGeneric(u32 tid, uptr addr, uptr pc_, uptr bp_, uptr sp_, bool is_write_, 286 uptr access_size_); 287 void Print(); 288 }; 289 290 // clang-format off 291 #define ASAN_FOR_EACH_ERROR_KIND(macro) \ 292 macro(DeadlySignal) \ 293 macro(DoubleFree) \ 294 macro(NewDeleteSizeMismatch) \ 295 macro(FreeNotMalloced) \ 296 macro(AllocTypeMismatch) \ 297 macro(MallocUsableSizeNotOwned) \ 298 macro(SanitizerGetAllocatedSizeNotOwned) \ 299 macro(StringFunctionMemoryRangesOverlap) \ 300 macro(StringFunctionSizeOverflow) \ 301 macro(BadParamsToAnnotateContiguousContainer) \ 302 macro(ODRViolation) \ 303 macro(InvalidPointerPair) \ 304 macro(Generic) 305 // clang-format on 306 307 #define ASAN_DEFINE_ERROR_KIND(name) kErrorKind##name, 308 #define ASAN_ERROR_DESCRIPTION_MEMBER(name) Error##name name; 309 #define ASAN_ERROR_DESCRIPTION_CONSTRUCTOR(name) \ 310 ErrorDescription(Error##name const &e) : kind(kErrorKind##name), name(e) {} 311 #define ASAN_ERROR_DESCRIPTION_PRINT(name) \ 312 case kErrorKind##name: \ 313 return name.Print(); 314 315 enum ErrorKind { 316 kErrorKindInvalid = 0, 317 ASAN_FOR_EACH_ERROR_KIND(ASAN_DEFINE_ERROR_KIND) 318 }; 319 320 struct ErrorDescription { 321 ErrorKind kind; 322 // We're using a tagged union because it allows us to have a trivially 323 // copiable type and use the same structures as the public interface. 324 // 325 // We can add a wrapper around it to make it "more c++-like", but that would 326 // add a lot of code and the benefit wouldn't be that big. 327 union { 328 ErrorBase Base; 329 ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_MEMBER) 330 }; 331 ErrorDescriptionErrorDescription332 ErrorDescription() { internal_memset(this, 0, sizeof(*this)); } ASAN_FOR_EACH_ERROR_KINDErrorDescription333 ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_CONSTRUCTOR) 334 335 bool IsValid() { return kind != kErrorKindInvalid; } PrintErrorDescription336 void Print() { 337 switch (kind) { 338 ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_PRINT) 339 case kErrorKindInvalid: 340 CHECK(0); 341 } 342 CHECK(0); 343 } 344 }; 345 346 #undef ASAN_FOR_EACH_ERROR_KIND 347 #undef ASAN_DEFINE_ERROR_KIND 348 #undef ASAN_ERROR_DESCRIPTION_MEMBER 349 #undef ASAN_ERROR_DESCRIPTION_CONSTRUCTOR 350 #undef ASAN_ERROR_DESCRIPTION_PRINT 351 352 } // namespace __asan 353 354 #endif // ASAN_ERRORS_H 355