Esempio n. 1
0
    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]))
Esempio n. 2
0
    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
Esempio n. 3
0
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)