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.
Files changed (176) hide show
  1. _crosshair_tracers.cpython-312-darwin.so +0 -0
  2. crosshair/__init__.py +42 -0
  3. crosshair/__main__.py +8 -0
  4. crosshair/_mark_stacks.h +790 -0
  5. crosshair/_preliminaries_test.py +18 -0
  6. crosshair/_tracers.h +94 -0
  7. crosshair/_tracers_pycompat.h +522 -0
  8. crosshair/_tracers_test.py +138 -0
  9. crosshair/abcstring.py +245 -0
  10. crosshair/auditwall.py +190 -0
  11. crosshair/auditwall_test.py +77 -0
  12. crosshair/codeconfig.py +113 -0
  13. crosshair/codeconfig_test.py +117 -0
  14. crosshair/condition_parser.py +1237 -0
  15. crosshair/condition_parser_test.py +497 -0
  16. crosshair/conftest.py +30 -0
  17. crosshair/copyext.py +155 -0
  18. crosshair/copyext_test.py +84 -0
  19. crosshair/core.py +1763 -0
  20. crosshair/core_and_libs.py +149 -0
  21. crosshair/core_regestered_types_test.py +82 -0
  22. crosshair/core_test.py +1316 -0
  23. crosshair/diff_behavior.py +314 -0
  24. crosshair/diff_behavior_test.py +261 -0
  25. crosshair/dynamic_typing.py +346 -0
  26. crosshair/dynamic_typing_test.py +210 -0
  27. crosshair/enforce.py +282 -0
  28. crosshair/enforce_test.py +182 -0
  29. crosshair/examples/PEP316/__init__.py +1 -0
  30. crosshair/examples/PEP316/bugs_detected/__init__.py +0 -0
  31. crosshair/examples/PEP316/bugs_detected/getattr_magic.py +16 -0
  32. crosshair/examples/PEP316/bugs_detected/hash_consistent_with_equals.py +31 -0
  33. crosshair/examples/PEP316/bugs_detected/shopping_cart.py +24 -0
  34. crosshair/examples/PEP316/bugs_detected/showcase.py +39 -0
  35. crosshair/examples/PEP316/correct_code/__init__.py +0 -0
  36. crosshair/examples/PEP316/correct_code/arith.py +60 -0
  37. crosshair/examples/PEP316/correct_code/chess.py +77 -0
  38. crosshair/examples/PEP316/correct_code/nesting_inference.py +17 -0
  39. crosshair/examples/PEP316/correct_code/numpy_examples.py +132 -0
  40. crosshair/examples/PEP316/correct_code/rolling_average.py +35 -0
  41. crosshair/examples/PEP316/correct_code/showcase.py +104 -0
  42. crosshair/examples/__init__.py +0 -0
  43. crosshair/examples/check_examples_test.py +146 -0
  44. crosshair/examples/deal/__init__.py +1 -0
  45. crosshair/examples/icontract/__init__.py +1 -0
  46. crosshair/examples/icontract/bugs_detected/__init__.py +0 -0
  47. crosshair/examples/icontract/bugs_detected/showcase.py +41 -0
  48. crosshair/examples/icontract/bugs_detected/wrong_sign.py +8 -0
  49. crosshair/examples/icontract/correct_code/__init__.py +0 -0
  50. crosshair/examples/icontract/correct_code/arith.py +51 -0
  51. crosshair/examples/icontract/correct_code/showcase.py +94 -0
  52. crosshair/fnutil.py +391 -0
  53. crosshair/fnutil_test.py +75 -0
  54. crosshair/fuzz_core_test.py +516 -0
  55. crosshair/libimpl/__init__.py +0 -0
  56. crosshair/libimpl/arraylib.py +161 -0
  57. crosshair/libimpl/binascii_ch_test.py +30 -0
  58. crosshair/libimpl/binascii_test.py +67 -0
  59. crosshair/libimpl/binasciilib.py +150 -0
  60. crosshair/libimpl/bisectlib_test.py +23 -0
  61. crosshair/libimpl/builtinslib.py +5228 -0
  62. crosshair/libimpl/builtinslib_ch_test.py +1191 -0
  63. crosshair/libimpl/builtinslib_test.py +3735 -0
  64. crosshair/libimpl/codecslib.py +86 -0
  65. crosshair/libimpl/codecslib_test.py +86 -0
  66. crosshair/libimpl/collectionslib.py +264 -0
  67. crosshair/libimpl/collectionslib_ch_test.py +252 -0
  68. crosshair/libimpl/collectionslib_test.py +332 -0
  69. crosshair/libimpl/copylib.py +23 -0
  70. crosshair/libimpl/copylib_test.py +18 -0
  71. crosshair/libimpl/datetimelib.py +2559 -0
  72. crosshair/libimpl/datetimelib_ch_test.py +354 -0
  73. crosshair/libimpl/datetimelib_test.py +112 -0
  74. crosshair/libimpl/decimallib.py +5257 -0
  75. crosshair/libimpl/decimallib_ch_test.py +78 -0
  76. crosshair/libimpl/decimallib_test.py +76 -0
  77. crosshair/libimpl/encodings/__init__.py +23 -0
  78. crosshair/libimpl/encodings/_encutil.py +187 -0
  79. crosshair/libimpl/encodings/ascii.py +44 -0
  80. crosshair/libimpl/encodings/latin_1.py +40 -0
  81. crosshair/libimpl/encodings/utf_8.py +93 -0
  82. crosshair/libimpl/encodings_ch_test.py +83 -0
  83. crosshair/libimpl/fractionlib.py +16 -0
  84. crosshair/libimpl/fractionlib_test.py +80 -0
  85. crosshair/libimpl/functoolslib.py +34 -0
  86. crosshair/libimpl/functoolslib_test.py +56 -0
  87. crosshair/libimpl/hashliblib.py +30 -0
  88. crosshair/libimpl/hashliblib_test.py +18 -0
  89. crosshair/libimpl/heapqlib.py +47 -0
  90. crosshair/libimpl/heapqlib_test.py +21 -0
  91. crosshair/libimpl/importliblib.py +18 -0
  92. crosshair/libimpl/importliblib_test.py +38 -0
  93. crosshair/libimpl/iolib.py +216 -0
  94. crosshair/libimpl/iolib_ch_test.py +128 -0
  95. crosshair/libimpl/iolib_test.py +19 -0
  96. crosshair/libimpl/ipaddresslib.py +8 -0
  97. crosshair/libimpl/itertoolslib.py +44 -0
  98. crosshair/libimpl/itertoolslib_test.py +44 -0
  99. crosshair/libimpl/jsonlib.py +984 -0
  100. crosshair/libimpl/jsonlib_ch_test.py +42 -0
  101. crosshair/libimpl/jsonlib_test.py +51 -0
  102. crosshair/libimpl/mathlib.py +179 -0
  103. crosshair/libimpl/mathlib_ch_test.py +44 -0
  104. crosshair/libimpl/mathlib_test.py +67 -0
  105. crosshair/libimpl/oslib.py +7 -0
  106. crosshair/libimpl/pathliblib_test.py +10 -0
  107. crosshair/libimpl/randomlib.py +178 -0
  108. crosshair/libimpl/randomlib_test.py +120 -0
  109. crosshair/libimpl/relib.py +846 -0
  110. crosshair/libimpl/relib_ch_test.py +169 -0
  111. crosshair/libimpl/relib_test.py +493 -0
  112. crosshair/libimpl/timelib.py +72 -0
  113. crosshair/libimpl/timelib_test.py +82 -0
  114. crosshair/libimpl/typeslib.py +15 -0
  115. crosshair/libimpl/typeslib_test.py +36 -0
  116. crosshair/libimpl/unicodedatalib.py +75 -0
  117. crosshair/libimpl/unicodedatalib_test.py +42 -0
  118. crosshair/libimpl/urlliblib.py +23 -0
  119. crosshair/libimpl/urlliblib_test.py +19 -0
  120. crosshair/libimpl/weakreflib.py +13 -0
  121. crosshair/libimpl/weakreflib_test.py +69 -0
  122. crosshair/libimpl/zliblib.py +15 -0
  123. crosshair/libimpl/zliblib_test.py +13 -0
  124. crosshair/lsp_server.py +261 -0
  125. crosshair/lsp_server_test.py +30 -0
  126. crosshair/main.py +973 -0
  127. crosshair/main_test.py +543 -0
  128. crosshair/objectproxy.py +376 -0
  129. crosshair/objectproxy_test.py +41 -0
  130. crosshair/opcode_intercept.py +601 -0
  131. crosshair/opcode_intercept_test.py +304 -0
  132. crosshair/options.py +218 -0
  133. crosshair/options_test.py +10 -0
  134. crosshair/patch_equivalence_test.py +75 -0
  135. crosshair/path_cover.py +209 -0
  136. crosshair/path_cover_test.py +138 -0
  137. crosshair/path_search.py +161 -0
  138. crosshair/path_search_test.py +52 -0
  139. crosshair/pathing_oracle.py +271 -0
  140. crosshair/pathing_oracle_test.py +21 -0
  141. crosshair/pure_importer.py +27 -0
  142. crosshair/pure_importer_test.py +16 -0
  143. crosshair/py.typed +0 -0
  144. crosshair/register_contract.py +273 -0
  145. crosshair/register_contract_test.py +190 -0
  146. crosshair/simplestructs.py +1165 -0
  147. crosshair/simplestructs_test.py +283 -0
  148. crosshair/smtlib.py +24 -0
  149. crosshair/smtlib_test.py +14 -0
  150. crosshair/statespace.py +1199 -0
  151. crosshair/statespace_test.py +108 -0
  152. crosshair/stubs_parser.py +352 -0
  153. crosshair/stubs_parser_test.py +43 -0
  154. crosshair/test_util.py +329 -0
  155. crosshair/test_util_test.py +26 -0
  156. crosshair/tools/__init__.py +0 -0
  157. crosshair/tools/check_help_in_doc.py +264 -0
  158. crosshair/tools/check_init_and_setup_coincide.py +119 -0
  159. crosshair/tools/generate_demo_table.py +127 -0
  160. crosshair/tracers.py +544 -0
  161. crosshair/tracers_test.py +154 -0
  162. crosshair/type_repo.py +151 -0
  163. crosshair/unicode_categories.py +589 -0
  164. crosshair/unicode_categories_test.py +27 -0
  165. crosshair/util.py +741 -0
  166. crosshair/util_test.py +173 -0
  167. crosshair/watcher.py +307 -0
  168. crosshair/watcher_test.py +107 -0
  169. crosshair/z3util.py +76 -0
  170. crosshair/z3util_test.py +11 -0
  171. crosshair_tool-0.0.99.dist-info/METADATA +144 -0
  172. crosshair_tool-0.0.99.dist-info/RECORD +176 -0
  173. crosshair_tool-0.0.99.dist-info/WHEEL +6 -0
  174. crosshair_tool-0.0.99.dist-info/entry_points.txt +3 -0
  175. crosshair_tool-0.0.99.dist-info/licenses/LICENSE +93 -0
  176. crosshair_tool-0.0.99.dist-info/top_level.txt +2 -0
@@ -0,0 +1,67 @@
1
+ import binascii
2
+ import sys
3
+ from array import array
4
+
5
+ import pytest
6
+
7
+ from crosshair.test_util import summarize_execution
8
+ from crosshair.tracers import ResumedTracing
9
+
10
+
11
+ @pytest.mark.parametrize(
12
+ "input_bytes",
13
+ [
14
+ b"", # empty
15
+ b"//==", # padding 2
16
+ b"AAA=", # padding 1
17
+ b"9999", # no padding
18
+ b"3=4=", # discontinuous padding
19
+ b"34=&=", # unexpected chars in padding
20
+ b"34=", # wrong padding
21
+ b"333====", # over-padding
22
+ b"This/12+yearOld/Fox=", # valid, long
23
+ "", # empty string
24
+ "9009", # nonempty string
25
+ "\u2165", # unicode string
26
+ ],
27
+ )
28
+ @pytest.mark.parametrize("strict_mode", [True, False])
29
+ def test_base64_decode(space, input_bytes, strict_mode):
30
+ kw = {"strict_mode": strict_mode} if sys.version_info >= (3, 11) else {}
31
+ concrete_result = summarize_execution(
32
+ binascii.a2b_base64, (input_bytes,), kw, detach_path=False
33
+ )
34
+ with ResumedTracing():
35
+ symbolic_result = summarize_execution(
36
+ binascii.a2b_base64, (input_bytes,), kw, detach_path=False
37
+ )
38
+ assert concrete_result == symbolic_result
39
+
40
+
41
+ @pytest.mark.parametrize("newline", [True, False])
42
+ @pytest.mark.parametrize(
43
+ "input_bytes",
44
+ [
45
+ b"", # empty
46
+ b"H",
47
+ b"Ha",
48
+ b"Hai",
49
+ b"Hair",
50
+ "", # empty string
51
+ "Hair", # nonempty string
52
+ "\u2165", # unicode string
53
+ bytearray(b"Hair"), # bytearray
54
+ memoryview(b"Hair"), # memoryview
55
+ array("B", b"Hair"), # array
56
+ ],
57
+ )
58
+ def test_base64_encode(space, input_bytes, newline):
59
+ kw = {"newline": newline}
60
+ concrete_result = summarize_execution(
61
+ binascii.b2a_base64, (input_bytes,), kw, detach_path=False
62
+ )
63
+ with ResumedTracing():
64
+ symbolic_result = summarize_execution(
65
+ binascii.b2a_base64, (input_bytes,), kw, detach_path=False
66
+ )
67
+ assert concrete_result == symbolic_result
@@ -0,0 +1,150 @@
1
+ import binascii
2
+ from functools import partial
3
+ from typing import Dict, Iterable, Tuple, Union
4
+
5
+ from crosshair.core import register_patch
6
+ from crosshair.libimpl.builtinslib import _ALL_BYTES_TYPES, SymbolicBytes
7
+ from crosshair.util import name_of_type
8
+
9
+ _ORD_OF_NEWLINE = ord("\n")
10
+ _ORD_OF_EQUALS = ord("=")
11
+
12
+
13
+ def _bit_chunk_iter(
14
+ seq: Iterable[int], input_bit_size: int, output_bit_size: int
15
+ ) -> Iterable[int]:
16
+ """Turns a sequence of N-bit integers into a sequence of M-bit integers"""
17
+ accumulated = 0
18
+ bits_accumulated = 0
19
+ input_size = 1 << input_bit_size
20
+ for chunk in seq:
21
+ accumulated = accumulated * input_size + chunk
22
+ bits_accumulated += input_bit_size
23
+ while bits_accumulated >= output_bit_size:
24
+ remaining_bits = bits_accumulated - output_bit_size
25
+ if remaining_bits == 0:
26
+ yield accumulated
27
+ accumulated = bits_accumulated = 0
28
+ else:
29
+ top, bottom = divmod(accumulated, 1 << remaining_bits)
30
+ yield top
31
+ accumulated = bottom
32
+ bits_accumulated = remaining_bits
33
+ if bits_accumulated > 0:
34
+ zero_bits = output_bit_size - bits_accumulated
35
+ yield accumulated * (1 << zero_bits)
36
+
37
+
38
+ def _remap(
39
+ table: Dict[Tuple[int, int], int],
40
+ input_ints: Iterable[int],
41
+ error_type=None,
42
+ error_message=None,
43
+ ):
44
+ output_ints = []
45
+ padding = 0
46
+ for ch in input_ints:
47
+ for (minval, maxval), target_start in table.items():
48
+ if all([minval <= ch, ch <= maxval]):
49
+ if minval != 0:
50
+ ch -= minval
51
+ if target_start != 0:
52
+ ch += target_start
53
+ output_ints.append(ch)
54
+ if padding != 0:
55
+ raise binascii.Error("Discontinuous padding not allowed")
56
+ break
57
+ else:
58
+ if ch == _ORD_OF_EQUALS:
59
+ padding += 1
60
+ elif error_message:
61
+ raise (error_type or binascii.Error)(error_message)
62
+ return output_ints, padding
63
+
64
+
65
+ def _reverse_map(table: Dict[Tuple[int, int], int]):
66
+ ret = {}
67
+ for (minval, maxval), target_start in table.items():
68
+ ret[(target_start, target_start + maxval - minval)] = minval
69
+ return ret
70
+
71
+
72
+ _DECODE_BASE64_MAP = {
73
+ (ord("A"), ord("Z")): 0,
74
+ (ord("a"), ord("z")): 26,
75
+ (ord("0"), ord("9")): 52,
76
+ (ord("+"), ord("+")): 62,
77
+ (ord("/"), ord("/")): 63,
78
+ }
79
+ _ENCODE_BASE64_MAP = _reverse_map(_DECODE_BASE64_MAP)
80
+
81
+ _DECODE_MAPPER_BASE64 = partial(_remap, _DECODE_BASE64_MAP)
82
+ _DECODE_MAPPER_BASE64_STRICT = partial(
83
+ _remap,
84
+ _DECODE_BASE64_MAP,
85
+ error_type=binascii.Error,
86
+ error_message="Only base64 data is allowed",
87
+ )
88
+ _ENCODE_MAPPER_BASE64 = partial(_remap, _ENCODE_BASE64_MAP)
89
+
90
+
91
+ def make_bytes(arg: object) -> Union[bytes, bytearray, memoryview]:
92
+ if isinstance(arg, (bytes, bytearray, memoryview)):
93
+ return arg
94
+ if isinstance(arg, str):
95
+ try:
96
+ return arg.encode("ascii")
97
+ except UnicodeEncodeError:
98
+ raise ValueError("string argument should contain only ASCII characters")
99
+ else:
100
+ raise TypeError(
101
+ f"a bytes-like object is required, not '{name_of_type(type(arg))}'"
102
+ )
103
+
104
+
105
+ def _b2a_base64(data, /, *, newline=True): # encode
106
+ if not isinstance(data, _ALL_BYTES_TYPES):
107
+ raise TypeError(
108
+ f"a bytes-like object is required, not '{name_of_type(type(data))}'"
109
+ )
110
+ output_ints, _padding_count = _ENCODE_MAPPER_BASE64(
111
+ _bit_chunk_iter(data, input_bit_size=8, output_bit_size=6)
112
+ )
113
+ spillover = len(output_ints) % 4
114
+ if spillover > 0:
115
+ output_ints.extend([_ORD_OF_EQUALS for _ in range(4 - spillover)])
116
+ if newline:
117
+ output_ints.append(_ORD_OF_NEWLINE)
118
+ return SymbolicBytes(output_ints)
119
+
120
+
121
+ def _a2b_base64(data, /, *, strict_mode: bool = False):
122
+ data = make_bytes(data)
123
+ input_ints, padding_count = (
124
+ _DECODE_MAPPER_BASE64_STRICT if strict_mode else _DECODE_MAPPER_BASE64
125
+ )(data)
126
+
127
+ data_char_count = len(input_ints)
128
+ uneven = data_char_count % 4 != 0
129
+ if uneven:
130
+ if data_char_count % 4 == 1:
131
+ raise binascii.Error(
132
+ f"Invalid base64-encoded string: number of data characters ({len(input_ints)}) cannot be 1 more than a multiple of 4"
133
+ )
134
+ expected_padding = 4 - (data_char_count % 4)
135
+ if padding_count < expected_padding:
136
+ raise binascii.Error("Incorrect padding")
137
+ elif strict_mode and padding_count > expected_padding:
138
+ raise binascii.Error("Excess data after padding")
139
+ output_ints = [
140
+ byt for byt in _bit_chunk_iter(input_ints, input_bit_size=6, output_bit_size=8)
141
+ ]
142
+ if uneven:
143
+ output_ints = output_ints[:-1]
144
+ return SymbolicBytes(output_ints)
145
+
146
+
147
+ def make_registrations():
148
+ # NOTE: these power the base64 module, so we get that for free
149
+ register_patch(binascii.b2a_base64, _b2a_base64)
150
+ register_patch(binascii.a2b_base64, _a2b_base64)
@@ -0,0 +1,23 @@
1
+ import bisect
2
+ from typing import List
3
+
4
+ from crosshair.core_and_libs import proxy_for_type, standalone_statespace
5
+ from crosshair.tracers import NoTracing
6
+
7
+ # NOTE: We don't patch anything in bisect, but it has lgic written in C, so make sure it
8
+ # works with symbolics.
9
+
10
+
11
+ def test_bisect_left():
12
+ with standalone_statespace as space:
13
+ with NoTracing():
14
+ lst = proxy_for_type(List[int], "lst")
15
+ x = proxy_for_type(int, "x")
16
+ space.add(lst.__len__() == 2)
17
+ space.add(lst[0] < 10)
18
+ space.add(lst[1] > 20)
19
+ space.add(x >= 10)
20
+ space.add(x <= 20)
21
+ assert bisect.bisect_left(lst, x) == 1
22
+ assert bisect.bisect_left([0, 100], x) == 1
23
+ assert bisect.bisect_left(lst, 15) == 1