-
-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy patharray.py
More file actions
104 lines (91 loc) · 2.93 KB
/
Copy patharray.py
File metadata and controls
104 lines (91 loc) · 2.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
from fuzzeddataprovider import FuzzedDataProvider
import array
TYPECODES = list("bBhHiIlLqQfd")
# Top-level operation constants for FuzzerRunOne
OP_FROMBYTES = 0
OP_METHODS = 1
OP_SLICE = 2
# Array method operation constants for op_array_methods
METHOD_REVERSE = 0
METHOD_BYTESWAP = 1
METHOD_POP = 2
METHOD_COUNT = 3
METHOD_INDEX = 4
METHOD_INSERT = 5
METHOD_REMOVE = 6
METHOD_TOBYTES = 7
def _consume_array(fdp):
tc = fdp.PickValueInList(TYPECODES)
itemsize = array.array(tc).itemsize
n_items = fdp.ConsumeIntInRange(0, min(fdp.remaining_bytes() // itemsize, 200))
data = fdp.ConsumeBytes(n_items * itemsize)
a = array.array(tc)
a.frombytes(data)
return a, tc
def op_array_frombytes(fdp):
a, tc = _consume_array(fdp)
a.tobytes()
a.tolist()
def op_array_methods(fdp):
a, tc = _consume_array(fdp)
if len(a) == 0:
return
num_ops = fdp.ConsumeIntInRange(1, 20)
for _ in range(num_ops):
if fdp.remaining_bytes() == 0:
break
op = fdp.ConsumeIntInRange(METHOD_REVERSE, METHOD_TOBYTES)
if op == METHOD_REVERSE:
a.reverse()
elif op == METHOD_BYTESWAP:
a.byteswap()
elif op == METHOD_POP and len(a) > 0:
a.pop()
elif op == METHOD_COUNT and len(a) > 0:
val = fdp.ConsumeRandomValue()
a.count(val)
elif op == METHOD_INDEX and len(a) > 0:
val = fdp.ConsumeRandomValue()
try:
a.index(val)
except ValueError:
pass
elif op == METHOD_INSERT and len(a) > 0:
idx = fdp.ConsumeIntInRange(0, len(a) - 1)
val = fdp.ConsumeRandomValue()
a.insert(idx, val)
elif op == METHOD_REMOVE and len(a) > 0:
val = fdp.ConsumeRandomValue()
try:
a.remove(val)
except ValueError:
pass
elif op == METHOD_TOBYTES:
a.tobytes()
def op_array_slice(fdp):
a, tc = _consume_array(fdp)
if len(a) < 2:
return
start = fdp.ConsumeIntInRange(0, len(a) - 1)
end = fdp.ConsumeIntInRange(start, len(a))
_ = a[start:end]
b = array.array(tc, a[start:end])
a[start:end] = b
# Fuzzes the array module's C implementation (Modules/arraymodule.c).
# Exercises array construction from raw bytes via frombytes(), element-level
# operations (reverse, byteswap, pop, count, index, insert, remove), and
# slice read/write across all 12 typecodes (b/B/h/H/i/I/l/L/q/Q/f/d).
def FuzzerRunOne(FuzzerInput):
if len(FuzzerInput) < 1 or len(FuzzerInput) > 0x10000:
return
fdp = FuzzedDataProvider(FuzzerInput)
op = fdp.ConsumeIntInRange(OP_FROMBYTES, OP_SLICE)
try:
if op == OP_FROMBYTES:
op_array_frombytes(fdp)
elif op == OP_METHODS:
op_array_methods(fdp)
elif op == OP_SLICE:
op_array_slice(fdp)
except Exception:
pass