diff -r 000000000000 -r 96e5fb8b040d kerneltest/f32test/loader/security/t_fuzzldr.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/f32test/loader/security/t_fuzzldr.cpp Thu Dec 17 09:24:54 2009 +0200 @@ -0,0 +1,920 @@ +// 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: +// f32test\loader\security\t_fuzzldr.cpp +// +// + +#define __E32TEST_EXTENSION__ +#include +#include +#include +#include +#include "t_hash.h" + +// Fuzzing parameters + +const TInt KFuzzImages = 5; +const TInt KRandomFieldIterations = 8; +const TTimeIntervalMicroSeconds32 KDllTimeout = 10 * 1000000; + +#define FUZZFIELD(OBJ, NAME) { (const TText*)(L ## #OBJ L"." L ## #NAME), sizeof(((OBJ*)8)->NAME), _FOFF(OBJ, NAME) } +#define DUMBFIELD(NAME, SIZE, OFFSET) { (const TText*)L ## NAME, SIZE, OFFSET } +#define FUZZEND { NULL, 0, 0 } + +struct SFuzzField + { + const TText* name; + TInt size; + TInt offset; + }; + +const SFuzzField HeaderFields[] = + { + FUZZFIELD(E32ImageHeaderV, iUid1), + FUZZFIELD(E32ImageHeaderV, iUid2), + FUZZFIELD(E32ImageHeaderV, iUid3), + FUZZFIELD(E32ImageHeaderV, iUidChecksum), + FUZZFIELD(E32ImageHeaderV, iSignature), + FUZZFIELD(E32ImageHeaderV, iHeaderCrc), + FUZZFIELD(E32ImageHeaderV, iModuleVersion), + FUZZFIELD(E32ImageHeaderV, iCompressionType), + FUZZFIELD(E32ImageHeaderV, iToolsVersion.iMajor), + FUZZFIELD(E32ImageHeaderV, iToolsVersion.iMinor), + FUZZFIELD(E32ImageHeaderV, iToolsVersion.iBuild), + FUZZFIELD(E32ImageHeaderV, iTimeLo), + FUZZFIELD(E32ImageHeaderV, iTimeHi), + FUZZFIELD(E32ImageHeaderV, iFlags), + FUZZFIELD(E32ImageHeaderV, iCodeSize), + FUZZFIELD(E32ImageHeaderV, iDataSize), + FUZZFIELD(E32ImageHeaderV, iHeapSizeMin), + FUZZFIELD(E32ImageHeaderV, iHeapSizeMax), + FUZZFIELD(E32ImageHeaderV, iStackSize), + FUZZFIELD(E32ImageHeaderV, iBssSize), + FUZZFIELD(E32ImageHeaderV, iEntryPoint), + FUZZFIELD(E32ImageHeaderV, iCodeBase), + FUZZFIELD(E32ImageHeaderV, iDataBase), + FUZZFIELD(E32ImageHeaderV, iDllRefTableCount), + FUZZFIELD(E32ImageHeaderV, iExportDirOffset), + FUZZFIELD(E32ImageHeaderV, iExportDirCount), + FUZZFIELD(E32ImageHeaderV, iTextSize), + FUZZFIELD(E32ImageHeaderV, iCodeOffset), + FUZZFIELD(E32ImageHeaderV, iDataOffset), + FUZZFIELD(E32ImageHeaderV, iImportOffset), + FUZZFIELD(E32ImageHeaderV, iCodeRelocOffset), + FUZZFIELD(E32ImageHeaderV, iDataRelocOffset), + FUZZFIELD(E32ImageHeaderV, iProcessPriority), + FUZZFIELD(E32ImageHeaderV, iCpuIdentifier), + FUZZFIELD(E32ImageHeaderV, iUncompressedSize), + FUZZFIELD(E32ImageHeaderV, iS.iSecureId), + FUZZFIELD(E32ImageHeaderV, iS.iVendorId), + FUZZFIELD(E32ImageHeaderV, iS.iCaps.iCaps[0]), + FUZZFIELD(E32ImageHeaderV, iS.iCaps.iCaps[1]), + FUZZFIELD(E32ImageHeaderV, iExceptionDescriptor), + FUZZFIELD(E32ImageHeaderV, iSpare2), + FUZZFIELD(E32ImageHeaderV, iExportDescSize), + FUZZFIELD(E32ImageHeaderV, iExportDescType), + FUZZFIELD(E32ImageHeaderV, iExportDesc[0]), + FUZZEND + }; + +const SFuzzField ImportSectionFields[] = + { + FUZZFIELD(E32ImportSection, iSize), + FUZZEND + }; + +const SFuzzField ImportBlockFields[] = + { + FUZZFIELD(E32ImportBlock, iOffsetOfDllName), // we should fuzz the string also + FUZZFIELD(E32ImportBlock, iNumberOfImports), + FUZZEND + }; + +const SFuzzField ImportEntryFields[] = + { + DUMBFIELD("import", 4, 0), + FUZZEND + }; + +const SFuzzField RelocSectionFields[] = + { + FUZZFIELD(E32RelocSection, iSize), + FUZZFIELD(E32RelocSection, iNumberOfRelocs), + FUZZEND + }; + +const SFuzzField RelocBlockFields[] = + { + FUZZFIELD(E32RelocBlock, iPageOffset), + FUZZFIELD(E32RelocBlock, iBlockSize), + FUZZEND + }; + +const SFuzzField RelocEntryFields[] = + { + DUMBFIELD("reloc", 2, 0), + FUZZEND + }; + +const SFuzzField ExportEntryFields[] = + { + DUMBFIELD("export", 4, 0), + FUZZEND + }; + +const SFuzzField CompressedDataFields[] = + { + DUMBFIELD("data1", 4, 0), + DUMBFIELD("data2", 4, 4), + DUMBFIELD("data3", 4, 16), + DUMBFIELD("data4", 4, 64), + DUMBFIELD("data5", 4, 256), + DUMBFIELD("data6", 4, 1024), + DUMBFIELD("data7", 4, 4096), + FUZZEND + }; + +// Values to try for different sizes, signed here but can be interpreted as either +// each will also try the smaller sizes' values +const TInt8 Values8[] = { KMinTInt8, -100, -10, -2, -1, 0, 1, 2, 10, 100, KMaxTInt8 }; +const TInt Values8Count = sizeof(Values8)/sizeof(TInt8); +const TInt16 Values16[] = { KMinTInt16, -10000, -256, -255, 128, 255, 256, 10000, KMaxTInt16 }; +const TInt Values16Count = sizeof(Values16)/sizeof(TInt16); +const TInt32 Values32[] = { KMinTInt32, -1000000000, -65536, -65535, 32768, 65535, 65536, 268435455, 268435456, 1000000000, KMaxTInt32 }; +const TInt Values32Count = sizeof(Values32)/sizeof(TInt32); +const TInt ValuesCount[] = { 0, Values8Count, Values8Count+Values16Count, 0, Values8Count+Values16Count+Values32Count }; +const TInt Offsets[] = { 1, 2, 4, 16, -1, -2, -4, -16 }; +const TInt OffsetsCount = sizeof(Offsets)/sizeof(TInt); + +// Regular boring definitions and stuff + +RTest test(_L("T_FUZZLDR")); +RFs TheFs; +CFileMan* FileMan; + +_LIT(KOrigDir, "Z:\\sys\\bin\\"); +_LIT(KSysBin, ":\\sys\\bin\\"); +_LIT(KSysHash, ":\\sys\\hash\\"); +_LIT(KImageName, "fuzzv"); +_LIT(KExeExt, ".exe"); +_LIT(KDllExt, ".dll"); +_LIT(KMyself, "t_fuzzldr"); +_LIT(KSlaveArg, "-l "); + +TFileName Provided; +TFileName Original; +TFileName Current; +TFileName Hash; +TFileName HashDir; +TBool LoadDll; +RFile File; +RTimer Timer; +TUint8* Target; +E32ImageHeaderV* Header; +E32ImageHeaderV* CleanHeader; +CSHA1* Hasher; + +TInt FileSize; +TInt OutFileSize; +TUint8* CleanFileData; +TPtr8 CleanFileDes(CleanFileData, 0); +TUint8* FileData; +TPtr8 FileDes(FileData, 0); +TUint8* EndOfFile; +TChar Drive = '?', InternalDrive = '?', RemovableDrive = '?'; + +TBool Verbose; +TBool Forever = EFalse; +TUint32 Seed = 0; +typedef void (*TFieldFuzzer)(const SFuzzField*, TInt); + +enum SetMode { + ESetLiteral, + ESetOffset, + ESetRandom, + ESetXor, +}; + +enum ValueMode { + EValLiteral, + EValOffset, + EValRandom, + EValXor, + EValList, + EValOffsetList, +}; + + +TUint32 Rand() + { + Seed *= 69069; + Seed += 5; + return Seed; + } + + +TUint32 Rand(TUint32 aLimit) + { + TUint64 temp = (TUint64)Rand() * (TUint64)aLimit; + return (TUint32)(temp>>32); + } + + +void PrepareName(TInt aNum, TBool aDll) + { + Original = KOrigDir; + Original += KImageName; + Original.AppendNum(aNum); + Original += aDll ? KDllExt : KExeExt; + Current.Zero(); + Current.Append(Drive); + Current += KSysBin; + Current += KImageName; + Current.AppendNum(aNum); + Current += aDll ? KDllExt : KExeExt; + Hash = HashDir; + Hash += KImageName; + Hash.AppendNum(aNum); + Hash += aDll ? KDllExt : KExeExt; + } + + +void PrepareProvidedName() + { + Original = KOrigDir; + Original += Provided; + Current.Zero(); + Current.Append(Drive); + Current += KSysBin; + Current += Provided; + Hash = HashDir; + Hash += Provided; + } + + +void MakeCleanCopy() + { + Mem::Copy(FileData, CleanFileData, FileSize); + } + + +void LoadCleanFile() + { + test_KErrNone(File.Open(TheFs, Original, EFileRead)); + test_KErrNone(File.Size(FileSize)); + OutFileSize = FileSize; + CleanFileData = new TUint8[FileSize]; + test_NotNull(CleanFileData); + FileData = new TUint8[FileSize]; + EndOfFile = FileData + FileSize; + test_NotNull(FileData); + CleanFileDes.Set(CleanFileData, 0, FileSize); + test_KErrNone(File.Read(CleanFileDes)); + File.Close(); + Header = (E32ImageHeaderV*)FileData; + CleanHeader = (E32ImageHeaderV*)CleanFileData; + FileDes.Set(FileData, FileSize, FileSize); + MakeCleanCopy(); + test(CleanHeader->iUid1==(TUint32)KExecutableImageUidValue || CleanHeader->iUid1==(TUint32)KDynamicLibraryUidValue); + LoadDll = CleanHeader->iUid1==(TUint32)KDynamicLibraryUidValue; + } + + +void DoneFile() + { + delete[] FileData; + delete[] CleanFileData; + } + + +void RecalcChecksums() + { + if (Header->iUidChecksum == CleanHeader->iUidChecksum) + { + TUidType uids = *(const TUidType*)Header; + TCheckedUid chkuid(uids); + const TUint32* pChkUid = (const TUint32*)&chkuid; + Header->iUidChecksum = pChkUid[3]; + } + if (Header->iHeaderCrc == CleanHeader->iHeaderCrc) + { + Header->iHeaderCrc = KImageCrcInitialiser; + TUint32 crc = 0; + Mem::Crc32(crc, Header, sizeof(E32ImageHeaderV)); + Header->iHeaderCrc = crc; + } + } + + +void Load() + { + RecalcChecksums(); + test_KErrNone(File.Replace(TheFs, Current, EFileWrite)); + test_KErrNone(File.Write(FileDes, OutFileSize)); + test_KErrNone(File.Flush()); + File.Close(); + if (Drive == RemovableDrive) + { + TPtrC8 data(FileData, OutFileSize); + Hasher->Reset(); + Hasher->Update(data); + TBuf8 hashVal = Hasher->Final(); + test_KErrNone(File.Replace(TheFs, Hash, EFileWrite)); + test_KErrNone(File.Write(hashVal)); + test_KErrNone(File.Flush()); + File.Close(); + } + RProcess p; + TInt r; + if (LoadDll) + { + TFileName args; + args.Copy(KSlaveArg); + args.Append(Current); + test_KErrNone(p.Create(KMyself, args)); + TRequestStatus logon, rendez, timeout; + p.Logon(logon); + p.Rendezvous(rendez); + p.Resume(); + User::WaitForRequest(rendez); + test(rendez==KErrNone); + Timer.After(timeout, KDllTimeout); + User::WaitForRequest(logon, timeout); + if (logon == KRequestPending) + { + p.Kill(0); + User::WaitForRequest(logon); + } + else + { + Timer.Cancel(); + User::WaitForRequest(timeout); + } + p.Close(); + // we don't check the return code as passing it back makes the log output + // super spammy with KPANIC on - it prints for every nonzero return code. + if (Verbose) test.Printf(_L("\n")); + } + else + { + r = p.Create(Current, KNullDesC); + if (r==KErrNone) + p.Kill(0); + if (Verbose) test.Printf(_L("=> %d\n"), r); + } + p.Close(); + } + + +template void SetFieldTo(const SFuzzField* aField, T aSetTo, SetMode aMode) + { + T* field = (T*)(Target + aField->offset); + if ((TUint8*)field >= EndOfFile) + { + if (Verbose) test.Printf(_L("skipping, eof ")); + return; + } + if (aMode == ESetOffset) + aSetTo += *field; + else if (aMode == ESetRandom) + aSetTo = (T)Rand(); + else if (aMode == ESetXor) + aSetTo ^= *field; + *field = aSetTo; + if (Verbose) test.Printf(_L("%d "), aSetTo); + } + + +void SetField(const SFuzzField* aField, TInt aValue, ValueMode aMode) + { + if (aMode < EValList) + { + switch(aField->size) + { + case 1: + SetFieldTo(aField, aValue, (SetMode)aMode); + break; + case 2: + SetFieldTo(aField, aValue, (SetMode)aMode); + break; + case 4: + SetFieldTo(aField, aValue, (SetMode)aMode); + break; + } + } + else if (aMode == EValList) + { + switch(aField->size) + { + case 1: + SetFieldTo(aField, Values8[aValue], ESetLiteral); + break; + case 2: + if (aValue < ValuesCount[1]) + SetFieldTo(aField, Values8[aValue], ESetLiteral); + else + SetFieldTo(aField, Values16[aValue-ValuesCount[1]], ESetLiteral); + break; + case 4: + if (aValue < ValuesCount[1]) + SetFieldTo(aField, Values8[aValue], ESetLiteral); + else if (aValue < ValuesCount[2]) + SetFieldTo(aField, Values16[aValue-ValuesCount[1]], ESetLiteral); + else + SetFieldTo(aField, Values32[aValue-ValuesCount[2]], ESetLiteral); + break; + } + } + else if (aMode == EValOffsetList) + { + switch(aField->size) + { + case 1: + SetFieldTo(aField, Offsets[aValue], ESetOffset); + break; + case 2: + SetFieldTo(aField, Offsets[aValue], ESetOffset); + break; + case 4: + SetFieldTo(aField, Offsets[aValue], ESetOffset); + break; + } + } + } + + +void FuzzFieldsDeterministically(const SFuzzField* aFields, TInt aOffset) + { + Target = FileData + aOffset; + + TInt f = -1; + while (aFields[++f].name) + { + test.Printf(_L("FIELD: %s ...\n"), aFields[f].name); + TInt v; + if (Verbose) test.Next(_L("Using preset values")); + for (v = 0; v < ValuesCount[aFields[f].size]; ++v) + { + MakeCleanCopy(); + SetField(&aFields[f], v, EValList); + Load(); + } + if (Verbose) test.Next(_L("Using preset offsets")); + for (v = 0; v < OffsetsCount; ++v) + { + MakeCleanCopy(); + SetField(&aFields[f], v, EValOffsetList); + Load(); + } + if (Verbose) test.Next(_L("Flipping single bits")); + for (v = 0; v < aFields[f].size*8; ++v) + { + MakeCleanCopy(); + SetField(&aFields[f], 1<iCodeSize + CleanHeader->iCodeOffset; + for (v = codeend-4; v <= codeend+4; ++v) + { + MakeCleanCopy(); + SetField(&aFields[f], v, EValLiteral); + Load(); + } + } + } + } + + +void FuzzFieldsRandomly(const SFuzzField* aFields, TInt aOffset) + { + Target = FileData + aOffset; + + TInt f = 0; + while (aFields[f].name) + { + test.Printf(_L("FIELD: %s ... (random)\n"), aFields[f].name); + TInt v; + for (v = 0; v < KRandomFieldIterations; ++v) + { + MakeCleanCopy(); + SetField(&aFields[f], 0, EValRandom); + Load(); + } + f++; + } + } + + +void FuzzBlockRandomly(TInt aOffset, TInt aSize) + { + SFuzzField field; + field.size = 1; + Target = FileData + aOffset; + + test.Printf(_L("FIELD: random words in data\n")); + TInt v; + for (v = 0; v < KRandomFieldIterations * 4; ++v) + { + MakeCleanCopy(); + field.offset = Rand(aSize); + if (Verbose) test.Printf(_L("@ %d, "), field.offset); + SetField(&field, 0, EValRandom); + Load(); + } + } + + +void FuzzFile(TBool aRandom) + { + TTime before, after; + before.UniversalTime(); + LoadCleanFile(); + + TFieldFuzzer FuzzFields = aRandom ? FuzzFieldsRandomly : FuzzFieldsDeterministically; + + // E32ImageHeader + FuzzFields(HeaderFields, 0); + + if (CleanHeader->iCompressionType == KFormatNotCompressed) + { + // import table + TInt offset = CleanHeader->iImportOffset; + if (offset != 0) + { + FuzzFields(ImportSectionFields, offset); + offset += sizeof(E32ImportSection); + FuzzFields(ImportBlockFields, offset); + offset += sizeof(E32ImportBlock); + FuzzFields(ImportEntryFields, offset); + } + + // code relocations + offset = CleanHeader->iCodeRelocOffset; + if (offset != 0) + { + FuzzFields(RelocSectionFields, offset); + offset += sizeof(E32RelocSection); + FuzzFields(RelocBlockFields, offset); + offset += sizeof(E32RelocBlock); + FuzzFields(RelocEntryFields, offset); + } + + // data relocations + offset = CleanHeader->iDataRelocOffset; + if (offset != 0) + { + FuzzFields(RelocSectionFields, offset); + offset += sizeof(E32RelocSection); + FuzzFields(RelocBlockFields, offset); + offset += sizeof(E32RelocBlock); + FuzzFields(RelocEntryFields, offset); + } + + // export table + offset = CleanHeader->iExportDirOffset; + if (offset != 0) + { + FuzzFields(ExportEntryFields, offset); + } + } + else + { + if (aRandom) + { + // random bits of the compressed data + FuzzBlockRandomly(CleanHeader->iCodeOffset, FileSize - CleanHeader->iCodeOffset); + } + else + { + // arbitrary bits of the compressed data + FuzzFields(CompressedDataFields, CleanHeader->iCodeOffset); + } + } + + DoneFile(); + after.UniversalTime(); + TTimeIntervalSeconds interval; + after.SecondsFrom(before, interval); + test.Printf(_L("Took %d seconds\n"), interval.Int()); + } + + +void FuzzTruncateTo(TInt size) + { + OutFileSize = size - 4; + if (Verbose) test.Printf(_L("%d "), OutFileSize); + Load(); + OutFileSize = size - 1; + if (Verbose) test.Printf(_L("%d "), OutFileSize); + Load(); + if (size == FileSize) + return; + OutFileSize = size; + if (Verbose) test.Printf(_L("%d "), OutFileSize); + Load(); + OutFileSize = size + 1; + if (Verbose) test.Printf(_L("%d "), OutFileSize); + Load(); + OutFileSize = size + 4; + if (Verbose) test.Printf(_L("%d "), OutFileSize); + Load(); + } + + +void FuzzTruncate() + { + TTime before, after; + before.UniversalTime(); + LoadCleanFile(); + + FuzzTruncateTo(CleanHeader->iCodeOffset); + if (CleanHeader->iCompressionType == KFormatNotCompressed) + FuzzTruncateTo(CleanHeader->iCodeOffset+CleanHeader->iCodeSize); + FuzzTruncateTo(FileSize); + + DoneFile(); + after.UniversalTime(); + TTimeIntervalSeconds interval; + after.SecondsFrom(before, interval); + test.Printf(_L("Took %d seconds\n"), interval.Int()); + } + + +void FuzzAllTestImages() + { + TInt i; + Drive = InternalDrive; + test.Next(_L("Fuzzing deterministically")); + for (i=1; i<=KFuzzImages; ++i) + { + test.Next(_L("Next binary...")); + test.Printf(_L("Fuzzing exe %d\n"), i); + PrepareName(i, EFalse); + FuzzFile(EFalse); + if(i==5) + continue; // DLL 5 doesn't exist because toolchain doesn't like DLLs with no exports + test.Next(_L("Next binary...")); + test.Printf(_L("Fuzzing dll %d\n"), i); + PrepareName(i, ETrue); + FuzzFile(EFalse); + } + Drive = RemovableDrive; + test.Next(_L("Fuzzing deterministically on removable media")); + for (i=1; i<=KFuzzImages; ++i) + { + test.Next(_L("Next binary...")); + test.Printf(_L("Fuzzing exe %d\n"), i); + PrepareName(i, EFalse); + FuzzFile(EFalse); + if(i==5) + continue; // DLL 5 doesn't exist because toolchain doesn't like DLLs with no exports + test.Next(_L("Next binary...")); + test.Printf(_L("Fuzzing dll %d\n"), i); + PrepareName(i, ETrue); + FuzzFile(EFalse); + } + Drive = InternalDrive; + test.Next(_L("Fuzzing by truncation")); + for (i=1; i<=KFuzzImages; ++i) + { + test.Next(_L("Next binary...")); + test.Printf(_L("Fuzzing exe %d\n"), i); + PrepareName(i, EFalse); + FuzzTruncate(); + if(i==5) + continue; // DLL 5 doesn't exist because toolchain doesn't like DLLs with no exports + test.Next(_L("Next binary...")); + test.Printf(_L("Fuzzing dll %d\n"), i); + PrepareName(i, ETrue); + FuzzTruncate(); + } + Drive = RemovableDrive; + test.Next(_L("Fuzzing by truncation on removable media")); + for (i=1; i<=KFuzzImages; ++i) + { + test.Next(_L("Next binary...")); + test.Printf(_L("Fuzzing exe %d\n"), i); + PrepareName(i, EFalse); + FuzzTruncate(); + if(i==5) + continue; // DLL 5 doesn't exist because toolchain doesn't like DLLs with no exports + test.Next(_L("Next binary...")); + test.Printf(_L("Fuzzing dll %d\n"), i); + PrepareName(i, ETrue); + FuzzTruncate(); + } + test.Next(_L("Fuzzing randomly")); + do + { + for (i=1; i<=KFuzzImages; ++i) + { + Drive = InternalDrive; + test.Next(_L("Next binary...")); + test.Printf(_L("Fuzzing exe %d\n"), i); + PrepareName(i, EFalse); + FuzzFile(ETrue); + if(i==5) + continue; // DLL 5 doesn't exist because toolchain doesn't like DLLs with no exports + test.Next(_L("Next binary...")); + test.Printf(_L("Fuzzing dll %d\n"), i); + PrepareName(i, ETrue); + FuzzFile(ETrue); + Drive = RemovableDrive; + test.Next(_L("Next binary...")); + test.Printf(_L("Fuzzing exe %d on removable media\n"), i); + PrepareName(i, EFalse); + FuzzFile(ETrue); + if(i==5) + continue; // DLL 5 doesn't exist because toolchain doesn't like DLLs with no exports + test.Next(_L("Next binary...")); + test.Printf(_L("Fuzzing dll %d on removable media\n"), i); + PrepareName(i, ETrue); + FuzzFile(ETrue); + } + } + while (Forever); + } + + +void FuzzProvidedImage() + { + test.Printf(_L("Fuzzing file %S\n"), &Provided); + PrepareProvidedName(); + Drive = InternalDrive; + test.Next(_L("Fuzzing deterministically")); + FuzzFile(EFalse); + Drive = RemovableDrive; + test.Next(_L("Fuzzing deterministically on removable media")); + FuzzFile(EFalse); + test.Next(_L("Fuzzing by truncation")); + FuzzTruncate(); + Drive = RemovableDrive; + test.Next(_L("Fuzzing by truncation on removable media")); + FuzzTruncate(); + test.Next(_L("Fuzzing randomly")); + do + { + Drive = InternalDrive; + test.Next(_L("Internal drive")); + FuzzFile(ETrue); + Drive = RemovableDrive; + test.Next(_L("Removable drive")); + FuzzFile(ETrue); + } + while (Forever); + } + + +GLDEF_C TInt E32Main() + { + // default to verbose unless the fasttest trace flag is on + Verbose = (UserSvr::DebugMask(2)&0x00000002) == 0; + + TFileName cmd; + User::CommandLine(cmd); + TLex lex(cmd); + FOREVER + { + lex.SkipSpace(); + if (lex.Eos()) + break; + TChar next = lex.Peek(); + if (next == '-' || next == '/') + { + // option + lex.Inc(); + switch(lex.Get()) + { + case 'v': + Verbose = ETrue; + break; + case 'q': + Verbose = EFalse; + break; + case 'l': + { + // being used as a slave to load a DLL + TPtrC libname(lex.NextToken()); + RLibrary l; + RProcess::Rendezvous(KErrNone); + l.Load(libname); + return KErrNone; + } + case 's': + // random seed + lex.SkipSpace(); + test_KErrNone(lex.Val(Seed, EHex)); + test.Printf(_L("Using supplied random seed %08x\n"), Seed); + break; + case 'f': + // run forever + Forever = ETrue; + break; + } + } + else + { + // filename, at least i assume it is :) + Provided.Copy(lex.NextToken()); + } + } + + test.Title(); + test.Next(_L("Setup")); + __UHEAP_MARK; + CTrapCleanup* cleanup; + cleanup=CTrapCleanup::New(); + + if (Seed == 0) + { + TTime time; + time.UniversalTime(); + Seed = (TUint32)time.Int64(); + test.Printf(_L("Random seed is %08x\n"), Seed); + } + + test_KErrNone(TheFs.Connect()); + test_TRAP(FileMan=CFileMan::NewL(TheFs)); + test_KErrNone(Timer.CreateLocal()); + test_TRAP(Hasher=CSHA1::NewL()); + HashDir.Append(TheFs.GetSystemDriveChar()); + HashDir.Append(KSysHash); + TInt r = TheFs.MkDirAll(HashDir); + test(r == KErrNone || r == KErrAlreadyExists); + + // Find some interesting drives + for (TInt driveno = EDriveA; driveno <= EDriveZ; ++driveno) + { + TDriveInfo di; + test_KErrNone(TheFs.Drive(di, driveno)); + if (di.iType == EMediaNotPresent) + continue; + TChar drivechar; + test_KErrNone(TheFs.DriveToChar(driveno, drivechar)); + if ((di.iDriveAtt & KDriveAttInternal) && InternalDrive == '?') + InternalDrive = drivechar; + else if ((di.iDriveAtt & KDriveAttRemovable) && RemovableDrive == '?') + RemovableDrive = drivechar; + else + continue; + + TFileName fn; + fn.Append(drivechar); + fn.Append(KSysBin); + TheFs.MkDirAll(fn); + test(r == KErrNone || r == KErrAlreadyExists); + } + test.Printf(_L("Using %c as internal drive, %c as removable\n"), (TUint)InternalDrive, (TUint)RemovableDrive); + + // Turn off evil lazy dll unloading + RLoader l; + test_KErrNone(l.Connect()); + test_KErrNone(l.CancelLazyDllUnload()); + l.Close(); + + test.Start(_L("Fuzzing loader")); + if (Provided.Length() == 0) + FuzzAllTestImages(); + else + FuzzProvidedImage(); + test.End(); + + delete Hasher; + Timer.Close(); + delete FileMan; + TheFs.Close(); + test.Close(); + delete cleanup; + __UHEAP_MARKEND; + return KErrNone; + } + +