crosshair-tool 0.0.99__cp312-cp312-macosx_10_13_x86_64.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-312-darwin.so +0 -0
- crosshair/__init__.py +42 -0
- crosshair/__main__.py +8 -0
- crosshair/_mark_stacks.h +790 -0
- crosshair/_preliminaries_test.py +18 -0
- crosshair/_tracers.h +94 -0
- crosshair/_tracers_pycompat.h +522 -0
- crosshair/_tracers_test.py +138 -0
- crosshair/abcstring.py +245 -0
- crosshair/auditwall.py +190 -0
- crosshair/auditwall_test.py +77 -0
- crosshair/codeconfig.py +113 -0
- crosshair/codeconfig_test.py +117 -0
- crosshair/condition_parser.py +1237 -0
- crosshair/condition_parser_test.py +497 -0
- crosshair/conftest.py +30 -0
- crosshair/copyext.py +155 -0
- crosshair/copyext_test.py +84 -0
- crosshair/core.py +1763 -0
- crosshair/core_and_libs.py +149 -0
- crosshair/core_regestered_types_test.py +82 -0
- crosshair/core_test.py +1316 -0
- crosshair/diff_behavior.py +314 -0
- crosshair/diff_behavior_test.py +261 -0
- crosshair/dynamic_typing.py +346 -0
- crosshair/dynamic_typing_test.py +210 -0
- crosshair/enforce.py +282 -0
- crosshair/enforce_test.py +182 -0
- crosshair/examples/PEP316/__init__.py +1 -0
- crosshair/examples/PEP316/bugs_detected/__init__.py +0 -0
- crosshair/examples/PEP316/bugs_detected/getattr_magic.py +16 -0
- crosshair/examples/PEP316/bugs_detected/hash_consistent_with_equals.py +31 -0
- crosshair/examples/PEP316/bugs_detected/shopping_cart.py +24 -0
- crosshair/examples/PEP316/bugs_detected/showcase.py +39 -0
- crosshair/examples/PEP316/correct_code/__init__.py +0 -0
- crosshair/examples/PEP316/correct_code/arith.py +60 -0
- crosshair/examples/PEP316/correct_code/chess.py +77 -0
- crosshair/examples/PEP316/correct_code/nesting_inference.py +17 -0
- crosshair/examples/PEP316/correct_code/numpy_examples.py +132 -0
- crosshair/examples/PEP316/correct_code/rolling_average.py +35 -0
- crosshair/examples/PEP316/correct_code/showcase.py +104 -0
- crosshair/examples/__init__.py +0 -0
- crosshair/examples/check_examples_test.py +146 -0
- crosshair/examples/deal/__init__.py +1 -0
- crosshair/examples/icontract/__init__.py +1 -0
- crosshair/examples/icontract/bugs_detected/__init__.py +0 -0
- crosshair/examples/icontract/bugs_detected/showcase.py +41 -0
- crosshair/examples/icontract/bugs_detected/wrong_sign.py +8 -0
- crosshair/examples/icontract/correct_code/__init__.py +0 -0
- crosshair/examples/icontract/correct_code/arith.py +51 -0
- crosshair/examples/icontract/correct_code/showcase.py +94 -0
- crosshair/fnutil.py +391 -0
- crosshair/fnutil_test.py +75 -0
- crosshair/fuzz_core_test.py +516 -0
- crosshair/libimpl/__init__.py +0 -0
- crosshair/libimpl/arraylib.py +161 -0
- 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 +23 -0
- crosshair/libimpl/builtinslib.py +5228 -0
- crosshair/libimpl/builtinslib_ch_test.py +1191 -0
- crosshair/libimpl/builtinslib_test.py +3735 -0
- crosshair/libimpl/codecslib.py +86 -0
- crosshair/libimpl/codecslib_test.py +86 -0
- crosshair/libimpl/collectionslib.py +264 -0
- crosshair/libimpl/collectionslib_ch_test.py +252 -0
- crosshair/libimpl/collectionslib_test.py +332 -0
- crosshair/libimpl/copylib.py +23 -0
- crosshair/libimpl/copylib_test.py +18 -0
- crosshair/libimpl/datetimelib.py +2559 -0
- crosshair/libimpl/datetimelib_ch_test.py +354 -0
- crosshair/libimpl/datetimelib_test.py +112 -0
- crosshair/libimpl/decimallib.py +5257 -0
- crosshair/libimpl/decimallib_ch_test.py +78 -0
- crosshair/libimpl/decimallib_test.py +76 -0
- crosshair/libimpl/encodings/__init__.py +23 -0
- crosshair/libimpl/encodings/_encutil.py +187 -0
- crosshair/libimpl/encodings/ascii.py +44 -0
- crosshair/libimpl/encodings/latin_1.py +40 -0
- crosshair/libimpl/encodings/utf_8.py +93 -0
- crosshair/libimpl/encodings_ch_test.py +83 -0
- crosshair/libimpl/fractionlib.py +16 -0
- crosshair/libimpl/fractionlib_test.py +80 -0
- crosshair/libimpl/functoolslib.py +34 -0
- crosshair/libimpl/functoolslib_test.py +56 -0
- crosshair/libimpl/hashliblib.py +30 -0
- crosshair/libimpl/hashliblib_test.py +18 -0
- crosshair/libimpl/heapqlib.py +47 -0
- crosshair/libimpl/heapqlib_test.py +21 -0
- crosshair/libimpl/importliblib.py +18 -0
- crosshair/libimpl/importliblib_test.py +38 -0
- crosshair/libimpl/iolib.py +216 -0
- crosshair/libimpl/iolib_ch_test.py +128 -0
- crosshair/libimpl/iolib_test.py +19 -0
- crosshair/libimpl/ipaddresslib.py +8 -0
- crosshair/libimpl/itertoolslib.py +44 -0
- crosshair/libimpl/itertoolslib_test.py +44 -0
- crosshair/libimpl/jsonlib.py +984 -0
- crosshair/libimpl/jsonlib_ch_test.py +42 -0
- crosshair/libimpl/jsonlib_test.py +51 -0
- crosshair/libimpl/mathlib.py +179 -0
- crosshair/libimpl/mathlib_ch_test.py +44 -0
- crosshair/libimpl/mathlib_test.py +67 -0
- crosshair/libimpl/oslib.py +7 -0
- crosshair/libimpl/pathliblib_test.py +10 -0
- crosshair/libimpl/randomlib.py +178 -0
- crosshair/libimpl/randomlib_test.py +120 -0
- crosshair/libimpl/relib.py +846 -0
- crosshair/libimpl/relib_ch_test.py +169 -0
- crosshair/libimpl/relib_test.py +493 -0
- crosshair/libimpl/timelib.py +72 -0
- crosshair/libimpl/timelib_test.py +82 -0
- crosshair/libimpl/typeslib.py +15 -0
- crosshair/libimpl/typeslib_test.py +36 -0
- crosshair/libimpl/unicodedatalib.py +75 -0
- crosshair/libimpl/unicodedatalib_test.py +42 -0
- crosshair/libimpl/urlliblib.py +23 -0
- crosshair/libimpl/urlliblib_test.py +19 -0
- 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 +261 -0
- crosshair/lsp_server_test.py +30 -0
- crosshair/main.py +973 -0
- crosshair/main_test.py +543 -0
- crosshair/objectproxy.py +376 -0
- crosshair/objectproxy_test.py +41 -0
- crosshair/opcode_intercept.py +601 -0
- crosshair/opcode_intercept_test.py +304 -0
- crosshair/options.py +218 -0
- crosshair/options_test.py +10 -0
- crosshair/patch_equivalence_test.py +75 -0
- crosshair/path_cover.py +209 -0
- crosshair/path_cover_test.py +138 -0
- crosshair/path_search.py +161 -0
- crosshair/path_search_test.py +52 -0
- crosshair/pathing_oracle.py +271 -0
- crosshair/pathing_oracle_test.py +21 -0
- crosshair/pure_importer.py +27 -0
- crosshair/pure_importer_test.py +16 -0
- crosshair/py.typed +0 -0
- crosshair/register_contract.py +273 -0
- crosshair/register_contract_test.py +190 -0
- crosshair/simplestructs.py +1165 -0
- crosshair/simplestructs_test.py +283 -0
- crosshair/smtlib.py +24 -0
- crosshair/smtlib_test.py +14 -0
- crosshair/statespace.py +1199 -0
- crosshair/statespace_test.py +108 -0
- crosshair/stubs_parser.py +352 -0
- crosshair/stubs_parser_test.py +43 -0
- crosshair/test_util.py +329 -0
- crosshair/test_util_test.py +26 -0
- crosshair/tools/__init__.py +0 -0
- crosshair/tools/check_help_in_doc.py +264 -0
- crosshair/tools/check_init_and_setup_coincide.py +119 -0
- crosshair/tools/generate_demo_table.py +127 -0
- crosshair/tracers.py +544 -0
- crosshair/tracers_test.py +154 -0
- crosshair/type_repo.py +151 -0
- crosshair/unicode_categories.py +589 -0
- crosshair/unicode_categories_test.py +27 -0
- crosshair/util.py +741 -0
- crosshair/util_test.py +173 -0
- crosshair/watcher.py +307 -0
- crosshair/watcher_test.py +107 -0
- crosshair/z3util.py +76 -0
- crosshair/z3util_test.py +11 -0
- crosshair_tool-0.0.99.dist-info/METADATA +144 -0
- crosshair_tool-0.0.99.dist-info/RECORD +176 -0
- crosshair_tool-0.0.99.dist-info/WHEEL +6 -0
- crosshair_tool-0.0.99.dist-info/entry_points.txt +3 -0
- crosshair_tool-0.0.99.dist-info/licenses/LICENSE +93 -0
- crosshair_tool-0.0.99.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import time as real_time
|
|
2
|
+
from inspect import Signature
|
|
3
|
+
from math import isfinite
|
|
4
|
+
from typing import Any, Literal
|
|
5
|
+
|
|
6
|
+
from crosshair.core import register_patch
|
|
7
|
+
from crosshair.register_contract import register_contract
|
|
8
|
+
from crosshair.statespace import context_statespace
|
|
9
|
+
from crosshair.tracers import NoTracing
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class EarliestPossibleTime:
|
|
13
|
+
monotonic: float = 0.0
|
|
14
|
+
process_time: float = 0.0
|
|
15
|
+
|
|
16
|
+
def __init__(self, *a):
|
|
17
|
+
pass
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# Imprecision at high values becomes a sort of artificial problem
|
|
21
|
+
_UNREALISTICALLY_LARGE_TIME_FLOAT = float(60 * 60 * 24 * 365 * 100_000)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _gte_last(kind: Literal["monotonic", "process_time"], value: Any) -> bool:
|
|
25
|
+
with NoTracing():
|
|
26
|
+
earliest_times = context_statespace().extra(EarliestPossibleTime)
|
|
27
|
+
threshold = getattr(earliest_times, kind)
|
|
28
|
+
setattr(earliest_times, kind, value)
|
|
29
|
+
return all([threshold <= value, value < _UNREALISTICALLY_LARGE_TIME_FLOAT])
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _sleep(value: float) -> None:
|
|
33
|
+
with NoTracing():
|
|
34
|
+
earliest_times = context_statespace().extra(EarliestPossibleTime)
|
|
35
|
+
earliest_times.monotonic += value
|
|
36
|
+
return None
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def make_registrations():
|
|
40
|
+
register_contract(
|
|
41
|
+
real_time.time,
|
|
42
|
+
post=lambda __return__: __return__ > 0.0 and isfinite(__return__),
|
|
43
|
+
sig=Signature(parameters=[], return_annotation=float),
|
|
44
|
+
)
|
|
45
|
+
register_contract(
|
|
46
|
+
real_time.time_ns,
|
|
47
|
+
post=lambda __return__: __return__ > 0,
|
|
48
|
+
sig=Signature(parameters=[], return_annotation=int),
|
|
49
|
+
)
|
|
50
|
+
register_contract(
|
|
51
|
+
real_time.monotonic,
|
|
52
|
+
post=lambda __return__: _gte_last("monotonic", __return__)
|
|
53
|
+
and isfinite(__return__),
|
|
54
|
+
sig=Signature(parameters=[], return_annotation=float),
|
|
55
|
+
)
|
|
56
|
+
register_contract(
|
|
57
|
+
real_time.monotonic_ns,
|
|
58
|
+
post=lambda __return__: _gte_last("monotonic", __return__ / 1_000_000_000),
|
|
59
|
+
sig=Signature(parameters=[], return_annotation=int),
|
|
60
|
+
)
|
|
61
|
+
register_contract(
|
|
62
|
+
real_time.process_time,
|
|
63
|
+
post=lambda __return__: _gte_last("process_time", __return__)
|
|
64
|
+
and isfinite(__return__),
|
|
65
|
+
sig=Signature(parameters=[], return_annotation=float),
|
|
66
|
+
)
|
|
67
|
+
register_contract(
|
|
68
|
+
real_time.process_time_ns,
|
|
69
|
+
post=lambda __return__: _gte_last("process_time", __return__ / 1_000_000_000),
|
|
70
|
+
sig=Signature(parameters=[], return_annotation=int),
|
|
71
|
+
)
|
|
72
|
+
register_patch(real_time.sleep, _sleep)
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import time
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from crosshair.statespace import CANNOT_CONFIRM, CONFIRMED, POST_FAIL
|
|
6
|
+
from crosshair.test_util import check_states
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@pytest.mark.demo
|
|
10
|
+
def test_time():
|
|
11
|
+
def f():
|
|
12
|
+
"""
|
|
13
|
+
Can time go backwards?
|
|
14
|
+
|
|
15
|
+
NOTE: CrossHair allows time() to produce ANY value.
|
|
16
|
+
Although highly unlikely, it's possible that the system clock
|
|
17
|
+
is set backwards while a program executes.
|
|
18
|
+
(BTW: use time.monotonic if you don't want it to go backwards!)
|
|
19
|
+
|
|
20
|
+
CrossHair's counterexample includes a monkey-patching context
|
|
21
|
+
manager that lets you reproduce the issue, e.g.:
|
|
22
|
+
with crosshair.patch_to_return({time.time: [2.0, 1.0]}):
|
|
23
|
+
f()
|
|
24
|
+
|
|
25
|
+
post: _ >= 0
|
|
26
|
+
"""
|
|
27
|
+
start = time.time()
|
|
28
|
+
return time.time() - start
|
|
29
|
+
|
|
30
|
+
check_states(f, POST_FAIL)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def test_time_ns():
|
|
34
|
+
def f():
|
|
35
|
+
"""post: _ >= 0"""
|
|
36
|
+
start = time.time_ns()
|
|
37
|
+
return time.time_ns() - start
|
|
38
|
+
|
|
39
|
+
check_states(f, POST_FAIL)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@pytest.mark.demo
|
|
43
|
+
def test_monotonic():
|
|
44
|
+
def f():
|
|
45
|
+
"""
|
|
46
|
+
Can time increase by one second between monotonic() calls?
|
|
47
|
+
|
|
48
|
+
post: _ != 1.0
|
|
49
|
+
"""
|
|
50
|
+
start = time.monotonic()
|
|
51
|
+
end = time.monotonic()
|
|
52
|
+
return end - start
|
|
53
|
+
|
|
54
|
+
check_states(f, POST_FAIL)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def test_monotonic_confirm():
|
|
58
|
+
def f():
|
|
59
|
+
"""post: _ >= 0"""
|
|
60
|
+
start = time.monotonic()
|
|
61
|
+
return time.monotonic() - start
|
|
62
|
+
|
|
63
|
+
check_states(f, CONFIRMED)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def test_monotonic_ns():
|
|
67
|
+
def f():
|
|
68
|
+
"""post: _ >= 0"""
|
|
69
|
+
start = time.monotonic_ns()
|
|
70
|
+
return time.monotonic_ns() - start
|
|
71
|
+
|
|
72
|
+
check_states(f, CANNOT_CONFIRM)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def test_sleep():
|
|
76
|
+
def f():
|
|
77
|
+
"""post: _ >= 60.0"""
|
|
78
|
+
start = time.monotonic()
|
|
79
|
+
time.sleep(60.01)
|
|
80
|
+
return time.monotonic() - start
|
|
81
|
+
|
|
82
|
+
check_states(f, CANNOT_CONFIRM)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from types import MappingProxyType
|
|
2
|
+
from typing import Any, Dict
|
|
3
|
+
|
|
4
|
+
from crosshair.core import register_patch, register_type
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def _repr(map: MappingProxyType):
|
|
8
|
+
if not isinstance(map, MappingProxyType):
|
|
9
|
+
raise TypeError
|
|
10
|
+
return f"mappingproxy({repr(dict(map))})"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def make_registrations():
|
|
14
|
+
register_type(MappingProxyType, lambda p, kt=Any, vt=Any: MappingProxyType(p(Dict[kt, vt]))) # type: ignore
|
|
15
|
+
register_patch(MappingProxyType.__repr__, _repr)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
from types import MappingProxyType
|
|
3
|
+
from typing import Dict
|
|
4
|
+
|
|
5
|
+
import pytest
|
|
6
|
+
|
|
7
|
+
from crosshair import ResumedTracing
|
|
8
|
+
from crosshair.core import deep_realize, proxy_for_type
|
|
9
|
+
from crosshair.libimpl.builtinslib import SymbolicInt
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@pytest.mark.skipif(
|
|
13
|
+
sys.version_info < (3, 9), reason="MappingProxyType not subscriptable in 3.8"
|
|
14
|
+
)
|
|
15
|
+
def test_mappingproxy_repr(space):
|
|
16
|
+
d = proxy_for_type(MappingProxyType[int, int], "d")
|
|
17
|
+
with ResumedTracing():
|
|
18
|
+
assert repr(d).startswith("mappingproxy(")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def test_mappingproxy_deep_realize(space):
|
|
22
|
+
inner = proxy_for_type(Dict[int, int], "inner")
|
|
23
|
+
with ResumedTracing():
|
|
24
|
+
space.add(inner._inner.__len__() == 1)
|
|
25
|
+
key = next(iter(inner.keys()))
|
|
26
|
+
assert type(key) is SymbolicInt
|
|
27
|
+
orig = MappingProxyType(inner)
|
|
28
|
+
assert type(orig) is MappingProxyType
|
|
29
|
+
copy = deep_realize(orig)
|
|
30
|
+
assert type(copy) is MappingProxyType
|
|
31
|
+
with ResumedTracing():
|
|
32
|
+
val_from_orig = orig[key]
|
|
33
|
+
realized_key = deep_realize(key)
|
|
34
|
+
val_from_copy = copy[realized_key]
|
|
35
|
+
assert type(val_from_orig) is SymbolicInt
|
|
36
|
+
assert type(val_from_copy) is int
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import unicodedata
|
|
3
|
+
|
|
4
|
+
from crosshair.core import register_patch, with_realized_args
|
|
5
|
+
from crosshair.libimpl.builtinslib import AnySymbolicStr, SymbolicInt
|
|
6
|
+
from crosshair.statespace import context_statespace
|
|
7
|
+
from crosshair.tracers import NoTracing
|
|
8
|
+
from crosshair.unicode_categories import UnicodeMaskCache
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def _decimal(ch: str) -> float:
|
|
12
|
+
codepoint = ord(ch)
|
|
13
|
+
with NoTracing():
|
|
14
|
+
if not isinstance(ch, AnySymbolicStr):
|
|
15
|
+
return unicodedata.decimal(ch)
|
|
16
|
+
space = context_statespace()
|
|
17
|
+
smt_codepoint = SymbolicInt._coerce_to_smt_sort(codepoint)
|
|
18
|
+
cache = space.extra(UnicodeMaskCache)
|
|
19
|
+
if not space.smt_fork(cache.decimal_exists()(smt_codepoint)):
|
|
20
|
+
raise ValueError
|
|
21
|
+
return SymbolicInt(cache.decimal_int()(smt_codepoint))
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _digit(ch: str) -> float:
|
|
25
|
+
codepoint = ord(ch)
|
|
26
|
+
with NoTracing():
|
|
27
|
+
if not isinstance(ch, AnySymbolicStr):
|
|
28
|
+
return unicodedata.digit(ch)
|
|
29
|
+
space = context_statespace()
|
|
30
|
+
smt_codepoint = SymbolicInt._coerce_to_smt_sort(codepoint)
|
|
31
|
+
cache = space.extra(UnicodeMaskCache)
|
|
32
|
+
if not space.smt_fork(cache.digit_exists()(smt_codepoint)):
|
|
33
|
+
raise ValueError
|
|
34
|
+
return SymbolicInt(cache.digit_int()(smt_codepoint))
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _numeric(ch: str) -> float:
|
|
38
|
+
codepoint = ord(ch)
|
|
39
|
+
with NoTracing():
|
|
40
|
+
if not isinstance(ch, AnySymbolicStr):
|
|
41
|
+
return unicodedata.numeric(ch)
|
|
42
|
+
space = context_statespace()
|
|
43
|
+
smt_codepoint = SymbolicInt._coerce_to_smt_sort(codepoint)
|
|
44
|
+
cache = space.extra(UnicodeMaskCache)
|
|
45
|
+
if not space.smt_fork(cache.numeric_exists()(smt_codepoint)):
|
|
46
|
+
raise ValueError
|
|
47
|
+
numerator = SymbolicInt(cache.numeric_numerator()(smt_codepoint))
|
|
48
|
+
denominator = SymbolicInt(cache.numeric_denominator()(smt_codepoint))
|
|
49
|
+
return numerator / float(denominator)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def make_registrations():
|
|
53
|
+
register_patch(unicodedata.lookup, with_realized_args(unicodedata.lookup))
|
|
54
|
+
register_patch(unicodedata.name, with_realized_args(unicodedata.name))
|
|
55
|
+
register_patch(unicodedata.decimal, _decimal)
|
|
56
|
+
register_patch(unicodedata.digit, _digit)
|
|
57
|
+
register_patch(unicodedata.numeric, _numeric)
|
|
58
|
+
# TOOD: implement this using get_unicode_categories() - should be easy:
|
|
59
|
+
register_patch(unicodedata.category, with_realized_args(unicodedata.category))
|
|
60
|
+
register_patch(
|
|
61
|
+
unicodedata.bidirectional, with_realized_args(unicodedata.bidirectional)
|
|
62
|
+
)
|
|
63
|
+
register_patch(unicodedata.combining, with_realized_args(unicodedata.combining))
|
|
64
|
+
register_patch(
|
|
65
|
+
unicodedata.east_asian_width, with_realized_args(unicodedata.east_asian_width)
|
|
66
|
+
)
|
|
67
|
+
register_patch(unicodedata.mirrored, with_realized_args(unicodedata.mirrored))
|
|
68
|
+
register_patch(
|
|
69
|
+
unicodedata.decomposition, with_realized_args(unicodedata.decomposition)
|
|
70
|
+
)
|
|
71
|
+
register_patch(unicodedata.normalize, with_realized_args(unicodedata.normalize))
|
|
72
|
+
if sys.version_info >= (3, 8):
|
|
73
|
+
register_patch(
|
|
74
|
+
unicodedata.is_normalized, with_realized_args(unicodedata.is_normalized)
|
|
75
|
+
)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import unicodedata
|
|
2
|
+
from typing import *
|
|
3
|
+
|
|
4
|
+
import pytest
|
|
5
|
+
|
|
6
|
+
from crosshair.core_and_libs import NoTracing, standalone_statespace
|
|
7
|
+
from crosshair.libimpl.builtinslib import LazyIntSymbolicStr
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def test_numeric():
|
|
11
|
+
with standalone_statespace as space:
|
|
12
|
+
with NoTracing():
|
|
13
|
+
fourstr = LazyIntSymbolicStr(list(map(ord, "4")))
|
|
14
|
+
halfstr = LazyIntSymbolicStr(list(map(ord, "\u00bd"))) # (1/2 character)
|
|
15
|
+
four = unicodedata.numeric(fourstr)
|
|
16
|
+
half = unicodedata.numeric(halfstr)
|
|
17
|
+
assert type(four) is float
|
|
18
|
+
assert four == 4.0
|
|
19
|
+
assert half == 0.5
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def test_decimal():
|
|
23
|
+
with standalone_statespace as space:
|
|
24
|
+
with NoTracing():
|
|
25
|
+
thai4 = LazyIntSymbolicStr(list(map(ord, "\u0e54"))) # (Thai numerial 4)
|
|
26
|
+
super4 = LazyIntSymbolicStr(list(map(ord, "\u2074"))) # (superscript 4)
|
|
27
|
+
four = unicodedata.decimal(thai4)
|
|
28
|
+
assert type(four) is int
|
|
29
|
+
assert four == 4
|
|
30
|
+
with pytest.raises(ValueError):
|
|
31
|
+
unicodedata.decimal(super4)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def test_digit():
|
|
35
|
+
with standalone_statespace as space:
|
|
36
|
+
with NoTracing():
|
|
37
|
+
thai4 = LazyIntSymbolicStr(list(map(ord, "\u0e54"))) # (Thai numerial 4)
|
|
38
|
+
super4 = LazyIntSymbolicStr(list(map(ord, "\u2074"))) # (superscript 4)
|
|
39
|
+
four = unicodedata.digit(thai4)
|
|
40
|
+
assert type(four) is int
|
|
41
|
+
assert four == 4
|
|
42
|
+
assert unicodedata.digit(super4) == 4
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import urllib.parse
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class DevNullDict:
|
|
6
|
+
def get(self, k, default):
|
|
7
|
+
return default
|
|
8
|
+
|
|
9
|
+
def __setitem__(self, k, v):
|
|
10
|
+
pass
|
|
11
|
+
|
|
12
|
+
def __len__(self):
|
|
13
|
+
return 0
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def make_registrations():
|
|
17
|
+
# Avoid nondeterminism in urllib by disabling internal caching.
|
|
18
|
+
if sys.version_info < (3, 11):
|
|
19
|
+
# TODO: This is destructive! But not terribly harmful. Consider alternatives.
|
|
20
|
+
urllib.parse._parse_cache = DevNullDict() # type: ignore
|
|
21
|
+
else:
|
|
22
|
+
# (3.11 uses functools.lru_cache, which we disable elsewhere)
|
|
23
|
+
assert not hasattr(urllib.parse, "_parse_cache")
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from urllib.parse import urlparse
|
|
2
|
+
|
|
3
|
+
from crosshair.options import AnalysisOptionSet
|
|
4
|
+
from crosshair.statespace import POST_FAIL, MessageType
|
|
5
|
+
from crosshair.test_util import check_states
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def test_urllib_parse():
|
|
9
|
+
def f(urlstring: str):
|
|
10
|
+
"""
|
|
11
|
+
pre: len(urlstring) == 3
|
|
12
|
+
pre: urlstring[0:2] == "//"
|
|
13
|
+
pre: urlstring[2] != "["
|
|
14
|
+
pre: urlstring[2] != "]"
|
|
15
|
+
post: __return__.netloc != "h"
|
|
16
|
+
"""
|
|
17
|
+
return urlparse(urlstring)
|
|
18
|
+
|
|
19
|
+
check_states(f, POST_FAIL)
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
from weakref import WeakKeyDictionary, WeakSet, WeakValueDictionary, proxy, ref
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from crosshair.tracers import ResumedTracing
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Thing:
|
|
9
|
+
x: int = 0
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def test_weakref(space):
|
|
13
|
+
thing1 = Thing()
|
|
14
|
+
assert ref(thing1)() is thing1
|
|
15
|
+
with ResumedTracing():
|
|
16
|
+
assert ref(thing1)() is None
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def test_weakref_WeakKeyDictionary(space):
|
|
20
|
+
d = WeakKeyDictionary()
|
|
21
|
+
thing1 = Thing()
|
|
22
|
+
thing2 = Thing()
|
|
23
|
+
d[thing1] = 1
|
|
24
|
+
d[thing2] = 2
|
|
25
|
+
assert len(d) == 2
|
|
26
|
+
assert thing1 in d
|
|
27
|
+
assert set(d.keys()) == {thing1, thing2}
|
|
28
|
+
with ResumedTracing():
|
|
29
|
+
assert set(d.keys()) == set()
|
|
30
|
+
# You would expect the following assertions to work too
|
|
31
|
+
# However, they don't require getting the referred object, so they appear to still exist:
|
|
32
|
+
# assert thing1 not in d
|
|
33
|
+
# assert len(d) == 0
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def test_weakref_WeakValueDictionary(space):
|
|
37
|
+
d = WeakValueDictionary()
|
|
38
|
+
thing1 = Thing()
|
|
39
|
+
thing2 = Thing()
|
|
40
|
+
d[1] = thing1
|
|
41
|
+
d[2] = thing2
|
|
42
|
+
assert len(d) == 2
|
|
43
|
+
assert 1 in d
|
|
44
|
+
assert set(d.keys()) == {1, 2}
|
|
45
|
+
with ResumedTracing():
|
|
46
|
+
assert set(d.keys()) == set()
|
|
47
|
+
assert 1 not in d
|
|
48
|
+
# You would expect the length to update too.
|
|
49
|
+
# However, it doesn't require getting the referred object, so it appears to still exist:
|
|
50
|
+
# assert len(d) == 0
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@pytest.mark.xfail(reason="weakref.WeakSet is not yet supported")
|
|
54
|
+
def test_weakref_WeakSet(space):
|
|
55
|
+
s = WeakSet()
|
|
56
|
+
thing1 = Thing()
|
|
57
|
+
s.add(thing1)
|
|
58
|
+
assert thing1 in s
|
|
59
|
+
with ResumedTracing():
|
|
60
|
+
assert thing1 not in s
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@pytest.mark.xfail(reason="weakref.proxy is not yet supported")
|
|
64
|
+
def test_weakref_proxy(space):
|
|
65
|
+
thing1 = Thing()
|
|
66
|
+
thing1.x
|
|
67
|
+
p = proxy(thing1)
|
|
68
|
+
with pytest.raises(ReferenceError), ResumedTracing():
|
|
69
|
+
p.x
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import zlib
|
|
2
|
+
|
|
3
|
+
from crosshair.core import register_patch, with_realized_args
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def make_registrations():
|
|
7
|
+
for fn in (
|
|
8
|
+
zlib.adler32,
|
|
9
|
+
zlib.compress,
|
|
10
|
+
zlib.crc32,
|
|
11
|
+
zlib.decompress,
|
|
12
|
+
type(zlib.compressobj()).compress,
|
|
13
|
+
type(zlib.decompressobj()).decompress,
|
|
14
|
+
):
|
|
15
|
+
register_patch(fn, with_realized_args(fn))
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import zlib
|
|
2
|
+
|
|
3
|
+
from crosshair.core import proxy_for_type, realize
|
|
4
|
+
from crosshair.tracers import ResumedTracing
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def test_compress_on_symbolic(space):
|
|
8
|
+
buffer = proxy_for_type(bytes, "buffer")
|
|
9
|
+
with ResumedTracing():
|
|
10
|
+
space.add(len(buffer) == 1)
|
|
11
|
+
result = zlib.compress(buffer)
|
|
12
|
+
realized_buffer = realize(buffer)
|
|
13
|
+
assert zlib.decompress(result) == realized_buffer
|