21 #include "t_heapcorruption.h" |
21 #include "t_heapcorruption.h" |
22 #include <e32base.h> |
22 #include <e32base.h> |
23 #include <e32base_private.h> |
23 #include <e32base_private.h> |
24 #include <e32cmn.h> |
24 #include <e32cmn.h> |
25 #include <e32cmn_private.h> |
25 #include <e32cmn_private.h> |
26 |
26 #include "dla.h" |
27 |
27 #include "slab.h" |
28 #define __NEXT_CELL(p) ((SCell*)(((TUint8*)p)+p->len)) |
28 #include "page_alloc.h" |
|
29 #include "heap_hybrid.h" |
29 |
30 |
30 TBool gEnableMemoryMonitor = EFalse; |
31 TBool gEnableMemoryMonitor = EFalse; |
31 |
32 |
|
33 #ifdef _DEBUG |
|
34 const TInt KDbgHeaderSize = (TInt)RHeap::EDebugHdrSize; |
|
35 #else |
|
36 const TInt KDbgHeaderSize = 0; |
|
37 #endif |
32 |
38 |
33 /** |
39 /** |
34 Test heap that will corrupt some cells to generate BTrace events. |
40 Friend class of RHeapHybrid to access to hybrid heap metadata |
35 */ |
41 */ |
36 class RMyDummyHeap : public RHeap |
42 class TestHybridHeap |
37 { |
43 { |
38 public: |
44 public: |
39 //EBadFreeCellAddress |
45 TBool Init(); |
40 void CorruptFreeMemory1() |
46 TBool Check(); |
41 { |
47 TInt AllocLen(TAny* aBfr); |
42 SCell* f = (SCell*)&iFree; |
48 void EnableHeavyMemoryMonitoring(); |
43 f->next = (SCell*)iTop; |
49 void CorruptFreeDLBfr(TAny* aBfr); |
44 f->next += sizeof(TUint8); |
50 void CorruptFreeDLBfrLth(TAny* aBfr); |
45 } |
51 void CorruptAllocatedDLBfrSize(TAny* aBfr); |
46 |
52 TAny* CorruptAllocatedDLMemoryAddress(TAny* aBfr); |
47 //EBadFreeCellSize |
53 |
48 void CorruptFreeMemory2() |
54 private: |
49 { |
55 RHybridHeap* iHybridHeap; |
50 SCell* p = (SCell*)&iFree; |
|
51 SCell* n = p->next; |
|
52 n->len = iMinCell-1; |
|
53 } |
|
54 |
|
55 //EBadAllocatedCellAddress |
|
56 void CorruptAllocatedMemory1() |
|
57 { |
|
58 SCell* c = (SCell*)iBase; |
|
59 SCell* f = (SCell*)&iFree; |
|
60 |
|
61 f = f->next; |
|
62 f = f->next; |
|
63 c->len = (TInt)f->next - (TInt)c; |
|
64 } |
|
65 |
|
66 //additional utilities |
|
67 void CorruptAllocatedMemorySize(void* aAddress) |
|
68 { |
|
69 SCell* addres = GetAddress(aAddress); |
|
70 SCell* c = (SCell*)iBase; |
|
71 for(;;) |
|
72 { |
|
73 if(c == addres) |
|
74 { |
|
75 c->len = iMinCell-1; |
|
76 break; |
|
77 } |
|
78 c = __NEXT_CELL(c); |
|
79 } |
|
80 } |
|
81 |
|
82 void CorruptAllocatedMemoryAddress(void* aAddress) |
|
83 { |
|
84 SCell* pF = &iFree; // free cells |
|
85 pF = pF->next; // next free cell |
|
86 if (!pF) |
|
87 pF = (SCell*)iTop; |
|
88 SCell* addres = GetAddress(aAddress); |
|
89 SCell* c = (SCell*)iBase; |
|
90 for(;;) |
|
91 { |
|
92 if(c == addres) |
|
93 { |
|
94 c->len = (TInt)pF->next - (TInt)c; |
|
95 break; |
|
96 } |
|
97 c = __NEXT_CELL(c); |
|
98 } |
|
99 } |
|
100 |
|
101 void EnableHeavyMemoryMonitoring() |
|
102 { |
|
103 iFlags |= EMonitorMemory; |
|
104 } |
|
105 }; |
56 }; |
106 |
57 |
107 |
58 |
|
59 |
|
60 TBool TestHybridHeap::Init() |
|
61 { |
|
62 RHybridHeap::STestCommand cmd; |
|
63 cmd.iCommand = RHybridHeap::EHeapMetaData; |
|
64 RAllocator& heap = User::Allocator(); |
|
65 TInt ret = heap.DebugFunction(RHeap::EHybridHeap, &cmd, 0); |
|
66 if (ret != KErrNone) |
|
67 return EFalse; |
|
68 iHybridHeap = (RHybridHeap*) cmd.iData; |
|
69 |
|
70 return ETrue; |
|
71 } |
|
72 |
|
73 TBool TestHybridHeap::Check() |
|
74 { |
|
75 if ( iHybridHeap ) |
|
76 { |
|
77 iHybridHeap->Check(); |
|
78 } |
|
79 |
|
80 return EFalse; |
|
81 } |
|
82 |
|
83 TInt TestHybridHeap::AllocLen(TAny* aBfr) |
|
84 { |
|
85 if ( iHybridHeap ) |
|
86 { |
|
87 return iHybridHeap->AllocLen(aBfr); |
|
88 } |
|
89 return 0; |
|
90 } |
|
91 |
|
92 void TestHybridHeap::EnableHeavyMemoryMonitoring() |
|
93 { |
|
94 if ( iHybridHeap ) |
|
95 { |
|
96 iHybridHeap->iFlags |= RAllocator::EMonitorMemory; |
|
97 } |
|
98 |
|
99 } |
|
100 |
|
101 |
|
102 void TestHybridHeap::CorruptFreeDLBfr(TAny* aBfr) |
|
103 { |
|
104 |
|
105 if ( aBfr ) |
|
106 { |
|
107 mchunkptr p = MEM2CHUNK((TUint8*)aBfr-KDbgHeaderSize); |
|
108 p->iHead |= CINUSE_BIT; |
|
109 } |
|
110 } |
|
111 |
|
112 void TestHybridHeap::CorruptFreeDLBfrLth(TAny* aBfr) |
|
113 { |
|
114 |
|
115 if ( aBfr ) |
|
116 { |
|
117 mchunkptr p = MEM2CHUNK((TUint8*)aBfr-KDbgHeaderSize); |
|
118 p->iHead &= INUSE_BITS; // Set zero length |
|
119 } |
|
120 } |
|
121 |
|
122 void TestHybridHeap::CorruptAllocatedDLBfrSize(TAny* aBfr) |
|
123 { |
|
124 |
|
125 if ( aBfr ) |
|
126 { |
|
127 mchunkptr p = MEM2CHUNK((TUint8*)aBfr-KDbgHeaderSize); |
|
128 TInt size = CHUNKSIZE(p); |
|
129 size >>= 1; // Set double length |
|
130 p->iHead = size | INUSE_BITS; |
|
131 } |
|
132 } |
|
133 |
|
134 TAny* TestHybridHeap::CorruptAllocatedDLMemoryAddress(TAny* aBfr) |
|
135 { |
|
136 |
|
137 if ( aBfr ) |
|
138 { |
|
139 TUint8* p = (TUint8*)aBfr; |
|
140 p += 3; |
|
141 aBfr = (TAny*)p; |
|
142 } |
|
143 return aBfr; |
|
144 } |
|
145 |
|
146 |
108 /** |
147 /** |
109 Heap corruption 2: |
148 Heap corruption 0: |
110 - Overrunning an array using memset |
149 - Allocate (DL) buffer, corrupt it and free |
111 (EHeapCorruption - EBadAllocatedCellSize) |
|
112 */ |
150 */ |
113 void Memory_Corruption2() |
151 void Memory_Corruption0(TestHybridHeap& aHeap) |
114 { |
152 { |
115 if(gEnableMemoryMonitor) |
153 if(gEnableMemoryMonitor) |
116 { |
154 aHeap.EnableHeavyMemoryMonitoring(); |
117 RMyDummyHeap* h = (RMyDummyHeap*)&User::Heap(); |
|
118 h->EnableHeavyMemoryMonitoring(); |
|
119 } |
|
120 |
155 |
121 char* buf = new char[10]; //will be aligned to 12 |
156 char* buf = new char[10]; //will be aligned to 12 |
122 char* buf2 = new char[10]; //will be aligned to 12 |
157 char* buf2 = new char[10]; //will be aligned to 12 |
123 TInt a = User::Heap().AllocLen(buf); |
158 TInt a = aHeap.AllocLen(buf); |
124 memset(buf, 255, a+1); //memory corruption |
159 memset(buf, 0xfc, a+a); //memory corruption |
125 |
160 |
126 if(!gEnableMemoryMonitor) |
161 if(!gEnableMemoryMonitor) |
127 User::Heap().Check(); //force 'heap walker' to check the heap |
162 aHeap.Check(); //force 'heap walker' to check the heap |
128 |
163 |
129 delete buf2; |
164 delete buf2; |
130 delete buf; //when heavy monitoring is ON should send trace |
165 delete buf; //when heavy monitoring is ON should send trace and panic |
131 } |
166 } |
132 |
167 |
133 |
168 //Corrupt free DL memory and Check() |
134 //causes EBadFreeCellAddress corruption type |
169 void Memory_Corruption1(TestHybridHeap& aHeap) |
135 void Memory_Corruption3() |
|
136 { |
170 { |
137 TInt* p1 = new TInt(); |
171 TInt* p1 = new TInt(); |
138 TInt* p2 = new TInt(); |
172 TInt* p2 = new TInt(); |
139 TInt* p3 = new TInt(); |
173 TInt* p3 = new TInt(); |
140 TInt* p4 = new TInt(); |
174 TInt* p4 = new TInt(); |
142 TInt* p6 = new TInt(); |
176 TInt* p6 = new TInt(); |
143 delete p2; |
177 delete p2; |
144 delete p4; |
178 delete p4; |
145 delete p6; |
179 delete p6; |
146 |
180 |
147 RMyDummyHeap* h = (RMyDummyHeap*)&User::Heap(); |
181 aHeap.CorruptFreeDLBfr(p4); |
148 h->CorruptFreeMemory1(); |
182 aHeap.Check(); // Should panic here |
149 User::Heap().Check(); |
|
150 |
183 |
151 delete p5; |
184 delete p5; |
152 delete p3; |
185 delete p3; |
153 delete p1; |
186 delete p1; |
154 } |
187 } |
155 |
188 |
156 |
189 |
157 //causes EBadFreeCellSize RHeap corruption type |
190 //corrupt free DL buffer length |
158 void Memory_Corruption4() |
191 void Memory_Corruption2(TestHybridHeap& aHeap) |
159 { |
192 { |
160 TInt* p1 = new TInt(); |
193 TInt* p1 = new TInt(); |
161 TInt* p2 = new TInt(); |
194 TInt* p2 = new TInt(); |
162 TInt* p3 = new TInt(); |
195 TInt* p3 = new TInt(); |
163 delete p2; |
196 delete p2; |
164 |
197 |
165 RMyDummyHeap* h = (RMyDummyHeap*)&User::Heap(); |
198 aHeap.CorruptFreeDLBfrLth(p2); |
166 h->CorruptFreeMemory2(); |
199 aHeap.Check(); // Should panic here |
167 User::Heap().Check(); |
|
168 |
200 |
169 delete p3; |
201 delete p3; |
170 |
202 |
171 delete p1; |
203 delete p1; |
172 } |
204 } |
173 |
205 |
174 |
206 |
175 //causes EBadAllocatedCellAddress corruption type |
207 //Corrupt allocated DL buffer size |
176 void Memory_Corruption5() |
208 void Memory_Corruption3(TestHybridHeap& aHeap) |
177 { |
209 { |
178 TInt* p1 = new TInt; |
210 TInt* p1 = new TInt; |
179 TInt* p2 = new TInt; |
211 TInt* p2 = new TInt; |
180 TInt* p3 = new TInt; |
212 TInt* p3 = new TInt; |
181 TInt* p4 = new TInt; |
213 TInt* p4 = new TInt; |
184 TInt* p7 = new TInt; |
216 TInt* p7 = new TInt; |
185 delete p2; |
217 delete p2; |
186 delete p4; |
218 delete p4; |
187 delete p6; |
219 delete p6; |
188 |
220 |
189 RMyDummyHeap* h = (RMyDummyHeap*)&User::Heap(); |
221 aHeap.CorruptAllocatedDLBfrSize(p7); |
190 //h->CorruptAllocatedMemory1(); |
222 aHeap.Check(); |
191 h->CorruptAllocatedMemoryAddress((void*)p7); |
|
192 User::Heap().Check(); |
|
193 |
223 |
194 delete p7; |
224 delete p7; |
195 delete p5; |
225 delete p5; |
196 delete p3; |
226 delete p3; |
197 delete p1; |
227 delete p1; |
198 } |
228 } |
199 |
229 |
200 |
230 |
201 void Memory_Corruption_Special1() |
231 void Memory_Corruption4(TestHybridHeap& aHeap) |
202 { |
232 { |
203 char* buf = new char; |
233 char* buf = new char; |
204 RMyDummyHeap* h = (RMyDummyHeap*)&User::Heap(); |
234 aHeap.EnableHeavyMemoryMonitoring(); |
205 h->EnableHeavyMemoryMonitoring(); |
235 buf = (char*)aHeap.CorruptAllocatedDLMemoryAddress((TAny*)buf); |
206 h->CorruptAllocatedMemoryAddress((void*)buf); |
|
207 delete buf;// should output EHeapCorruption trace |
236 delete buf;// should output EHeapCorruption trace |
208 } |
237 } |
209 |
238 |
210 |
239 |
211 |
240 |
212 // Local Functions |
241 // Local Functions |
213 LOCAL_D TInt threadTraceHeapCorruptionTestThread(TAny* param) |
242 LOCAL_D TInt threadTraceHeapCorruptionTestThread(TAny* param) |
214 { |
243 { |
|
244 TestHybridHeap heap; |
|
245 heap.Init(); |
|
246 |
215 TInt t = *((TInt*)param); |
247 TInt t = *((TInt*)param); |
216 switch(t) |
248 switch(t) |
217 { |
249 { |
218 case RHeap::EBadAllocatedCellSize: |
250 case 0: // Corrupt allocated buffer and free it |
219 Memory_Corruption2(); |
251 Memory_Corruption0(heap); |
220 break; |
252 break; |
221 case RHeap::EBadFreeCellAddress: |
253 case 1: |
222 Memory_Corruption3(); |
254 Memory_Corruption1(heap); |
223 break; |
255 break; |
224 case RHeap::EBadFreeCellSize: |
256 case 2: |
225 Memory_Corruption4(); |
257 Memory_Corruption2(heap); |
226 break; |
258 break; |
227 case RHeap::EBadAllocatedCellAddress: |
259 case 3: |
228 Memory_Corruption5(); |
260 Memory_Corruption3(heap); |
229 break; |
261 break; |
230 case 1000: |
262 case 1000: |
231 Memory_Corruption_Special1(); |
263 Memory_Corruption4(heap); |
232 break; |
264 break; |
233 default: |
265 default: |
234 User::Invariant(); |
266 User::Invariant(); |
235 break; |
267 break; |
236 } |
268 } |
247 TInt r = KErrNone; |
279 TInt r = KErrNone; |
248 gEnableMemoryMonitor = EFalse; |
280 gEnableMemoryMonitor = EFalse; |
249 |
281 |
250 switch(aTestType) |
282 switch(aTestType) |
251 { |
283 { |
252 case 0: ////RHeap::EBadAllocatedCellSize with heavy monitoring enabled |
284 case 0: ////Corrupt allocated DL buffer and free it with heavy monitoring enabled |
253 type = RHeap::EBadAllocatedCellSize; |
285 type = 0; |
254 gEnableMemoryMonitor = ETrue; |
286 gEnableMemoryMonitor = ETrue; |
255 r = thread.Create(_L("t_tbrace_heapcorruption"), threadTraceHeapCorruptionTestThread, |
287 r = thread.Create(_L("t_tbrace_heapcorruption"), threadTraceHeapCorruptionTestThread, |
256 KDefaultStackSize, 0x2000, 0x2000, &type); |
288 KDefaultStackSize, 0x2000, 0x2000, &type); |
257 thread.Logon(stat); |
289 thread.Logon(stat); |
258 thread.Resume(); |
290 thread.Resume(); |
259 User::WaitForRequest(stat); |
291 User::WaitForRequest(stat); |
260 thread.Close(); |
292 thread.Close(); |
261 break; |
293 break; |
262 |
294 |
263 case 1: //RHeap::EBadFreeCellAddress: |
295 case 1: //RHeap::EBadFreeCellAddress: |
264 type = RHeap::EBadFreeCellAddress; |
296 type = 1; |
265 r = thread.Create(_L("t_tbrace_heapcorruption"), threadTraceHeapCorruptionTestThread, |
297 r = thread.Create(_L("t_tbrace_heapcorruption"), threadTraceHeapCorruptionTestThread, |
266 KDefaultStackSize, 0x2000, 0x2000, &type); |
298 KDefaultStackSize, 0x2000, 0x2000, &type); |
267 thread.Logon(stat); |
299 thread.Logon(stat); |
268 thread.Resume(); |
300 thread.Resume(); |
269 User::WaitForRequest(stat); |
301 User::WaitForRequest(stat); |
270 thread.Close(); |
302 thread.Close(); |
271 break; |
303 break; |
272 |
304 |
273 case 2: //RHeap::EBadFreeCellSize: |
305 case 2: //RHeap::EBadFreeCellSize: |
274 type = RHeap::EBadFreeCellSize; |
306 type = 2; |
275 r = thread.Create(_L("t_tbrace_heapcorruption"), threadTraceHeapCorruptionTestThread, |
307 r = thread.Create(_L("t_tbrace_heapcorruption"), threadTraceHeapCorruptionTestThread, |
276 KDefaultStackSize, 0x2000, 0x2000, &type); |
308 KDefaultStackSize, 0x2000, 0x2000, &type); |
277 thread.Logon(stat); |
309 thread.Logon(stat); |
278 thread.Resume(); |
310 thread.Resume(); |
279 User::WaitForRequest(stat); |
311 User::WaitForRequest(stat); |
280 thread.Close(); |
312 thread.Close(); |
281 break; |
313 break; |
282 |
314 |
283 case 3: //RHeap::EBadAllocatedCellSize: |
315 case 3: //RHeap::EBadAllocatedCellSize: |
284 type = RHeap::EBadAllocatedCellSize; |
316 type = 0; // Without memory monitorin this time |
285 r = thread.Create(_L("t_tbrace_heapcorruption"), threadTraceHeapCorruptionTestThread, |
317 r = thread.Create(_L("t_tbrace_heapcorruption"), threadTraceHeapCorruptionTestThread, |
286 KDefaultStackSize, 0x2000, 0x2000, &type); |
318 KDefaultStackSize, 0x2000, 0x2000, &type); |
287 thread.Logon(stat); |
319 thread.Logon(stat); |
288 thread.Resume(); |
320 thread.Resume(); |
289 User::WaitForRequest(stat); |
321 User::WaitForRequest(stat); |
290 thread.Close(); |
322 thread.Close(); |
291 break; |
323 break; |
292 |
324 |
293 case 4: //RHeap::EBadAllocatedCellAddress: |
325 case 4: //RHeap::EBadAllocatedCellAddress: |
294 type = RHeap::EBadAllocatedCellAddress; |
326 type = 3; |
295 r = thread.Create(_L("t_tbrace_heapcorruption"), threadTraceHeapCorruptionTestThread, |
327 r = thread.Create(_L("t_tbrace_heapcorruption"), threadTraceHeapCorruptionTestThread, |
296 KDefaultStackSize, 0x2000, 0x2000, &type); |
328 KDefaultStackSize, 0x2000, 0x2000, &type); |
297 thread.Logon(stat); |
329 thread.Logon(stat); |
298 thread.Resume(); |
330 thread.Resume(); |
299 User::WaitForRequest(stat); |
331 User::WaitForRequest(stat); |