coretrace-python-analyzer 0.1.0__py3-none-any.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.
- coretrace_python/__init__.py +4 -0
- coretrace_python/__main__.py +4 -0
- coretrace_python/abstract/__init__.py +45 -0
- coretrace_python/abstract/constants.py +226 -0
- coretrace_python/abstract/heap.py +252 -0
- coretrace_python/abstract/ranges.py +285 -0
- coretrace_python/abstract/values.py +56 -0
- coretrace_python/analysis/__init__.py +31 -0
- coretrace_python/analysis/manager.py +165 -0
- coretrace_python/analysis/provider.py +73 -0
- coretrace_python/bundled/dependency/dependency_policy/dependency_policy.py +46 -0
- coretrace_python/bundled/dependency/dependency_policy/plugin.toml +9 -0
- coretrace_python/bundled/dependency/reachable_vulnerability/plugin.toml +9 -0
- coretrace_python/bundled/dependency/reachable_vulnerability/reachable_vulnerability.py +56 -0
- coretrace_python/bundled/dependency/sample_advisories/plugin.toml +9 -0
- coretrace_python/bundled/dependency/sample_advisories/sample_advisories.py +109 -0
- coretrace_python/bundled/dependency/vulnerable_dependency/plugin.toml +9 -0
- coretrace_python/bundled/dependency/vulnerable_dependency/vulnerable_dependency.py +43 -0
- coretrace_python/bundled/models/cli/cli_models.py +35 -0
- coretrace_python/bundled/models/cli/plugin.toml +9 -0
- coretrace_python/bundled/models/credentials/credential_models.py +43 -0
- coretrace_python/bundled/models/credentials/plugin.toml +9 -0
- coretrace_python/bundled/models/django/django_models.py +123 -0
- coretrace_python/bundled/models/django/plugin.toml +9 -0
- coretrace_python/bundled/models/fastapi/fastapi_models.py +29 -0
- coretrace_python/bundled/models/fastapi/plugin.toml +9 -0
- coretrace_python/bundled/models/flask/flask_models.py +53 -0
- coretrace_python/bundled/models/flask/plugin.toml +9 -0
- coretrace_python/bundled/models/http_clients/http_client_models.py +43 -0
- coretrace_python/bundled/models/http_clients/plugin.toml +9 -0
- coretrace_python/bundled/models/python_stdlib/plugin.toml +9 -0
- coretrace_python/bundled/models/python_stdlib/python_stdlib.py +68 -0
- coretrace_python/bundled/models/sqlalchemy/plugin.toml +9 -0
- coretrace_python/bundled/models/sqlalchemy/sqlalchemy_models.py +47 -0
- coretrace_python/bundled/secrets/config_secrets/config_secrets.py +38 -0
- coretrace_python/bundled/secrets/config_secrets/plugin.toml +9 -0
- coretrace_python/bundled/secrets/hardcoded_secrets/hardcoded_secrets.py +19 -0
- coretrace_python/bundled/secrets/hardcoded_secrets/plugin.toml +9 -0
- coretrace_python/bundled/security/command_injection/command_injection.py +17 -0
- coretrace_python/bundled/security/command_injection/plugin.toml +9 -0
- coretrace_python/bundled/security/insecure_deserialization/insecure_deserialization.py +17 -0
- coretrace_python/bundled/security/insecure_deserialization/plugin.toml +9 -0
- coretrace_python/bundled/security/open_redirect/open_redirect.py +17 -0
- coretrace_python/bundled/security/open_redirect/plugin.toml +9 -0
- coretrace_python/bundled/security/path_traversal/path_traversal.py +17 -0
- coretrace_python/bundled/security/path_traversal/plugin.toml +9 -0
- coretrace_python/bundled/security/plaintext_credentials/plaintext_credentials.py +21 -0
- coretrace_python/bundled/security/plaintext_credentials/plugin.toml +9 -0
- coretrace_python/bundled/security/sql_injection/plugin.toml +9 -0
- coretrace_python/bundled/security/sql_injection/sql_injection.py +17 -0
- coretrace_python/bundled/security/ssrf/plugin.toml +9 -0
- coretrace_python/bundled/security/ssrf/ssrf.py +17 -0
- coretrace_python/bundled/security/xss/plugin.toml +9 -0
- coretrace_python/bundled/security/xss/xss.py +17 -0
- coretrace_python/bundled/syntax/dangerous_eval/dangerous_eval.py +19 -0
- coretrace_python/bundled/syntax/dangerous_eval/plugin.toml +9 -0
- coretrace_python/bundled/syntax/flask_debug/flask_debug.py +63 -0
- coretrace_python/bundled/syntax/flask_debug/plugin.toml +9 -0
- coretrace_python/bundled/syntax/missing_timeout/missing_timeout.py +51 -0
- coretrace_python/bundled/syntax/missing_timeout/plugin.toml +9 -0
- coretrace_python/bundled/syntax/weak_crypto/plugin.toml +9 -0
- coretrace_python/bundled/syntax/weak_crypto/weak_crypto.py +19 -0
- coretrace_python/cache.py +310 -0
- coretrace_python/cfg/__init__.py +46 -0
- coretrace_python/cfg/builder.py +589 -0
- coretrace_python/cfg/dominance.py +183 -0
- coretrace_python/cfg/model.py +166 -0
- coretrace_python/cli.py +216 -0
- coretrace_python/dataflow/__init__.py +29 -0
- coretrace_python/dataflow/lattice.py +78 -0
- coretrace_python/dataflow/solver.py +96 -0
- coretrace_python/dependency/__init__.py +44 -0
- coretrace_python/dependency/advisories.py +168 -0
- coretrace_python/dependency/correlation.py +87 -0
- coretrace_python/dependency/graph.py +274 -0
- coretrace_python/dependency/policy.py +65 -0
- coretrace_python/dependency/sbom.py +65 -0
- coretrace_python/engine.py +688 -0
- coretrace_python/findings/__init__.py +13 -0
- coretrace_python/findings/coverage.py +45 -0
- coretrace_python/findings/model.py +49 -0
- coretrace_python/findings/refutation.py +427 -0
- coretrace_python/frontend/__init__.py +18 -0
- coretrace_python/frontend/ast_adapter.py +447 -0
- coretrace_python/frontend/parser.py +23 -0
- coretrace_python/hir/__init__.py +5 -0
- coretrace_python/hir/nodes.py +584 -0
- coretrace_python/hir/visitors.py +36 -0
- coretrace_python/interprocedural/__init__.py +49 -0
- coretrace_python/interprocedural/callgraph.py +291 -0
- coretrace_python/interprocedural/modulegraph.py +218 -0
- coretrace_python/interprocedural/summaries.py +463 -0
- coretrace_python/ir/__init__.py +5 -0
- coretrace_python/ir/defuse.py +74 -0
- coretrace_python/ir/lowering.py +575 -0
- coretrace_python/ir/model.py +481 -0
- coretrace_python/ir/printer.py +201 -0
- coretrace_python/ir/ssa.py +277 -0
- coretrace_python/plugins/__init__.py +58 -0
- coretrace_python/plugins/api.py +153 -0
- coretrace_python/plugins/detectors.py +114 -0
- coretrace_python/plugins/loader.py +84 -0
- coretrace_python/plugins/manifest.py +112 -0
- coretrace_python/plugins/registry.py +34 -0
- coretrace_python/plugins/secrets.py +330 -0
- coretrace_python/reporters/__init__.py +22 -0
- coretrace_python/reporters/json_format.py +48 -0
- coretrace_python/reporters/report.py +23 -0
- coretrace_python/reporters/sarif.py +70 -0
- coretrace_python/reporters/text.py +24 -0
- coretrace_python/semantic/__init__.py +9 -0
- coretrace_python/semantic/identity.py +39 -0
- coretrace_python/semantic/imports.py +131 -0
- coretrace_python/semantic/scopes.py +473 -0
- coretrace_python/semantic/symbols.py +87 -0
- coretrace_python/source/__init__.py +13 -0
- coretrace_python/source/manager.py +81 -0
- coretrace_python/source/model.py +57 -0
- coretrace_python/taint/__init__.py +55 -0
- coretrace_python/taint/engine.py +800 -0
- coretrace_python/taint/models.py +317 -0
- coretrace_python/taint/routes.py +99 -0
- coretrace_python_analyzer-0.1.0.dist-info/METADATA +74 -0
- coretrace_python_analyzer-0.1.0.dist-info/RECORD +126 -0
- coretrace_python_analyzer-0.1.0.dist-info/WHEEL +4 -0
- coretrace_python_analyzer-0.1.0.dist-info/entry_points.txt +2 -0
|
@@ -0,0 +1,584 @@
|
|
|
1
|
+
"""Immutable nodes for the Python high-level intermediate representation."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import TypeAlias
|
|
7
|
+
|
|
8
|
+
from coretrace_python.source import SourceSpan
|
|
9
|
+
|
|
10
|
+
HIR_SCHEMA_VERSION = 1
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass(frozen=True, slots=True)
|
|
14
|
+
class Name:
|
|
15
|
+
identifier: str
|
|
16
|
+
span: SourceSpan
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dataclass(frozen=True, slots=True)
|
|
20
|
+
class Constant:
|
|
21
|
+
value: object
|
|
22
|
+
span: SourceSpan
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass(frozen=True, slots=True)
|
|
26
|
+
class BinaryOp:
|
|
27
|
+
operator: str
|
|
28
|
+
left: Expression
|
|
29
|
+
right: Expression
|
|
30
|
+
span: SourceSpan
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@dataclass(frozen=True, slots=True)
|
|
34
|
+
class UnaryOp:
|
|
35
|
+
operator: str
|
|
36
|
+
operand: Expression
|
|
37
|
+
span: SourceSpan
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@dataclass(frozen=True, slots=True)
|
|
41
|
+
class BoolOp:
|
|
42
|
+
"""``and`` / ``or`` over two or more values; chained comparisons lower to ``and``."""
|
|
43
|
+
|
|
44
|
+
operator: str
|
|
45
|
+
values: tuple[Expression, ...]
|
|
46
|
+
span: SourceSpan
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@dataclass(frozen=True, slots=True)
|
|
50
|
+
class Compare:
|
|
51
|
+
operator: str
|
|
52
|
+
left: Expression
|
|
53
|
+
right: Expression
|
|
54
|
+
span: SourceSpan
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@dataclass(frozen=True, slots=True)
|
|
58
|
+
class Attribute:
|
|
59
|
+
value: Expression
|
|
60
|
+
name: str
|
|
61
|
+
span: SourceSpan
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@dataclass(frozen=True, slots=True)
|
|
65
|
+
class Subscript:
|
|
66
|
+
value: Expression
|
|
67
|
+
key: Expression
|
|
68
|
+
span: SourceSpan
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@dataclass(frozen=True, slots=True)
|
|
72
|
+
class Keyword:
|
|
73
|
+
"""A keyword argument; ``name`` is ``None`` for ``**mapping`` unpacking."""
|
|
74
|
+
|
|
75
|
+
name: str | None
|
|
76
|
+
value: Expression
|
|
77
|
+
span: SourceSpan
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
@dataclass(frozen=True, slots=True)
|
|
81
|
+
class Call:
|
|
82
|
+
callee: Expression
|
|
83
|
+
arguments: tuple[Expression, ...]
|
|
84
|
+
keywords: tuple[Keyword, ...]
|
|
85
|
+
span: SourceSpan
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
@dataclass(frozen=True, slots=True)
|
|
89
|
+
class Tuple:
|
|
90
|
+
elements: tuple[Expression, ...]
|
|
91
|
+
span: SourceSpan
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
@dataclass(frozen=True, slots=True)
|
|
95
|
+
class List:
|
|
96
|
+
elements: tuple[Expression, ...]
|
|
97
|
+
span: SourceSpan
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
@dataclass(frozen=True, slots=True)
|
|
101
|
+
class Dict:
|
|
102
|
+
"""Items are ``(key, value)``; a ``None`` key is a ``**mapping`` unpacking."""
|
|
103
|
+
|
|
104
|
+
items: tuple[tuple[Expression | None, Expression], ...]
|
|
105
|
+
span: SourceSpan
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
@dataclass(frozen=True, slots=True)
|
|
109
|
+
class FormattedString:
|
|
110
|
+
"""An f-string: constant text and formatted expressions, in order. Conversions and
|
|
111
|
+
format specifications are dropped; expressions nested in a specification are parts."""
|
|
112
|
+
|
|
113
|
+
parts: tuple[Expression, ...]
|
|
114
|
+
span: SourceSpan
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
@dataclass(frozen=True, slots=True)
|
|
118
|
+
class Slice:
|
|
119
|
+
lower: Expression | None
|
|
120
|
+
upper: Expression | None
|
|
121
|
+
step: Expression | None
|
|
122
|
+
span: SourceSpan
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
@dataclass(frozen=True, slots=True)
|
|
126
|
+
class Starred:
|
|
127
|
+
"""``*iterable`` in a call argument list or a list or tuple display."""
|
|
128
|
+
|
|
129
|
+
value: Expression
|
|
130
|
+
span: SourceSpan
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
@dataclass(frozen=True, slots=True)
|
|
134
|
+
class Set:
|
|
135
|
+
elements: tuple[Expression, ...]
|
|
136
|
+
span: SourceSpan
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
@dataclass(frozen=True, slots=True)
|
|
140
|
+
class Conditional:
|
|
141
|
+
"""``body if test else orelse``; the CFG builder lays it out as a branch."""
|
|
142
|
+
|
|
143
|
+
test: Expression
|
|
144
|
+
body: Expression
|
|
145
|
+
orelse: Expression
|
|
146
|
+
span: SourceSpan
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
@dataclass(frozen=True, slots=True)
|
|
150
|
+
class Lambda:
|
|
151
|
+
"""An anonymous function; its body is a scope of its own and is not lowered."""
|
|
152
|
+
|
|
153
|
+
parameters: tuple[Parameter, ...]
|
|
154
|
+
body: Expression
|
|
155
|
+
span: SourceSpan
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
@dataclass(frozen=True, slots=True)
|
|
159
|
+
class Await:
|
|
160
|
+
value: Expression
|
|
161
|
+
span: SourceSpan
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
@dataclass(frozen=True, slots=True)
|
|
165
|
+
class Yield:
|
|
166
|
+
value: Expression | None
|
|
167
|
+
span: SourceSpan
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
@dataclass(frozen=True, slots=True)
|
|
171
|
+
class ComprehensionGenerator:
|
|
172
|
+
"""One ``for target in iterable if condition...`` clause of a comprehension."""
|
|
173
|
+
|
|
174
|
+
target: Target
|
|
175
|
+
iterable: Expression
|
|
176
|
+
conditions: tuple[Expression, ...]
|
|
177
|
+
span: SourceSpan
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
@dataclass(frozen=True, slots=True)
|
|
181
|
+
class Comprehension:
|
|
182
|
+
"""A list, set, dict or generator comprehension; ``kind`` names which one. A dict
|
|
183
|
+
comprehension's ``element`` is the value and ``key`` its key."""
|
|
184
|
+
|
|
185
|
+
kind: str
|
|
186
|
+
element: Expression
|
|
187
|
+
generators: tuple[ComprehensionGenerator, ...]
|
|
188
|
+
span: SourceSpan
|
|
189
|
+
key: Expression | None = None
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
Expression: TypeAlias = (
|
|
193
|
+
Name
|
|
194
|
+
| Constant
|
|
195
|
+
| BinaryOp
|
|
196
|
+
| UnaryOp
|
|
197
|
+
| BoolOp
|
|
198
|
+
| Compare
|
|
199
|
+
| Attribute
|
|
200
|
+
| Subscript
|
|
201
|
+
| Call
|
|
202
|
+
| Tuple
|
|
203
|
+
| List
|
|
204
|
+
| Dict
|
|
205
|
+
| FormattedString
|
|
206
|
+
| Slice
|
|
207
|
+
| Starred
|
|
208
|
+
| Set
|
|
209
|
+
| Conditional
|
|
210
|
+
| Lambda
|
|
211
|
+
| Await
|
|
212
|
+
| Yield
|
|
213
|
+
| Comprehension
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
Target: TypeAlias = Name | Attribute | Subscript | Tuple
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
@dataclass(frozen=True, slots=True)
|
|
220
|
+
class Parameter:
|
|
221
|
+
"""``kind`` is ``positional``, ``keyword``, ``var_positional`` or ``var_keyword``.
|
|
222
|
+
``annotation`` is kept when it is an expression the HIR can represent."""
|
|
223
|
+
|
|
224
|
+
name: str
|
|
225
|
+
span: SourceSpan
|
|
226
|
+
default: Expression | None = None
|
|
227
|
+
kind: str = "positional"
|
|
228
|
+
annotation: Expression | None = None
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
@dataclass(frozen=True, slots=True)
|
|
232
|
+
class Assign:
|
|
233
|
+
target: Target
|
|
234
|
+
value: Expression
|
|
235
|
+
span: SourceSpan
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
@dataclass(frozen=True, slots=True)
|
|
239
|
+
class AugAssign:
|
|
240
|
+
target: Name | Attribute | Subscript
|
|
241
|
+
operator: str
|
|
242
|
+
value: Expression
|
|
243
|
+
span: SourceSpan
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
@dataclass(frozen=True, slots=True)
|
|
247
|
+
class Return:
|
|
248
|
+
value: Expression | None
|
|
249
|
+
span: SourceSpan
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
@dataclass(frozen=True, slots=True)
|
|
253
|
+
class ExpressionStatement:
|
|
254
|
+
expression: Expression
|
|
255
|
+
span: SourceSpan
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
@dataclass(frozen=True, slots=True)
|
|
259
|
+
class Pass:
|
|
260
|
+
span: SourceSpan
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
@dataclass(frozen=True, slots=True)
|
|
264
|
+
class Delete:
|
|
265
|
+
targets: tuple[Target, ...]
|
|
266
|
+
span: SourceSpan
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
@dataclass(frozen=True, slots=True)
|
|
270
|
+
class Declaration:
|
|
271
|
+
"""``name: annotation`` without a value: a dataclass field or an annotated local."""
|
|
272
|
+
|
|
273
|
+
name: str
|
|
274
|
+
annotation: Expression | None
|
|
275
|
+
span: SourceSpan
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
@dataclass(frozen=True, slots=True)
|
|
279
|
+
class ValuePattern:
|
|
280
|
+
"""``case <expression>``: equality with a value."""
|
|
281
|
+
|
|
282
|
+
value: Expression
|
|
283
|
+
span: SourceSpan
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
@dataclass(frozen=True, slots=True)
|
|
287
|
+
class SingletonPattern:
|
|
288
|
+
"""``case None`` / ``True`` / ``False``: identity with a singleton."""
|
|
289
|
+
|
|
290
|
+
value: object
|
|
291
|
+
span: SourceSpan
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
@dataclass(frozen=True, slots=True)
|
|
295
|
+
class WildcardPattern:
|
|
296
|
+
span: SourceSpan
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
@dataclass(frozen=True, slots=True)
|
|
300
|
+
class CapturePattern:
|
|
301
|
+
"""``case name`` or ``case <pattern> as name``: binds the subject."""
|
|
302
|
+
|
|
303
|
+
name: str
|
|
304
|
+
pattern: Pattern | None
|
|
305
|
+
span: SourceSpan
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
@dataclass(frozen=True, slots=True)
|
|
309
|
+
class OrPattern:
|
|
310
|
+
alternatives: tuple[Pattern, ...]
|
|
311
|
+
span: SourceSpan
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
@dataclass(frozen=True, slots=True)
|
|
315
|
+
class StarPattern:
|
|
316
|
+
"""``*rest`` inside a sequence pattern; ``name`` is ``None`` for ``*_``."""
|
|
317
|
+
|
|
318
|
+
name: str | None
|
|
319
|
+
span: SourceSpan
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
@dataclass(frozen=True, slots=True)
|
|
323
|
+
class SequencePattern:
|
|
324
|
+
patterns: tuple[Pattern, ...]
|
|
325
|
+
span: SourceSpan
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
@dataclass(frozen=True, slots=True)
|
|
329
|
+
class MappingPattern:
|
|
330
|
+
"""``{key: pattern, ..., **rest}``; keys are expressions, ``rest`` a name or ``None``."""
|
|
331
|
+
|
|
332
|
+
keys: tuple[Expression, ...]
|
|
333
|
+
patterns: tuple[Pattern, ...]
|
|
334
|
+
rest: str | None
|
|
335
|
+
span: SourceSpan
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
@dataclass(frozen=True, slots=True)
|
|
339
|
+
class ClassPattern:
|
|
340
|
+
"""``Cls(p, ..., name=pattern, ...)``: positional sub-patterns need the class's
|
|
341
|
+
``__match_args__``; keyword ones match attributes."""
|
|
342
|
+
|
|
343
|
+
cls: Expression
|
|
344
|
+
patterns: tuple[Pattern, ...]
|
|
345
|
+
keyword_names: tuple[str, ...]
|
|
346
|
+
keyword_patterns: tuple[Pattern, ...]
|
|
347
|
+
span: SourceSpan
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
@dataclass(frozen=True, slots=True)
|
|
351
|
+
class UnsupportedPattern:
|
|
352
|
+
"""A pattern the HIR does not represent; the CFG builder reports it."""
|
|
353
|
+
|
|
354
|
+
kind: str
|
|
355
|
+
span: SourceSpan
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
Pattern: TypeAlias = (
|
|
359
|
+
ValuePattern
|
|
360
|
+
| SingletonPattern
|
|
361
|
+
| WildcardPattern
|
|
362
|
+
| CapturePattern
|
|
363
|
+
| OrPattern
|
|
364
|
+
| StarPattern
|
|
365
|
+
| SequencePattern
|
|
366
|
+
| MappingPattern
|
|
367
|
+
| ClassPattern
|
|
368
|
+
| UnsupportedPattern
|
|
369
|
+
)
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
@dataclass(frozen=True, slots=True)
|
|
373
|
+
class MatchCase:
|
|
374
|
+
pattern: Pattern
|
|
375
|
+
guard: Expression | None
|
|
376
|
+
body: tuple[Statement, ...]
|
|
377
|
+
span: SourceSpan
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
@dataclass(frozen=True, slots=True)
|
|
381
|
+
class Match:
|
|
382
|
+
"""``match subject:``; the CFG builder lays it out as an ``if`` chain."""
|
|
383
|
+
|
|
384
|
+
subject: Expression
|
|
385
|
+
cases: tuple[MatchCase, ...]
|
|
386
|
+
span: SourceSpan
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
@dataclass(frozen=True, slots=True)
|
|
390
|
+
class Assert:
|
|
391
|
+
test: Expression
|
|
392
|
+
message: Expression | None
|
|
393
|
+
span: SourceSpan
|
|
394
|
+
|
|
395
|
+
|
|
396
|
+
@dataclass(frozen=True, slots=True)
|
|
397
|
+
class If:
|
|
398
|
+
condition: Expression
|
|
399
|
+
body: tuple[Statement, ...]
|
|
400
|
+
orelse: tuple[Statement, ...]
|
|
401
|
+
span: SourceSpan
|
|
402
|
+
|
|
403
|
+
|
|
404
|
+
@dataclass(frozen=True, slots=True)
|
|
405
|
+
class While:
|
|
406
|
+
condition: Expression
|
|
407
|
+
body: tuple[Statement, ...]
|
|
408
|
+
span: SourceSpan
|
|
409
|
+
orelse: tuple[Statement, ...] = ()
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+
@dataclass(frozen=True, slots=True)
|
|
413
|
+
class For:
|
|
414
|
+
target: Name
|
|
415
|
+
iterable: Expression
|
|
416
|
+
body: tuple[Statement, ...]
|
|
417
|
+
is_async: bool
|
|
418
|
+
span: SourceSpan
|
|
419
|
+
orelse: tuple[Statement, ...] = ()
|
|
420
|
+
|
|
421
|
+
|
|
422
|
+
@dataclass(frozen=True, slots=True)
|
|
423
|
+
class Break:
|
|
424
|
+
span: SourceSpan
|
|
425
|
+
|
|
426
|
+
|
|
427
|
+
@dataclass(frozen=True, slots=True)
|
|
428
|
+
class Continue:
|
|
429
|
+
span: SourceSpan
|
|
430
|
+
|
|
431
|
+
|
|
432
|
+
@dataclass(frozen=True, slots=True)
|
|
433
|
+
class Raise:
|
|
434
|
+
exception: Expression | None
|
|
435
|
+
span: SourceSpan
|
|
436
|
+
cause: Expression | None = None
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
@dataclass(frozen=True, slots=True)
|
|
440
|
+
class WithItem:
|
|
441
|
+
context: Expression
|
|
442
|
+
target: Name | None
|
|
443
|
+
span: SourceSpan
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
@dataclass(frozen=True, slots=True)
|
|
447
|
+
class With:
|
|
448
|
+
items: tuple[WithItem, ...]
|
|
449
|
+
body: tuple[Statement, ...]
|
|
450
|
+
is_async: bool
|
|
451
|
+
span: SourceSpan
|
|
452
|
+
|
|
453
|
+
|
|
454
|
+
@dataclass(frozen=True, slots=True)
|
|
455
|
+
class EnterWith:
|
|
456
|
+
"""Synthetic statement the CFG builder emits when a ``with`` body starts."""
|
|
457
|
+
|
|
458
|
+
item: WithItem
|
|
459
|
+
span: SourceSpan
|
|
460
|
+
|
|
461
|
+
|
|
462
|
+
@dataclass(frozen=True, slots=True)
|
|
463
|
+
class ExitWith:
|
|
464
|
+
"""Synthetic statement the CFG builder emits when a ``with`` body falls through."""
|
|
465
|
+
|
|
466
|
+
item: WithItem
|
|
467
|
+
span: SourceSpan
|
|
468
|
+
|
|
469
|
+
|
|
470
|
+
@dataclass(frozen=True, slots=True)
|
|
471
|
+
class ExceptHandler:
|
|
472
|
+
"""``except type as name:``; ``type`` is ``None`` for a bare ``except``."""
|
|
473
|
+
|
|
474
|
+
type: Expression | None
|
|
475
|
+
name: str | None
|
|
476
|
+
body: tuple[Statement, ...]
|
|
477
|
+
span: SourceSpan
|
|
478
|
+
|
|
479
|
+
|
|
480
|
+
@dataclass(frozen=True, slots=True)
|
|
481
|
+
class Try:
|
|
482
|
+
body: tuple[Statement, ...]
|
|
483
|
+
handlers: tuple[ExceptHandler, ...]
|
|
484
|
+
orelse: tuple[Statement, ...]
|
|
485
|
+
finalbody: tuple[Statement, ...]
|
|
486
|
+
span: SourceSpan
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
@dataclass(frozen=True, slots=True)
|
|
490
|
+
class EnterHandler:
|
|
491
|
+
"""Synthetic statement the CFG builder emits at the start of a handler block."""
|
|
492
|
+
|
|
493
|
+
handler: ExceptHandler
|
|
494
|
+
span: SourceSpan
|
|
495
|
+
|
|
496
|
+
|
|
497
|
+
@dataclass(frozen=True, slots=True)
|
|
498
|
+
class ImportAlias:
|
|
499
|
+
name: str
|
|
500
|
+
as_name: str | None
|
|
501
|
+
span: SourceSpan
|
|
502
|
+
|
|
503
|
+
|
|
504
|
+
@dataclass(frozen=True, slots=True)
|
|
505
|
+
class Import:
|
|
506
|
+
names: tuple[ImportAlias, ...]
|
|
507
|
+
span: SourceSpan
|
|
508
|
+
|
|
509
|
+
|
|
510
|
+
@dataclass(frozen=True, slots=True)
|
|
511
|
+
class ImportFrom:
|
|
512
|
+
module: str | None
|
|
513
|
+
names: tuple[ImportAlias, ...]
|
|
514
|
+
level: int
|
|
515
|
+
span: SourceSpan
|
|
516
|
+
|
|
517
|
+
|
|
518
|
+
@dataclass(frozen=True, slots=True)
|
|
519
|
+
class Global:
|
|
520
|
+
names: tuple[str, ...]
|
|
521
|
+
span: SourceSpan
|
|
522
|
+
|
|
523
|
+
|
|
524
|
+
@dataclass(frozen=True, slots=True)
|
|
525
|
+
class Nonlocal:
|
|
526
|
+
names: tuple[str, ...]
|
|
527
|
+
span: SourceSpan
|
|
528
|
+
|
|
529
|
+
|
|
530
|
+
@dataclass(frozen=True, slots=True)
|
|
531
|
+
class Function:
|
|
532
|
+
name: str
|
|
533
|
+
parameters: tuple[Parameter, ...]
|
|
534
|
+
body: tuple[Statement, ...]
|
|
535
|
+
is_async: bool
|
|
536
|
+
span: SourceSpan
|
|
537
|
+
decorators: tuple[Expression, ...] = ()
|
|
538
|
+
|
|
539
|
+
|
|
540
|
+
@dataclass(frozen=True, slots=True)
|
|
541
|
+
class Class:
|
|
542
|
+
name: str
|
|
543
|
+
bases: tuple[Expression, ...]
|
|
544
|
+
body: tuple[Statement, ...]
|
|
545
|
+
span: SourceSpan
|
|
546
|
+
decorators: tuple[Expression, ...] = ()
|
|
547
|
+
|
|
548
|
+
|
|
549
|
+
Statement: TypeAlias = (
|
|
550
|
+
Assign
|
|
551
|
+
| AugAssign
|
|
552
|
+
| Return
|
|
553
|
+
| ExpressionStatement
|
|
554
|
+
| Pass
|
|
555
|
+
| Delete
|
|
556
|
+
| Match
|
|
557
|
+
| Declaration
|
|
558
|
+
| Assert
|
|
559
|
+
| If
|
|
560
|
+
| While
|
|
561
|
+
| For
|
|
562
|
+
| Break
|
|
563
|
+
| Continue
|
|
564
|
+
| Raise
|
|
565
|
+
| With
|
|
566
|
+
| EnterWith
|
|
567
|
+
| ExitWith
|
|
568
|
+
| Try
|
|
569
|
+
| EnterHandler
|
|
570
|
+
| Import
|
|
571
|
+
| ImportFrom
|
|
572
|
+
| Global
|
|
573
|
+
| Nonlocal
|
|
574
|
+
| Function
|
|
575
|
+
| Class
|
|
576
|
+
)
|
|
577
|
+
|
|
578
|
+
|
|
579
|
+
@dataclass(frozen=True, slots=True)
|
|
580
|
+
class Module:
|
|
581
|
+
name: str
|
|
582
|
+
body: tuple[Statement, ...]
|
|
583
|
+
span: SourceSpan
|
|
584
|
+
is_package: bool = False
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"""Generic traversal helpers over PyHIR nodes."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Iterator
|
|
6
|
+
from dataclasses import fields
|
|
7
|
+
|
|
8
|
+
from coretrace_python.hir import nodes
|
|
9
|
+
|
|
10
|
+
Node = (
|
|
11
|
+
nodes.Statement
|
|
12
|
+
| nodes.Expression
|
|
13
|
+
| nodes.ComprehensionGenerator
|
|
14
|
+
| nodes.Keyword
|
|
15
|
+
| nodes.WithItem
|
|
16
|
+
| nodes.Parameter
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def children(node: Node) -> Iterator[Node]:
|
|
21
|
+
"""Yield the direct child nodes of ``node`` in source order."""
|
|
22
|
+
|
|
23
|
+
for field in fields(node):
|
|
24
|
+
yield from _nodes_in(getattr(node, field.name))
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _nodes_in(value: object) -> Iterator[Node]:
|
|
28
|
+
if _is_node(value):
|
|
29
|
+
yield value # type: ignore[misc]
|
|
30
|
+
elif isinstance(value, tuple):
|
|
31
|
+
for item in value:
|
|
32
|
+
yield from _nodes_in(item)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _is_node(value: object) -> bool:
|
|
36
|
+
return hasattr(value, "span") and not isinstance(value, nodes.ImportAlias)
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"""Call graph and function summaries (architecture §19, §20)."""
|
|
2
|
+
|
|
3
|
+
from coretrace_python.interprocedural.callgraph import (
|
|
4
|
+
CallGraph,
|
|
5
|
+
CallGraphAnalysis,
|
|
6
|
+
CallSite,
|
|
7
|
+
ExternalSymbol,
|
|
8
|
+
KnownFunction,
|
|
9
|
+
Target,
|
|
10
|
+
UnknownTarget,
|
|
11
|
+
)
|
|
12
|
+
from coretrace_python.interprocedural.modulegraph import (
|
|
13
|
+
ModuleGraph,
|
|
14
|
+
build_module_graph,
|
|
15
|
+
discover_files,
|
|
16
|
+
discover_sources,
|
|
17
|
+
project_symbol,
|
|
18
|
+
)
|
|
19
|
+
from coretrace_python.interprocedural.summaries import (
|
|
20
|
+
ExternalCall,
|
|
21
|
+
FunctionSummary,
|
|
22
|
+
Mutation,
|
|
23
|
+
ProjectSummaries,
|
|
24
|
+
SummaryAnalysis,
|
|
25
|
+
SummaryIndex,
|
|
26
|
+
SummaryTable,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
__all__ = [
|
|
30
|
+
"CallGraph",
|
|
31
|
+
"CallGraphAnalysis",
|
|
32
|
+
"CallSite",
|
|
33
|
+
"ExternalCall",
|
|
34
|
+
"ExternalSymbol",
|
|
35
|
+
"FunctionSummary",
|
|
36
|
+
"KnownFunction",
|
|
37
|
+
"ModuleGraph",
|
|
38
|
+
"Mutation",
|
|
39
|
+
"ProjectSummaries",
|
|
40
|
+
"SummaryAnalysis",
|
|
41
|
+
"SummaryIndex",
|
|
42
|
+
"SummaryTable",
|
|
43
|
+
"Target",
|
|
44
|
+
"UnknownTarget",
|
|
45
|
+
"build_module_graph",
|
|
46
|
+
"discover_files",
|
|
47
|
+
"discover_sources",
|
|
48
|
+
"project_symbol",
|
|
49
|
+
]
|