from .base_primitive import BasePrimitive
[docs]
class Group(BasePrimitive):
"""This primitive represents a list of static values, stepping through each one on mutation.
You can tie a block
to a group primitive to specify that the block should cycle through all possible mutations for *each* value
within the group. The group primitive is useful for example for representing a list of valid opcodes.
:param name: Name, for referencing later. Names should always be provided, but if not, a default name will be given,
defaults to None
:type name: str, optional
:param values: List of possible raw values this group can take.
:type values: list of bytes or list of str
:param default_value: Value used when the element is not being fuzzed - should typically represent a valid value,
defaults to None
:type default_value: str, optional
:param encoding: String encoding, ex: utf_16_le for Microsoft Unicode, defaults to ascii
:type encoding: str, optional
:param fuzzable: Enable/disable fuzzing of this primitive, defaults to true
:type fuzzable: bool, optional
"""
def __init__(self, name=None, values=None, default_value=None, encoding="ascii", *args, **kwargs):
assert len(values) > 0, "You can't have an empty value list for your group!"
for val in values:
assert isinstance(val, (bytes, str)), "Value list may only contain string/byte types"
values = list(map(lambda value: value if isinstance(value, bytes) else value.encode(encoding=encoding), values))
if default_value is None:
default_value = values[0]
default_value = default_value if isinstance(default_value, bytes) else default_value.encode(encoding=encoding)
if default_value in values:
values.remove(default_value)
super(Group, self).__init__(name=name, default_value=default_value, *args, **kwargs)
self.values = values
def mutations(self, default_value):
for value in self.values:
yield value
def num_mutations(self, default_value):
"""
Calculate and return the total number of mutations for this individual primitive.
Args:
default_value:
Returns:
int: Number of mutated forms this primitive can take
"""
return len(self.values)