diff options
Diffstat (limited to 'qemu/tests/image-fuzzer/qcow2/fuzz.py')
-rw-r--r-- | qemu/tests/image-fuzzer/qcow2/fuzz.py | 367 |
1 files changed, 0 insertions, 367 deletions
diff --git a/qemu/tests/image-fuzzer/qcow2/fuzz.py b/qemu/tests/image-fuzzer/qcow2/fuzz.py deleted file mode 100644 index 20eba6bc1..000000000 --- a/qemu/tests/image-fuzzer/qcow2/fuzz.py +++ /dev/null @@ -1,367 +0,0 @@ -# Fuzzing functions for qcow2 fields -# -# Copyright (C) 2014 Maria Kustova <maria.k@catit.be> -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -# - -import random - -UINT8 = 0xff -UINT16 = 0xffff -UINT32 = 0xffffffff -UINT64 = 0xffffffffffffffff -# Most significant bit orders -UINT32_M = 31 -UINT64_M = 63 -# Fuzz vectors -UINT8_V = [0, 0x10, UINT8/4, UINT8/2 - 1, UINT8/2, UINT8/2 + 1, UINT8 - 1, - UINT8] -UINT16_V = [0, 0x100, 0x1000, UINT16/4, UINT16/2 - 1, UINT16/2, UINT16/2 + 1, - UINT16 - 1, UINT16] -UINT32_V = [0, 0x100, 0x1000, 0x10000, 0x100000, UINT32/4, UINT32/2 - 1, - UINT32/2, UINT32/2 + 1, UINT32 - 1, UINT32] -UINT64_V = UINT32_V + [0x1000000, 0x10000000, 0x100000000, UINT64/4, - UINT64/2 - 1, UINT64/2, UINT64/2 + 1, UINT64 - 1, - UINT64] -STRING_V = ['%s%p%x%d', '.1024d', '%.2049d', '%p%p%p%p', '%x%x%x%x', - '%d%d%d%d', '%s%s%s%s', '%99999999999s', '%08x', '%%20d', '%%20n', - '%%20x', '%%20s', '%s%s%s%s%s%s%s%s%s%s', '%p%p%p%p%p%p%p%p%p%p', - '%#0123456x%08x%x%s%p%d%n%o%u%c%h%l%q%j%z%Z%t%i%e%g%f%a%C%S%08x%%', - '%s x 129', '%x x 257'] - - -def random_from_intervals(intervals): - """Select a random integer number from the list of specified intervals. - - Each interval is a tuple of lower and upper limits of the interval. The - limits are included. Intervals in a list should not overlap. - """ - total = reduce(lambda x, y: x + y[1] - y[0] + 1, intervals, 0) - r = random.randint(0, total - 1) + intervals[0][0] - for x in zip(intervals, intervals[1:]): - r = r + (r > x[0][1]) * (x[1][0] - x[0][1] - 1) - return r - - -def random_bits(bit_ranges): - """Generate random binary mask with ones in the specified bit ranges. - - Each bit_ranges is a list of tuples of lower and upper limits of bit - positions will be fuzzed. The limits are included. Random amount of bits - in range limits will be set to ones. The mask is returned in decimal - integer format. - """ - bit_numbers = [] - # Select random amount of random positions in bit_ranges - for rng in bit_ranges: - bit_numbers += random.sample(range(rng[0], rng[1] + 1), - random.randint(0, rng[1] - rng[0] + 1)) - val = 0 - # Set bits on selected positions to ones - for bit in bit_numbers: - val |= 1 << bit - return val - - -def truncate_string(strings, length): - """Return strings truncated to specified length.""" - if type(strings) == list: - return [s[:length] for s in strings] - else: - return strings[:length] - - -def validator(current, pick, choices): - """Return a value not equal to the current selected by the pick - function from choices. - """ - while True: - val = pick(choices) - if not val == current: - return val - - -def int_validator(current, intervals): - """Return a random value from intervals not equal to the current. - - This function is useful for selection from valid values except current one. - """ - return validator(current, random_from_intervals, intervals) - - -def bit_validator(current, bit_ranges): - """Return a random bit mask not equal to the current. - - This function is useful for selection from valid values except current one. - """ - return validator(current, random_bits, bit_ranges) - - -def string_validator(current, strings): - """Return a random string value from the list not equal to the current. - - This function is useful for selection from valid values except current one. - """ - return validator(current, random.choice, strings) - - -def selector(current, constraints, validate=int_validator): - """Select one value from all defined by constraints. - - Each constraint produces one random value satisfying to it. The function - randomly selects one value satisfying at least one constraint (depending on - constraints overlaps). - """ - def iter_validate(c): - """Apply validate() only to constraints represented as lists. - - This auxiliary function replaces short circuit conditions not supported - in Python 2.4 - """ - if type(c) == list: - return validate(current, c) - else: - return c - - fuzz_values = [iter_validate(c) for c in constraints] - # Remove current for cases it's implicitly specified in constraints - # Duplicate validator functionality to prevent decreasing of probability - # to get one of allowable values - # TODO: remove validators after implementation of intelligent selection - # of fields will be fuzzed - try: - fuzz_values.remove(current) - except ValueError: - pass - return random.choice(fuzz_values) - - -def magic(current): - """Fuzz magic header field. - - The function just returns the current magic value and provides uniformity - of calls for all fuzzing functions. - """ - return current - - -def version(current): - """Fuzz version header field.""" - constraints = UINT32_V + [ - [(2, 3)], # correct values - [(0, 1), (4, UINT32)] - ] - return selector(current, constraints) - - -def backing_file_offset(current): - """Fuzz backing file offset header field.""" - constraints = UINT64_V - return selector(current, constraints) - - -def backing_file_size(current): - """Fuzz backing file size header field.""" - constraints = UINT32_V - return selector(current, constraints) - - -def cluster_bits(current): - """Fuzz cluster bits header field.""" - constraints = UINT32_V + [ - [(9, 20)], # correct values - [(0, 9), (20, UINT32)] - ] - return selector(current, constraints) - - -def size(current): - """Fuzz image size header field.""" - constraints = UINT64_V - return selector(current, constraints) - - -def crypt_method(current): - """Fuzz crypt method header field.""" - constraints = UINT32_V + [ - 1, - [(2, UINT32)] - ] - return selector(current, constraints) - - -def l1_size(current): - """Fuzz L1 table size header field.""" - constraints = UINT32_V - return selector(current, constraints) - - -def l1_table_offset(current): - """Fuzz L1 table offset header field.""" - constraints = UINT64_V - return selector(current, constraints) - - -def refcount_table_offset(current): - """Fuzz refcount table offset header field.""" - constraints = UINT64_V - return selector(current, constraints) - - -def refcount_table_clusters(current): - """Fuzz refcount table clusters header field.""" - constraints = UINT32_V - return selector(current, constraints) - - -def nb_snapshots(current): - """Fuzz number of snapshots header field.""" - constraints = UINT32_V - return selector(current, constraints) - - -def snapshots_offset(current): - """Fuzz snapshots offset header field.""" - constraints = UINT64_V - return selector(current, constraints) - - -def incompatible_features(current): - """Fuzz incompatible features header field.""" - constraints = [ - [(0, 1)], # allowable values - [(0, UINT64_M)] - ] - return selector(current, constraints, bit_validator) - - -def compatible_features(current): - """Fuzz compatible features header field.""" - constraints = [ - [(0, UINT64_M)] - ] - return selector(current, constraints, bit_validator) - - -def autoclear_features(current): - """Fuzz autoclear features header field.""" - constraints = [ - [(0, UINT64_M)] - ] - return selector(current, constraints, bit_validator) - - -def refcount_order(current): - """Fuzz number of refcount order header field.""" - constraints = UINT32_V - return selector(current, constraints) - - -def header_length(current): - """Fuzz number of refcount order header field.""" - constraints = UINT32_V + [ - 72, - 104, - [(0, UINT32)] - ] - return selector(current, constraints) - - -def bf_name(current): - """Fuzz the backing file name.""" - constraints = [ - truncate_string(STRING_V, len(current)) - ] - return selector(current, constraints, string_validator) - - -def ext_magic(current): - """Fuzz magic field of a header extension.""" - constraints = UINT32_V - return selector(current, constraints) - - -def ext_length(current): - """Fuzz length field of a header extension.""" - constraints = UINT32_V - return selector(current, constraints) - - -def bf_format(current): - """Fuzz backing file format in the corresponding header extension.""" - constraints = [ - truncate_string(STRING_V, len(current)), - truncate_string(STRING_V, (len(current) + 7) & ~7) # Fuzz padding - ] - return selector(current, constraints, string_validator) - - -def feature_type(current): - """Fuzz feature type field of a feature name table header extension.""" - constraints = UINT8_V - return selector(current, constraints) - - -def feature_bit_number(current): - """Fuzz bit number field of a feature name table header extension.""" - constraints = UINT8_V - return selector(current, constraints) - - -def feature_name(current): - """Fuzz feature name field of a feature name table header extension.""" - constraints = [ - truncate_string(STRING_V, len(current)), - truncate_string(STRING_V, 46) # Fuzz padding (field length = 46) - ] - return selector(current, constraints, string_validator) - - -def l1_entry(current): - """Fuzz an entry of the L1 table.""" - constraints = UINT64_V - # Reserved bits are ignored - # Added a possibility when only flags are fuzzed - offset = 0x7fffffffffffffff & \ - random.choice([selector(current, constraints), current]) - is_cow = random.randint(0, 1) - return offset + (is_cow << UINT64_M) - - -def l2_entry(current): - """Fuzz an entry of an L2 table.""" - constraints = UINT64_V - # Reserved bits are ignored - # Add a possibility when only flags are fuzzed - offset = 0x3ffffffffffffffe & \ - random.choice([selector(current, constraints), current]) - is_compressed = random.randint(0, 1) - is_cow = random.randint(0, 1) - is_zero = random.randint(0, 1) - value = offset + (is_cow << UINT64_M) + \ - (is_compressed << UINT64_M - 1) + is_zero - return value - - -def refcount_table_entry(current): - """Fuzz an entry of the refcount table.""" - constraints = UINT64_V - return selector(current, constraints) - - -def refcount_block_entry(current): - """Fuzz an entry of a refcount block.""" - constraints = UINT16_V - return selector(current, constraints) |