def next_val(self, field): """Return a new value to mutate a field with. Do not modify the field directly in this function. Override the ``mutate()`` function if that is needed (the field is only passed into this function as a reference). :field: The pfp.fields.Field instance that will receive the new value. Passed in for reference only. :returns: The next value for the field """ import pfp.fuzz.rand as rand if self.choices is not None: choices = self._resolve_member_val(self.choices, field) new_val = rand.choice(choices) return self._resolve_val(new_val) elif self.prob is not None: prob = self._resolve_member_val(self.prob, field) rand_val = rand.random() curr_total = 0.0 # iterate through each of the probability choices until # we reach one that matches the current rand_val for prob_percent, prob_val in prob: if rand_val <= curr_total + prob_percent: return self._resolve_val(prob_val) curr_total += prob_percent raise MutationError( "probabilities did not add up to 100%! {}".format( [str(x[0]) + " - " + str(x[1])[:10] for x in prob]))
def _resolve_val(self, val): import pfp.fuzz.rand as rand if hasattr(val, "__call__"): return val() elif isinstance(val, dict) and "min" in val and "max" in val: return rand.randint(val["min"], val["max"]) elif hasattr(val, "__iter__"): return rand.choice(val) else: return val
def mutate(field, strat_name_or_cls, num=100, at_once=1): """Mutate the provided field (probably a Dom or struct instance) using the strategy specified with ``strat_name_or_class``, yielding ``num`` mutations that affect up to ``at_once`` fields at once. This function will yield back the field after each mutation. :param pfp.fields.Field field: The field to mutate (can be anything, not just Dom/Structs) :param strat_name_or_class: Can be the name of a strategy, or the actual strategy class (not an instance) :param int num: The number of mutations to yield :param int at_once: The number of fields to mutate at once :returns: None """ import pfp.fuzz.rand as rand init() strat = get_strategy(strat_name_or_cls) to_mutate = strat.which(field) with_strats = [] for to_mutate_field in to_mutate: field_strat = strat.get_field_strat(to_mutate_field) if field_strat is not None: with_strats.append((to_mutate_field, field_strat)) # we don't need these ones anymore del to_mutate # save the current value of all subfields without # triggering events field._pfp__snapshot(recurse=True) count = 0 for x in six.moves.range(num): chosen_fields = set() # modify `at_once` number of fields for at_onces in six.moves.xrange(at_once): rand_field, field_strat = rand.choice(with_strats) if rand_field in chosen_fields: continue chosen_fields.add(rand_field) field_strat.mutate(rand_field) # yield back the original field yield field # restore the saved value of all subfields without # triggering events field._pfp__restore_snapshot(recurse=True)