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 
21 namespace __asan {
22 
23 void DescribeThread(AsanThreadContext *context);
DescribeThread(AsanThread * t)24 static inline void DescribeThread(AsanThread *t) {
25   if (t) DescribeThread(t->context());
26 }
27 const char *ThreadNameWithParenthesis(AsanThreadContext *t, char buff[],
28                                       uptr buff_len);
29 const char *ThreadNameWithParenthesis(u32 tid, char buff[], uptr buff_len);
30 
31 class Decorator : public __sanitizer::SanitizerCommonDecorator {
32  public:
Decorator()33   Decorator() : SanitizerCommonDecorator() {}
Access()34   const char *Access() { return Blue(); }
Location()35   const char *Location() { return Green(); }
Allocation()36   const char *Allocation() { return Magenta(); }
37 
ShadowByte(u8 byte)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 
72 enum ShadowKind : u8 {
73   kShadowKindLow,
74   kShadowKindGap,
75   kShadowKindHigh,
76 };
77 static const char *const ShadowNames[] = {"low shadow", "shadow gap",
78                                           "high shadow"};
79 
80 struct ShadowAddressDescription {
81   uptr addr;
82   ShadowKind kind;
83   u8 shadow_byte;
84 
85   void Print() const;
86 };
87 
88 bool GetShadowAddressInformation(uptr addr, ShadowAddressDescription *descr);
89 bool DescribeAddressIfShadow(uptr addr);
90 
91 enum AccessType {
92   kAccessTypeLeft,
93   kAccessTypeRight,
94   kAccessTypeInside,
95   kAccessTypeUnknown,  // This means we have an AddressSanitizer bug!
96 };
97 
98 struct 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 
107 struct 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 
118 bool GetHeapAddressInformation(uptr addr, uptr access_size,
119                                HeapAddressDescription *descr);
120 bool DescribeAddressIfHeap(uptr addr, uptr access_size = 1);
121 
122 struct 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 
133 bool GetStackAddressInformation(uptr addr, uptr access_size,
134                                 StackAddressDescription *descr);
135 
136 struct 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 
152 bool GetGlobalAddressInformation(uptr addr, uptr access_size,
153                                  GlobalAddressDescription *descr);
154 bool 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.
164 void PrintAddressDescription(uptr addr, uptr access_size = 1,
165                              const char *bug_type = "");
166 
167 enum AddressKind {
168   kAddressKindWild,
169   kAddressKindShadow,
170   kAddressKindHeap,
171   kAddressKindStack,
172   kAddressKindGlobal,
173 };
174 
175 class 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 
Address()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 
StoreTo(AddressDescriptionData * dst)231   void StoreTo(AddressDescriptionData *dst) const { *dst = data; }
232 
AsShadow()233   const ShadowAddressDescription *AsShadow() const {
234     return data.kind == kAddressKindShadow ? &data.shadow : nullptr;
235   }
AsHeap()236   const HeapAddressDescription *AsHeap() const {
237     return data.kind == kAddressKindHeap ? &data.heap : nullptr;
238   }
AsStack()239   const StackAddressDescription *AsStack() const {
240     return data.kind == kAddressKindStack ? &data.stack : nullptr;
241   }
AsGlobal()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