1
2import sys
3
4import nose.tools
5
6import claripy
7from claripy.bv import BVV, Extract, SignExt, ZeroExt, Concat, SDiv
8from claripy.errors import ClaripyTypeError, ClaripyZeroDivisionError, ClaripyValueError
9
10
11def test_bv():
12    a = BVV(1, 8)
13    b = BVV(2, 8)
14    assert a | b == 3
15    assert a & b == 0
16    assert a / b == 0
17    assert b * b == 4
18    assert a.signed == a.value
19    assert a + 8 == 9
20
21    c = BVV(128, 8)
22    assert c.signed == -128
23
24    d = BVV(255, 8)
25    assert Extract(1, 0, d) == 3
26    assert SignExt(8, d).value == 2**16-1
27    assert ZeroExt(8, d).size() == 16
28    assert ZeroExt(8, d).value == 255
29
30    e = BVV(0b1010, 4)
31    f = BVV(0b11, 2)
32    assert Concat(e, e, e, e) == 0b1010101010101010
33    assert Concat(e,f,f) == 0b10101111
34
35    # test that __div__ is unsigned
36    assert BVV(5, 8) / BVV(254, 8) == 0
37    assert SDiv(BVV(5, 8), BVV(-2, 8)) == -2
38
39    zero = BVV(0, 8)
40
41    assert -a == 255
42    assert ~a == 254
43    assert -zero == 0
44    assert ~zero == 255
45
46
47def test_get_byte():
48    a = claripy.BVV(0xabcdef12, 32)
49    assert a.get_byte(0).args[0] == 0xab
50    assert a.get_byte(1).args[0] == 0xcd
51
52    try:
53        assert a.get_byte(4).args[0]
54    except ValueError:
55        pass
56    else:
57        assert False, "get_byte(4) did not raise an exception"
58
59    b = claripy.BVV(0x1, 2)
60    assert b.get_byte(0).args[0] == 0x1
61    assert b.get_byte(0).args[1] == 8
62
63
64def test_get_bytes():
65    a = claripy.BVV(0xabcdef12, 32)
66    assert a.get_bytes(0, 1).args[0] == 0xab
67    assert a.get_bytes(0, 2).args[0] == 0xabcd
68
69    assert a.get_bytes(1, 1).args[0] == 0xcd
70
71    try:
72        assert a.get_bytes(4, 1).args[0]
73    except ValueError:
74        pass
75    else:
76        assert False, "get_bytes(4, 1) did not raise an exception"
77
78    assert a.get_bytes(0, 0).args[0] == 0
79    assert a.get_bytes(0, 0).args[1] == 0
80
81    b = claripy.BVV(0x3f0, 10)
82    assert b.get_bytes(0, 1).args[0] == 0x3
83    assert b.get_bytes(0, 1).args[1] == 8
84    assert b.get_bytes(0, 2).args[0] == 0x3f0
85    assert b.get_bytes(0, 2).args[1] == 16
86    assert b.get_bytes(1, 1).args[0] == 0xf0
87    assert b.get_bytes(1, 1).args[1] == 8
88
89
90def test_zero_length():
91    a = BVV(1, 8)
92    b = BVV(0, 0)
93    assert Concat(a, b) == 1
94    assert b == b
95
96    nose.tools.assert_raises(ClaripyTypeError, lambda: a + b)
97    nose.tools.assert_raises(ClaripyTypeError, lambda: a - b)
98    nose.tools.assert_raises(ClaripyTypeError, lambda: a * b)
99    nose.tools.assert_raises(ClaripyTypeError, lambda: a / b)
100
101
102def test_zero_division_errors():
103    a = BVV(1, 32)
104    b = BVV(0, 32)
105
106    def _check_exception(va, vb, op):
107
108        try:
109            if hasattr(va, op):
110                getattr(va, op)(vb)
111            elif hasattr(claripy, op):
112                getattr(claripy, op)(va, vb)
113            else:
114                raise Exception('Operation %s does not exist.' % op)
115            raise Exception('The expected exception is not raised.')
116        except Exception as ex:  # pylint:disable=broad-except
117            assert type(ex) is ClaripyZeroDivisionError
118
119    _check_exception(a, b, '__div__')
120    _check_exception(a, b, '__truediv__')
121    _check_exception(a, b, '__floordiv__')
122    _check_exception(a, b, '__mod__')
123    _check_exception(b, a, '__rdiv__')
124    _check_exception(b, a, '__rtruediv__')
125    _check_exception(b, a, '__rfloordiv__')
126    _check_exception(b, a, '__rmod__')
127    _check_exception(a, b, 'SMod')
128    _check_exception(a, b, 'SDiv')
129
130def test_type_errors():
131    nose.tools.assert_raises(TypeError, lambda: claripy.BVV(None))
132    nose.tools.assert_raises(TypeError, lambda: claripy.BVV(3))
133    nose.tools.assert_raises(TypeError, lambda: claripy.BVV(1.2))
134    nose.tools.assert_raises(TypeError, lambda: claripy.BVV(b"asdf", b"qwer"))
135    nose.tools.assert_raises(ClaripyValueError, lambda: claripy.BVV(b"asdf", 8))
136
137    nose.tools.assert_raises(TypeError, lambda: claripy.BVS(None, None))
138    nose.tools.assert_raises(TypeError, lambda: claripy.BVS(None, 3))
139    nose.tools.assert_raises(TypeError, lambda: claripy.BVS(3, 3))
140    nose.tools.assert_raises(TypeError, lambda: claripy.BVS(3, None))
141    nose.tools.assert_raises(TypeError, lambda: claripy.BVS('asdf', None))
142
143
144if __name__ == '__main__':
145
146    if len(sys.argv) > 1:
147        globals()["test_" + sys.argv[1]]()
148
149    else:
150        g = globals().copy()
151        for func_name, func in g.items():
152            if func_name.startswith("test_") and hasattr(func, "__call__"):
153                func()
154