|  | 
| 1 |  | -# pylint:disable=missing-class-docstring,multiple-statements | 
|  | 1 | +# pylint:disable=missing-class-docstring | 
|  | 2 | +import unittest | 
|  | 3 | + | 
| 2 | 4 | import claripy | 
| 3 | 5 | 
 | 
| 4 | 6 | 
 | 
| @@ -55,149 +57,137 @@ def apply_annotation(self, o, a): | 
| 55 | 57 |         return o + a.number | 
| 56 | 58 | 
 | 
| 57 | 59 | 
 | 
| 58 |  | -def test_backend(): | 
| 59 |  | -    x = claripy.BVV(10, 32).annotate(AnnotationA("a", 1)) | 
| 60 |  | -    assert BackendA().convert(x) == 11 | 
| 61 |  | - | 
| 62 |  | - | 
| 63 |  | -def test_simplification(): | 
| 64 |  | -    x = claripy.BVS("x", 32).annotate(AnnotationA("a", 1)) | 
| 65 |  | -    y = x ^ x | 
| 66 |  | -    assert y.depth == 1 | 
| 67 |  | -    assert len(y.annotations) == 0 | 
| 68 |  | - | 
| 69 |  | -    x = claripy.BVS("x", 32).annotate(AnnotationB("a", 1)) | 
| 70 |  | -    y = x ^ x | 
| 71 |  | -    assert y.depth == 2 | 
| 72 |  | - | 
| 73 |  | -    x = claripy.BVS("x", 32).annotate(AnnotationC("a", 1)) | 
| 74 |  | -    y = x ^ x | 
| 75 |  | -    assert y.depth == 1 | 
| 76 |  | -    assert len(y.annotations) == 1 | 
| 77 |  | -    assert y.annotations[0].number == 2 | 
| 78 |  | - | 
| 79 |  | - | 
| 80 |  | -def test_missing_annotations_from_simplification(): | 
| 81 |  | -    relocatable_anno = AnnotationC("a", 2) | 
| 82 |  | - | 
| 83 |  | -    x0 = claripy.BVS("x", 32) | 
| 84 |  | -    x1 = claripy.BVV(24, 32) | 
| 85 |  | -    k = (x1 + x0).annotate(relocatable_anno) | 
| 86 |  | - | 
| 87 |  | -    x3 = claripy.simplify(k) | 
| 88 |  | - | 
| 89 |  | -    assert len(x3.annotations) == 1 | 
| 90 |  | - | 
| 91 |  | - | 
| 92 |  | -def test_annotations(): | 
| 93 |  | -    x = claripy.BVS("x", 32) + 1 | 
| 94 |  | -    xx = x._apply_to_annotations(lambda a: a) | 
| 95 |  | -    assert x is xx | 
| 96 |  | - | 
| 97 |  | -    a1 = AnnotationA("a", 1) | 
| 98 |  | -    a2 = AnnotationA("a", 1) | 
| 99 |  | - | 
| 100 |  | -    x1 = x.annotate(a1) | 
| 101 |  | -    x2 = x1.annotate(a2) | 
| 102 |  | -    x2a = x.annotate(a1, a2) | 
| 103 |  | -    x3 = x2.remove_annotation(a1) | 
| 104 |  | -    x4 = x3.remove_annotation(a2) | 
| 105 |  | -    x5 = x2.remove_annotations({a1, a2}) | 
| 106 |  | - | 
| 107 |  | -    assert x.variables == x1.variables | 
| 108 |  | -    assert x.variables == x2.variables | 
| 109 |  | -    assert x.variables == x2a.variables | 
| 110 |  | -    assert x.variables == x3.variables | 
| 111 |  | -    assert x.variables == x4.variables | 
| 112 |  | -    assert x.variables == x5.variables | 
| 113 |  | - | 
| 114 |  | -    assert x is not x1 | 
| 115 |  | -    assert x is not x2 | 
| 116 |  | -    assert x is not x3 | 
| 117 |  | -    assert x1 is not x2 | 
| 118 |  | -    assert x1 is not x3 | 
| 119 |  | -    assert x2 is not x3 | 
| 120 |  | -    assert x2 is x2a | 
| 121 |  | -    assert x is x4 | 
| 122 |  | -    assert x is x5 | 
| 123 |  | - | 
| 124 |  | -    assert x.op == x1.op | 
| 125 |  | -    assert x.annotations == () | 
| 126 |  | -    assert x1.annotations == (a1,) | 
| 127 |  | -    assert x2.annotations == (a1, a2) | 
| 128 |  | -    assert x3.annotations == (a2,) | 
| 129 |  | - | 
| 130 |  | -    assert claripy.backends.z3.convert(x).eq(claripy.backends.z3.convert(x3)) | 
| 131 |  | - | 
| 132 |  | -    const = claripy.BVV(1, 32) | 
| 133 |  | -    consta = const.annotate(AnnotationB("a", 0)) | 
| 134 |  | -    const1 = consta + 1 | 
| 135 |  | -    const1a = const1.annotate(AnnotationB("b", 1)) | 
| 136 |  | -    const2 = const1a + 1 | 
| 137 |  | -    # const2 should be (const1a + 1), instead of (1 + 1 + 1) | 
| 138 |  | -    # the flatten simplifier for __add__ should not be applied as AnnotationB is not relocatable (and not eliminatable) | 
| 139 |  | -    assert const2.depth == 3 | 
| 140 |  | - | 
| 141 |  | - | 
| 142 |  | -def test_eagerness(): | 
| 143 |  | -    x = claripy.BVV(10, 32).annotate(AnnotationD()) | 
| 144 |  | -    y = x + 1 | 
| 145 |  | -    assert y.annotations == x.annotations | 
| 146 |  | - | 
| 147 |  | - | 
| 148 |  | -def test_ast_hash_should_consider_relocatable_annotations(): | 
| 149 |  | -    relocatable_anno = AnnotationC("a", 2) | 
| 150 |  | -    const = claripy.BVV(1337, 32) | 
| 151 |  | -    x0 = claripy.BVS("x", 32).annotate(relocatable_anno) | 
| 152 |  | -    y0 = claripy.Concat(x0, const) | 
| 153 |  | - | 
| 154 |  | -    # make the annotation not relocatable | 
| 155 |  | -    # this is of course a hack, but it can demonstrate the problem | 
| 156 |  | -    relocatable_anno._relocatable = False | 
| 157 |  | -    x0._relocatable_annotations = frozenset() | 
| 158 |  | - | 
| 159 |  | -    y1 = claripy.Concat(x0, const) | 
| 160 |  | - | 
| 161 |  | -    assert len(y0.annotations) == 1 | 
| 162 |  | -    assert len(y1.annotations) == 0 | 
| 163 |  | -    assert y0._hash != y1._hash | 
| 164 |  | - | 
| 165 |  | - | 
| 166 |  | -def test_remove_relocatable_annotations(): | 
| 167 |  | -    relocatable_anno = AnnotationC("a", 2) | 
| 168 |  | -    const = claripy.BVV(1337, 32) | 
| 169 |  | - | 
| 170 |  | -    x0 = claripy.BVS("x", 32).annotate(relocatable_anno) | 
| 171 |  | -    y0 = claripy.Concat(x0, const) | 
| 172 |  | -    assert len(y0.annotations) == 1 | 
| 173 |  | -    assert y0.annotations == (relocatable_anno,) | 
| 174 |  | - | 
| 175 |  | -    y1 = y0.remove_annotation(relocatable_anno) | 
| 176 |  | - | 
| 177 |  | -    assert len(y1.annotations) == 0 | 
| 178 |  | - | 
| 179 |  | - | 
| 180 |  | -def test_duplicated_annotations_from_makelike(): | 
| 181 |  | -    relocatable_anno = AnnotationC("a", 2) | 
| 182 |  | - | 
| 183 |  | -    x0 = claripy.BVS("x", 32).annotate(relocatable_anno) | 
| 184 |  | -    x1 = claripy.BVV(24, 32) | 
| 185 |  | - | 
| 186 |  | -    # make_like() should not re-apply child annotations if the child is the make_like target | 
| 187 |  | -    x2 = x0 + x1 | 
| 188 |  | -    assert len(x2.annotations) == 1 | 
| 189 |  | - | 
| 190 |  | -    # simplify() should not re-apply annotations since annotations are kept during the simplification process by | 
| 191 |  | -    # make_like(). | 
| 192 |  | -    x3 = claripy.simplify(x0 + x1) | 
| 193 |  | -    assert len(x3.annotations) == 1 | 
|  | 60 | +class TestAnnotation(unittest.TestCase): | 
|  | 61 | +    def test_backend(self): | 
|  | 62 | +        x = claripy.BVV(10, 32).annotate(AnnotationA("a", 1)) | 
|  | 63 | +        assert BackendA().convert(x) == 11 | 
|  | 64 | + | 
|  | 65 | +    def test_simplification(self): | 
|  | 66 | +        x = claripy.BVS("x", 32).annotate(AnnotationA("a", 1)) | 
|  | 67 | +        y = x ^ x | 
|  | 68 | +        assert y.depth == 1 | 
|  | 69 | +        assert len(y.annotations) == 0 | 
|  | 70 | + | 
|  | 71 | +        x = claripy.BVS("x", 32).annotate(AnnotationB("a", 1)) | 
|  | 72 | +        y = x ^ x | 
|  | 73 | +        assert y.depth == 2 | 
|  | 74 | + | 
|  | 75 | +        x = claripy.BVS("x", 32).annotate(AnnotationC("a", 1)) | 
|  | 76 | +        y = x ^ x | 
|  | 77 | +        assert y.depth == 1 | 
|  | 78 | +        assert len(y.annotations) == 1 | 
|  | 79 | +        assert y.annotations[0].number == 2 | 
|  | 80 | + | 
|  | 81 | +    def test_missing_annotations_from_simplification(self): | 
|  | 82 | +        relocatable_anno = AnnotationC("a", 2) | 
|  | 83 | + | 
|  | 84 | +        x0 = claripy.BVS("x", 32) | 
|  | 85 | +        x1 = claripy.BVV(24, 32) | 
|  | 86 | +        k = (x1 + x0).annotate(relocatable_anno) | 
|  | 87 | + | 
|  | 88 | +        x3 = claripy.simplify(k) | 
|  | 89 | + | 
|  | 90 | +        assert len(x3.annotations) == 1 | 
|  | 91 | + | 
|  | 92 | +    def test_annotations(self): | 
|  | 93 | +        x = claripy.BVS("x", 32) + 1 | 
|  | 94 | +        xx = x._apply_to_annotations(lambda a: a) | 
|  | 95 | +        assert x is xx | 
|  | 96 | + | 
|  | 97 | +        a1 = AnnotationA("a", 1) | 
|  | 98 | +        a2 = AnnotationA("a", 1) | 
|  | 99 | + | 
|  | 100 | +        x1 = x.annotate(a1) | 
|  | 101 | +        x2 = x1.annotate(a2) | 
|  | 102 | +        x2a = x.annotate(a1, a2) | 
|  | 103 | +        x3 = x2.remove_annotation(a1) | 
|  | 104 | +        x4 = x3.remove_annotation(a2) | 
|  | 105 | +        x5 = x2.remove_annotations({a1, a2}) | 
|  | 106 | + | 
|  | 107 | +        assert x.variables == x1.variables | 
|  | 108 | +        assert x.variables == x2.variables | 
|  | 109 | +        assert x.variables == x2a.variables | 
|  | 110 | +        assert x.variables == x3.variables | 
|  | 111 | +        assert x.variables == x4.variables | 
|  | 112 | +        assert x.variables == x5.variables | 
|  | 113 | + | 
|  | 114 | +        assert x is not x1 | 
|  | 115 | +        assert x is not x2 | 
|  | 116 | +        assert x is not x3 | 
|  | 117 | +        assert x1 is not x2 | 
|  | 118 | +        assert x1 is not x3 | 
|  | 119 | +        assert x2 is not x3 | 
|  | 120 | +        assert x2 is x2a | 
|  | 121 | +        assert x is x4 | 
|  | 122 | +        assert x is x5 | 
|  | 123 | + | 
|  | 124 | +        assert x.op == x1.op | 
|  | 125 | +        assert x.annotations == () | 
|  | 126 | +        assert x1.annotations == (a1,) | 
|  | 127 | +        assert x2.annotations == (a1, a2) | 
|  | 128 | +        assert x3.annotations == (a2,) | 
|  | 129 | + | 
|  | 130 | +        assert claripy.backends.z3.convert(x).eq(claripy.backends.z3.convert(x3)) | 
|  | 131 | + | 
|  | 132 | +        const = claripy.BVV(1, 32) | 
|  | 133 | +        consta = const.annotate(AnnotationB("a", 0)) | 
|  | 134 | +        const1 = consta + 1 | 
|  | 135 | +        const1a = const1.annotate(AnnotationB("b", 1)) | 
|  | 136 | +        const2 = const1a + 1 | 
|  | 137 | +        # const2 should be (const1a + 1), instead of (1 + 1 + 1) | 
|  | 138 | +        # the flatten simplifier for __add__ should not be applied as AnnotationB is not relocatable (and not eliminatable) | 
|  | 139 | +        assert const2.depth == 3 | 
|  | 140 | + | 
|  | 141 | +    def test_eagerness(self): | 
|  | 142 | +        x = claripy.BVV(10, 32).annotate(AnnotationD()) | 
|  | 143 | +        y = x + 1 | 
|  | 144 | +        assert y.annotations == x.annotations | 
|  | 145 | + | 
|  | 146 | +    def test_ast_hash_should_consider_relocatable_annotations(self): | 
|  | 147 | +        relocatable_anno = AnnotationC("a", 2) | 
|  | 148 | +        const = claripy.BVV(1337, 32) | 
|  | 149 | +        x0 = claripy.BVS("x", 32).annotate(relocatable_anno) | 
|  | 150 | +        y0 = claripy.Concat(x0, const) | 
|  | 151 | + | 
|  | 152 | +        # make the annotation not relocatable | 
|  | 153 | +        # this is of course a hack, but it can demonstrate the problem | 
|  | 154 | +        relocatable_anno._relocatable = False | 
|  | 155 | +        x0._relocatable_annotations = frozenset() | 
|  | 156 | + | 
|  | 157 | +        y1 = claripy.Concat(x0, const) | 
|  | 158 | + | 
|  | 159 | +        assert len(y0.annotations) == 1 | 
|  | 160 | +        assert len(y1.annotations) == 0 | 
|  | 161 | +        assert y0._hash != y1._hash | 
|  | 162 | + | 
|  | 163 | +    def test_remove_relocatable_annotations(self): | 
|  | 164 | +        relocatable_anno = AnnotationC("a", 2) | 
|  | 165 | +        const = claripy.BVV(1337, 32) | 
|  | 166 | + | 
|  | 167 | +        x0 = claripy.BVS("x", 32).annotate(relocatable_anno) | 
|  | 168 | +        y0 = claripy.Concat(x0, const) | 
|  | 169 | +        assert len(y0.annotations) == 1 | 
|  | 170 | +        assert y0.annotations == (relocatable_anno,) | 
|  | 171 | + | 
|  | 172 | +        y1 = y0.remove_annotation(relocatable_anno) | 
|  | 173 | + | 
|  | 174 | +        assert len(y1.annotations) == 0 | 
|  | 175 | + | 
|  | 176 | +    def test_duplicated_annotations_from_makelike(self): | 
|  | 177 | +        relocatable_anno = AnnotationC("a", 2) | 
|  | 178 | + | 
|  | 179 | +        x0 = claripy.BVS("x", 32).annotate(relocatable_anno) | 
|  | 180 | +        x1 = claripy.BVV(24, 32) | 
|  | 181 | + | 
|  | 182 | +        # make_like() should not re-apply child annotations if the child is the make_like target | 
|  | 183 | +        x2 = x0 + x1 | 
|  | 184 | +        assert len(x2.annotations) == 1 | 
|  | 185 | + | 
|  | 186 | +        # simplify() should not re-apply annotations since annotations are kept during the simplification process by | 
|  | 187 | +        # make_like(). | 
|  | 188 | +        x3 = claripy.simplify(x0 + x1) | 
|  | 189 | +        assert len(x3.annotations) == 1 | 
| 194 | 190 | 
 | 
| 195 | 191 | 
 | 
| 196 | 192 | if __name__ == "__main__": | 
| 197 |  | -    test_annotations() | 
| 198 |  | -    test_backend() | 
| 199 |  | -    test_eagerness() | 
| 200 |  | -    test_ast_hash_should_consider_relocatable_annotations() | 
| 201 |  | -    test_remove_relocatable_annotations() | 
| 202 |  | -    test_duplicated_annotations_from_makelike() | 
| 203 |  | -    test_simplification() | 
|  | 193 | +    unittest.main() | 
0 commit comments