os/kernelhwsrv/kerneltest/f32test/loader/security/t_fuzzldr.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // f32test\loader\security\t_fuzzldr.cpp
    15 // 
    16 //
    17 
    18 #define __E32TEST_EXTENSION__
    19 #include <e32test.h>
    20 #include <e32svr.h>
    21 #include <e32uid.h>
    22 #include <f32file.h>
    23 #include <f32image.h>
    24 #include "t_hash.h"
    25 
    26 // Fuzzing parameters
    27 
    28 const TInt KFuzzImages = 5;
    29 const TInt KRandomFieldIterations = 8;
    30 const TTimeIntervalMicroSeconds32 KDllTimeout = 10 * 1000000;
    31 
    32 #define FUZZFIELD(OBJ, NAME) { (const TText*)(L ## #OBJ L"." L ## #NAME), sizeof(((OBJ*)8)->NAME), _FOFF(OBJ, NAME) }
    33 #define DUMBFIELD(NAME, SIZE, OFFSET) { (const TText*)L ## NAME, SIZE, OFFSET }
    34 #define FUZZEND { NULL, 0, 0 }
    35 
    36 struct SFuzzField
    37 	{
    38 	const TText* name;
    39 	TInt size;
    40 	TInt offset;
    41 	};
    42 
    43 const SFuzzField HeaderFields[] =
    44 	{
    45 	FUZZFIELD(E32ImageHeaderV, iUid1),
    46 	FUZZFIELD(E32ImageHeaderV, iUid2),
    47 	FUZZFIELD(E32ImageHeaderV, iUid3),
    48 	FUZZFIELD(E32ImageHeaderV, iUidChecksum),
    49 	FUZZFIELD(E32ImageHeaderV, iSignature),
    50 	FUZZFIELD(E32ImageHeaderV, iHeaderCrc),
    51 	FUZZFIELD(E32ImageHeaderV, iModuleVersion),
    52 	FUZZFIELD(E32ImageHeaderV, iCompressionType),
    53 	FUZZFIELD(E32ImageHeaderV, iToolsVersion.iMajor),
    54 	FUZZFIELD(E32ImageHeaderV, iToolsVersion.iMinor),
    55 	FUZZFIELD(E32ImageHeaderV, iToolsVersion.iBuild),
    56 	FUZZFIELD(E32ImageHeaderV, iTimeLo),
    57 	FUZZFIELD(E32ImageHeaderV, iTimeHi),
    58 	FUZZFIELD(E32ImageHeaderV, iFlags),
    59 	FUZZFIELD(E32ImageHeaderV, iCodeSize),
    60 	FUZZFIELD(E32ImageHeaderV, iDataSize),
    61 	FUZZFIELD(E32ImageHeaderV, iHeapSizeMin),
    62 	FUZZFIELD(E32ImageHeaderV, iHeapSizeMax),
    63 	FUZZFIELD(E32ImageHeaderV, iStackSize),
    64 	FUZZFIELD(E32ImageHeaderV, iBssSize),
    65 	FUZZFIELD(E32ImageHeaderV, iEntryPoint),
    66 	FUZZFIELD(E32ImageHeaderV, iCodeBase),
    67 	FUZZFIELD(E32ImageHeaderV, iDataBase),
    68 	FUZZFIELD(E32ImageHeaderV, iDllRefTableCount),
    69 	FUZZFIELD(E32ImageHeaderV, iExportDirOffset),
    70 	FUZZFIELD(E32ImageHeaderV, iExportDirCount),
    71 	FUZZFIELD(E32ImageHeaderV, iTextSize),
    72 	FUZZFIELD(E32ImageHeaderV, iCodeOffset),
    73 	FUZZFIELD(E32ImageHeaderV, iDataOffset),
    74 	FUZZFIELD(E32ImageHeaderV, iImportOffset),
    75 	FUZZFIELD(E32ImageHeaderV, iCodeRelocOffset),
    76 	FUZZFIELD(E32ImageHeaderV, iDataRelocOffset),
    77 	FUZZFIELD(E32ImageHeaderV, iProcessPriority),
    78 	FUZZFIELD(E32ImageHeaderV, iCpuIdentifier),
    79 	FUZZFIELD(E32ImageHeaderV, iUncompressedSize),
    80 	FUZZFIELD(E32ImageHeaderV, iS.iSecureId),
    81 	FUZZFIELD(E32ImageHeaderV, iS.iVendorId),
    82 	FUZZFIELD(E32ImageHeaderV, iS.iCaps.iCaps[0]),
    83 	FUZZFIELD(E32ImageHeaderV, iS.iCaps.iCaps[1]),
    84 	FUZZFIELD(E32ImageHeaderV, iExceptionDescriptor),
    85 	FUZZFIELD(E32ImageHeaderV, iSpare2),
    86 	FUZZFIELD(E32ImageHeaderV, iExportDescSize),
    87 	FUZZFIELD(E32ImageHeaderV, iExportDescType),
    88 	FUZZFIELD(E32ImageHeaderV, iExportDesc[0]),
    89 	FUZZEND
    90 	};
    91 
    92 const SFuzzField ImportSectionFields[] =
    93 	{
    94 	FUZZFIELD(E32ImportSection, iSize),
    95 	FUZZEND
    96 	};
    97 
    98 const SFuzzField ImportBlockFields[] =
    99 	{
   100 	FUZZFIELD(E32ImportBlock, iOffsetOfDllName), // we should fuzz the string also
   101 	FUZZFIELD(E32ImportBlock, iNumberOfImports),
   102 	FUZZEND
   103 	};
   104 
   105 const SFuzzField ImportEntryFields[] =
   106 	{
   107 	DUMBFIELD("import", 4, 0),
   108 	FUZZEND
   109 	};
   110 
   111 const SFuzzField RelocSectionFields[] =
   112 	{
   113 	FUZZFIELD(E32RelocSection, iSize),
   114 	FUZZFIELD(E32RelocSection, iNumberOfRelocs),
   115 	FUZZEND
   116 	};
   117 
   118 const SFuzzField RelocBlockFields[] =
   119 	{
   120 	FUZZFIELD(E32RelocBlock, iPageOffset),
   121 	FUZZFIELD(E32RelocBlock, iBlockSize),
   122 	FUZZEND
   123 	};
   124 
   125 const SFuzzField RelocEntryFields[] =
   126 	{
   127 	DUMBFIELD("reloc", 2, 0),
   128 	FUZZEND
   129 	};
   130 
   131 const SFuzzField ExportEntryFields[] =
   132 	{
   133 	DUMBFIELD("export", 4, 0),
   134 	FUZZEND
   135 	};
   136 
   137 const SFuzzField CompressedDataFields[] =
   138 	{
   139 	DUMBFIELD("data1", 4, 0),
   140 	DUMBFIELD("data2", 4, 4),
   141 	DUMBFIELD("data3", 4, 16),
   142 	DUMBFIELD("data4", 4, 64),
   143 	DUMBFIELD("data5", 4, 256),
   144 	DUMBFIELD("data6", 4, 1024),
   145 	DUMBFIELD("data7", 4, 4096),
   146 	FUZZEND
   147 	};
   148 
   149 // Values to try for different sizes, signed here but can be interpreted as either
   150 // each will also try the smaller sizes' values
   151 const TInt8 Values8[] = { KMinTInt8, -100, -10, -2, -1, 0, 1, 2, 10, 100, KMaxTInt8 };
   152 const TInt Values8Count = sizeof(Values8)/sizeof(TInt8);
   153 const TInt16 Values16[] = { KMinTInt16, -10000, -256, -255, 128, 255, 256, 10000, KMaxTInt16 };
   154 const TInt Values16Count = sizeof(Values16)/sizeof(TInt16);
   155 const TInt32 Values32[] = { KMinTInt32, -1000000000, -65536, -65535, 32768, 65535, 65536, 268435455, 268435456, 1000000000, KMaxTInt32 };
   156 const TInt Values32Count = sizeof(Values32)/sizeof(TInt32);
   157 const TInt ValuesCount[] = { 0, Values8Count, Values8Count+Values16Count, 0, Values8Count+Values16Count+Values32Count };
   158 const TInt Offsets[] = { 1, 2, 4, 16, -1, -2, -4, -16 };
   159 const TInt OffsetsCount = sizeof(Offsets)/sizeof(TInt);
   160 
   161 // Regular boring definitions and stuff
   162 
   163 RTest test(_L("T_FUZZLDR"));
   164 RFs TheFs;
   165 CFileMan* FileMan;
   166 
   167 _LIT(KOrigDir, "Z:\\sys\\bin\\");
   168 _LIT(KSysBin, ":\\sys\\bin\\");
   169 _LIT(KSysHash, ":\\sys\\hash\\");
   170 _LIT(KImageName, "fuzzv");
   171 _LIT(KExeExt, ".exe");
   172 _LIT(KDllExt, ".dll");
   173 _LIT(KMyself, "t_fuzzldr");
   174 _LIT(KSlaveArg, "-l ");
   175 
   176 TFileName Provided;
   177 TFileName Original;
   178 TFileName Current;
   179 TFileName Hash;
   180 TFileName HashDir;
   181 TBool LoadDll;
   182 RFile File;
   183 RTimer Timer;
   184 TUint8* Target;
   185 E32ImageHeaderV* Header;
   186 E32ImageHeaderV* CleanHeader;
   187 CSHA1* Hasher;
   188 
   189 TInt FileSize;
   190 TInt OutFileSize;
   191 TUint8* CleanFileData;
   192 TPtr8 CleanFileDes(CleanFileData, 0);
   193 TUint8* FileData;
   194 TPtr8 FileDes(FileData, 0);
   195 TUint8* EndOfFile;
   196 TChar Drive = '?', InternalDrive = '?', RemovableDrive = '?';
   197 
   198 TBool Verbose;
   199 TBool Forever = EFalse;
   200 TUint32 Seed = 0;
   201 typedef void (*TFieldFuzzer)(const SFuzzField*, TInt);
   202 
   203 enum SetMode {
   204 	ESetLiteral,
   205 	ESetOffset,
   206 	ESetRandom,
   207 	ESetXor,
   208 };
   209 
   210 enum ValueMode {
   211 	EValLiteral,
   212 	EValOffset,
   213 	EValRandom,
   214 	EValXor,
   215 	EValList,
   216 	EValOffsetList,
   217 };
   218 
   219 
   220 TUint32 Rand()
   221 	{
   222 	Seed *= 69069;
   223 	Seed += 5;
   224 	return Seed;
   225 	}
   226 
   227 
   228 TUint32 Rand(TUint32 aLimit)
   229 	{
   230 	TUint64 temp = (TUint64)Rand() * (TUint64)aLimit;
   231 	return (TUint32)(temp>>32);
   232 	}
   233 
   234 
   235 void PrepareName(TInt aNum, TBool aDll)
   236 	{
   237 	Original = KOrigDir;
   238 	Original += KImageName;
   239 	Original.AppendNum(aNum);
   240 	Original += aDll ? KDllExt : KExeExt;
   241 	Current.Zero();
   242 	Current.Append(Drive);
   243 	Current += KSysBin;
   244 	Current += KImageName;
   245 	Current.AppendNum(aNum);
   246 	Current += aDll ? KDllExt : KExeExt;
   247 	Hash = HashDir;
   248 	Hash += KImageName;
   249 	Hash.AppendNum(aNum);
   250 	Hash += aDll ? KDllExt : KExeExt;
   251 	}
   252 
   253 
   254 void PrepareProvidedName()
   255 	{
   256 	Original = KOrigDir;
   257 	Original += Provided;
   258 	Current.Zero();
   259 	Current.Append(Drive);
   260 	Current += KSysBin;
   261 	Current += Provided;
   262 	Hash = HashDir;
   263 	Hash += Provided;
   264 	}
   265 
   266 
   267 void MakeCleanCopy()
   268 	{
   269 	Mem::Copy(FileData, CleanFileData, FileSize);
   270 	}
   271 
   272 
   273 void LoadCleanFile()
   274 	{
   275 	test_KErrNone(File.Open(TheFs, Original, EFileRead));
   276 	test_KErrNone(File.Size(FileSize));
   277 	OutFileSize = FileSize;
   278 	CleanFileData = new TUint8[FileSize];
   279 	test_NotNull(CleanFileData);
   280 	FileData = new TUint8[FileSize];
   281 	EndOfFile = FileData + FileSize;
   282 	test_NotNull(FileData);
   283 	CleanFileDes.Set(CleanFileData, 0, FileSize);
   284 	test_KErrNone(File.Read(CleanFileDes));
   285 	File.Close();
   286 	Header = (E32ImageHeaderV*)FileData;
   287 	CleanHeader = (E32ImageHeaderV*)CleanFileData;
   288 	FileDes.Set(FileData, FileSize, FileSize);
   289 	MakeCleanCopy();
   290 	test(CleanHeader->iUid1==(TUint32)KExecutableImageUidValue || CleanHeader->iUid1==(TUint32)KDynamicLibraryUidValue);
   291 	LoadDll = CleanHeader->iUid1==(TUint32)KDynamicLibraryUidValue;
   292 	}
   293 
   294 
   295 void DoneFile()
   296 	{
   297 	delete[] FileData;
   298 	delete[] CleanFileData;
   299 	}
   300 
   301 
   302 void RecalcChecksums()
   303 	{
   304 	if (Header->iUidChecksum == CleanHeader->iUidChecksum)
   305 		{
   306 		TUidType uids = *(const TUidType*)Header;
   307 		TCheckedUid chkuid(uids);
   308 		const TUint32* pChkUid = (const TUint32*)&chkuid;
   309 		Header->iUidChecksum = pChkUid[3];
   310 		}
   311 	if (Header->iHeaderCrc == CleanHeader->iHeaderCrc)
   312 		{
   313 		Header->iHeaderCrc = KImageCrcInitialiser;
   314 		TUint32 crc = 0;
   315 		Mem::Crc32(crc, Header, sizeof(E32ImageHeaderV));
   316 		Header->iHeaderCrc = crc;
   317 		}
   318 	}
   319 
   320 
   321 void Load()
   322 	{
   323 	RecalcChecksums();
   324 	test_KErrNone(File.Replace(TheFs, Current, EFileWrite));
   325 	test_KErrNone(File.Write(FileDes, OutFileSize));
   326 	test_KErrNone(File.Flush());
   327 	File.Close();
   328 	if (Drive == RemovableDrive)
   329 		{
   330 		TPtrC8 data(FileData, OutFileSize);
   331 		Hasher->Reset();
   332 		Hasher->Update(data);
   333 		TBuf8<SHA1_HASH> hashVal = Hasher->Final();
   334 		test_KErrNone(File.Replace(TheFs, Hash, EFileWrite));
   335 		test_KErrNone(File.Write(hashVal));
   336 		test_KErrNone(File.Flush());
   337 		File.Close();
   338 		}
   339 	RProcess p;
   340 	TInt r;
   341 	if (LoadDll)
   342 		{
   343 		TFileName args;
   344 		args.Copy(KSlaveArg);
   345 		args.Append(Current);
   346 		test_KErrNone(p.Create(KMyself, args));
   347 		TRequestStatus logon, rendez, timeout;
   348 		p.Logon(logon);
   349 		p.Rendezvous(rendez);
   350 		p.Resume();
   351 		User::WaitForRequest(rendez);
   352 		test(rendez==KErrNone);
   353 		Timer.After(timeout, KDllTimeout);
   354 		User::WaitForRequest(logon, timeout);
   355 		if (logon == KRequestPending)
   356 			{
   357 			p.Kill(0);
   358 			User::WaitForRequest(logon);
   359 			}
   360 		else
   361 			{
   362 			Timer.Cancel();
   363 			User::WaitForRequest(timeout);
   364 			}
   365 		p.Close();
   366 		// we don't check the return code as passing it back makes the log output
   367 		// super spammy with KPANIC on - it prints for every nonzero return code.
   368 		if (Verbose) test.Printf(_L("\n"));
   369 		}
   370 	else
   371 		{
   372 		r = p.Create(Current, KNullDesC);
   373 		if (r==KErrNone)
   374 			p.Kill(0);
   375 		if (Verbose) test.Printf(_L("=> %d\n"), r);
   376 		}
   377 	p.Close();
   378 	}
   379 
   380 
   381 template <typename T> void SetFieldTo(const SFuzzField* aField, T aSetTo, SetMode aMode)
   382 	{
   383 	T* field = (T*)(Target + aField->offset);
   384 	if ((TUint8*)field >= EndOfFile)
   385 		{
   386 		if (Verbose) test.Printf(_L("skipping, eof "));
   387 		return;
   388 		}
   389 	if (aMode == ESetOffset)
   390 		aSetTo += *field;
   391 	else if (aMode == ESetRandom)
   392 		aSetTo = (T)Rand();
   393 	else if (aMode == ESetXor)
   394 		aSetTo ^= *field;
   395 	*field = aSetTo;
   396 	if (Verbose) test.Printf(_L("%d "), aSetTo);
   397 	}
   398 
   399 
   400 void SetField(const SFuzzField* aField, TInt aValue, ValueMode aMode)
   401 	{
   402 	if (aMode < EValList)
   403 		{
   404 		switch(aField->size)
   405 			{
   406 		case 1:
   407 			SetFieldTo<TInt8>(aField, aValue, (SetMode)aMode);
   408 			break;
   409 		case 2:
   410 			SetFieldTo<TInt16>(aField, aValue, (SetMode)aMode);
   411 			break;
   412 		case 4:
   413 			SetFieldTo<TInt32>(aField, aValue, (SetMode)aMode);
   414 			break;
   415 			}
   416 		}
   417 	else if (aMode == EValList)
   418 		{
   419 		switch(aField->size)
   420 			{
   421 		case 1:
   422 			SetFieldTo<TInt8>(aField, Values8[aValue], ESetLiteral);
   423 			break;
   424 		case 2:
   425 			if (aValue < ValuesCount[1])
   426 				SetFieldTo<TInt16>(aField, Values8[aValue], ESetLiteral);
   427 			else
   428 				SetFieldTo<TInt16>(aField, Values16[aValue-ValuesCount[1]], ESetLiteral);
   429 			break;
   430 		case 4:
   431 			if (aValue < ValuesCount[1])
   432 				SetFieldTo<TInt32>(aField, Values8[aValue], ESetLiteral);
   433 			else if (aValue < ValuesCount[2])
   434 				SetFieldTo<TInt32>(aField, Values16[aValue-ValuesCount[1]], ESetLiteral);
   435 			else
   436 				SetFieldTo<TInt32>(aField, Values32[aValue-ValuesCount[2]], ESetLiteral);
   437 			break;
   438 			}
   439 		}
   440 	else if (aMode == EValOffsetList)
   441 		{
   442 		switch(aField->size)
   443 			{
   444 		case 1:
   445 			SetFieldTo<TInt8>(aField, Offsets[aValue], ESetOffset);
   446 			break;
   447 		case 2:
   448 			SetFieldTo<TInt16>(aField, Offsets[aValue], ESetOffset);
   449 			break;
   450 		case 4:
   451 			SetFieldTo<TInt32>(aField, Offsets[aValue], ESetOffset);
   452 			break;
   453 			}
   454 		}
   455 	}
   456 
   457 
   458 void FuzzFieldsDeterministically(const SFuzzField* aFields, TInt aOffset)
   459 	{
   460 	Target = FileData + aOffset;
   461 
   462 	TInt f = -1;
   463    	while (aFields[++f].name)
   464 		{
   465 		test.Printf(_L("FIELD: %s ...\n"), aFields[f].name);
   466 		TInt v;
   467 		if (Verbose) test.Next(_L("Using preset values"));
   468 		for (v = 0; v < ValuesCount[aFields[f].size]; ++v)
   469 			{
   470 			MakeCleanCopy();
   471 			SetField(&aFields[f], v, EValList);
   472 			Load();
   473 			}
   474 		if (Verbose) test.Next(_L("Using preset offsets"));
   475 		for (v = 0; v < OffsetsCount; ++v)
   476 			{
   477 			MakeCleanCopy();
   478 			SetField(&aFields[f], v, EValOffsetList);
   479 			Load();
   480 			}
   481 		if (Verbose) test.Next(_L("Flipping single bits"));
   482 		for (v = 0; v < aFields[f].size*8; ++v)
   483 			{
   484 			MakeCleanCopy();
   485 			SetField(&aFields[f], 1<<v, EValXor);
   486 			Load();
   487 			}
   488 		if (Verbose) test.Next(_L("Inverting"));
   489 		MakeCleanCopy();
   490 		SetField(&aFields[f], 0xffffffffu, EValXor);
   491 		Load();
   492 
   493 		// things that are offsets all go below, pointless on
   494 		// narrow fields
   495 		if (aFields[f].size == 4)
   496 			{
   497 			if (Verbose) test.Next(_L("Using filesize relative values"));
   498 			for (v = FileSize-4; v <= FileSize+4; ++v)
   499 				{
   500 				MakeCleanCopy();
   501 				SetField(&aFields[f], v, EValLiteral);
   502 				Load();
   503 				}
   504 			if (Verbose) test.Next(_L("Using code-end relative values"));
   505 			TInt codeend = CleanHeader->iCodeSize + CleanHeader->iCodeOffset;
   506 			for (v = codeend-4; v <= codeend+4; ++v)
   507 				{
   508 				MakeCleanCopy();
   509 				SetField(&aFields[f], v, EValLiteral);
   510 				Load();
   511 				}
   512 			}
   513 		}
   514 	}
   515 
   516 
   517 void FuzzFieldsRandomly(const SFuzzField* aFields, TInt aOffset)
   518 	{
   519 	Target = FileData + aOffset;
   520 
   521 	TInt f = 0;
   522    	while (aFields[f].name)
   523 		{
   524 		test.Printf(_L("FIELD: %s ... (random)\n"), aFields[f].name);
   525 		TInt v;
   526 		for (v = 0; v < KRandomFieldIterations; ++v)
   527 			{
   528 			MakeCleanCopy();
   529 			SetField(&aFields[f], 0, EValRandom);
   530 			Load();
   531 			}
   532 		f++;
   533 		}
   534 	}
   535 
   536 
   537 void FuzzBlockRandomly(TInt aOffset, TInt aSize)
   538 	{
   539 	SFuzzField field;
   540 	field.size = 1;
   541 	Target = FileData + aOffset;
   542 	
   543 	test.Printf(_L("FIELD: random words in data\n"));
   544 	TInt v;
   545 	for (v = 0; v < KRandomFieldIterations * 4; ++v)
   546 		{
   547 		MakeCleanCopy();
   548 		field.offset = Rand(aSize);
   549 		if (Verbose) test.Printf(_L("@ %d, "), field.offset);
   550 		SetField(&field, 0, EValRandom);
   551 		Load();
   552 		}
   553 	}
   554 
   555 
   556 void FuzzFile(TBool aRandom)
   557 	{
   558 	TTime before, after;
   559 	before.UniversalTime();
   560 	LoadCleanFile();
   561 	
   562 	TFieldFuzzer FuzzFields = aRandom ? FuzzFieldsRandomly : FuzzFieldsDeterministically;
   563 
   564 	// E32ImageHeader
   565 	FuzzFields(HeaderFields, 0);
   566 
   567 	if (CleanHeader->iCompressionType == KFormatNotCompressed)
   568 		{
   569 		// import table
   570 		TInt offset = CleanHeader->iImportOffset;
   571 		if (offset != 0)
   572 			{
   573 			FuzzFields(ImportSectionFields, offset);
   574 			offset += sizeof(E32ImportSection);
   575 			FuzzFields(ImportBlockFields, offset);
   576 			offset += sizeof(E32ImportBlock);
   577 			FuzzFields(ImportEntryFields, offset);
   578 			}
   579 
   580 		// code relocations
   581 		offset = CleanHeader->iCodeRelocOffset;
   582 		if (offset != 0)
   583 			{
   584 			FuzzFields(RelocSectionFields, offset);
   585 			offset += sizeof(E32RelocSection);
   586 			FuzzFields(RelocBlockFields, offset);
   587 			offset += sizeof(E32RelocBlock);
   588 			FuzzFields(RelocEntryFields, offset);
   589 			}
   590 
   591 		// data relocations
   592 		offset = CleanHeader->iDataRelocOffset;
   593 		if (offset != 0)
   594 			{
   595 			FuzzFields(RelocSectionFields, offset);
   596 			offset += sizeof(E32RelocSection);
   597 			FuzzFields(RelocBlockFields, offset);
   598 			offset += sizeof(E32RelocBlock);
   599 			FuzzFields(RelocEntryFields, offset);
   600 			}
   601 
   602 		// export table
   603 		offset = CleanHeader->iExportDirOffset;
   604 		if (offset != 0)
   605 			{
   606 			FuzzFields(ExportEntryFields, offset);
   607 			}
   608 		}
   609 	else
   610 		{
   611 		if (aRandom)
   612 			{
   613 			// random bits of the compressed data
   614 			FuzzBlockRandomly(CleanHeader->iCodeOffset, FileSize - CleanHeader->iCodeOffset);
   615 			}
   616 		else
   617 			{
   618 			// arbitrary bits of the compressed data
   619 			FuzzFields(CompressedDataFields, CleanHeader->iCodeOffset);
   620 			}
   621 		}
   622 
   623 	DoneFile();
   624 	after.UniversalTime();
   625 	TTimeIntervalSeconds interval;
   626 	after.SecondsFrom(before, interval);
   627 	test.Printf(_L("Took %d seconds\n"), interval.Int());
   628 	}
   629 
   630 
   631 void FuzzTruncateTo(TInt size)
   632 	{
   633 	OutFileSize = size - 4;
   634 	if (Verbose) test.Printf(_L("%d "), OutFileSize);
   635 	Load();
   636 	OutFileSize = size - 1;
   637 	if (Verbose) test.Printf(_L("%d "), OutFileSize);
   638 	Load();
   639 	if (size == FileSize)
   640 		return;
   641 	OutFileSize = size;
   642 	if (Verbose) test.Printf(_L("%d "), OutFileSize);
   643 	Load();
   644 	OutFileSize = size + 1;
   645 	if (Verbose) test.Printf(_L("%d "), OutFileSize);
   646 	Load();
   647 	OutFileSize = size + 4;
   648 	if (Verbose) test.Printf(_L("%d "), OutFileSize);
   649 	Load();
   650 	}
   651 
   652 
   653 void FuzzTruncate()
   654 	{
   655 	TTime before, after;
   656 	before.UniversalTime();
   657 	LoadCleanFile();
   658 
   659 	FuzzTruncateTo(CleanHeader->iCodeOffset);
   660 	if (CleanHeader->iCompressionType == KFormatNotCompressed)
   661 		FuzzTruncateTo(CleanHeader->iCodeOffset+CleanHeader->iCodeSize);
   662 	FuzzTruncateTo(FileSize);
   663 
   664 	DoneFile();
   665 	after.UniversalTime();
   666 	TTimeIntervalSeconds interval;
   667 	after.SecondsFrom(before, interval);
   668 	test.Printf(_L("Took %d seconds\n"), interval.Int());
   669 	}
   670 
   671 
   672 void FuzzAllTestImages()
   673 	{
   674 	TInt i;
   675 	Drive = InternalDrive;
   676 	test.Next(_L("Fuzzing deterministically"));
   677 	for (i=1; i<=KFuzzImages; ++i)
   678 		{
   679 		test.Next(_L("Next binary..."));
   680 		test.Printf(_L("Fuzzing exe %d\n"), i);
   681 		PrepareName(i, EFalse);
   682 		FuzzFile(EFalse);
   683 		if(i==5)
   684 			continue; // DLL 5 doesn't exist because toolchain doesn't like DLLs with no exports
   685 		test.Next(_L("Next binary..."));
   686 		test.Printf(_L("Fuzzing dll %d\n"), i);
   687 		PrepareName(i, ETrue);
   688 		FuzzFile(EFalse);
   689 		}
   690 	Drive = RemovableDrive;
   691 	test.Next(_L("Fuzzing deterministically on removable media"));
   692 	for (i=1; i<=KFuzzImages; ++i)
   693 		{
   694 		test.Next(_L("Next binary..."));
   695 		test.Printf(_L("Fuzzing exe %d\n"), i);
   696 		PrepareName(i, EFalse);
   697 		FuzzFile(EFalse);
   698 		if(i==5)
   699 			continue; // DLL 5 doesn't exist because toolchain doesn't like DLLs with no exports
   700 		test.Next(_L("Next binary..."));
   701 		test.Printf(_L("Fuzzing dll %d\n"), i);
   702 		PrepareName(i, ETrue);
   703 		FuzzFile(EFalse);
   704 		}
   705 	Drive = InternalDrive;
   706 	test.Next(_L("Fuzzing by truncation"));
   707 	for (i=1; i<=KFuzzImages; ++i)
   708 		{
   709 		test.Next(_L("Next binary..."));
   710 		test.Printf(_L("Fuzzing exe %d\n"), i);
   711 		PrepareName(i, EFalse);
   712 		FuzzTruncate();
   713 		if(i==5)
   714 			continue; // DLL 5 doesn't exist because toolchain doesn't like DLLs with no exports
   715 		test.Next(_L("Next binary..."));
   716 		test.Printf(_L("Fuzzing dll %d\n"), i);
   717 		PrepareName(i, ETrue);
   718 		FuzzTruncate();
   719 		}	
   720 	Drive = RemovableDrive;
   721 	test.Next(_L("Fuzzing by truncation on removable media"));
   722 	for (i=1; i<=KFuzzImages; ++i)
   723 		{
   724 		test.Next(_L("Next binary..."));
   725 		test.Printf(_L("Fuzzing exe %d\n"), i);
   726 		PrepareName(i, EFalse);
   727 		FuzzTruncate();
   728 		if(i==5)
   729 			continue; // DLL 5 doesn't exist because toolchain doesn't like DLLs with no exports
   730 		test.Next(_L("Next binary..."));
   731 		test.Printf(_L("Fuzzing dll %d\n"), i);
   732 		PrepareName(i, ETrue);
   733 		FuzzTruncate();
   734 		}	
   735 	test.Next(_L("Fuzzing randomly"));
   736 	do
   737 		{
   738 		for (i=1; i<=KFuzzImages; ++i)
   739 			{
   740 			Drive = InternalDrive;
   741 			test.Next(_L("Next binary..."));
   742 			test.Printf(_L("Fuzzing exe %d\n"), i);
   743 			PrepareName(i, EFalse);
   744 			FuzzFile(ETrue);
   745 			if(i==5)
   746 				continue; // DLL 5 doesn't exist because toolchain doesn't like DLLs with no exports
   747 			test.Next(_L("Next binary..."));
   748 			test.Printf(_L("Fuzzing dll %d\n"), i);
   749 			PrepareName(i, ETrue);
   750 			FuzzFile(ETrue);
   751 			Drive = RemovableDrive;
   752 			test.Next(_L("Next binary..."));
   753 			test.Printf(_L("Fuzzing exe %d on removable media\n"), i);
   754 			PrepareName(i, EFalse);
   755 			FuzzFile(ETrue);
   756 			if(i==5)
   757 				continue; // DLL 5 doesn't exist because toolchain doesn't like DLLs with no exports
   758 			test.Next(_L("Next binary..."));
   759 			test.Printf(_L("Fuzzing dll %d on removable media\n"), i);
   760 			PrepareName(i, ETrue);
   761 			FuzzFile(ETrue);
   762 			}
   763 		}
   764 	while (Forever);
   765 	}
   766 
   767 
   768 void FuzzProvidedImage()
   769 	{
   770 	test.Printf(_L("Fuzzing file %S\n"), &Provided);
   771 	PrepareProvidedName();
   772 	Drive = InternalDrive;
   773 	test.Next(_L("Fuzzing deterministically"));
   774 	FuzzFile(EFalse);
   775 	Drive = RemovableDrive;
   776 	test.Next(_L("Fuzzing deterministically on removable media"));
   777 	FuzzFile(EFalse);
   778 	test.Next(_L("Fuzzing by truncation"));
   779 	FuzzTruncate();
   780 	Drive = RemovableDrive;
   781 	test.Next(_L("Fuzzing by truncation on removable media"));
   782 	FuzzTruncate();
   783 	test.Next(_L("Fuzzing randomly"));
   784 	do
   785 		{
   786 		Drive = InternalDrive;
   787 		test.Next(_L("Internal drive"));
   788 		FuzzFile(ETrue);
   789 		Drive = RemovableDrive;
   790 		test.Next(_L("Removable drive"));
   791 		FuzzFile(ETrue);
   792 		}
   793 	while (Forever);
   794 	}
   795 
   796 
   797 GLDEF_C TInt E32Main()
   798 	{
   799 	// default to verbose unless the fasttest trace flag is on
   800 	Verbose = (UserSvr::DebugMask(2)&0x00000002) == 0;
   801 
   802 	TFileName cmd;
   803 	User::CommandLine(cmd);
   804 	TLex lex(cmd);
   805 	FOREVER
   806 		{
   807 		lex.SkipSpace();
   808 		if (lex.Eos())
   809 			break;
   810 		TChar next = lex.Peek();
   811 		if (next == '-' || next == '/')
   812 			{
   813 			// option
   814 			lex.Inc();
   815 			switch(lex.Get())
   816 				{
   817 			case 'v':
   818 				Verbose = ETrue;
   819 				break;
   820 			case 'q':
   821 				Verbose = EFalse;
   822 				break;
   823 			case 'l':
   824 				{
   825 				// being used as a slave to load a DLL
   826 				TPtrC libname(lex.NextToken());
   827 				RLibrary l;
   828 				RProcess::Rendezvous(KErrNone);
   829 				l.Load(libname);
   830 				return KErrNone;
   831 				}
   832 			case 's':
   833 				// random seed
   834 				lex.SkipSpace();
   835 				test_KErrNone(lex.Val(Seed, EHex));
   836 				test.Printf(_L("Using supplied random seed %08x\n"), Seed);
   837 				break;
   838 			case 'f':
   839 				// run forever
   840 				Forever = ETrue;
   841 				break;
   842 				}
   843 			}
   844 		else
   845 			{
   846 			// filename, at least i assume it is :)
   847 			Provided.Copy(lex.NextToken());
   848 			}
   849 		}
   850 
   851 	test.Title();
   852 	test.Next(_L("Setup"));
   853 	__UHEAP_MARK;
   854 	CTrapCleanup* cleanup;
   855 	cleanup=CTrapCleanup::New();
   856 
   857 	if (Seed == 0)
   858 		{
   859 		TTime time;
   860 		time.UniversalTime();
   861 		Seed = (TUint32)time.Int64();
   862 		test.Printf(_L("Random seed is %08x\n"), Seed);
   863 		}
   864 
   865 	test_KErrNone(TheFs.Connect());
   866 	test_TRAP(FileMan=CFileMan::NewL(TheFs));
   867 	test_KErrNone(Timer.CreateLocal());
   868 	test_TRAP(Hasher=CSHA1::NewL());
   869 	HashDir.Append(TheFs.GetSystemDriveChar());
   870 	HashDir.Append(KSysHash);
   871 	TInt r = TheFs.MkDirAll(HashDir);
   872 	test(r == KErrNone || r == KErrAlreadyExists);	
   873 
   874 	// Find some interesting drives
   875 	for (TInt driveno = EDriveA; driveno <= EDriveZ; ++driveno)
   876 		{
   877 		TDriveInfo di;
   878 		test_KErrNone(TheFs.Drive(di, driveno));
   879 		if (di.iType == EMediaNotPresent)
   880 			continue;
   881 		TChar drivechar;
   882 		test_KErrNone(TheFs.DriveToChar(driveno, drivechar));
   883 		if ((di.iDriveAtt & KDriveAttInternal) && InternalDrive == '?')
   884 			InternalDrive = drivechar;
   885 		else if ((di.iDriveAtt & KDriveAttRemovable) && RemovableDrive == '?')
   886 			RemovableDrive = drivechar;
   887 		else
   888 			continue;
   889 
   890 		TFileName fn;
   891 		fn.Append(drivechar);
   892 		fn.Append(KSysBin);
   893 		TheFs.MkDirAll(fn);
   894 		test(r == KErrNone || r == KErrAlreadyExists);	
   895 		}
   896 	test.Printf(_L("Using %c as internal drive, %c as removable\n"), (TUint)InternalDrive, (TUint)RemovableDrive);
   897 
   898 	// Turn off evil lazy dll unloading
   899 	RLoader l;
   900 	test_KErrNone(l.Connect());
   901 	test_KErrNone(l.CancelLazyDllUnload());
   902 	l.Close();
   903 
   904 	test.Start(_L("Fuzzing loader"));
   905 	if (Provided.Length() == 0)
   906 		FuzzAllTestImages();
   907 	else
   908 		FuzzProvidedImage();
   909 	test.End();
   910 
   911 	delete Hasher;
   912 	Timer.Close();
   913 	delete FileMan;
   914 	TheFs.Close();
   915 	test.Close();
   916 	delete cleanup;
   917 	__UHEAP_MARKEND;
   918 	return KErrNone;
   919 	}
   920 
   921