asan_report.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  1. //===-- asan_report.cpp ---------------------------------------------------===//
  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. // This file contains error reporting code.
  12. //===----------------------------------------------------------------------===//
  13. #include "asan_report.h"
  14. #include "asan_descriptions.h"
  15. #include "asan_errors.h"
  16. #include "asan_flags.h"
  17. #include "asan_internal.h"
  18. #include "asan_mapping.h"
  19. #include "asan_scariness_score.h"
  20. #include "asan_stack.h"
  21. #include "asan_thread.h"
  22. #include "sanitizer_common/sanitizer_common.h"
  23. #include "sanitizer_common/sanitizer_flags.h"
  24. #include "sanitizer_common/sanitizer_interface_internal.h"
  25. #include "sanitizer_common/sanitizer_report_decorator.h"
  26. #include "sanitizer_common/sanitizer_stackdepot.h"
  27. #include "sanitizer_common/sanitizer_symbolizer.h"
  28. namespace __asan {
  29. // -------------------- User-specified callbacks ----------------- {{{1
  30. static void (*error_report_callback)(const char*);
  31. static char *error_message_buffer = nullptr;
  32. static uptr error_message_buffer_pos = 0;
  33. static Mutex error_message_buf_mutex;
  34. static const unsigned kAsanBuggyPcPoolSize = 25;
  35. static __sanitizer::atomic_uintptr_t AsanBuggyPcPool[kAsanBuggyPcPoolSize];
  36. void AppendToErrorMessageBuffer(const char *buffer) {
  37. Lock l(&error_message_buf_mutex);
  38. if (!error_message_buffer) {
  39. error_message_buffer =
  40. (char*)MmapOrDieQuietly(kErrorMessageBufferSize, __func__);
  41. error_message_buffer_pos = 0;
  42. }
  43. uptr length = internal_strlen(buffer);
  44. RAW_CHECK(kErrorMessageBufferSize >= error_message_buffer_pos);
  45. uptr remaining = kErrorMessageBufferSize - error_message_buffer_pos;
  46. internal_strncpy(error_message_buffer + error_message_buffer_pos,
  47. buffer, remaining);
  48. error_message_buffer[kErrorMessageBufferSize - 1] = '\0';
  49. // FIXME: reallocate the buffer instead of truncating the message.
  50. error_message_buffer_pos += Min(remaining, length);
  51. }
  52. // ---------------------- Helper functions ----------------------- {{{1
  53. void PrintMemoryByte(InternalScopedString *str, const char *before, u8 byte,
  54. bool in_shadow, const char *after) {
  55. Decorator d;
  56. str->AppendF("%s%s%x%x%s%s", before,
  57. in_shadow ? d.ShadowByte(byte) : d.MemoryByte(), byte >> 4,
  58. byte & 15, d.Default(), after);
  59. }
  60. static void PrintZoneForPointer(uptr ptr, uptr zone_ptr,
  61. const char *zone_name) {
  62. if (zone_ptr) {
  63. if (zone_name) {
  64. Printf("malloc_zone_from_ptr(%p) = %p, which is %s\n", (void *)ptr,
  65. (void *)zone_ptr, zone_name);
  66. } else {
  67. Printf("malloc_zone_from_ptr(%p) = %p, which doesn't have a name\n",
  68. (void *)ptr, (void *)zone_ptr);
  69. }
  70. } else {
  71. Printf("malloc_zone_from_ptr(%p) = 0\n", (void *)ptr);
  72. }
  73. }
  74. // ---------------------- Address Descriptions ------------------- {{{1
  75. bool ParseFrameDescription(const char *frame_descr,
  76. InternalMmapVector<StackVarDescr> *vars) {
  77. CHECK(frame_descr);
  78. const char *p;
  79. // This string is created by the compiler and has the following form:
  80. // "n alloc_1 alloc_2 ... alloc_n"
  81. // where alloc_i looks like "offset size len ObjectName"
  82. // or "offset size len ObjectName:line".
  83. uptr n_objects = (uptr)internal_simple_strtoll(frame_descr, &p, 10);
  84. if (n_objects == 0)
  85. return false;
  86. for (uptr i = 0; i < n_objects; i++) {
  87. uptr beg = (uptr)internal_simple_strtoll(p, &p, 10);
  88. uptr size = (uptr)internal_simple_strtoll(p, &p, 10);
  89. uptr len = (uptr)internal_simple_strtoll(p, &p, 10);
  90. if (beg == 0 || size == 0 || *p != ' ') {
  91. return false;
  92. }
  93. p++;
  94. char *colon_pos = internal_strchr(p, ':');
  95. uptr line = 0;
  96. uptr name_len = len;
  97. if (colon_pos != nullptr && colon_pos < p + len) {
  98. name_len = colon_pos - p;
  99. line = (uptr)internal_simple_strtoll(colon_pos + 1, nullptr, 10);
  100. }
  101. StackVarDescr var = {beg, size, p, name_len, line};
  102. vars->push_back(var);
  103. p += len;
  104. }
  105. return true;
  106. }
  107. // -------------------- Different kinds of reports ----------------- {{{1
  108. // Use ScopedInErrorReport to run common actions just before and
  109. // immediately after printing error report.
  110. class ScopedInErrorReport {
  111. public:
  112. explicit ScopedInErrorReport(bool fatal = false)
  113. : halt_on_error_(fatal || flags()->halt_on_error) {
  114. // Make sure the registry and sanitizer report mutexes are locked while
  115. // we're printing an error report.
  116. // We can lock them only here to avoid self-deadlock in case of
  117. // recursive reports.
  118. asanThreadRegistry().Lock();
  119. Printf(
  120. "=================================================================\n");
  121. }
  122. ~ScopedInErrorReport() {
  123. if (halt_on_error_ && !__sanitizer_acquire_crash_state()) {
  124. asanThreadRegistry().Unlock();
  125. return;
  126. }
  127. ASAN_ON_ERROR();
  128. if (current_error_.IsValid()) current_error_.Print();
  129. // Make sure the current thread is announced.
  130. DescribeThread(GetCurrentThread());
  131. // We may want to grab this lock again when printing stats.
  132. asanThreadRegistry().Unlock();
  133. // Print memory stats.
  134. if (flags()->print_stats)
  135. __asan_print_accumulated_stats();
  136. if (common_flags()->print_cmdline)
  137. PrintCmdline();
  138. if (common_flags()->print_module_map == 2)
  139. DumpProcessMap();
  140. // Copy the message buffer so that we could start logging without holding a
  141. // lock that gets acquired during printing.
  142. InternalMmapVector<char> buffer_copy(kErrorMessageBufferSize);
  143. {
  144. Lock l(&error_message_buf_mutex);
  145. internal_memcpy(buffer_copy.data(),
  146. error_message_buffer, kErrorMessageBufferSize);
  147. // Clear error_message_buffer so that if we find other errors
  148. // we don't re-log this error.
  149. error_message_buffer_pos = 0;
  150. }
  151. LogFullErrorReport(buffer_copy.data());
  152. if (error_report_callback) {
  153. error_report_callback(buffer_copy.data());
  154. }
  155. if (halt_on_error_ && common_flags()->abort_on_error) {
  156. // On Android the message is truncated to 512 characters.
  157. // FIXME: implement "compact" error format, possibly without, or with
  158. // highly compressed stack traces?
  159. // FIXME: or just use the summary line as abort message?
  160. SetAbortMessage(buffer_copy.data());
  161. }
  162. // In halt_on_error = false mode, reset the current error object (before
  163. // unlocking).
  164. if (!halt_on_error_)
  165. internal_memset(&current_error_, 0, sizeof(current_error_));
  166. if (halt_on_error_) {
  167. Report("ABORTING\n");
  168. Die();
  169. }
  170. }
  171. void ReportError(const ErrorDescription &description) {
  172. // Can only report one error per ScopedInErrorReport.
  173. CHECK_EQ(current_error_.kind, kErrorKindInvalid);
  174. internal_memcpy(&current_error_, &description, sizeof(current_error_));
  175. }
  176. static ErrorDescription &CurrentError() {
  177. return current_error_;
  178. }
  179. private:
  180. ScopedErrorReportLock error_report_lock_;
  181. // Error currently being reported. This enables the destructor to interact
  182. // with the debugger and point it to an error description.
  183. static ErrorDescription current_error_;
  184. bool halt_on_error_;
  185. };
  186. ErrorDescription ScopedInErrorReport::current_error_(LINKER_INITIALIZED);
  187. void ReportDeadlySignal(const SignalContext &sig) {
  188. ScopedInErrorReport in_report(/*fatal*/ true);
  189. ErrorDeadlySignal error(GetCurrentTidOrInvalid(), sig);
  190. in_report.ReportError(error);
  191. }
  192. void ReportDoubleFree(uptr addr, BufferedStackTrace *free_stack) {
  193. ScopedInErrorReport in_report;
  194. ErrorDoubleFree error(GetCurrentTidOrInvalid(), free_stack, addr);
  195. in_report.ReportError(error);
  196. }
  197. void ReportNewDeleteTypeMismatch(uptr addr, uptr delete_size,
  198. uptr delete_alignment,
  199. BufferedStackTrace *free_stack) {
  200. ScopedInErrorReport in_report;
  201. ErrorNewDeleteTypeMismatch error(GetCurrentTidOrInvalid(), free_stack, addr,
  202. delete_size, delete_alignment);
  203. in_report.ReportError(error);
  204. }
  205. void ReportFreeNotMalloced(uptr addr, BufferedStackTrace *free_stack) {
  206. ScopedInErrorReport in_report;
  207. ErrorFreeNotMalloced error(GetCurrentTidOrInvalid(), free_stack, addr);
  208. in_report.ReportError(error);
  209. }
  210. void ReportAllocTypeMismatch(uptr addr, BufferedStackTrace *free_stack,
  211. AllocType alloc_type,
  212. AllocType dealloc_type) {
  213. ScopedInErrorReport in_report;
  214. ErrorAllocTypeMismatch error(GetCurrentTidOrInvalid(), free_stack, addr,
  215. alloc_type, dealloc_type);
  216. in_report.ReportError(error);
  217. }
  218. void ReportMallocUsableSizeNotOwned(uptr addr, BufferedStackTrace *stack) {
  219. ScopedInErrorReport in_report;
  220. ErrorMallocUsableSizeNotOwned error(GetCurrentTidOrInvalid(), stack, addr);
  221. in_report.ReportError(error);
  222. }
  223. void ReportSanitizerGetAllocatedSizeNotOwned(uptr addr,
  224. BufferedStackTrace *stack) {
  225. ScopedInErrorReport in_report;
  226. ErrorSanitizerGetAllocatedSizeNotOwned error(GetCurrentTidOrInvalid(), stack,
  227. addr);
  228. in_report.ReportError(error);
  229. }
  230. void ReportCallocOverflow(uptr count, uptr size, BufferedStackTrace *stack) {
  231. ScopedInErrorReport in_report(/*fatal*/ true);
  232. ErrorCallocOverflow error(GetCurrentTidOrInvalid(), stack, count, size);
  233. in_report.ReportError(error);
  234. }
  235. void ReportReallocArrayOverflow(uptr count, uptr size,
  236. BufferedStackTrace *stack) {
  237. ScopedInErrorReport in_report(/*fatal*/ true);
  238. ErrorReallocArrayOverflow error(GetCurrentTidOrInvalid(), stack, count, size);
  239. in_report.ReportError(error);
  240. }
  241. void ReportPvallocOverflow(uptr size, BufferedStackTrace *stack) {
  242. ScopedInErrorReport in_report(/*fatal*/ true);
  243. ErrorPvallocOverflow error(GetCurrentTidOrInvalid(), stack, size);
  244. in_report.ReportError(error);
  245. }
  246. void ReportInvalidAllocationAlignment(uptr alignment,
  247. BufferedStackTrace *stack) {
  248. ScopedInErrorReport in_report(/*fatal*/ true);
  249. ErrorInvalidAllocationAlignment error(GetCurrentTidOrInvalid(), stack,
  250. alignment);
  251. in_report.ReportError(error);
  252. }
  253. void ReportInvalidAlignedAllocAlignment(uptr size, uptr alignment,
  254. BufferedStackTrace *stack) {
  255. ScopedInErrorReport in_report(/*fatal*/ true);
  256. ErrorInvalidAlignedAllocAlignment error(GetCurrentTidOrInvalid(), stack,
  257. size, alignment);
  258. in_report.ReportError(error);
  259. }
  260. void ReportInvalidPosixMemalignAlignment(uptr alignment,
  261. BufferedStackTrace *stack) {
  262. ScopedInErrorReport in_report(/*fatal*/ true);
  263. ErrorInvalidPosixMemalignAlignment error(GetCurrentTidOrInvalid(), stack,
  264. alignment);
  265. in_report.ReportError(error);
  266. }
  267. void ReportAllocationSizeTooBig(uptr user_size, uptr total_size, uptr max_size,
  268. BufferedStackTrace *stack) {
  269. ScopedInErrorReport in_report(/*fatal*/ true);
  270. ErrorAllocationSizeTooBig error(GetCurrentTidOrInvalid(), stack, user_size,
  271. total_size, max_size);
  272. in_report.ReportError(error);
  273. }
  274. void ReportRssLimitExceeded(BufferedStackTrace *stack) {
  275. ScopedInErrorReport in_report(/*fatal*/ true);
  276. ErrorRssLimitExceeded error(GetCurrentTidOrInvalid(), stack);
  277. in_report.ReportError(error);
  278. }
  279. void ReportOutOfMemory(uptr requested_size, BufferedStackTrace *stack) {
  280. ScopedInErrorReport in_report(/*fatal*/ true);
  281. ErrorOutOfMemory error(GetCurrentTidOrInvalid(), stack, requested_size);
  282. in_report.ReportError(error);
  283. }
  284. void ReportStringFunctionMemoryRangesOverlap(const char *function,
  285. const char *offset1, uptr length1,
  286. const char *offset2, uptr length2,
  287. BufferedStackTrace *stack) {
  288. ScopedInErrorReport in_report;
  289. ErrorStringFunctionMemoryRangesOverlap error(
  290. GetCurrentTidOrInvalid(), stack, (uptr)offset1, length1, (uptr)offset2,
  291. length2, function);
  292. in_report.ReportError(error);
  293. }
  294. void ReportStringFunctionSizeOverflow(uptr offset, uptr size,
  295. BufferedStackTrace *stack) {
  296. ScopedInErrorReport in_report;
  297. ErrorStringFunctionSizeOverflow error(GetCurrentTidOrInvalid(), stack, offset,
  298. size);
  299. in_report.ReportError(error);
  300. }
  301. void ReportBadParamsToAnnotateContiguousContainer(uptr beg, uptr end,
  302. uptr old_mid, uptr new_mid,
  303. BufferedStackTrace *stack) {
  304. ScopedInErrorReport in_report;
  305. ErrorBadParamsToAnnotateContiguousContainer error(
  306. GetCurrentTidOrInvalid(), stack, beg, end, old_mid, new_mid);
  307. in_report.ReportError(error);
  308. }
  309. void ReportBadParamsToAnnotateDoubleEndedContiguousContainer(
  310. uptr storage_beg, uptr storage_end, uptr old_container_beg,
  311. uptr old_container_end, uptr new_container_beg, uptr new_container_end,
  312. BufferedStackTrace *stack) {
  313. ScopedInErrorReport in_report;
  314. ErrorBadParamsToAnnotateDoubleEndedContiguousContainer error(
  315. GetCurrentTidOrInvalid(), stack, storage_beg, storage_end,
  316. old_container_beg, old_container_end, new_container_beg,
  317. new_container_end);
  318. in_report.ReportError(error);
  319. }
  320. void ReportODRViolation(const __asan_global *g1, u32 stack_id1,
  321. const __asan_global *g2, u32 stack_id2) {
  322. ScopedInErrorReport in_report;
  323. ErrorODRViolation error(GetCurrentTidOrInvalid(), g1, stack_id1, g2,
  324. stack_id2);
  325. in_report.ReportError(error);
  326. }
  327. // ----------------------- CheckForInvalidPointerPair ----------- {{{1
  328. static NOINLINE void ReportInvalidPointerPair(uptr pc, uptr bp, uptr sp,
  329. uptr a1, uptr a2) {
  330. ScopedInErrorReport in_report;
  331. ErrorInvalidPointerPair error(GetCurrentTidOrInvalid(), pc, bp, sp, a1, a2);
  332. in_report.ReportError(error);
  333. }
  334. static bool IsInvalidPointerPair(uptr a1, uptr a2) {
  335. if (a1 == a2)
  336. return false;
  337. // 256B in shadow memory can be iterated quite fast
  338. static const uptr kMaxOffset = 2048;
  339. uptr left = a1 < a2 ? a1 : a2;
  340. uptr right = a1 < a2 ? a2 : a1;
  341. uptr offset = right - left;
  342. if (offset <= kMaxOffset)
  343. return __asan_region_is_poisoned(left, offset);
  344. AsanThread *t = GetCurrentThread();
  345. // check whether left is a stack memory pointer
  346. if (uptr shadow_offset1 = t->GetStackVariableShadowStart(left)) {
  347. uptr shadow_offset2 = t->GetStackVariableShadowStart(right);
  348. return shadow_offset2 == 0 || shadow_offset1 != shadow_offset2;
  349. }
  350. // check whether left is a heap memory address
  351. HeapAddressDescription hdesc1, hdesc2;
  352. if (GetHeapAddressInformation(left, 0, &hdesc1) &&
  353. hdesc1.chunk_access.access_type == kAccessTypeInside)
  354. return !GetHeapAddressInformation(right, 0, &hdesc2) ||
  355. hdesc2.chunk_access.access_type != kAccessTypeInside ||
  356. hdesc1.chunk_access.chunk_begin != hdesc2.chunk_access.chunk_begin;
  357. // check whether left is an address of a global variable
  358. GlobalAddressDescription gdesc1, gdesc2;
  359. if (GetGlobalAddressInformation(left, 0, &gdesc1))
  360. return !GetGlobalAddressInformation(right - 1, 0, &gdesc2) ||
  361. !gdesc1.PointsInsideTheSameVariable(gdesc2);
  362. if (t->GetStackVariableShadowStart(right) ||
  363. GetHeapAddressInformation(right, 0, &hdesc2) ||
  364. GetGlobalAddressInformation(right - 1, 0, &gdesc2))
  365. return true;
  366. // At this point we know nothing about both a1 and a2 addresses.
  367. return false;
  368. }
  369. static inline void CheckForInvalidPointerPair(void *p1, void *p2) {
  370. switch (flags()->detect_invalid_pointer_pairs) {
  371. case 0:
  372. return;
  373. case 1:
  374. if (p1 == nullptr || p2 == nullptr)
  375. return;
  376. break;
  377. }
  378. uptr a1 = reinterpret_cast<uptr>(p1);
  379. uptr a2 = reinterpret_cast<uptr>(p2);
  380. if (IsInvalidPointerPair(a1, a2)) {
  381. GET_CALLER_PC_BP_SP;
  382. ReportInvalidPointerPair(pc, bp, sp, a1, a2);
  383. }
  384. }
  385. // ----------------------- Mac-specific reports ----------------- {{{1
  386. void ReportMacMzReallocUnknown(uptr addr, uptr zone_ptr, const char *zone_name,
  387. BufferedStackTrace *stack) {
  388. ScopedInErrorReport in_report;
  389. Printf(
  390. "mz_realloc(%p) -- attempting to realloc unallocated memory.\n"
  391. "This is an unrecoverable problem, exiting now.\n",
  392. (void *)addr);
  393. PrintZoneForPointer(addr, zone_ptr, zone_name);
  394. stack->Print();
  395. DescribeAddressIfHeap(addr);
  396. }
  397. // -------------- SuppressErrorReport -------------- {{{1
  398. // Avoid error reports duplicating for ASan recover mode.
  399. static bool SuppressErrorReport(uptr pc) {
  400. if (!common_flags()->suppress_equal_pcs) return false;
  401. for (unsigned i = 0; i < kAsanBuggyPcPoolSize; i++) {
  402. uptr cmp = atomic_load_relaxed(&AsanBuggyPcPool[i]);
  403. if (cmp == 0 && atomic_compare_exchange_strong(&AsanBuggyPcPool[i], &cmp,
  404. pc, memory_order_relaxed))
  405. return false;
  406. if (cmp == pc) return true;
  407. }
  408. Die();
  409. }
  410. void ReportGenericError(uptr pc, uptr bp, uptr sp, uptr addr, bool is_write,
  411. uptr access_size, u32 exp, bool fatal) {
  412. if (__asan_test_only_reported_buggy_pointer) {
  413. *__asan_test_only_reported_buggy_pointer = addr;
  414. return;
  415. }
  416. if (!fatal && SuppressErrorReport(pc)) return;
  417. ENABLE_FRAME_POINTER;
  418. // Optimization experiments.
  419. // The experiments can be used to evaluate potential optimizations that remove
  420. // instrumentation (assess false negatives). Instead of completely removing
  421. // some instrumentation, compiler can emit special calls into runtime
  422. // (e.g. __asan_report_exp_load1 instead of __asan_report_load1) and pass
  423. // mask of experiments (exp).
  424. // The reaction to a non-zero value of exp is to be defined.
  425. (void)exp;
  426. ScopedInErrorReport in_report(fatal);
  427. ErrorGeneric error(GetCurrentTidOrInvalid(), pc, bp, sp, addr, is_write,
  428. access_size);
  429. in_report.ReportError(error);
  430. }
  431. } // namespace __asan
  432. // --------------------------- Interface --------------------- {{{1
  433. using namespace __asan;
  434. void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write,
  435. uptr access_size, u32 exp) {
  436. ENABLE_FRAME_POINTER;
  437. bool fatal = flags()->halt_on_error;
  438. ReportGenericError(pc, bp, sp, addr, is_write, access_size, exp, fatal);
  439. }
  440. void NOINLINE __asan_set_error_report_callback(void (*callback)(const char*)) {
  441. Lock l(&error_message_buf_mutex);
  442. error_report_callback = callback;
  443. }
  444. void __asan_describe_address(uptr addr) {
  445. // Thread registry must be locked while we're describing an address.
  446. asanThreadRegistry().Lock();
  447. PrintAddressDescription(addr, 1, "");
  448. asanThreadRegistry().Unlock();
  449. }
  450. int __asan_report_present() {
  451. return ScopedInErrorReport::CurrentError().kind != kErrorKindInvalid;
  452. }
  453. uptr __asan_get_report_pc() {
  454. if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
  455. return ScopedInErrorReport::CurrentError().Generic.pc;
  456. return 0;
  457. }
  458. uptr __asan_get_report_bp() {
  459. if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
  460. return ScopedInErrorReport::CurrentError().Generic.bp;
  461. return 0;
  462. }
  463. uptr __asan_get_report_sp() {
  464. if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
  465. return ScopedInErrorReport::CurrentError().Generic.sp;
  466. return 0;
  467. }
  468. uptr __asan_get_report_address() {
  469. ErrorDescription &err = ScopedInErrorReport::CurrentError();
  470. if (err.kind == kErrorKindGeneric)
  471. return err.Generic.addr_description.Address();
  472. else if (err.kind == kErrorKindDoubleFree)
  473. return err.DoubleFree.addr_description.addr;
  474. return 0;
  475. }
  476. int __asan_get_report_access_type() {
  477. if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
  478. return ScopedInErrorReport::CurrentError().Generic.is_write;
  479. return 0;
  480. }
  481. uptr __asan_get_report_access_size() {
  482. if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
  483. return ScopedInErrorReport::CurrentError().Generic.access_size;
  484. return 0;
  485. }
  486. const char *__asan_get_report_description() {
  487. if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
  488. return ScopedInErrorReport::CurrentError().Generic.bug_descr;
  489. return ScopedInErrorReport::CurrentError().Base.scariness.GetDescription();
  490. }
  491. extern "C" {
  492. SANITIZER_INTERFACE_ATTRIBUTE
  493. void __sanitizer_ptr_sub(void *a, void *b) {
  494. CheckForInvalidPointerPair(a, b);
  495. }
  496. SANITIZER_INTERFACE_ATTRIBUTE
  497. void __sanitizer_ptr_cmp(void *a, void *b) {
  498. CheckForInvalidPointerPair(a, b);
  499. }
  500. } // extern "C"
  501. // Provide default implementation of __asan_on_error that does nothing
  502. // and may be overriden by user.
  503. SANITIZER_INTERFACE_WEAK_DEF(void, __asan_on_error, void) {}