asan_descriptions.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  1. //===-- asan_descriptions.cpp -----------------------------------*- 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 functions for getting information about an address and/or printing it.
  12. //===----------------------------------------------------------------------===//
  13. #include "asan_descriptions.h"
  14. #include "asan_mapping.h"
  15. #include "asan_report.h"
  16. #include "asan_stack.h"
  17. #include "sanitizer_common/sanitizer_stackdepot.h"
  18. namespace __asan {
  19. AsanThreadIdAndName::AsanThreadIdAndName(AsanThreadContext *t) {
  20. Init(t->tid, t->name);
  21. }
  22. AsanThreadIdAndName::AsanThreadIdAndName(u32 tid) {
  23. if (tid == kInvalidTid) {
  24. Init(tid, "");
  25. } else {
  26. asanThreadRegistry().CheckLocked();
  27. AsanThreadContext *t = GetThreadContextByTidLocked(tid);
  28. Init(tid, t->name);
  29. }
  30. }
  31. void AsanThreadIdAndName::Init(u32 tid, const char *tname) {
  32. int len = internal_snprintf(name, sizeof(name), "T%d", tid);
  33. CHECK(((unsigned int)len) < sizeof(name));
  34. if (tname[0] != '\0')
  35. internal_snprintf(&name[len], sizeof(name) - len, " (%s)", tname);
  36. }
  37. void DescribeThread(AsanThreadContext *context) {
  38. CHECK(context);
  39. asanThreadRegistry().CheckLocked();
  40. // No need to announce the main thread.
  41. if (context->tid == kMainTid || context->announced) {
  42. return;
  43. }
  44. context->announced = true;
  45. InternalScopedString str;
  46. str.append("Thread %s", AsanThreadIdAndName(context).c_str());
  47. if (context->parent_tid == kInvalidTid) {
  48. str.append(" created by unknown thread\n");
  49. Printf("%s", str.data());
  50. return;
  51. }
  52. str.append(" created by %s here:\n",
  53. AsanThreadIdAndName(context->parent_tid).c_str());
  54. Printf("%s", str.data());
  55. StackDepotGet(context->stack_id).Print();
  56. // Recursively described parent thread if needed.
  57. if (flags()->print_full_thread_history) {
  58. AsanThreadContext *parent_context =
  59. GetThreadContextByTidLocked(context->parent_tid);
  60. DescribeThread(parent_context);
  61. }
  62. }
  63. // Shadow descriptions
  64. static bool GetShadowKind(uptr addr, ShadowKind *shadow_kind) {
  65. CHECK(!AddrIsInMem(addr));
  66. if (AddrIsInShadowGap(addr)) {
  67. *shadow_kind = kShadowKindGap;
  68. } else if (AddrIsInHighShadow(addr)) {
  69. *shadow_kind = kShadowKindHigh;
  70. } else if (AddrIsInLowShadow(addr)) {
  71. *shadow_kind = kShadowKindLow;
  72. } else {
  73. return false;
  74. }
  75. return true;
  76. }
  77. bool DescribeAddressIfShadow(uptr addr) {
  78. ShadowAddressDescription descr;
  79. if (!GetShadowAddressInformation(addr, &descr)) return false;
  80. descr.Print();
  81. return true;
  82. }
  83. bool GetShadowAddressInformation(uptr addr, ShadowAddressDescription *descr) {
  84. if (AddrIsInMem(addr)) return false;
  85. ShadowKind shadow_kind;
  86. if (!GetShadowKind(addr, &shadow_kind)) return false;
  87. if (shadow_kind != kShadowKindGap) descr->shadow_byte = *(u8 *)addr;
  88. descr->addr = addr;
  89. descr->kind = shadow_kind;
  90. return true;
  91. }
  92. // Heap descriptions
  93. static void GetAccessToHeapChunkInformation(ChunkAccess *descr,
  94. AsanChunkView chunk, uptr addr,
  95. uptr access_size) {
  96. descr->bad_addr = addr;
  97. if (chunk.AddrIsAtLeft(addr, access_size, &descr->offset)) {
  98. descr->access_type = kAccessTypeLeft;
  99. } else if (chunk.AddrIsAtRight(addr, access_size, &descr->offset)) {
  100. descr->access_type = kAccessTypeRight;
  101. if (descr->offset < 0) {
  102. descr->bad_addr -= descr->offset;
  103. descr->offset = 0;
  104. }
  105. } else if (chunk.AddrIsInside(addr, access_size, &descr->offset)) {
  106. descr->access_type = kAccessTypeInside;
  107. } else {
  108. descr->access_type = kAccessTypeUnknown;
  109. }
  110. descr->chunk_begin = chunk.Beg();
  111. descr->chunk_size = chunk.UsedSize();
  112. descr->user_requested_alignment = chunk.UserRequestedAlignment();
  113. descr->alloc_type = chunk.GetAllocType();
  114. }
  115. static void PrintHeapChunkAccess(uptr addr, const ChunkAccess &descr) {
  116. Decorator d;
  117. InternalScopedString str;
  118. str.append("%s", d.Location());
  119. switch (descr.access_type) {
  120. case kAccessTypeLeft:
  121. str.append("%p is located %zd bytes before",
  122. (void *)descr.bad_addr, descr.offset);
  123. break;
  124. case kAccessTypeRight:
  125. str.append("%p is located %zd bytes after",
  126. (void *)descr.bad_addr, descr.offset);
  127. break;
  128. case kAccessTypeInside:
  129. str.append("%p is located %zd bytes inside of", (void *)descr.bad_addr,
  130. descr.offset);
  131. break;
  132. case kAccessTypeUnknown:
  133. str.append(
  134. "%p is located somewhere around (this is AddressSanitizer bug!)",
  135. (void *)descr.bad_addr);
  136. }
  137. str.append(" %zu-byte region [%p,%p)\n", descr.chunk_size,
  138. (void *)descr.chunk_begin,
  139. (void *)(descr.chunk_begin + descr.chunk_size));
  140. str.append("%s", d.Default());
  141. Printf("%s", str.data());
  142. }
  143. bool GetHeapAddressInformation(uptr addr, uptr access_size,
  144. HeapAddressDescription *descr) {
  145. AsanChunkView chunk = FindHeapChunkByAddress(addr);
  146. if (!chunk.IsValid()) {
  147. return false;
  148. }
  149. descr->addr = addr;
  150. GetAccessToHeapChunkInformation(&descr->chunk_access, chunk, addr,
  151. access_size);
  152. CHECK_NE(chunk.AllocTid(), kInvalidTid);
  153. descr->alloc_tid = chunk.AllocTid();
  154. descr->alloc_stack_id = chunk.GetAllocStackId();
  155. descr->free_tid = chunk.FreeTid();
  156. if (descr->free_tid != kInvalidTid)
  157. descr->free_stack_id = chunk.GetFreeStackId();
  158. return true;
  159. }
  160. static StackTrace GetStackTraceFromId(u32 id) {
  161. CHECK(id);
  162. StackTrace res = StackDepotGet(id);
  163. CHECK(res.trace);
  164. return res;
  165. }
  166. bool DescribeAddressIfHeap(uptr addr, uptr access_size) {
  167. HeapAddressDescription descr;
  168. if (!GetHeapAddressInformation(addr, access_size, &descr)) {
  169. Printf(
  170. "AddressSanitizer can not describe address in more detail "
  171. "(wild memory access suspected).\n");
  172. return false;
  173. }
  174. descr.Print();
  175. return true;
  176. }
  177. // Stack descriptions
  178. bool GetStackAddressInformation(uptr addr, uptr access_size,
  179. StackAddressDescription *descr) {
  180. AsanThread *t = FindThreadByStackAddress(addr);
  181. if (!t) return false;
  182. descr->addr = addr;
  183. descr->tid = t->tid();
  184. // Try to fetch precise stack frame for this access.
  185. AsanThread::StackFrameAccess access;
  186. if (!t->GetStackFrameAccessByAddr(addr, &access)) {
  187. descr->frame_descr = nullptr;
  188. return true;
  189. }
  190. descr->offset = access.offset;
  191. descr->access_size = access_size;
  192. descr->frame_pc = access.frame_pc;
  193. descr->frame_descr = access.frame_descr;
  194. #if SANITIZER_PPC64V1
  195. // On PowerPC64 ELFv1, the address of a function actually points to a
  196. // three-doubleword data structure with the first field containing
  197. // the address of the function's code.
  198. descr->frame_pc = *reinterpret_cast<uptr *>(descr->frame_pc);
  199. #endif
  200. descr->frame_pc += 16;
  201. return true;
  202. }
  203. static void PrintAccessAndVarIntersection(const StackVarDescr &var, uptr addr,
  204. uptr access_size, uptr prev_var_end,
  205. uptr next_var_beg) {
  206. uptr var_end = var.beg + var.size;
  207. uptr addr_end = addr + access_size;
  208. const char *pos_descr = nullptr;
  209. // If the variable [var.beg, var_end) is the nearest variable to the
  210. // current memory access, indicate it in the log.
  211. if (addr >= var.beg) {
  212. if (addr_end <= var_end)
  213. pos_descr = "is inside"; // May happen if this is a use-after-return.
  214. else if (addr < var_end)
  215. pos_descr = "partially overflows";
  216. else if (addr_end <= next_var_beg &&
  217. next_var_beg - addr_end >= addr - var_end)
  218. pos_descr = "overflows";
  219. } else {
  220. if (addr_end > var.beg)
  221. pos_descr = "partially underflows";
  222. else if (addr >= prev_var_end && addr - prev_var_end >= var.beg - addr_end)
  223. pos_descr = "underflows";
  224. }
  225. InternalScopedString str;
  226. str.append(" [%zd, %zd)", var.beg, var_end);
  227. // Render variable name.
  228. str.append(" '");
  229. for (uptr i = 0; i < var.name_len; ++i) {
  230. str.append("%c", var.name_pos[i]);
  231. }
  232. str.append("'");
  233. if (var.line > 0) {
  234. str.append(" (line %zd)", var.line);
  235. }
  236. if (pos_descr) {
  237. Decorator d;
  238. // FIXME: we may want to also print the size of the access here,
  239. // but in case of accesses generated by memset it may be confusing.
  240. str.append("%s <== Memory access at offset %zd %s this variable%s\n",
  241. d.Location(), addr, pos_descr, d.Default());
  242. } else {
  243. str.append("\n");
  244. }
  245. Printf("%s", str.data());
  246. }
  247. bool DescribeAddressIfStack(uptr addr, uptr access_size) {
  248. StackAddressDescription descr;
  249. if (!GetStackAddressInformation(addr, access_size, &descr)) return false;
  250. descr.Print();
  251. return true;
  252. }
  253. // Global descriptions
  254. static void DescribeAddressRelativeToGlobal(uptr addr, uptr access_size,
  255. const __asan_global &g) {
  256. InternalScopedString str;
  257. Decorator d;
  258. str.append("%s", d.Location());
  259. if (addr < g.beg) {
  260. str.append("%p is located %zd bytes before", (void *)addr,
  261. g.beg - addr);
  262. } else if (addr + access_size > g.beg + g.size) {
  263. if (addr < g.beg + g.size) addr = g.beg + g.size;
  264. str.append("%p is located %zd bytes after", (void *)addr,
  265. addr - (g.beg + g.size));
  266. } else {
  267. // Can it happen?
  268. str.append("%p is located %zd bytes inside of", (void *)addr, addr - g.beg);
  269. }
  270. str.append(" global variable '%s' defined in '",
  271. MaybeDemangleGlobalName(g.name));
  272. PrintGlobalLocation(&str, g);
  273. str.append("' (0x%zx) of size %zu\n", g.beg, g.size);
  274. str.append("%s", d.Default());
  275. PrintGlobalNameIfASCII(&str, g);
  276. Printf("%s", str.data());
  277. }
  278. bool GetGlobalAddressInformation(uptr addr, uptr access_size,
  279. GlobalAddressDescription *descr) {
  280. descr->addr = addr;
  281. int globals_num = GetGlobalsForAddress(addr, descr->globals, descr->reg_sites,
  282. ARRAY_SIZE(descr->globals));
  283. descr->size = globals_num;
  284. descr->access_size = access_size;
  285. return globals_num != 0;
  286. }
  287. bool DescribeAddressIfGlobal(uptr addr, uptr access_size,
  288. const char *bug_type) {
  289. GlobalAddressDescription descr;
  290. if (!GetGlobalAddressInformation(addr, access_size, &descr)) return false;
  291. descr.Print(bug_type);
  292. return true;
  293. }
  294. void ShadowAddressDescription::Print() const {
  295. Printf("Address %p is located in the %s area.\n", (void *)addr,
  296. ShadowNames[kind]);
  297. }
  298. void GlobalAddressDescription::Print(const char *bug_type) const {
  299. for (int i = 0; i < size; i++) {
  300. DescribeAddressRelativeToGlobal(addr, access_size, globals[i]);
  301. if (bug_type &&
  302. 0 == internal_strcmp(bug_type, "initialization-order-fiasco") &&
  303. reg_sites[i]) {
  304. Printf(" registered at:\n");
  305. StackDepotGet(reg_sites[i]).Print();
  306. }
  307. }
  308. }
  309. bool GlobalAddressDescription::PointsInsideTheSameVariable(
  310. const GlobalAddressDescription &other) const {
  311. if (size == 0 || other.size == 0) return false;
  312. for (uptr i = 0; i < size; i++) {
  313. const __asan_global &a = globals[i];
  314. for (uptr j = 0; j < other.size; j++) {
  315. const __asan_global &b = other.globals[j];
  316. if (a.beg == b.beg &&
  317. a.beg <= addr &&
  318. b.beg <= other.addr &&
  319. (addr + access_size) < (a.beg + a.size) &&
  320. (other.addr + other.access_size) < (b.beg + b.size))
  321. return true;
  322. }
  323. }
  324. return false;
  325. }
  326. void StackAddressDescription::Print() const {
  327. Decorator d;
  328. Printf("%s", d.Location());
  329. Printf("Address %p is located in stack of thread %s", (void *)addr,
  330. AsanThreadIdAndName(tid).c_str());
  331. if (!frame_descr) {
  332. Printf("%s\n", d.Default());
  333. return;
  334. }
  335. Printf(" at offset %zu in frame%s\n", offset, d.Default());
  336. // Now we print the frame where the alloca has happened.
  337. // We print this frame as a stack trace with one element.
  338. // The symbolizer may print more than one frame if inlining was involved.
  339. // The frame numbers may be different than those in the stack trace printed
  340. // previously. That's unfortunate, but I have no better solution,
  341. // especially given that the alloca may be from entirely different place
  342. // (e.g. use-after-scope, or different thread's stack).
  343. Printf("%s", d.Default());
  344. StackTrace alloca_stack(&frame_pc, 1);
  345. alloca_stack.Print();
  346. InternalMmapVector<StackVarDescr> vars;
  347. vars.reserve(16);
  348. if (!ParseFrameDescription(frame_descr, &vars)) {
  349. Printf(
  350. "AddressSanitizer can't parse the stack frame "
  351. "descriptor: |%s|\n",
  352. frame_descr);
  353. // 'addr' is a stack address, so return true even if we can't parse frame
  354. return;
  355. }
  356. uptr n_objects = vars.size();
  357. // Report the number of stack objects.
  358. Printf(" This frame has %zu object(s):\n", n_objects);
  359. // Report all objects in this frame.
  360. for (uptr i = 0; i < n_objects; i++) {
  361. uptr prev_var_end = i ? vars[i - 1].beg + vars[i - 1].size : 0;
  362. uptr next_var_beg = i + 1 < n_objects ? vars[i + 1].beg : ~(0UL);
  363. PrintAccessAndVarIntersection(vars[i], offset, access_size, prev_var_end,
  364. next_var_beg);
  365. }
  366. Printf(
  367. "HINT: this may be a false positive if your program uses "
  368. "some custom stack unwind mechanism, swapcontext or vfork\n");
  369. if (SANITIZER_WINDOWS)
  370. Printf(" (longjmp, SEH and C++ exceptions *are* supported)\n");
  371. else
  372. Printf(" (longjmp and C++ exceptions *are* supported)\n");
  373. DescribeThread(GetThreadContextByTidLocked(tid));
  374. }
  375. void HeapAddressDescription::Print() const {
  376. PrintHeapChunkAccess(addr, chunk_access);
  377. asanThreadRegistry().CheckLocked();
  378. AsanThreadContext *alloc_thread = GetThreadContextByTidLocked(alloc_tid);
  379. StackTrace alloc_stack = GetStackTraceFromId(alloc_stack_id);
  380. Decorator d;
  381. AsanThreadContext *free_thread = nullptr;
  382. if (free_tid != kInvalidTid) {
  383. free_thread = GetThreadContextByTidLocked(free_tid);
  384. Printf("%sfreed by thread %s here:%s\n", d.Allocation(),
  385. AsanThreadIdAndName(free_thread).c_str(), d.Default());
  386. StackTrace free_stack = GetStackTraceFromId(free_stack_id);
  387. free_stack.Print();
  388. Printf("%spreviously allocated by thread %s here:%s\n", d.Allocation(),
  389. AsanThreadIdAndName(alloc_thread).c_str(), d.Default());
  390. } else {
  391. Printf("%sallocated by thread %s here:%s\n", d.Allocation(),
  392. AsanThreadIdAndName(alloc_thread).c_str(), d.Default());
  393. }
  394. alloc_stack.Print();
  395. DescribeThread(GetCurrentThread());
  396. if (free_thread) DescribeThread(free_thread);
  397. DescribeThread(alloc_thread);
  398. }
  399. AddressDescription::AddressDescription(uptr addr, uptr access_size,
  400. bool shouldLockThreadRegistry) {
  401. if (GetShadowAddressInformation(addr, &data.shadow)) {
  402. data.kind = kAddressKindShadow;
  403. return;
  404. }
  405. if (GetHeapAddressInformation(addr, access_size, &data.heap)) {
  406. data.kind = kAddressKindHeap;
  407. return;
  408. }
  409. bool isStackMemory = false;
  410. if (shouldLockThreadRegistry) {
  411. ThreadRegistryLock l(&asanThreadRegistry());
  412. isStackMemory = GetStackAddressInformation(addr, access_size, &data.stack);
  413. } else {
  414. isStackMemory = GetStackAddressInformation(addr, access_size, &data.stack);
  415. }
  416. if (isStackMemory) {
  417. data.kind = kAddressKindStack;
  418. return;
  419. }
  420. if (GetGlobalAddressInformation(addr, access_size, &data.global)) {
  421. data.kind = kAddressKindGlobal;
  422. return;
  423. }
  424. data.kind = kAddressKindWild;
  425. data.wild.addr = addr;
  426. data.wild.access_size = access_size;
  427. }
  428. void WildAddressDescription::Print() const {
  429. Printf("Address %p is a wild pointer inside of access range of size %p.\n",
  430. (void *)addr, (void *)access_size);
  431. }
  432. void PrintAddressDescription(uptr addr, uptr access_size,
  433. const char *bug_type) {
  434. ShadowAddressDescription shadow_descr;
  435. if (GetShadowAddressInformation(addr, &shadow_descr)) {
  436. shadow_descr.Print();
  437. return;
  438. }
  439. GlobalAddressDescription global_descr;
  440. if (GetGlobalAddressInformation(addr, access_size, &global_descr)) {
  441. global_descr.Print(bug_type);
  442. return;
  443. }
  444. StackAddressDescription stack_descr;
  445. if (GetStackAddressInformation(addr, access_size, &stack_descr)) {
  446. stack_descr.Print();
  447. return;
  448. }
  449. HeapAddressDescription heap_descr;
  450. if (GetHeapAddressInformation(addr, access_size, &heap_descr)) {
  451. heap_descr.Print();
  452. return;
  453. }
  454. // We exhausted our possibilities. Bail out.
  455. Printf(
  456. "AddressSanitizer can not describe address in more detail "
  457. "(wild memory access suspected).\n");
  458. }
  459. } // namespace __asan