|
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 |