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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
|
from builtins import range
from random import shuffle, seed
from miasm2.core.interval import interval
from miasm2.analysis.modularintervals import ModularIntervals
from miasm2.expression.expression import *
from miasm2.expression.simplifications import expr_simp
def gen_all_intervals(size):
"""Return every possible interval for element of @size bit
-> 2**(2**size) (number of partition)
"""
nb_elements = 1 << size
for bvec in range(1 << nb_elements):
# Bit vector: if bit i is on, i is in the interval
to_ret = interval()
for i in range(nb_elements):
if bvec & i == i:
to_ret += [(i, i)]
yield to_ret
def interval_elements(interv):
"""Generator on element of an interval"""
for sub_range in interv:
for i in range(sub_range[0], sub_range[1] + 1):
yield i
size = 4
left, right = list(gen_all_intervals(size)), list(gen_all_intervals(size))
right_int = list(range(1 << size))
mask = (1 << size) - 1
def test(left, right):
"""Launch tests on left OP right"""
global size, mask
for left_i in left:
left_i = ModularIntervals(size, left_i)
left_values = list(interval_elements(left_i))
# Check operations without other arguments
## Check NEG
result = - left_i
for x in left_values:
rez = (- x) & mask
assert rez in result
# Check operations on intervals
for right_i in right:
right_i = ModularIntervals(size, right_i)
right_values = list(interval_elements(right_i))
# Check operations available only on integer
if len(right_values) == 1:
# Check mod
value = right_values[0]
# Avoid division by zero
if value != 0:
result = left_i % value
for x in left_values:
rez = (x % value) & mask
assert rez in result
# Check ADD
result = left_i + right_i
for x in left_values:
for y in right_values:
rez = (x + y) & mask
assert rez in result
# Check OR
result = left_i | right_i
for x in left_values:
for y in right_values:
rez = (x | y) & mask
assert rez in result
# Check AND
result = left_i & right_i
for x in left_values:
for y in right_values:
rez = (x & y) & mask
assert rez in result
# Check XOR
result = left_i ^ right_i
for x in left_values:
for y in right_values:
rez = (x ^ y) & mask
assert rez in result
# Check MUL
result = left_i * right_i
for x in left_values:
for y in right_values:
rez = (x * y) & mask
assert rez in result
# Check >>
result = left_i >> right_i
for x in left_values:
for y in right_values:
rez = (x >> y) & mask
assert rez in result
# Check <<
result = left_i << right_i
for x in left_values:
for y in right_values:
rez = (x << y) & mask
assert rez in result
# Check a>>
result = left_i.arithmetic_shift_right(right_i)
for x in left_values:
x = ExprInt(x, size)
for y in right_values:
y = ExprInt(y, size)
rez = int(expr_simp(ExprOp('a>>', x, y)))
assert rez in result
# Check >>>
result = left_i.rotation_right(right_i)
for x in left_values:
x = ExprInt(x, size)
for y in right_values:
y = ExprInt(y, size)
rez = int(expr_simp(ExprOp('>>>', x, y)))
assert rez in result
# Check <<<
result = left_i.rotation_left(right_i)
for x in left_values:
x = ExprInt(x, size)
for y in right_values:
y = ExprInt(y, size)
rez = int(expr_simp(ExprOp('<<<', x, y)))
assert rez in result
# Following tests take around 10 minutes with PyPy, but too long for Python
# interval_uniq = [interval([(i, i)]) for i in xrange(1 << size)]
# test(left, interval_uniq)
# test(interval_uniq, right)
# Uncomment the following line for a full test over intervals, which may take
# several hours
# test(left, right)
# Random pick for tests
seed(0)
shuffle(left)
shuffle(right)
test(left[:100], right[:100])
|