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