crosshair-tool 0.0.56__cp39-cp39-macosx_11_0_arm64.whl → 0.0.100__cp39-cp39-macosx_11_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- _crosshair_tracers.cpython-39-darwin.so +0 -0
- crosshair/__init__.py +1 -1
- crosshair/_mark_stacks.h +51 -24
- crosshair/_tracers.h +9 -5
- crosshair/_tracers_test.py +19 -9
- crosshair/auditwall.py +9 -8
- crosshair/auditwall_test.py +31 -19
- crosshair/codeconfig.py +3 -2
- crosshair/condition_parser.py +17 -133
- crosshair/condition_parser_test.py +54 -96
- crosshair/conftest.py +1 -1
- crosshair/copyext.py +91 -22
- crosshair/copyext_test.py +33 -0
- crosshair/core.py +259 -203
- crosshair/core_and_libs.py +20 -0
- crosshair/core_regestered_types_test.py +82 -0
- crosshair/core_test.py +693 -664
- crosshair/diff_behavior.py +76 -21
- crosshair/diff_behavior_test.py +132 -23
- crosshair/dynamic_typing.py +128 -18
- crosshair/dynamic_typing_test.py +91 -4
- crosshair/enforce.py +1 -6
- crosshair/enforce_test.py +15 -23
- crosshair/examples/check_examples_test.py +2 -1
- crosshair/fnutil.py +2 -3
- crosshair/fnutil_test.py +0 -7
- crosshair/fuzz_core_test.py +70 -83
- crosshair/libimpl/arraylib.py +10 -7
- crosshair/libimpl/binascii_ch_test.py +30 -0
- crosshair/libimpl/binascii_test.py +67 -0
- crosshair/libimpl/binasciilib.py +150 -0
- crosshair/libimpl/bisectlib_test.py +5 -5
- crosshair/libimpl/builtinslib.py +1002 -682
- crosshair/libimpl/builtinslib_ch_test.py +108 -30
- crosshair/libimpl/builtinslib_test.py +431 -143
- crosshair/libimpl/codecslib.py +22 -2
- crosshair/libimpl/codecslib_test.py +41 -9
- crosshair/libimpl/collectionslib.py +44 -8
- crosshair/libimpl/collectionslib_test.py +108 -20
- crosshair/libimpl/copylib.py +1 -1
- crosshair/libimpl/copylib_test.py +18 -0
- crosshair/libimpl/datetimelib.py +84 -67
- crosshair/libimpl/datetimelib_ch_test.py +12 -7
- crosshair/libimpl/datetimelib_test.py +5 -6
- crosshair/libimpl/decimallib.py +5257 -0
- crosshair/libimpl/decimallib_ch_test.py +78 -0
- crosshair/libimpl/decimallib_test.py +76 -0
- crosshair/libimpl/encodings/_encutil.py +21 -11
- crosshair/libimpl/fractionlib.py +16 -0
- crosshair/libimpl/fractionlib_test.py +80 -0
- crosshair/libimpl/functoolslib.py +19 -7
- crosshair/libimpl/functoolslib_test.py +22 -6
- crosshair/libimpl/hashliblib.py +30 -0
- crosshair/libimpl/hashliblib_test.py +18 -0
- crosshair/libimpl/heapqlib.py +32 -5
- crosshair/libimpl/heapqlib_test.py +15 -12
- crosshair/libimpl/iolib.py +7 -4
- crosshair/libimpl/ipaddresslib.py +8 -0
- crosshair/libimpl/itertoolslib_test.py +1 -1
- crosshair/libimpl/mathlib.py +165 -2
- crosshair/libimpl/mathlib_ch_test.py +44 -0
- crosshair/libimpl/mathlib_test.py +59 -16
- crosshair/libimpl/oslib.py +7 -0
- crosshair/libimpl/pathliblib_test.py +10 -0
- crosshair/libimpl/randomlib.py +1 -0
- crosshair/libimpl/randomlib_test.py +6 -4
- crosshair/libimpl/relib.py +180 -59
- crosshair/libimpl/relib_ch_test.py +26 -2
- crosshair/libimpl/relib_test.py +77 -14
- crosshair/libimpl/timelib.py +35 -13
- crosshair/libimpl/timelib_test.py +13 -3
- crosshair/libimpl/typeslib.py +15 -0
- crosshair/libimpl/typeslib_test.py +36 -0
- crosshair/libimpl/unicodedatalib_test.py +3 -3
- crosshair/libimpl/weakreflib.py +13 -0
- crosshair/libimpl/weakreflib_test.py +69 -0
- crosshair/libimpl/zliblib.py +15 -0
- crosshair/libimpl/zliblib_test.py +13 -0
- crosshair/lsp_server.py +21 -10
- crosshair/main.py +48 -28
- crosshair/main_test.py +59 -14
- crosshair/objectproxy.py +39 -14
- crosshair/objectproxy_test.py +27 -13
- crosshair/opcode_intercept.py +212 -24
- crosshair/opcode_intercept_test.py +172 -18
- crosshair/options.py +0 -1
- crosshair/patch_equivalence_test.py +5 -21
- crosshair/path_cover.py +7 -5
- crosshair/path_search.py +6 -4
- crosshair/path_search_test.py +1 -2
- crosshair/pathing_oracle.py +53 -10
- crosshair/pathing_oracle_test.py +21 -0
- crosshair/pure_importer_test.py +5 -21
- crosshair/register_contract.py +16 -6
- crosshair/register_contract_test.py +2 -14
- crosshair/simplestructs.py +154 -85
- crosshair/simplestructs_test.py +16 -2
- crosshair/smtlib.py +24 -0
- crosshair/smtlib_test.py +14 -0
- crosshair/statespace.py +319 -196
- crosshair/statespace_test.py +45 -0
- crosshair/stubs_parser.py +0 -2
- crosshair/test_util.py +87 -25
- crosshair/test_util_test.py +26 -0
- crosshair/tools/check_init_and_setup_coincide.py +0 -3
- crosshair/tools/generate_demo_table.py +2 -2
- crosshair/tracers.py +141 -49
- crosshair/type_repo.py +11 -4
- crosshair/unicode_categories.py +1 -0
- crosshair/util.py +158 -76
- crosshair/util_test.py +13 -20
- crosshair/watcher.py +4 -4
- crosshair/z3util.py +1 -1
- {crosshair_tool-0.0.56.dist-info → crosshair_tool-0.0.100.dist-info}/METADATA +45 -36
- crosshair_tool-0.0.100.dist-info/RECORD +176 -0
- {crosshair_tool-0.0.56.dist-info → crosshair_tool-0.0.100.dist-info}/WHEEL +2 -1
- crosshair/examples/hypothesis/__init__.py +0 -2
- crosshair/examples/hypothesis/bugs_detected/simple_strategies.py +0 -74
- crosshair_tool-0.0.56.dist-info/RECORD +0 -152
- /crosshair/{examples/hypothesis/bugs_detected/__init__.py → py.typed} +0 -0
- {crosshair_tool-0.0.56.dist-info → crosshair_tool-0.0.100.dist-info}/entry_points.txt +0 -0
- {crosshair_tool-0.0.56.dist-info → crosshair_tool-0.0.100.dist-info/licenses}/LICENSE +0 -0
- {crosshair_tool-0.0.56.dist-info → crosshair_tool-0.0.100.dist-info}/top_level.txt +0 -0
crosshair/libimpl/mathlib.py
CHANGED
|
@@ -1,16 +1,179 @@
|
|
|
1
1
|
import math
|
|
2
|
+
import sys
|
|
3
|
+
from numbers import Real
|
|
4
|
+
|
|
5
|
+
import z3 # type: ignore
|
|
2
6
|
|
|
3
7
|
from crosshair import NoTracing, register_patch
|
|
4
|
-
from crosshair.
|
|
8
|
+
from crosshair.core import with_realized_args
|
|
9
|
+
from crosshair.libimpl.builtinslib import (
|
|
10
|
+
PreciseIeeeSymbolicFloat,
|
|
11
|
+
RealBasedSymbolicFloat,
|
|
12
|
+
SymbolicBool,
|
|
13
|
+
SymbolicIntable,
|
|
14
|
+
SymbolicValue,
|
|
15
|
+
smt_xor,
|
|
16
|
+
)
|
|
17
|
+
from crosshair.tracers import ResumedTracing
|
|
18
|
+
from crosshair.util import name_of_type
|
|
19
|
+
from crosshair.z3util import z3Not, z3Or
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _is_positive(x):
|
|
23
|
+
if isinstance(x, SymbolicValue):
|
|
24
|
+
if isinstance(x, PreciseIeeeSymbolicFloat):
|
|
25
|
+
return SymbolicBool(z3Not(z3.fpIsNegative(x.var)))
|
|
26
|
+
elif isinstance(x, RealBasedSymbolicFloat):
|
|
27
|
+
return SymbolicBool(x.var >= 0)
|
|
28
|
+
else:
|
|
29
|
+
with ResumedTracing():
|
|
30
|
+
return x >= 0
|
|
31
|
+
else:
|
|
32
|
+
return math.copysign(1, x) == 1
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _copysign(x, y):
|
|
36
|
+
if not isinstance(x, Real):
|
|
37
|
+
raise TypeError(f"must be real number, not {name_of_type(type(x))}")
|
|
38
|
+
if not isinstance(y, Real):
|
|
39
|
+
raise TypeError(f"must be real number, not {name_of_type(type(y))}")
|
|
40
|
+
with NoTracing():
|
|
41
|
+
x_is_positive = _is_positive(x)
|
|
42
|
+
y_is_positive = _is_positive(y)
|
|
43
|
+
# then invert as needed:
|
|
44
|
+
invert = smt_xor(x_is_positive, y_is_positive)
|
|
45
|
+
with NoTracing():
|
|
46
|
+
if isinstance(invert, SymbolicBool) and isinstance(
|
|
47
|
+
x, (PreciseIeeeSymbolicFloat, RealBasedSymbolicFloat)
|
|
48
|
+
):
|
|
49
|
+
return type(x)(z3.If(invert.var, -x.var, x.var))
|
|
50
|
+
with ResumedTracing():
|
|
51
|
+
return -x if invert else x
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
if sys.version_info >= (3, 9):
|
|
55
|
+
|
|
56
|
+
def _gcd(a=0, b=0):
|
|
57
|
+
while b:
|
|
58
|
+
a, b = b, a % b
|
|
59
|
+
return abs(a)
|
|
60
|
+
|
|
61
|
+
else: # (arguments were required in Python <= 3.8)
|
|
62
|
+
|
|
63
|
+
def _gcd(a, b):
|
|
64
|
+
while b:
|
|
65
|
+
a, b = b, a % b
|
|
66
|
+
return abs(a)
|
|
5
67
|
|
|
6
68
|
|
|
7
69
|
def _isfinite(x):
|
|
8
70
|
with NoTracing():
|
|
9
|
-
if isinstance(x,
|
|
71
|
+
if isinstance(x, (SymbolicIntable, RealBasedSymbolicFloat)):
|
|
10
72
|
return True
|
|
73
|
+
elif isinstance(x, PreciseIeeeSymbolicFloat):
|
|
74
|
+
return SymbolicBool(z3Not(z3Or(z3.fpIsNaN(x.var), z3.fpIsInf(x.var))))
|
|
11
75
|
else:
|
|
12
76
|
return math.isfinite(x)
|
|
13
77
|
|
|
14
78
|
|
|
79
|
+
def _isnan(x):
|
|
80
|
+
with NoTracing():
|
|
81
|
+
if isinstance(x, (SymbolicIntable, RealBasedSymbolicFloat)):
|
|
82
|
+
return False
|
|
83
|
+
elif isinstance(x, PreciseIeeeSymbolicFloat):
|
|
84
|
+
return SymbolicBool(z3.fpIsNaN(x.var))
|
|
85
|
+
else:
|
|
86
|
+
return math.isnan(x)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def _isinf(x):
|
|
90
|
+
with NoTracing():
|
|
91
|
+
if isinstance(x, (SymbolicIntable, RealBasedSymbolicFloat)):
|
|
92
|
+
return False
|
|
93
|
+
elif isinstance(x, PreciseIeeeSymbolicFloat):
|
|
94
|
+
return SymbolicBool(z3.fpIsInf(x.var))
|
|
95
|
+
else:
|
|
96
|
+
return math.isinf(x)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
_FUNCTIONS_WITH_REALIZATION = [
|
|
100
|
+
# TODO: we could attempt to implement some of these in the SMT solver
|
|
101
|
+
"acos",
|
|
102
|
+
"acosh",
|
|
103
|
+
"asin",
|
|
104
|
+
"asinh",
|
|
105
|
+
"atan",
|
|
106
|
+
"atan2",
|
|
107
|
+
"atanh",
|
|
108
|
+
"ceil",
|
|
109
|
+
"comb",
|
|
110
|
+
"cos",
|
|
111
|
+
"cosh",
|
|
112
|
+
"degrees",
|
|
113
|
+
"dist",
|
|
114
|
+
"erf",
|
|
115
|
+
"erfc",
|
|
116
|
+
"exp",
|
|
117
|
+
"expm1",
|
|
118
|
+
"fabs",
|
|
119
|
+
"factorial",
|
|
120
|
+
"floor",
|
|
121
|
+
"fmod",
|
|
122
|
+
"frexp",
|
|
123
|
+
"fsum",
|
|
124
|
+
"gamma",
|
|
125
|
+
"hypot",
|
|
126
|
+
"isclose",
|
|
127
|
+
"isqrt",
|
|
128
|
+
"ldexp",
|
|
129
|
+
"lgamma",
|
|
130
|
+
"log",
|
|
131
|
+
"log10",
|
|
132
|
+
"log1p",
|
|
133
|
+
"log2",
|
|
134
|
+
"modf",
|
|
135
|
+
"perm",
|
|
136
|
+
"pow",
|
|
137
|
+
"prod",
|
|
138
|
+
"radians",
|
|
139
|
+
"remainder",
|
|
140
|
+
"sin",
|
|
141
|
+
"sinh",
|
|
142
|
+
"sqrt",
|
|
143
|
+
"tan",
|
|
144
|
+
"tanh",
|
|
145
|
+
"trunc",
|
|
146
|
+
]
|
|
147
|
+
|
|
148
|
+
if sys.version_info >= (3, 9):
|
|
149
|
+
_FUNCTIONS_WITH_REALIZATION.extend(
|
|
150
|
+
[
|
|
151
|
+
"lcm",
|
|
152
|
+
"nextafter",
|
|
153
|
+
"ulp",
|
|
154
|
+
]
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
if sys.version_info >= (3, 11):
|
|
158
|
+
_FUNCTIONS_WITH_REALIZATION.extend(
|
|
159
|
+
[
|
|
160
|
+
"cbrt",
|
|
161
|
+
"exp2",
|
|
162
|
+
]
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
if sys.version_info >= (3, 12):
|
|
166
|
+
_FUNCTIONS_WITH_REALIZATION.append("sumprod")
|
|
167
|
+
|
|
168
|
+
|
|
15
169
|
def make_registrations():
|
|
170
|
+
register_patch(math.copysign, _copysign)
|
|
171
|
+
register_patch(math.gcd, _gcd)
|
|
16
172
|
register_patch(math.isfinite, _isfinite)
|
|
173
|
+
register_patch(math.isnan, _isnan)
|
|
174
|
+
register_patch(math.isinf, _isinf)
|
|
175
|
+
for fn_name in _FUNCTIONS_WITH_REALIZATION:
|
|
176
|
+
fn = getattr(math, fn_name)
|
|
177
|
+
register_patch(
|
|
178
|
+
fn, with_realized_args(fn, deep=True)
|
|
179
|
+
) # deep realization needed for Fraction instances
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import math
|
|
2
|
+
import sys
|
|
3
|
+
from typing import Union
|
|
4
|
+
|
|
5
|
+
import pytest # type: ignore
|
|
6
|
+
|
|
7
|
+
from crosshair.core import realize
|
|
8
|
+
from crosshair.core_and_libs import MessageType, analyze_function, run_checkables
|
|
9
|
+
from crosshair.options import AnalysisOptionSet
|
|
10
|
+
from crosshair.test_util import compare_results
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def check_copysign(
|
|
14
|
+
a: Union[int, float], b: Union[int, float], realize_a: bool, realize_b: bool
|
|
15
|
+
):
|
|
16
|
+
"""post: _"""
|
|
17
|
+
if realize_a:
|
|
18
|
+
a = realize(a)
|
|
19
|
+
if realize_b:
|
|
20
|
+
b = realize(b)
|
|
21
|
+
return compare_results(math.copysign, a, b)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def check_gcd(a: int, b: int):
|
|
25
|
+
"""
|
|
26
|
+
pre: all([-10 < a, a < 10, -10 < b, b < 10]) # for performance
|
|
27
|
+
post: _
|
|
28
|
+
"""
|
|
29
|
+
return compare_results(math.gcd, a, b)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
# This is the only real test definition.
|
|
33
|
+
# It runs crosshair on each of the "check" functions defined above.
|
|
34
|
+
@pytest.mark.parametrize("fn_name", [fn for fn in dir() if fn.startswith("check_")])
|
|
35
|
+
def test_builtin(fn_name: str) -> None:
|
|
36
|
+
this_module = sys.modules[__name__]
|
|
37
|
+
messages = run_checkables(
|
|
38
|
+
analyze_function(
|
|
39
|
+
getattr(this_module, fn_name),
|
|
40
|
+
AnalysisOptionSet(max_uninteresting_iterations=50),
|
|
41
|
+
)
|
|
42
|
+
)
|
|
43
|
+
errors = [m for m in messages if m.state > MessageType.PRE_UNSAT]
|
|
44
|
+
assert errors == []
|
|
@@ -1,24 +1,67 @@
|
|
|
1
1
|
import math
|
|
2
2
|
import sys
|
|
3
|
-
import unittest
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
from crosshair.
|
|
4
|
+
import pytest
|
|
5
|
+
|
|
6
|
+
from crosshair.core import proxy_for_type, standalone_statespace
|
|
7
|
+
from crosshair.libimpl.builtinslib import (
|
|
8
|
+
ModelingDirector,
|
|
9
|
+
PreciseIeeeSymbolicFloat,
|
|
10
|
+
RealBasedSymbolicFloat,
|
|
11
|
+
)
|
|
12
|
+
from crosshair.statespace import POST_FAIL
|
|
13
|
+
from crosshair.test_util import check_states
|
|
14
|
+
from crosshair.tracers import NoTracing, ResumedTracing
|
|
8
15
|
from crosshair.util import set_debug
|
|
9
16
|
|
|
10
17
|
|
|
11
|
-
|
|
12
|
-
def
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
def test_copysign_e2e():
|
|
19
|
+
def can_find_minus_zero(x: float):
|
|
20
|
+
"""post: math.copysign(1, _) == 1"""
|
|
21
|
+
if x == 0:
|
|
22
|
+
return x
|
|
23
|
+
return 1
|
|
24
|
+
|
|
25
|
+
check_states(can_find_minus_zero, POST_FAIL)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@pytest.mark.parametrize(
|
|
29
|
+
"FloatType", [PreciseIeeeSymbolicFloat, RealBasedSymbolicFloat]
|
|
30
|
+
)
|
|
31
|
+
def test_copysign_symbolics(FloatType, space):
|
|
32
|
+
space.extra(ModelingDirector).global_representations[float] = FloatType
|
|
33
|
+
x = FloatType("x")
|
|
34
|
+
y = FloatType("y")
|
|
35
|
+
with ResumedTracing():
|
|
36
|
+
assert not space.is_possible(math.copysign(x, -0.0) > 0.0)
|
|
37
|
+
assert space.is_possible(math.copysign(x, y) > 0.0)
|
|
38
|
+
assert space.is_possible(math.copysign(x, y) < 0.0)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def test_isfinite():
|
|
42
|
+
with standalone_statespace:
|
|
43
|
+
with NoTracing():
|
|
44
|
+
x = RealBasedSymbolicFloat("symfloat")
|
|
45
|
+
assert math.isfinite(x)
|
|
46
|
+
assert math.isfinite(2.3)
|
|
47
|
+
assert not math.isfinite(float("nan"))
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def test_isinf():
|
|
51
|
+
with standalone_statespace:
|
|
52
|
+
with NoTracing():
|
|
53
|
+
x = RealBasedSymbolicFloat("symfloat")
|
|
54
|
+
assert not math.isinf(x)
|
|
55
|
+
assert not math.isinf(float("nan"))
|
|
56
|
+
assert math.isinf(float("-inf"))
|
|
19
57
|
|
|
20
58
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
59
|
+
def test_log():
|
|
60
|
+
with standalone_statespace as space:
|
|
61
|
+
with NoTracing():
|
|
62
|
+
i = proxy_for_type(int, "i")
|
|
63
|
+
f = proxy_for_type(float, "f")
|
|
64
|
+
space.add(i > 0)
|
|
65
|
+
space.add(f > 0)
|
|
66
|
+
math.log(i)
|
|
67
|
+
math.log(f)
|
crosshair/libimpl/randomlib.py
CHANGED
|
@@ -76,6 +76,7 @@ class ExplicitRandom(random.Random):
|
|
|
76
76
|
|
|
77
77
|
|
|
78
78
|
def genint(factory: SymbolicFactory, cap: int):
|
|
79
|
+
# TODO: conditionally use SymbolicBoundedInt here and below
|
|
79
80
|
with NoTracing():
|
|
80
81
|
symbolic_int = SymbolicInt(factory.varname + factory.space.uniq(), int)
|
|
81
82
|
factory.space.add(0 <= symbolic_int.var)
|
|
@@ -7,6 +7,7 @@ from crosshair.core_and_libs import proxy_for_type, standalone_statespace
|
|
|
7
7
|
from crosshair.libimpl.randomlib import ExplicitRandom
|
|
8
8
|
from crosshair.statespace import CANNOT_CONFIRM, CONFIRMED, POST_FAIL, MessageType
|
|
9
9
|
from crosshair.test_util import check_states
|
|
10
|
+
from crosshair.tracers import ResumedTracing
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
def test_ExplicitRandom():
|
|
@@ -31,9 +32,10 @@ def test_proxy_random():
|
|
|
31
32
|
with standalone_statespace as space:
|
|
32
33
|
rng = proxy_for_type(random.Random, "rng")
|
|
33
34
|
i = rng.randrange(5, 10)
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
with ResumedTracing():
|
|
36
|
+
assert space.is_possible(i == 5)
|
|
37
|
+
assert space.is_possible(i == 9)
|
|
38
|
+
assert not space.is_possible(i == 4)
|
|
37
39
|
|
|
38
40
|
|
|
39
41
|
def test_global_randrange():
|
|
@@ -105,7 +107,7 @@ def test_global_uniform_inverted_args():
|
|
|
105
107
|
"""post: -2.0 <= _ <= 10.0"""
|
|
106
108
|
return random.uniform(10, -2)
|
|
107
109
|
|
|
108
|
-
check_states(f,
|
|
110
|
+
check_states(f, CONFIRMED)
|
|
109
111
|
|
|
110
112
|
|
|
111
113
|
def test_global_getrandbits():
|