mirror of
https://github.com/jtpereyda/boofuzz.git
synced 2026-10-12 02:16:58 +00:00
209 lines
8.5 KiB
Python
209 lines
8.5 KiB
Python
import itertools
|
|
import math
|
|
import unittest
|
|
from collections import Counter, OrderedDict
|
|
|
|
import pytest
|
|
|
|
from boofuzz import *
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def clear_requests():
|
|
yield
|
|
blocks.REQUESTS = {}
|
|
blocks.CURRENT = None
|
|
|
|
|
|
class TestString(unittest.TestCase):
|
|
def _given_string(self):
|
|
self.default_value = "ABCDEFGH"
|
|
self.default_default_value = "\x00" * len(self.default_value)
|
|
return String(name="boofuzz-unit-test-name", default_value=self.default_value)
|
|
|
|
def _given_string_max_len(self, max_len):
|
|
self.default_value = "ABCDEFGH"
|
|
self.default_default_value = "\x00" * len(self.default_value)
|
|
return String(name="boofuzz-unit-test-name", default_value=self.default_value, max_len=max_len)
|
|
|
|
def _given_string_size(self, size, padding, encoding):
|
|
self.default_value = "ABCDEFGH"
|
|
self.default_default_value = "\x00" * len(self.default_value)
|
|
return String(
|
|
name="boofuzz-unit-test-name",
|
|
default_value=self.default_value,
|
|
size=size,
|
|
padding=padding,
|
|
encoding=encoding,
|
|
)
|
|
|
|
def test_mutations(self):
|
|
uut = self._given_string()
|
|
|
|
generator = uut.mutations(default_value=self.default_default_value)
|
|
|
|
n = 0
|
|
for expected, actual in zip(String._fuzz_library, generator):
|
|
n += 1
|
|
self.assertEqual(expected, actual)
|
|
|
|
for expected, actual in zip(String._variable_mutation_multipliers, generator):
|
|
n += 1
|
|
self.assertEqual(self.default_default_value * expected, actual)
|
|
|
|
for sequence in String.long_string_seeds:
|
|
for size in [
|
|
length + delta
|
|
for length, delta in itertools.product(String._long_string_lengths, String._long_string_deltas)
|
|
]:
|
|
n += 1
|
|
expected = sequence * math.ceil(size / len(sequence))
|
|
self.assertEqual(expected[:size], next(generator))
|
|
|
|
for size in String._extra_long_string_lengths:
|
|
n += 1
|
|
expected = sequence * math.ceil(size / len(sequence))
|
|
self.assertEqual(expected[:size], next(generator))
|
|
|
|
for size in String._long_string_lengths:
|
|
s = "D" * size
|
|
for loc in uut.random_indices[size]:
|
|
n += 1
|
|
expected = s[:loc] + "\x00" + s[loc + 1 :]
|
|
self.assertEqual(expected, next(generator))
|
|
|
|
self.assertRaises(StopIteration, lambda: next(generator))
|
|
self.assertEqual(n, uut.num_mutations(default_value=self.default_value))
|
|
list_of_duplicates = [
|
|
item for item, count in Counter(uut.mutations(default_value=self.default_value)).items() if count > 1
|
|
]
|
|
self.assertEqual(0, len(list_of_duplicates))
|
|
|
|
def test_mutations_max_len(self):
|
|
lengths = [5, 10, 128, 1000, 100000]
|
|
|
|
for max_len in lengths:
|
|
uut = self._given_string_max_len(max_len=max_len)
|
|
generator = uut.mutations(default_value=self.default_default_value)
|
|
|
|
def truncate(b):
|
|
return b[:max_len]
|
|
|
|
n = 0
|
|
for expected, actual in zip(OrderedDict.fromkeys(list(map(truncate, String._fuzz_library))), generator):
|
|
n += 1
|
|
self.assertEqual(expected, actual)
|
|
|
|
for expected, actual in zip(String._variable_mutation_multipliers, generator):
|
|
n += 1
|
|
self.assertEqual(truncate(self.default_default_value * expected), actual)
|
|
if max_len <= len(self.default_default_value * expected):
|
|
break
|
|
|
|
for sequence in String.long_string_seeds:
|
|
for size in [
|
|
length + delta
|
|
for length, delta in itertools.product(String._long_string_lengths, String._long_string_deltas)
|
|
]:
|
|
if size <= max_len:
|
|
n += 1
|
|
expected = sequence * math.ceil(size / len(sequence))
|
|
self.assertEqual(truncate(expected[:size]), next(generator))
|
|
|
|
for size in String._extra_long_string_lengths:
|
|
if size <= max_len:
|
|
n += 1
|
|
expected = sequence * math.ceil(size / len(sequence))
|
|
self.assertEqual(truncate(expected[:size]), next(generator))
|
|
|
|
if max_len not in String._extra_long_string_lengths + [
|
|
length + delta
|
|
for length, delta in itertools.product(String._long_string_lengths, String._long_string_deltas)
|
|
]:
|
|
n += 1
|
|
expected = sequence * math.ceil(max_len / len(sequence))
|
|
self.assertEqual(truncate(expected), next(generator))
|
|
|
|
for size in String._long_string_lengths:
|
|
if size <= max_len:
|
|
s = "D" * size
|
|
for loc in uut.random_indices[size]:
|
|
expected = s[:loc] + "\x00" + s[loc + 1 :]
|
|
n += 1
|
|
self.assertEqual(truncate(expected), next(generator))
|
|
|
|
self.assertRaises(StopIteration, lambda: next(generator))
|
|
self.assertEqual(n, uut.num_mutations(default_value=self.default_value))
|
|
list_of_duplicates = [
|
|
item for item, count in Counter(uut.mutations(default_value=self.default_value)).items() if count > 1
|
|
]
|
|
self.assertEqual(0, len(list_of_duplicates))
|
|
|
|
def test_mutations_size(self):
|
|
lengths = [5, 10, 128, 1000, 100000]
|
|
pad = b"\x41"
|
|
encoding = "utf-8"
|
|
|
|
def fit_to_size(b):
|
|
b = b[:max_len].encode(encoding=encoding)
|
|
pad_len = max(0, max_len - len(b))
|
|
return b + pad * pad_len
|
|
|
|
for max_len in lengths:
|
|
uut = self._given_string_size(size=max_len, padding=pad, encoding=encoding)
|
|
generator = uut.mutations(default_value=self.default_default_value)
|
|
|
|
n = 0
|
|
for expected, actual in zip(OrderedDict.fromkeys(list(map(fit_to_size, String._fuzz_library))), generator):
|
|
n += 1
|
|
self.assertEqual(expected, uut.encode(actual))
|
|
|
|
for expected, actual in zip(String._variable_mutation_multipliers, generator):
|
|
n += 1
|
|
self.assertEqual(fit_to_size(self.default_default_value * expected), uut.encode(actual))
|
|
if max_len <= len(self.default_default_value * expected):
|
|
break
|
|
|
|
for sequence in String.long_string_seeds:
|
|
for size in [
|
|
length + delta
|
|
for length, delta in itertools.product(String._long_string_lengths, String._long_string_deltas)
|
|
]:
|
|
if size <= max_len:
|
|
n += 1
|
|
expected = sequence * math.ceil(size / len(sequence))
|
|
self.assertEqual(fit_to_size(expected[:size]), uut.encode(next(generator)))
|
|
|
|
for size in String._extra_long_string_lengths:
|
|
if size <= max_len:
|
|
n += 1
|
|
expected = sequence * math.ceil(size / len(sequence))
|
|
self.assertEqual(fit_to_size(expected[:size]), uut.encode(next(generator)))
|
|
|
|
if max_len not in String._extra_long_string_lengths + [
|
|
length + delta
|
|
for length, delta in itertools.product(String._long_string_lengths, String._long_string_deltas)
|
|
]:
|
|
n += 1
|
|
expected = sequence * math.ceil(max_len / len(sequence))
|
|
self.assertEqual(fit_to_size(expected), uut.encode(next(generator)))
|
|
|
|
for length in String._long_string_lengths:
|
|
if length <= max_len:
|
|
s = "D" * length
|
|
for loc in uut.random_indices[length]:
|
|
expected = s[:loc] + "\x00" + s[loc + 1 :]
|
|
n += 1
|
|
self.assertEqual(fit_to_size(expected), uut.encode(next(generator)))
|
|
|
|
self.assertRaises(StopIteration, lambda: next(generator))
|
|
self.assertEqual(n, uut.num_mutations(default_value=self.default_value))
|
|
list_of_duplicates = [
|
|
item for item, count in Counter(uut.mutations(default_value=self.default_value)).items() if count > 1
|
|
]
|
|
self.assertEqual(0, len(list_of_duplicates))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|