asan_descriptions.h revision 1.1.1.2
1//===-- asan_descriptions.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 asan_descriptions.cc.
11// TODO(filcab): Most struct definitions should move to the interface headers.
12//===----------------------------------------------------------------------===//
13#ifndef ASAN_DESCRIPTIONS_H
14#define ASAN_DESCRIPTIONS_H
15
16#include "asan_allocator.h"
17#include "asan_thread.h"
18#include "sanitizer_common/sanitizer_common.h"
19#include "sanitizer_common/sanitizer_report_decorator.h"
20
21namespace __asan {
22
23void DescribeThread(AsanThreadContext *context);
24static inline void DescribeThread(AsanThread *t) {
25  if (t) DescribeThread(t->context());
26}
27const char *ThreadNameWithParenthesis(AsanThreadContext *t, char buff[],
28                                      uptr buff_len);
29const char *ThreadNameWithParenthesis(u32 tid, char buff[], uptr buff_len);
30
31class Decorator : public __sanitizer::SanitizerCommonDecorator {
32 public:
33  Decorator() : SanitizerCommonDecorator() {}
34  const char *Access() { return Blue(); }
35  const char *Location() { return Green(); }
36  const char *Allocation() { return Magenta(); }
37
38  const char *ShadowByte(u8 byte) {
39    switch (byte) {
40      case kAsanHeapLeftRedzoneMagic:
41      case kAsanArrayCookieMagic:
42        return Red();
43      case kAsanHeapFreeMagic:
44        return Magenta();
45      case kAsanStackLeftRedzoneMagic:
46      case kAsanStackMidRedzoneMagic:
47      case kAsanStackRightRedzoneMagic:
48        return Red();
49      case kAsanStackAfterReturnMagic:
50        return Magenta();
51      case kAsanInitializationOrderMagic:
52        return Cyan();
53      case kAsanUserPoisonedMemoryMagic:
54      case kAsanContiguousContainerOOBMagic:
55      case kAsanAllocaLeftMagic:
56      case kAsanAllocaRightMagic:
57        return Blue();
58      case kAsanStackUseAfterScopeMagic:
59        return Magenta();
60      case kAsanGlobalRedzoneMagic:
61        return Red();
62      case kAsanInternalHeapMagic:
63        return Yellow();
64      case kAsanIntraObjectRedzone:
65        return Yellow();
66      default:
67        return Default();
68    }
69  }
70};
71
72enum ShadowKind : u8 {
73  kShadowKindLow,
74  kShadowKindGap,
75  kShadowKindHigh,
76};
77static const char *const ShadowNames[] = {"low shadow", "shadow gap",
78                                          "high shadow"};
79
80struct ShadowAddressDescription {
81  uptr addr;
82  ShadowKind kind;
83  u8 shadow_byte;
84
85  void Print() const;
86};
87
88bool GetShadowAddressInformation(uptr addr, ShadowAddressDescription *descr);
89bool DescribeAddressIfShadow(uptr addr);
90
91enum AccessType {
92  kAccessTypeLeft,
93  kAccessTypeRight,
94  kAccessTypeInside,
95  kAccessTypeUnknown,  // This means we have an AddressSanitizer bug!
96};
97
98struct ChunkAccess {
99  uptr bad_addr;
100  sptr offset;
101  uptr chunk_begin;
102  uptr chunk_size;
103  u32 access_type : 2;
104  u32 alloc_type : 2;
105};
106
107struct HeapAddressDescription {
108  uptr addr;
109  uptr alloc_tid;
110  uptr free_tid;
111  u32 alloc_stack_id;
112  u32 free_stack_id;
113  ChunkAccess chunk_access;
114
115  void Print() const;
116};
117
118bool GetHeapAddressInformation(uptr addr, uptr access_size,
119                               HeapAddressDescription *descr);
120bool DescribeAddressIfHeap(uptr addr, uptr access_size = 1);
121
122struct StackAddressDescription {
123  uptr addr;
124  uptr tid;
125  uptr offset;
126  uptr frame_pc;
127  uptr access_size;
128  const char *frame_descr;
129
130  void Print() const;
131};
132
133bool GetStackAddressInformation(uptr addr, uptr access_size,
134                                StackAddressDescription *descr);
135
136struct GlobalAddressDescription {
137  uptr addr;
138  // Assume address is close to at most four globals.
139  static const int kMaxGlobals = 4;
140  __asan_global globals[kMaxGlobals];
141  u32 reg_sites[kMaxGlobals];
142  uptr access_size;
143  u8 size;
144
145  void Print(const char *bug_type = "") const;
146
147  // Returns true when this descriptions points inside the same global variable
148  // as other. Descriptions can have different address within the variable
149  bool PointsInsideTheSameVariable(const GlobalAddressDescription &other) const;
150};
151
152bool GetGlobalAddressInformation(uptr addr, uptr access_size,
153                                 GlobalAddressDescription *descr);
154bool DescribeAddressIfGlobal(uptr addr, uptr access_size, const char *bug_type);
155
156// General function to describe an address. Will try to describe the address as
157// a shadow, global (variable), stack, or heap address.
158// bug_type is optional and is used for checking if we're reporting an
159// initialization-order-fiasco
160// The proper access_size should be passed for stack, global, and heap
161// addresses. Defaults to 1.
162// Each of the *AddressDescription functions has its own Print() member, which
163// may take access_size and bug_type parameters if needed.
164void PrintAddressDescription(uptr addr, uptr access_size = 1,
165                             const char *bug_type = "");
166
167enum AddressKind {
168  kAddressKindWild,
169  kAddressKindShadow,
170  kAddressKindHeap,
171  kAddressKindStack,
172  kAddressKindGlobal,
173};
174
175class AddressDescription {
176  struct AddressDescriptionData {
177    AddressKind kind;
178    union {
179      ShadowAddressDescription shadow;
180      HeapAddressDescription heap;
181      StackAddressDescription stack;
182      GlobalAddressDescription global;
183      uptr addr;
184    };
185  };
186
187  AddressDescriptionData data;
188
189 public:
190  AddressDescription() = default;
191  // shouldLockThreadRegistry allows us to skip locking if we're sure we already
192  // have done it.
193  AddressDescription(uptr addr, bool shouldLockThreadRegistry = true)
194      : AddressDescription(addr, 1, shouldLockThreadRegistry) {}
195  AddressDescription(uptr addr, uptr access_size,
196                     bool shouldLockThreadRegistry = true);
197
198  uptr Address() const {
199    switch (data.kind) {
200      case kAddressKindWild:
201        return data.addr;
202      case kAddressKindShadow:
203        return data.shadow.addr;
204      case kAddressKindHeap:
205        return data.heap.addr;
206      case kAddressKindStack:
207        return data.stack.addr;
208      case kAddressKindGlobal:
209        return data.global.addr;
210    }
211    UNREACHABLE("AddressInformation kind is invalid");
212  }
213  void Print(const char *bug_descr = nullptr) const {
214    switch (data.kind) {
215      case kAddressKindWild:
216        Printf("Address %p is a wild pointer.\n", data.addr);
217        return;
218      case kAddressKindShadow:
219        return data.shadow.Print();
220      case kAddressKindHeap:
221        return data.heap.Print();
222      case kAddressKindStack:
223        return data.stack.Print();
224      case kAddressKindGlobal:
225        // initialization-order-fiasco has a special Print()
226        return data.global.Print(bug_descr);
227    }
228    UNREACHABLE("AddressInformation kind is invalid");
229  }
230
231  void StoreTo(AddressDescriptionData *dst) const { *dst = data; }
232
233  const ShadowAddressDescription *AsShadow() const {
234    return data.kind == kAddressKindShadow ? &data.shadow : nullptr;
235  }
236  const HeapAddressDescription *AsHeap() const {
237    return data.kind == kAddressKindHeap ? &data.heap : nullptr;
238  }
239  const StackAddressDescription *AsStack() const {
240    return data.kind == kAddressKindStack ? &data.stack : nullptr;
241  }
242  const GlobalAddressDescription *AsGlobal() const {
243    return data.kind == kAddressKindGlobal ? &data.global : nullptr;
244  }
245};
246
247}  // namespace __asan
248
249#endif  // ASAN_DESCRIPTIONS_H
250