Heuristic values were added to fuzzing constraints and vectors. Signed-off-by: Maria Kustova <mari...@catit.be> --- tests/image-fuzzer/qcow2/fuzz.py | 71 +++++++++++++++++++++------------------- 1 file changed, 37 insertions(+), 34 deletions(-)
diff --git a/tests/image-fuzzer/qcow2/fuzz.py b/tests/image-fuzzer/qcow2/fuzz.py index 5852b4d..6e272c6 100644 --- a/tests/image-fuzzer/qcow2/fuzz.py +++ b/tests/image-fuzzer/qcow2/fuzz.py @@ -17,6 +17,7 @@ # import random +from sys import maxint as INT_MAX UINT8 = 0xff UINT16 = 0xffff @@ -25,16 +26,21 @@ UINT64 = 0xffffffffffffffff # Most significant bit orders UINT32_M = 31 UINT64_M = 63 +# Sizes +UINT64_S = 8 # Fuzz vectors -UINT8_V = [0, 0x10, UINT8/4, UINT8/2 - 1, UINT8/2, UINT8/2 + 1, UINT8 - 1, +UINT8_V = [0, 1, 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] +UINT16_V = [0, 1, 0x100, 0x1000, UINT16/4, UINT16/2 - 1, UINT16/2, + UINT16/2 + 1, UINT16 - 1, UINT16] +UINT32_V = UINT16_V + [UINT16 + 1, UINT16 + 2, 0x10000, 0x100000, + 0x1000000, 0x10000000, UINT32/4, UINT32/2 - 1, + UINT32/2, UINT32/2 + 1, UINT32 - 1, UINT32] +# Exclude the vector of 16 bit values +UINT64_V = UINT32_V[len(UINT16_V):] + \ + [0, 1, UINT32 + 1, UINT32 + 2, 0x100000000, INT_MAX/UINT64_S - 1, + INT_MAX / UINT64_S, INT_MAX/UINT64_S + 1, 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', @@ -124,6 +130,7 @@ def selector(current, constraints, validate=int_validator): 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. @@ -135,33 +142,22 @@ def selector(current, constraints, validate=int_validator): 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 + v_constraints = [x for x in constraints if x != current] + fuzz_values = [iter_validate(c) for c in v_constraints] 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 + """Fuzz magic header field.""" + constraints = ['VMDK', 'QED', '', 'OOOM'] + \ + [truncate_string(STRING_V, len(current))] + return selector(current, constraints, string_validator) def version(current): """Fuzz version header field.""" constraints = UINT32_V + [ - [(2, 3)], # correct values - [(0, 1), (4, UINT32)] + [(0, 4)] # includes valid values ] return selector(current, constraints) @@ -195,16 +191,18 @@ def size(current): def crypt_method(current): """Fuzz crypt method header field.""" - constraints = UINT32_V + [ - 1, - [(2, UINT32)] - ] + # UINT32_V includes valid values [0, 1] + constraints = UINT32_V return selector(current, constraints) def l1_size(current): """Fuzz L1 table size header field.""" - constraints = UINT32_V + # QCOW_MAX_L1_SIZE = 0x2000000 + max_size = 0x2000000 / UINT64_S + constraints = UINT32_V + \ + [max_size - 1, max_size, max_size + 1] + \ + [[(0, current + 1)]] return selector(current, constraints) @@ -222,12 +220,18 @@ def refcount_table_offset(current): def refcount_table_clusters(current): """Fuzz refcount table clusters header field.""" - constraints = UINT32_V + # QCOW_MAX_REFTABLE_SIZE = 0x800000, MIN_CLUSTER_BITS = 9 => + # max size of reftable in clusters = 1 << 14 + max_size = 1 << 14 + constraints = UINT32_V + \ + [max_size - 1, max_size, max_size + 1] + \ + [[(0, current + 1)]] return selector(current, constraints) def nb_snapshots(current): """Fuzz number of snapshots header field.""" + # QCOW_MAX_SNAPSHOTS = 1 << 16, included in UINT32_V constraints = UINT32_V return selector(current, constraints) @@ -273,8 +277,7 @@ def header_length(current): """Fuzz number of refcount order header field.""" constraints = UINT32_V + [ 72, - 104, - [(0, UINT32)] + 104 ] return selector(current, constraints) -- 1.9.3