about summary refs log tree commit diff stats
path: root/test/analysis/modularintervals.py
blob: 2d87756770bbf7592e798ac5f0b9c72e608aa170 (plain) (blame)
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 miasm.core.interval import interval
from miasm.analysis.modularintervals import ModularIntervals
from miasm.expression.expression import *
from miasm.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])