1
2 '''
3 Mutator base classes and interfaces.
4
5 A Mutator implements a method of mutating data/state for a Peach 2
6 fuzzer. For example a mutator might change the state flow defined
7 by a Peach fuzzer. Another mutator might mutate data based on
8 known relationships. Another mutator might perform numerical type
9 tests against fields.
10
11 @author: Michael Eddington
12 @version: $Id: mutator.py 1052 2008-07-17 06:46:50Z meddingt $
13 '''
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42 import random, threading
43 import pickle, types
44 from Peach.Engine.dom import *
45
47 '''
48 A Mutator implements a method of mutating data/state for a Peach 2
49 fuzzer. For example a mutator might change the state flow defined
50 by a Peach fuzzer. Another mutator might mutate data based on
51 known relationships. Another mutator might perform numerical type
52 tests against fields.
53 '''
54
55 elementType = "mutator"
56 dataTypes = ['template', 'string', 'number', 'flags', 'choice', 'sequence', 'blob', 'block']
57
59 self.name = "Mutator"
60 self._count = -1
61 pass
62
64 '''
65 DEPRICATED! SHould say: node.findDataElementByName(name)
66 '''
67 return node.findDataElementByName(name)
68
70 '''
71 Some mutators could contine forever, this
72 should indicate.
73 '''
74 return True
75
77 '''
78 Reset mutator
79 '''
80 pass
81
83 '''
84 Goto next mutation. When this is called
85 the state machine is updated as needed.
86 '''
87 pass
88
90 '''
91 Return a binary string that contains
92 any information about current state of
93 Mutator. This state information should be
94 enough to let the same mutator "restart"
95 and continue when setState() is called.
96 '''
97 pass
98
100 '''
101 Set the state of this object. Should put us
102 back in the same place as when we said
103 "getState()".
104 '''
105 pass
106
108 '''
109 If mutator is finite than the total test count
110 can be calculated. This calculation cannot
111 occur until after the state machine has been run
112 the first time. Once the state machine has been
113 run the count can be calculated. This typically
114 occurs in a separate thread as it can take some
115 time to calculate.
116
117 This method will return -1 until a the correct
118 value has been calculated.
119 '''
120 return self._count
121
123 '''
124 This method should calculate the count of this
125 mutator in a thread safe mannor. Typically
126 this method is called from a different thread.
127 It will never be called until the state machine
128 has run the first time through.
129 '''
130 return -1
131
132
133
134
137
140
143
144
145
146
149
152
155
158
161
164
166 '''
167 This class contains the needed state to seed a MutatorCollection.
168 '''
169
170 - def __init__(self, curFinite, finiteMutatorStates, infiniteMutatorStates):
171 '''
172 curFinite is index into finiteMutators we are at.
173 mutatorState is array of binary strings representing
174 the state of each mutator we are running.
175 '''
176 self.curFinite = curFinite
177 self.finiteMutatorStates = finiteMutatorStates
178 self.infiniteMutatorStates = infiniteMutatorStates
179
181 '''
182 Aggrigated collection of mutators.
183 '''
184
186 self.name = "MutatorCollection"
187
188
189 self._cycledAll = False
190
191 self._cyclePos = 0
192
193 self._mutators = mutators
194 self._finiteMutators = []
195 self._infiniteMutators = []
196 self._mutator = None
197
198 self._masterCount = 0
199 self._stateMasterCount = -1
200
201 for m in self._mutators:
202 if m.isFinite():
203 self._finiteMutators.append(m)
204 else:
205 self._infiniteMutators.append(m)
206
207
208 self._curFinite = 0
209 self._maxFinite = len(self._finiteMutators)
210 self._maxInfinite = len(self._infiniteMutators)
211
212 if self._maxFinite > 0:
213 self._mutator = self._finiteMutators[0]
214
215 elif self._maxInfinite > 0:
216 self._cycledAll = True
217 self._mutator = self._getRandomInfiniteMutator()
218
219 else:
220 raise Exception("MutatorCollection: No mutators!")
221
224
226 '''
227 Some mutators could contine forever, this
228 should indicate.
229 '''
230
231 return len(self._infiniteMutators) == 0
232
234 '''
235 Reset mutator
236 '''
237
238 self._cycledAll = False
239 self._cyclePos = 0
240 self._curFinite = 0
241
242 for m in self._mutators:
243 m.reset()
244
245 if self._maxFinite > 0:
246 self._mutator = self._finiteMutators[0]
247
248 elif self._maxInfinite > 0:
249 self._cycledAll = True
250 self._mutator = self._getRandomInfiniteMutator()
251
253 '''
254 Goto next mutation. When this is called
255 the state machine is updated as needed.
256 '''
257 try:
258
259 self._mutator.next()
260
261
262
263
264
265
266
267
268 if not self._cycledAll:
269 self._cyclePos += 1
270
271 if self._cyclePos >= self._maxFinite:
272 self._cycledAll = True
273 self._mutator = self._finiteMutators[self._curFinite]
274
275 else:
276 self._mutator = self._finiteMutators[self._cyclePos]
277
278
279 else:
280
281
282
283 if self._curFinite >= self._maxFinite:
284 self._mutator = self._getRandomInfiniteMutator()
285
286 except MutatorCompleted:
287
288
289
290
291
292
293
294
295
296
297
298
299
300 if not self._cycledAll:
301
302 self._cyclePos += 1
303 if self._cyclePos >= self._maxFinite:
304 self._cycledAll = True
305 self._mutator = self._finiteMutators[self._curFinite]
306
307 else:
308 self._mutator = self._finiteMutators[self._cyclePos]
309
310
311 else:
312
313
314 self._curFinite += 1
315
316
317 if self._curFinite >= self._maxFinite and self._maxInfinite == 0:
318 raise MutatorCompleted()
319
320
321 elif self._curFinite >= self._maxFinite:
322 self._mutator = self._getRandomInfiniteMutator()
323
324
325 else:
326 self._mutator = self._finiteMutators[self._curFinite]
327
328 self._masterCount += 1
329
331 '''
332 Get a random infinite mutator.
333 '''
334
335 idx = random.randint(0, self._maxInfinite)
336 return self._infiniteMutators[idx]
337
339 '''
340 Return a binary string that contains
341 any information about current state of
342 Mutator. This state information should be
343 enough to let the same mutator "restart"
344 and continue when setState() is called.
345 '''
346
347 return str(self._masterCount - 2)
348
350 '''
351 Set the state of this object. Should put us
352 back in the same place as when we said
353 "getState()".
354 '''
355 self._stateMasterCount = int(statePickle)
356 try:
357 for i in xrange(self._masterCount, self._stateMasterCount):
358 self.next()
359 except:
360 pass
361
363 '''
364 This count will change as we go through mutators.
365 '''
366
367 if not self.isFinite():
368 return -1
369
370 if not self._cycledAll:
371 return -1
372
373 count = 0
374 for m in self._finiteMutators:
375 if m.getCount() > -1:
376 count += m.getCount()
377 else:
378
379 return -1
380
381 if verbose:
382 for m in self._finiteMutators:
383 cnt = m.getCount()
384 print "Mutator %s is reporting %d test cases" % (m.name, cnt)
385
386 return count
387
388
389
390
393
396
399
400
401
402
405
408
411
414
417
420
422 '''
423 This class will try and calculate the total number
424 of test cases in another thread.
425
426 When the result is available self.hasCountEvent will
427 be set.
428 '''
429
431 threading.Thread.__init__(self)
432 self._mutator = mutator
433 self.hasCountEvent = threading.Event()
434 self.count = -1
435
439
440
442 '''
443 At end of available mutations
444 '''
445 pass
446
448 '''
449 Bad stuff just occured!
450 '''
451 pass
452
453
454