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/copyext.py
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
import sys
|
|
2
|
+
|
|
3
|
+
if sys.version_info >= (3, 14):
|
|
4
|
+
from copy import _atomic_types
|
|
5
|
+
else:
|
|
6
|
+
from copy import _deepcopy_atomic # type: ignore
|
|
2
7
|
from copy import _deepcopy_dict # type: ignore
|
|
3
8
|
from copy import _deepcopy_dispatch # type: ignore
|
|
4
9
|
from copy import _deepcopy_list # type: ignore
|
|
@@ -8,10 +13,17 @@ from copy import _reconstruct # type: ignore
|
|
|
8
13
|
from copy import Error
|
|
9
14
|
from copyreg import dispatch_table # type: ignore
|
|
10
15
|
from enum import Enum
|
|
11
|
-
from
|
|
16
|
+
from types import MappingProxyType
|
|
17
|
+
from typing import Any, Callable, Dict, Tuple
|
|
12
18
|
|
|
13
|
-
from crosshair.tracers import
|
|
14
|
-
from crosshair.util import
|
|
19
|
+
from crosshair.tracers import ResumedTracing
|
|
20
|
+
from crosshair.util import (
|
|
21
|
+
CrossHairInternal,
|
|
22
|
+
IdKeyedDict,
|
|
23
|
+
assert_tracing,
|
|
24
|
+
ch_stack,
|
|
25
|
+
debug,
|
|
26
|
+
)
|
|
15
27
|
|
|
16
28
|
_MISSING = object
|
|
17
29
|
|
|
@@ -22,22 +34,54 @@ class CopyMode(int, Enum):
|
|
|
22
34
|
REALIZE = 2
|
|
23
35
|
|
|
24
36
|
|
|
37
|
+
# We need to be able to realize some types that are not deep-copyable.
|
|
38
|
+
# Such realization overrides are defined here.
|
|
39
|
+
# TODO: This capability should probably be something that plugins can extend
|
|
40
|
+
_DEEP_REALIZATION_OVERRIDES = IdKeyedDict()
|
|
41
|
+
_DEEP_REALIZATION_OVERRIDES[MappingProxyType] = lambda p, m: MappingProxyType(
|
|
42
|
+
deepcopyext(dict(p), CopyMode.REALIZE, m)
|
|
43
|
+
)
|
|
44
|
+
if sys.version_info >= (3, 10):
|
|
45
|
+
_DEEP_REALIZATION_OVERRIDES[type({}.items())] = lambda p, m: deepcopyext(
|
|
46
|
+
p.mapping, CopyMode.REALIZE, m
|
|
47
|
+
).items()
|
|
48
|
+
_DEEP_REALIZATION_OVERRIDES[type({}.keys())] = lambda p, m: deepcopyext(
|
|
49
|
+
p.mapping, CopyMode.REALIZE, m
|
|
50
|
+
).keys()
|
|
51
|
+
_DEEP_REALIZATION_OVERRIDES[type({}.values())] = lambda p, m: deepcopyext(
|
|
52
|
+
p.mapping, CopyMode.REALIZE, m
|
|
53
|
+
).values()
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@assert_tracing(False)
|
|
25
57
|
def deepcopyext(obj: object, mode: CopyMode, memo: Dict) -> Any:
|
|
26
|
-
assert not is_tracing()
|
|
27
58
|
objid = id(obj)
|
|
28
59
|
cpy = memo.get(objid, _MISSING)
|
|
29
|
-
if cpy is _MISSING:
|
|
60
|
+
if cpy is not _MISSING:
|
|
61
|
+
if objid not in map(id, memo.get(id(memo), ())):
|
|
62
|
+
# we are trying to return some value that was not kept alive;
|
|
63
|
+
# it may have been garbage collected and replaced.
|
|
64
|
+
raise CrossHairInternal("Possibly transient value found in memo")
|
|
65
|
+
else:
|
|
66
|
+
_keep_alive(obj, memo)
|
|
67
|
+
deepconstruct_obj = obj
|
|
30
68
|
if mode == CopyMode.REALIZE:
|
|
31
69
|
cls = type(obj)
|
|
32
70
|
if hasattr(cls, "__ch_deep_realize__"):
|
|
33
|
-
cpy = obj.__ch_deep_realize__() # type: ignore
|
|
71
|
+
cpy = obj.__ch_deep_realize__(memo) # type: ignore
|
|
34
72
|
elif hasattr(cls, "__ch_realize__"):
|
|
35
73
|
# Do shallow realization here, and then fall through to
|
|
36
74
|
# _deepconstruct below.
|
|
37
|
-
|
|
75
|
+
deepconstruct_obj = obj.__ch_realize__() # type: ignore
|
|
76
|
+
# this transient object may be inserted into memo below
|
|
77
|
+
_keep_alive(deepconstruct_obj, memo)
|
|
78
|
+
else:
|
|
79
|
+
realization_override = _DEEP_REALIZATION_OVERRIDES.get(cls)
|
|
80
|
+
if realization_override:
|
|
81
|
+
cpy = realization_override(obj, memo)
|
|
38
82
|
if cpy is _MISSING:
|
|
39
83
|
try:
|
|
40
|
-
cpy = _deepconstruct(
|
|
84
|
+
cpy = _deepconstruct(deepconstruct_obj, mode, memo)
|
|
41
85
|
except TypeError as exc:
|
|
42
86
|
if mode == CopyMode.REGULAR:
|
|
43
87
|
raise
|
|
@@ -46,41 +90,66 @@ def deepcopyext(obj: object, mode: CopyMode, memo: Dict) -> Any:
|
|
|
46
90
|
type(obj),
|
|
47
91
|
"ignoring",
|
|
48
92
|
type(exc),
|
|
93
|
+
":",
|
|
94
|
+
str(exc),
|
|
49
95
|
"at",
|
|
50
|
-
|
|
96
|
+
ch_stack(currently_handling=exc),
|
|
51
97
|
)
|
|
52
|
-
cpy =
|
|
98
|
+
cpy = deepconstruct_obj
|
|
53
99
|
memo[objid] = cpy
|
|
54
|
-
_keep_alive(obj, memo)
|
|
55
100
|
return cpy
|
|
56
101
|
|
|
57
102
|
|
|
103
|
+
if sys.version_info >= (3, 14):
|
|
104
|
+
|
|
105
|
+
def lookup_dispatch(cls: type) -> Callable:
|
|
106
|
+
if cls in _atomic_types:
|
|
107
|
+
return lambda obj, memo: obj
|
|
108
|
+
return _deepcopy_dispatch.get(cls)
|
|
109
|
+
|
|
110
|
+
else:
|
|
111
|
+
|
|
112
|
+
def lookup_dispatch(cls: type) -> Callable:
|
|
113
|
+
return _deepcopy_dispatch.get(cls)
|
|
114
|
+
|
|
115
|
+
|
|
58
116
|
def _deepconstruct(obj: object, mode: CopyMode, memo: Dict):
|
|
59
117
|
cls = type(obj)
|
|
60
118
|
|
|
61
119
|
def subdeepcopy(obj: object, memo: Dict):
|
|
62
120
|
return deepcopyext(obj, mode, memo)
|
|
63
121
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
if creator
|
|
67
|
-
return obj
|
|
68
|
-
elif creator in (_deepcopy_dict, _deepcopy_list, _deepcopy_tuple):
|
|
122
|
+
creator = lookup_dispatch(cls)
|
|
123
|
+
if creator is not None:
|
|
124
|
+
if creator in (_deepcopy_dict, _deepcopy_list, _deepcopy_tuple):
|
|
69
125
|
return creator(obj, memo, deepcopy=subdeepcopy)
|
|
70
126
|
else:
|
|
127
|
+
# TODO: We loose subdeepcopy in this case - won't
|
|
128
|
+
# that make e.g. deep_realize be too shallow?
|
|
71
129
|
return creator(obj, memo)
|
|
72
130
|
if isinstance(obj, type):
|
|
73
131
|
return obj
|
|
74
132
|
if mode != CopyMode.REALIZE and hasattr(obj, "__deepcopy__"):
|
|
75
133
|
return obj.__deepcopy__(memo) # type: ignore
|
|
76
134
|
if cls in dispatch_table:
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
135
|
+
to_call = dispatch_table[cls]
|
|
136
|
+
call_args: Tuple = (obj,)
|
|
137
|
+
elif hasattr(cls, "__reduce_ex__"):
|
|
138
|
+
to_call = getattr(cls, "__reduce_ex__")
|
|
139
|
+
call_args = (obj, 4)
|
|
140
|
+
elif hasattr(cls, "__reduce__"):
|
|
141
|
+
to_call = getattr(cls, "__reduce__")
|
|
142
|
+
call_args = (obj,)
|
|
82
143
|
else:
|
|
83
144
|
raise Error("un(deep)copyable object of type %s" % cls)
|
|
145
|
+
if (
|
|
146
|
+
getattr(cls, "__reduce__") is object.__reduce__
|
|
147
|
+
and getattr(cls, "__reduce_ex__") is object.__reduce_ex__
|
|
148
|
+
):
|
|
149
|
+
reduct = to_call(*call_args)
|
|
150
|
+
else:
|
|
151
|
+
with ResumedTracing():
|
|
152
|
+
reduct = to_call(*call_args)
|
|
84
153
|
if isinstance(reduct, str):
|
|
85
154
|
return obj
|
|
86
155
|
return _reconstruct(obj, memo, *reduct, deepcopy=subdeepcopy)
|
crosshair/copyext_test.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import sys
|
|
1
2
|
from copy import deepcopy
|
|
2
3
|
from threading import RLock
|
|
3
4
|
from typing import Tuple
|
|
@@ -33,6 +34,16 @@ def test_deepcopyext_symbolic_set():
|
|
|
33
34
|
deepcopyext(s, CopyMode.REALIZE, {})
|
|
34
35
|
|
|
35
36
|
|
|
37
|
+
def test_deepcopyext_realize_simple(space):
|
|
38
|
+
x = SymbolicInt("x")
|
|
39
|
+
input = (x,)
|
|
40
|
+
output = deepcopyext(input, CopyMode.REALIZE, {})
|
|
41
|
+
assert input is not output
|
|
42
|
+
assert input[0] is not output[0]
|
|
43
|
+
assert type(input[0]) is SymbolicInt
|
|
44
|
+
assert type(output[0]) is int
|
|
45
|
+
|
|
46
|
+
|
|
36
47
|
def test_deepcopyext_realize(space):
|
|
37
48
|
x = SymbolicInt("x")
|
|
38
49
|
lock = RLock()
|
|
@@ -49,3 +60,25 @@ def test_deepcopyext_realize(space):
|
|
|
49
60
|
def test_deepcopyext_tuple_type():
|
|
50
61
|
assert deepcopy(Tuple) is Tuple
|
|
51
62
|
assert deepcopyext(Tuple, CopyMode.REALIZE, {}) is Tuple
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class RecursiveType:
|
|
66
|
+
a: "RecursiveType"
|
|
67
|
+
|
|
68
|
+
def set(self, a):
|
|
69
|
+
self.a = a
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def test_deepcopyext_recursivetype(space):
|
|
73
|
+
recursive_obj = RecursiveType()
|
|
74
|
+
recursive_obj.set(recursive_obj)
|
|
75
|
+
deepcopyext(recursive_obj, CopyMode.REALIZE, {})
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
@pytest.mark.skipif(
|
|
79
|
+
sys.version_info < (3, 10), reason="dict views not inspect-able before python 3.10"
|
|
80
|
+
)
|
|
81
|
+
def test_fsum_accepts_dict_values_argument(space):
|
|
82
|
+
d = {"a": proxy_for_type(int, "b")}
|
|
83
|
+
realized_vals = deepcopyext(d.values(), CopyMode.REALIZE, {})
|
|
84
|
+
assert type(next(iter(realized_vals))) is int
|