--- a/kerneltest/e32test/heap/t_heapcheck.cpp Tue Aug 31 16:34:26 2010 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,652 +0,0 @@
-// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
-// All rights reserved.
-// This component and the accompanying materials are made available
-// under the terms of the License "Eclipse Public License v1.0"
-// which accompanies this distribution, and is available
-// at the URL "http://www.eclipse.org/legal/epl-v10.html".
-//
-// Initial Contributors:
-// Nokia Corporation - initial contribution.
-//
-// Contributors:
-//
-// Description:
-// e32test\debug\t_heapcorruption.cpp
-// This is a test application that will cause heap corruption
-// to generate BTrace events (EHeapCorruption).
-//
-//
-
-// Include Files
-#include <e32test.h>
-#include <e32base.h>
-#include <e32panic.h>
-#include <e32cmn.h>
-#include "dla.h"
-#include "slab.h"
-#include "page_alloc.h"
-#include "heap_hybrid.h"
-
-LOCAL_D RTest test(_L("T_HEAPCHECK"));
-
-TUint32 gSeed = 0xb504f334;
-
-_LIT(KLitHeapCheck,"Heap Check");
-
-
-TUint32 Random()
-{
- gSeed *= 69069;
- gSeed += 41;
- return gSeed;
-}
-
-TInt RandomNumber(TInt aMin, TInt aMax)
-{
- TInt y = aMax - aMin;
- if ( y <= 0 )
- return aMax;
- TUint32 x = Random() & 0xff;
- TInt s = 0;
- while ( y > (0x100 << s) )
- {
- s++;
- }
- return (aMin + (x << s) % y);
-}
-
-
-/**
-Friend class of RHeapHybrid to access to hybrid heap metadata
-*/
-class TestHybridHeap
-{
- public:
- TBool Init();
- TBool Check();
- TUint8* Alloc(TInt aLth);
- TUint8* ReAlloc(TAny* aBfr, TInt aLth, TInt aMode);
- void Free(TAny* aBfr);
- TInt AllocLen(TAny* aBfr);
- TInt AllocSize(TInt& aTotalAllocSize);
- TBool SlabAllocatorExists();
- TBool PageAllocatorExists();
- TBool SlabsCreated();
- TBool CorruptSmallBin();
- TBool CorruptTreeBin();
- TBool ConfigurePageAllocator();
- TInt CopyPageBitmap(TUint8* aBitmap, TInt aLth);
- TBool RestorePageBitmap(TUint8* aBitmap, TInt aLth);
- void AllocateSomeBuffers(TUint8** aBfrs, TInt aMinLth, TInt MaxLth, TInt aCount);
- TBool PrintHeapInitData();
-
- private:
- RHybridHeap* iHybridHeap;
-};
-
-
-
-TBool TestHybridHeap::Init()
-{
- RHybridHeap::STestCommand cmd;
- cmd.iCommand = RHybridHeap::EHeapMetaData;
- RAllocator& heap = User::Allocator();
- TInt ret = heap.DebugFunction(RHeap::EHybridHeap, &cmd, 0);
- if (ret != KErrNone)
- return EFalse;
- iHybridHeap = (RHybridHeap*) cmd.iData;
-
- return ETrue;
-}
-
-TBool TestHybridHeap::Check()
-{
- if ( iHybridHeap )
- {
- iHybridHeap->Check();
- }
-
- return EFalse;
-}
-
-TUint8* TestHybridHeap::Alloc(TInt aLth)
-{
- if ( iHybridHeap )
- {
- return (TUint8*)iHybridHeap->Alloc(aLth);
- }
-
- return NULL;
-}
-
-TUint8* TestHybridHeap::ReAlloc(TAny* aBfr, TInt aLth, TInt aMode)
-{
- if ( iHybridHeap )
- {
- return (TUint8*)iHybridHeap->ReAlloc(aBfr, aLth, aMode);
- }
-
- return NULL;
-}
-
-void TestHybridHeap::Free(TAny* aBfr)
-{
- if ( iHybridHeap )
- {
- iHybridHeap->Free(aBfr);
- }
-}
-
-TInt TestHybridHeap::AllocLen(TAny* aBfr)
-{
- if ( iHybridHeap )
- {
- return iHybridHeap->AllocLen(aBfr);
- }
- return 0;
-}
-
-TInt TestHybridHeap::AllocSize(TInt& aTotalAllocSize)
-{
- aTotalAllocSize = 0;
- if ( iHybridHeap )
- {
- return iHybridHeap->AllocSize(aTotalAllocSize);
- }
- return 0;
-}
-
-TBool TestHybridHeap::SlabAllocatorExists()
-{
- TBool status = EFalse;
- if ( iHybridHeap )
- {
- status = !iHybridHeap->iDLOnly;
- }
-
- return status;
-}
-
-TBool TestHybridHeap::PageAllocatorExists()
-{
- TBool status = EFalse;
- if ( iHybridHeap )
- {
- status = (!iHybridHeap->iDLOnly && (iHybridHeap->iPageThreshold < 31));
- }
-
- return status;
-}
-
-TBool TestHybridHeap::SlabsCreated()
-{
- TBool status = EFalse;
- if ( iHybridHeap )
- {
- status = (iHybridHeap->iSlabThreshold != 0);
- }
-
- return status;
-}
-
-TBool TestHybridHeap::ConfigurePageAllocator()
-{
- TBool status = EFalse;
- if ( iHybridHeap )
- {
- RHybridHeap::STestCommand conf;
- conf.iCommand = RHybridHeap::ESetConfig;
- conf.iConfig.iPagePower = 14; // 16 Kb
- if ( iHybridHeap->DebugFunction(RHeap::EHybridHeap, (TAny*)&conf ) == KErrNone )
- status = ETrue;
- }
-
- return status;
-}
-
-
-TBool TestHybridHeap::CorruptTreeBin()
-{
- TBool status = EFalse;
- if ( iHybridHeap )
- {
- TUint i;
- for (i = 0; i < NTREEBINS; ++i)
- {
- tbinptr* tb = TREEBIN_AT(&iHybridHeap->iGlobalMallocState, i);
- tchunkptr t = *tb;
- if ( t )
- {
- // Corrupt tree bin by writing erroneous index value
- t->iIndex ++;
- return ETrue;
- }
- }
- }
-
- return status;
-}
-
-TBool TestHybridHeap::CorruptSmallBin()
-{
- TBool status = EFalse;
- if ( iHybridHeap )
- {
- TUint i;
- for (i = 0; i < NSMALLBINS; ++i)
- {
- sbinptr b = SMALLBIN_AT(&iHybridHeap->iGlobalMallocState, i);
- mchunkptr p = b->iBk;
- if ( p != b )
- {
- b->iBk = b;
- status = ETrue;
- }
- }
- }
-
- return status;
-}
-
-TInt TestHybridHeap::CopyPageBitmap(TUint8* aBitmap, TInt aLth)
-{
- TInt lth = 0;
- if ( iHybridHeap && (aLth > (TInt) sizeof(iHybridHeap->iBitMapBuffer)) )
- {// Dirty version
- memcpy(aBitmap, &iHybridHeap->iBitMapBuffer[0], sizeof(iHybridHeap->iBitMapBuffer));
- lth = sizeof(iHybridHeap->iBitMapBuffer) << 3;
- }
-
- return lth;
-}
-
-TBool TestHybridHeap::RestorePageBitmap(TUint8* aBitmap, TInt aLth)
-{
- TBool status = EFalse;
- if ( iHybridHeap && ((aLth >> 3) <= (TInt) sizeof(iHybridHeap->iBitMapBuffer)) )
- {// Dirty version
- memcpy(&iHybridHeap->iBitMapBuffer[0], aBitmap, (aLth >> 3));
- status = ETrue;
- }
-
- return status;
-}
-
-void TestHybridHeap::AllocateSomeBuffers(TUint8** aBfrs, TInt aMinLth, TInt MaxLth, TInt aCount )
-{
-
- TInt loop = RandomNumber(2, 8);
-
- while ( loop )
- {
- // allocate all buffers
- TInt i;
- for (i=0; i<aCount; ++i)
- {
- if (!aBfrs[i])
- {
- aBfrs[i] = (TUint8*)Alloc(RandomNumber(aMinLth, MaxLth));
- }
- }
-
- // free some cells
- TInt n = RandomNumber(2, aCount);
- while (--n)
- {
- i = RandomNumber(2, aCount);
- if (aBfrs[i])
- {
- Free(aBfrs[i]);
- aBfrs[i] = NULL;
- }
- }
-
- // realloc some cells
- n = RandomNumber(2, aCount);
- while (--n)
- {
- TInt new_len = RandomNumber(aMinLth, MaxLth);
- if (aBfrs[i])
- {
- TUint8* p = (TUint8*)ReAlloc(aBfrs[i], new_len, Random());
- if (p)
- {
- aBfrs[i] = p;
- }
- }
- }
-
- loop --;
- }
-
-}
-
-TBool TestHybridHeap::PrintHeapInitData()
-{
- TInt total;
- TInt count = AllocSize(total);
- RDebug::Printf("Heap initialised for test, alloc count: %d , alloc size: %d\n", count, total);
- if ( iHybridHeap )
- RDebug::Printf("Heap initialised for test, iCellCount: %d , iTotalAllocSize: %d\n", iHybridHeap->iCellCount, iHybridHeap->iTotalAllocSize);
- return (count != 0);
-}
-
-
-// Local Functions
-LOCAL_D TInt HeapCheckTestThread(TAny* param)
-{
- TInt t = *((TInt*)param);
- TUint8* bfrs[256];
- Mem::FillZ(bfrs, sizeof(bfrs));
- TestHybridHeap heap;
- test(heap.Init());
-
- switch( t )
- {
- case 1:
- {
- // Overwrite Doug Lea buffer and check()
- heap.AllocateSomeBuffers(bfrs, 0x40, 0xfff0, 256);
- test(heap.PrintHeapInitData());
- TUint8 *p = heap.Alloc(64);
- test( p != NULL );
- Mem::FillZ(p, 80); // Heap corrupted
- heap.Check(); // This should cause panic
- break;
- }
-
- case 2:
- // Corrupt a smallbin and check
- {
- TInt i = 0;
- TBool smallbin_corrupted = EFalse;
- while ( !smallbin_corrupted )
- {
- heap.AllocateSomeBuffers(bfrs, 0x4, 0xff, 256);
- smallbin_corrupted = heap.CorruptSmallBin();
- i ++;
- if ( i > 9 )
- break;
- }
- test(smallbin_corrupted);
- test(heap.PrintHeapInitData());
- heap.Check(); // This should cause panic
- }
- break;
-
- case 3:
- // Corrupt a treebin and check
- {
- TInt i = 0;
- TBool treebin_corrupted = EFalse;
- while ( !treebin_corrupted )
- {
- heap.AllocateSomeBuffers(bfrs, 0x100, 0x4000, 256);
- treebin_corrupted = heap.CorruptTreeBin();
- i ++;
- if ( i > 9 )
- break;
- }
- test(treebin_corrupted);
- test(heap.PrintHeapInitData());
- heap.Check(); // This should cause panic
- break;
- }
-
- case 10:
- // Overwrite slab buffer and check
- {
- TInt i = 0;
- TBool slabs_created = EFalse;
- if ( !heap.SlabAllocatorExists() )
- {
- User::Panic(KLitHeapCheck, ETHeapDebugUnmatchedCallToCheckHeap);
- }
-
- while ( !slabs_created )
- {
- // Allocate enough buffers to cause slab allocator to be
- // initialised
- heap.AllocateSomeBuffers(bfrs, 0x4, 0x2000, 256);
- slabs_created = heap.SlabsCreated();
- i ++;
- if ( i > 9 )
- break;
- }
- test(slabs_created);
- test(heap.PrintHeapInitData());
- i = 0;
- TUint8* p[10];
- while ( i < 10 )
- {
- p[i] = heap.Alloc(24);
- test( p[i] != NULL );
- i ++;
- }
- i = 0;
- while ( i < 10 )
- {
- heap.Free(p[i]);
- i +=2;
- }
- p[0] = heap.Alloc(24);
- test( p[0] != NULL );
- memset((TUint8*)(Floor(p[0], SLABSIZE) + sizeof(slabhdr)), 0xee, KMaxSlabPayload); // Heap corrupted
- heap.Check(); // This should cause panic
- break;
- }
-
- case 11:
- // Corrupt slab header
- {
- TInt i = 0;
- TBool slabs_created = EFalse;
- if ( !heap.SlabAllocatorExists() )
- {
- User::Panic(KLitHeapCheck, ETHeapDebugUnmatchedCallToCheckHeap);
- }
-
- while ( !slabs_created )
- {
- // Allocate enough buffers to cause slab allocator to be
- // initialised
- heap.AllocateSomeBuffers(bfrs, 0x4, 0x2000, 256);
- slabs_created = heap.SlabsCreated();
- i ++;
- if ( i > 9 )
- break;
- }
- test(slabs_created);
- test(heap.PrintHeapInitData());
- TUint8* p = heap.Alloc(28);
- test(p != NULL);
- p = Floor(p, SLABSIZE);
- *(TUint32*)p = 0xffeeddcc;
- heap.Check(); // This should cause panic
- break;
- }
-
- case 20:
- // Corrupt page bitmap data and check
- {
- if ( !heap.PageAllocatorExists() )
- {
- User::Panic(KLitHeapCheck, ETHeapDebugUnmatchedCallToCheckHeap);
- }
- test(heap.ConfigurePageAllocator());
- // Allocate some buffers to cause slab allocator to be
- // initialised
- heap.AllocateSomeBuffers(bfrs, 0x4000, 0x10000, 16);
- test(heap.PrintHeapInitData());
- TUint8* bitmap = heap.Alloc(128); // For saved bitmap
- test(bitmap != NULL);
- TInt bit_lth = heap.CopyPageBitmap(bitmap, 128);
- test(bit_lth != 0);
- memset(bitmap, 0xee, (bit_lth>>3)); // corrupt bitmap data
- heap.RestorePageBitmap(bitmap, bit_lth);
- heap.Check(); // This should cause panic
- break;
- }
-
- case 21:
- // Corrupt page bitmap with a earlier freed "ghost" buffer info
- {
- if ( !heap.PageAllocatorExists() )
- {
- User::Panic(KLitHeapCheck, ETHeapDebugUnmatchedCallToCheckHeap);
- }
- test(heap.ConfigurePageAllocator());
- // Allocate some buffers to cause slab allocator to be
- // initialised
- heap.AllocateSomeBuffers(bfrs, 0x4000, 0x10000, 16);
- test(heap.PrintHeapInitData());
- TUint8* bitmap = heap.Alloc(128); // For saved bitmap
- test(bitmap != NULL);
- TUint8* p = heap.Alloc(0x8000); // One more page buffer
- TInt bit_lth = heap.CopyPageBitmap(bitmap, 128);
- test(bit_lth != 0);
- heap.Free(p);
- heap.RestorePageBitmap(bitmap, bit_lth);
- heap.Check(); // This should cause panic
- break;
- }
-
- default:
- break;
- }
-
- User::Invariant(); // Should not reach here
- return 0;
-}
-
-
-class TestHeapCheck
-{
- public:
- void TestCheck(void);
- TInt TestThreadExit(RThread& aThread, TExitType aExitType, TInt aExitReason);
-};
-
-
-TInt TestHeapCheck::TestThreadExit(RThread& aThread, TExitType aExitType, TInt aExitReason)
-{
- // Disable JIT debugging.
- TBool justInTime=User::JustInTime();
- User::SetJustInTime(EFalse);
-
- TRequestStatus status;
- aThread.Logon(status);
- aThread.Resume();
- User::WaitForRequest(status);
- if (aExitType != aThread.ExitType())
- return KErrGeneral;
-
- if ( (status.Int() == ETHeapDebugUnmatchedCallToCheckHeap) && (aThread.ExitReason() == ETHeapDebugUnmatchedCallToCheckHeap))
- {
- CLOSE_AND_WAIT(aThread);
- // Put JIT debugging back to previous status.
- User::SetJustInTime(justInTime);
- return KErrNotSupported;
- }
-
- if ( status.Int() == ERTestFailed )
- return KErrGeneral;
-
- if ( aExitReason > 0 )
- {
- if (aExitReason != status.Int())
- return KErrGeneral;
-
- if (aExitReason != aThread.ExitReason())
- return KErrGeneral;
- }
-
- CLOSE_AND_WAIT(aThread);
-
- // Put JIT debugging back to previous status.
- User::SetJustInTime(justInTime);
- return KErrNone;
-
-}
-
-void TestHeapCheck::TestCheck()
-{
- TInt type;
- TInt r;
-
- test.Next(_L("Testing Doug Lea allocator check"));
- {
- type = 1;
- RThread thread;
- test(thread.Create(_L("Check UserHeap"),HeapCheckTestThread, KDefaultStackSize, 0x1000, 0x400000, (TAny*) &type)== KErrNone);
- test(TestThreadExit(thread, EExitPanic, ETHeapBadCellAddress)==KErrNone);
-
- type = 2;
- test(thread.Create(_L("Check UserHeap"),HeapCheckTestThread, KDefaultStackSize, 0x1000, 0x400000, (TAny*) &type)==KErrNone);
- test(TestThreadExit(thread, EExitPanic, ETHeapBadCellAddress)==KErrNone);
-
- type = 3;
- test(thread.Create(_L("Check UserHeap"),HeapCheckTestThread, KDefaultStackSize, 0x1000, 0x400000, (TAny*) &type)==KErrNone);
- test(TestThreadExit(thread, EExitPanic, ETHeapBadCellAddress)==KErrNone);
-
- }
-
- test.Next(_L("Testing Slab allocator check"));
- {
- type = 10;
- RThread thread;
- test(thread.Create(_L("Check UserHeap"),HeapCheckTestThread, KDefaultStackSize, 0x1000, 0x400000, (TAny*) &type)==KErrNone);
- r = TestThreadExit(thread, EExitPanic, ETHeapBadCellAddress);
- if ( r != KErrNotSupported )
- {
- test(r==KErrNone);
-
- type = 11;
- RThread thread;
- test(thread.Create(_L("Check UserHeap"),HeapCheckTestThread, KDefaultStackSize, 0x1000, 0x400000, (TAny*) &type)==KErrNone);
- test(TestThreadExit(thread, EExitPanic, ETHeapBadCellAddress)==KErrNone);
- }
- else test.Printf(_L("Slab allocator does not exist, testes bypassed\n"));
- }
-
- test.Next(_L("Testing Page allocator check"));
- {
- type = 20;
- RThread thread;
- test(thread.Create(_L("Check UserHeap"),HeapCheckTestThread, KDefaultStackSize, 0x1000, 0x800000, (TAny*) &type)==KErrNone);
- r = TestThreadExit(thread, EExitPanic, KErrNone); // Accept any panic reason here
- if ( r != KErrNotSupported )
- {
- test(r==KErrNone);
-
- type = 21;
- RThread thread;
- test(thread.Create(_L("Check UserHeap"),HeapCheckTestThread, KDefaultStackSize, 0x1000, 0x800000, (TAny*) &type)==KErrNone);
- test(TestThreadExit(thread, EExitPanic, KErrNone)==KErrNone); // Accept any panic reason here
- }
- else test.Printf(_L("Page allocator does not exist, testes bypassed\n"));
- }
-
-}
-
-
-
-
-// Global Functions
-
-GLDEF_C TInt E32Main(void)
- {
-
- test.Title();
-
- test.Start(_L("Testing Heap Check function"));
-
- TestHeapCheck T;
-
- T.TestCheck();
-
- test.End();
-
- return(0);
- }
-