coretrace-python-analyzer 0.16.0__py3-none-any.whl → 0.17.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.
@@ -1,4 +1,4 @@
1
1
  """CoreTrace's Python static analysis frontend."""
2
2
 
3
- __version__ = "0.16.0"
3
+ __version__ = "0.17.0"
4
4
 
@@ -80,6 +80,7 @@ from coretrace_python.interprocedural import (
80
80
  ModuleFunction,
81
81
  ModuleGraph,
82
82
  ProjectSummaries,
83
+ SignaturesAnalysis,
83
84
  SummaryAnalysis,
84
85
  SummaryIndex,
85
86
  SymbolRead,
@@ -164,6 +165,7 @@ ALL_ANALYSES: tuple[AnyAnalysis, ...] = (
164
165
  EscapedTemplates,
165
166
  ClearingAnalysis,
166
167
  TemplateCallsAnalysis,
168
+ SignaturesAnalysis,
167
169
  )
168
170
 
169
171
 
@@ -205,6 +207,7 @@ class ResultsEvicted(TransformationPass):
205
207
  EscapedTemplates,
206
208
  ClearingAnalysis,
207
209
  TemplateCallsAnalysis,
210
+ SignaturesAnalysis,
208
211
  }
209
212
  )
210
213
 
@@ -268,6 +271,7 @@ def build_manager(
268
271
  table = (models or SecurityModelRegistry()).freeze()
269
272
  manager.provide(SecurityModelAnalysis, table)
270
273
  manager.provide(MembersAnalysis, table.members_by_class())
274
+ manager.provide(SignaturesAnalysis, table.signatures())
271
275
  manager.provide(ClearingAnalysis, table.clearing())
272
276
  manager.provide(ProjectSummaries, SummaryIndex())
273
277
  manager.provide(RegisteredRoutes, _routes_of(manager))
@@ -323,6 +327,7 @@ def analyze_file(source: SourceFile, plugin_roots: Sequence[Path]) -> FileAnalys
323
327
  table = plugin_models(loaded.plugin for loaded in registry)
324
328
  manager.provide(SecurityModelAnalysis, table)
325
329
  manager.provide(MembersAnalysis, table.members_by_class())
330
+ manager.provide(SignaturesAnalysis, table.signatures())
326
331
  manager.provide(ClearingAnalysis, table.clearing())
327
332
  manager.provide(ProjectSummaries, SummaryIndex())
328
333
  manager.provide(RegisteredRoutes, _routes_of(manager))
@@ -418,6 +423,7 @@ def analyze_project(
418
423
  for manager in managers.values():
419
424
  manager.provide(SecurityModelAnalysis, models)
420
425
  manager.provide(MembersAnalysis, members)
426
+ manager.provide(SignaturesAnalysis, models.signatures())
421
427
  manager.provide(DependencyAnalysis, dependencies)
422
428
 
423
429
  imports: dict[str, ImportTable] = {}
@@ -730,6 +736,7 @@ def _analyse_batch(batch: _Batch) -> dict[str, dict[str, Any]]:
730
736
  for manager in managers.values():
731
737
  manager.provide(SecurityModelAnalysis, models)
732
738
  manager.provide(MembersAnalysis, members)
739
+ manager.provide(SignaturesAnalysis, models.signatures())
733
740
  manager.provide(DependencyAnalysis, dependencies)
734
741
  manager.provide(RegisteredRoutes, routes)
735
742
  manager.provide(EscapedTemplates, escaped)
@@ -8,6 +8,8 @@ from coretrace_python.interprocedural.callgraph import (
8
8
  ExternalSymbol,
9
9
  KnownFunction,
10
10
  ModuleFunction,
11
+ Signature,
12
+ SignaturesAnalysis,
11
13
  SymbolRead,
12
14
  Target,
13
15
  UnknownTarget,
@@ -56,6 +58,8 @@ __all__ = [
56
58
  "Mutation",
57
59
  "NonlocalWrite",
58
60
  "ProjectSummaries",
61
+ "Signature",
62
+ "SignaturesAnalysis",
59
63
  "SummaryAnalysis",
60
64
  "SummaryIndex",
61
65
  "SummaryTable",
@@ -9,6 +9,7 @@ reads, called or not: reading ``request.form`` runs its getter.
9
9
 
10
10
  from __future__ import annotations
11
11
 
12
+ import re
12
13
  from collections.abc import Mapping
13
14
  from dataclasses import dataclass, field
14
15
  from types import MappingProxyType
@@ -104,6 +105,30 @@ class SymbolRead:
104
105
  symbol: SymbolId
105
106
 
106
107
 
108
+ @dataclass(frozen=True)
109
+ class Signature:
110
+ """What the parameters of the methods of a class denote when the canonical symbol
111
+ of its base matches ``pattern``, by position after ``self``: a class symbol, or None
112
+ for a parameter denoting none. A method taking another number of parameters has
113
+ none. The engine derives signatures from the security models (§16)."""
114
+
115
+ pattern: str
116
+ parameters: tuple[SymbolId | None, ...]
117
+
118
+ def matches(self, base: SymbolId) -> bool:
119
+ return re.search(self.pattern, base.canonical_name) is not None
120
+
121
+
122
+ class SignaturesAnalysis(Analysis[tuple[Signature, ...]]):
123
+ """The signatures the models declare, provided by the engine; none on its own."""
124
+
125
+ name: ClassVar[str] = "interprocedural.signatures"
126
+
127
+ @classmethod
128
+ def compute(cls, ctx: AnalysisContext) -> tuple[Signature, ...]:
129
+ return ()
130
+
131
+
107
132
  @dataclass(frozen=True)
108
133
  class ModuleFunction:
109
134
  """One function of a module as a project plugin sees it: the name the call graph
@@ -357,6 +382,20 @@ def _annotated(
357
382
  return found
358
383
 
359
384
 
385
+ def _declared(
386
+ function: nodes.Function, ssa: FunctionIR, bases: tuple[SymbolId, ...], signatures: tuple[Signature, ...]
387
+ ) -> dict[Value, SymbolId]:
388
+ """Parameters a signature types by their position, for a method of a class one of
389
+ whose ``bases`` matches the signature and which takes the parameters it lists."""
390
+
391
+ given = function.parameters[1:]
392
+ for signature in signatures:
393
+ if any(signature.matches(base) for base in bases) and len(given) == len(signature.parameters):
394
+ typed = zip(ssa.parameters[1:], signature.parameters, strict=False)
395
+ return {value: symbol for value, symbol in typed if symbol is not None}
396
+ return {}
397
+
398
+
360
399
  def _typed_with_module_classes(
361
400
  function: nodes.Function, ssa: FunctionIR, classes: Mapping[str, frozenset[str]]
362
401
  ) -> dict[Value, str]:
@@ -372,12 +411,15 @@ def _typed_with_module_classes(
372
411
 
373
412
  class CallGraphAnalysis(Analysis[CallGraph]):
374
413
  name: ClassVar[str] = "interprocedural.callgraph"
375
- requires: ClassVar[frozenset[AnyAnalysis]] = frozenset({SSAAnalysis, ScopeAnalysis, SymbolAnalysis})
414
+ requires: ClassVar[frozenset[AnyAnalysis]] = frozenset(
415
+ {SSAAnalysis, ScopeAnalysis, SymbolAnalysis, SignaturesAnalysis}
416
+ )
376
417
 
377
418
  @classmethod
378
419
  def compute(cls, ctx: AnalysisContext) -> CallGraph:
379
420
  scopes = ctx.get(ScopeAnalysis)
380
421
  table = ctx.get(SymbolAnalysis)
422
+ signatures = ctx.get(SignaturesAnalysis)
381
423
  definitions: dict[str, nodes.Function] = {}
382
424
  for function in analyzable_functions(ctx.module):
383
425
  # A property and its setter, or a redefinition, share a qualified name; each
@@ -396,14 +438,15 @@ class CallGraphAnalysis(Analysis[CallGraph]):
396
438
  for statement in ctx.module.body
397
439
  if isinstance(statement, nodes.Class)
398
440
  }
441
+ # Inheritance follows the first base that resolves; a signature may match any.
399
442
  bases: dict[str, SymbolId] = {}
443
+ ancestry: dict[str, tuple[SymbolId, ...]] = {}
400
444
  for statement in ctx.module.body:
401
445
  if isinstance(statement, nodes.Class):
402
- for base_expression in statement.bases:
403
- symbol = table.resolve_expression(scopes.module_scope.id, base_expression)
404
- if symbol is not None:
405
- bases[statement.name] = symbol
406
- break
446
+ resolved = [table.resolve_expression(scopes.module_scope.id, base) for base in statement.bases]
447
+ ancestry[statement.name] = tuple(symbol for symbol in resolved if symbol is not None)
448
+ if ancestry[statement.name]:
449
+ bases[statement.name] = ancestry[statement.name][0]
407
450
  sites: dict[str, tuple[CallSite, ...]] = {}
408
451
  symbols: dict[str, Mapping[Value, SymbolId]] = {}
409
452
  reads: dict[str, tuple[SymbolRead, ...]] = {}
@@ -418,11 +461,13 @@ class CallGraphAnalysis(Analysis[CallGraph]):
418
461
  owner = name.rsplit(".", 1)[0] if "." in name and name.rsplit(".", 1)[0] in classes else None
419
462
  if owner is not None and _is_staticmethod(function):
420
463
  owner = None # a static method has no receiver
464
+ # A signature types parameters by their position; an annotation says more.
465
+ declared = _declared(function, ssa, ancestry.get(owner, ()) if owner is not None else (), signatures)
421
466
  targets, symbols[name] = resolve_targets(
422
467
  ssa,
423
468
  scopes,
424
469
  known,
425
- _annotated(function, ssa, scopes, table),
470
+ {**declared, **_annotated(function, ssa, scopes, table)},
426
471
  frozenset(definitions),
427
472
  classes,
428
473
  owner,
@@ -363,6 +363,12 @@ class SummaryIndex:
363
363
  def summary(self, symbol: SymbolId) -> FunctionSummary | None:
364
364
  return self.summaries.get(symbol)
365
365
 
366
+ def defines(self, owner: SymbolId) -> bool:
367
+ """Whether the project defines a function of ``owner``, a class or a module."""
368
+
369
+ prefix = owner.canonical_name + "."
370
+ return any(s.canonical_name.startswith(prefix) for s in self.symbols)
371
+
366
372
  def __eq__(self, other: object) -> bool:
367
373
  return isinstance(other, SummaryIndex) and dict(self.summaries) == dict(other.summaries)
368
374
 
@@ -12,6 +12,7 @@ from coretrace_python.taint.engine import (
12
12
  from coretrace_python.taint.models import (
13
13
  TEXT_KINDS,
14
14
  AuthorizationGuard,
15
+ BasePattern,
15
16
  EntryPoint,
16
17
  Model,
17
18
  ModelError,
@@ -47,6 +48,7 @@ __all__ = [
47
48
  "FILTER_FUNCTIONS",
48
49
  "TEXT_KINDS",
49
50
  "AuthorizationGuard",
51
+ "BasePattern",
50
52
  "EntryPoint",
51
53
  "EntryPointAnalysis",
52
54
  "EscapedTemplates",
@@ -80,6 +80,7 @@ from coretrace_python.semantic.symbols import SymbolAnalysis, SymbolId, SymbolTa
80
80
  from coretrace_python.source import SourceSpan
81
81
  from coretrace_python.taint.models import (
82
82
  TEXT_KINDS,
83
+ BasePattern,
83
84
  EntryPoint,
84
85
  ModelTable,
85
86
  SecurityModelAnalysis,
@@ -780,9 +781,11 @@ def entry_point_of(
780
781
  symbols: SymbolTable,
781
782
  owner: nodes.Class | None = None,
782
783
  instances: Instances | None = None,
784
+ project: SummaryIndex | None = None,
783
785
  ) -> EntryPoint | None:
784
786
  """The entry-point model matching one of the function's decorators or, for a
785
- method, one of the bases of ``owner``, if any."""
787
+ method, one of the bases of ``owner``, if any: by symbol, or by a base pattern when
788
+ the method is one the pattern covers (``project`` says what the base defines)."""
786
789
 
787
790
  scope = scopes.scope_for(function)
788
791
  enclosing = scope.parent if scope.parent is not None else scope.id
@@ -803,9 +806,24 @@ def entry_point_of(
803
806
  entry = models.entry_point(candidate)
804
807
  if entry is not None:
805
808
  return entry
809
+ pattern = models.base_pattern(candidate) if id(expression) in enclosing_of else None
810
+ if pattern is not None and _covered(function, candidate, pattern, project):
811
+ return EntryPoint(candidate, pattern.label, pattern.kinds)
806
812
  return None
807
813
 
808
814
 
815
+ def _covered(function: nodes.Function, base: SymbolId, pattern: BasePattern, project: SummaryIndex | None) -> bool:
816
+ """Whether a method of a class deriving from ``base`` is one ``pattern`` covers: it
817
+ takes the parameters the pattern lists and, when the project holds the base, the
818
+ base defines it; a utility method of the class is no entry point."""
819
+
820
+ if len(function.parameters) - 1 != len(pattern.parameters):
821
+ return False
822
+ if project is None or not project.defines(base):
823
+ return True
824
+ return project.summary(base.attribute(function.name)) is not None
825
+
826
+
809
827
  def function_entry_point(
810
828
  function: nodes.Function,
811
829
  module: nodes.Module,
@@ -814,6 +832,7 @@ def function_entry_point(
814
832
  symbols: SymbolTable,
815
833
  instances: Instances | None = None,
816
834
  routes: Routes | None = None,
835
+ project: SummaryIndex | None = None,
817
836
  ) -> EntryPoint | None:
818
837
  """The entry point ``function`` is: one of its decorators or, for a method, one of its
819
838
  class's bases matching an entry-point model, or a registration elsewhere (``routes``)."""
@@ -823,7 +842,7 @@ def function_entry_point(
823
842
  if enclosing_function is not None:
824
843
  # ``app = Flask(__name__)`` inside ``create_app``: routes defined there resolve.
825
844
  instances = {**(instances or {}), **local_instances(enclosing_function, scopes, symbols)}
826
- entry = entry_point_of(function, models, scopes, symbols, owner, instances)
845
+ entry = entry_point_of(function, models, scopes, symbols, owner, instances, project)
827
846
  if entry is None and routes:
828
847
  qualified = function.name if owner is None else f"{owner.name}.{function.name}"
829
848
  entry = routes.get(project_symbol(module.name, qualified))
@@ -849,23 +868,29 @@ def parameter_sources(
849
868
  symbols: SymbolTable,
850
869
  instances: Instances | None = None,
851
870
  routes: Routes | None = None,
871
+ project: SummaryIndex | None = None,
852
872
  ) -> Mapping[int, Source]:
853
873
  """The attacker-controlled parameters of ``function``, by index: every parameter of an
854
874
  entry point (``self`` excepted for a method), including one registered elsewhere
855
875
  (``routes``), and every parameter annotated with a typed-parameter symbol. An entry
856
876
  point's parameter annotated with scalars is text: FastAPI validates it before the
857
877
  handler runs, and a scalar cannot hold a query operator. So are the URL parameters
858
- a view receives after a request object."""
878
+ a view receives after a request object. A parameter a base pattern types with a
879
+ class is not input: the sources on that class say what it gives."""
859
880
 
860
881
  owner = _owner(module, function)
861
882
  sources: dict[int, Source] = {}
862
883
  scope = scopes.scope_for(function)
863
884
  enclosing = scope.parent if scope.parent is not None else scope.id
864
- entry = function_entry_point(function, module, models, scopes, symbols, instances, routes)
885
+ entry = function_entry_point(function, module, models, scopes, symbols, instances, routes, project)
865
886
  if entry is not None:
866
887
  first = 1 if owner is not None else 0
867
888
  request = models.request_object(entry.symbol)
889
+ pattern = models.base_pattern(entry.symbol) if models.entry_point(entry.symbol) is None else None
890
+ roles = pattern.parameters if pattern is not None else ()
868
891
  for index in range(first, len(function.parameters)):
892
+ if index - first < len(roles) and roles[index - first] is not None:
893
+ continue
869
894
  annotation = function.parameters[index].annotation
870
895
  text = (request is not None and index > first) or (
871
896
  annotation is not None and _scalar(annotation, symbols, enclosing)
@@ -1010,11 +1035,12 @@ class TaintAnalysis(FunctionAnalysis[TaintFacts]):
1010
1035
  graph = ctx.get(CallGraphAnalysis)
1011
1036
  models = ctx.get(SecurityModelAnalysis)
1012
1037
  scopes, symbols = ctx.get(ScopeAnalysis), ctx.get(SymbolAnalysis)
1013
- instances = factory_instances(ctx.module, scopes, symbols, ctx.get(SummaryAnalysis), ctx.get(ProjectSummaries))
1038
+ project = ctx.get(ProjectSummaries)
1039
+ instances = factory_instances(ctx.module, scopes, symbols, ctx.get(SummaryAnalysis), project)
1014
1040
  routes = ctx.get(RegisteredRoutes)
1015
1041
 
1016
1042
  def sources_of(member: nodes.Function) -> Mapping[int, Source]:
1017
- return parameter_sources(member, ctx.module, models, scopes, symbols, instances, routes)
1043
+ return parameter_sources(member, ctx.module, models, scopes, symbols, instances, routes, project)
1018
1044
 
1019
1045
  ssa = ctx.get(SSAAnalysis, function)
1020
1046
  heap = ctx.get(HeapAnalysis, function)
@@ -1068,9 +1094,10 @@ class EntryPointAnalysis(Analysis[tuple[ModuleFunction, ...]]):
1068
1094
  scopes, symbols = ctx.get(ScopeAnalysis), ctx.get(SymbolAnalysis)
1069
1095
  instances = factory_instances(ctx.module, scopes, symbols, ctx.get(SummaryAnalysis), ctx.get(ProjectSummaries))
1070
1096
  routes = ctx.get(RegisteredRoutes)
1097
+ project = ctx.get(ProjectSummaries)
1071
1098
  functions: list[ModuleFunction] = []
1072
1099
  for name, function in graph.definitions.items():
1073
- entry = function_entry_point(function, ctx.module, models, scopes, symbols, instances, routes)
1100
+ entry = function_entry_point(function, ctx.module, models, scopes, symbols, instances, routes, project)
1074
1101
  functions.append(ModuleFunction(name, function.span, entry.label if entry is not None else None))
1075
1102
  return tuple(functions)
1076
1103
 
@@ -17,7 +17,7 @@ from types import MappingProxyType
17
17
  from typing import ClassVar
18
18
 
19
19
  from coretrace_python.analysis import Analysis, AnalysisContext, MissingInputError
20
- from coretrace_python.interprocedural import Clearing, TemplateCalls, TemplateFilter
20
+ from coretrace_python.interprocedural import Clearing, Signature, TemplateCalls, TemplateFilter
21
21
  from coretrace_python.semantic.symbols import Members, SymbolId
22
22
 
23
23
 
@@ -145,6 +145,32 @@ class NamedParameter:
145
145
  return re.search(self.pattern, name) is not None
146
146
 
147
147
 
148
+ @dataclass(frozen=True)
149
+ class BasePattern:
150
+ """Methods of a class whose base's canonical symbol matches ``pattern`` are entry
151
+ points labelled ``label``, when they take the parameters the model lists, by
152
+ position after ``self``: a position left None is attacker input carrying ``kinds``;
153
+ one holding a class symbol denotes an object of that class, which the sources on
154
+ the class taint. A gRPC servicer's RPCs take the request, or the iterator of the
155
+ client's messages, and a ``ServicerContext``. When the project holds the base,
156
+ only the methods it defines are entry points; otherwise every method with that
157
+ number of parameters. Inheritance identifies a potential service, not its
158
+ registration on a server."""
159
+
160
+ pattern: str
161
+ label: str
162
+ parameters: tuple[SymbolId | None, ...] = (None,)
163
+ kinds: TaintKind = TaintKind.ALL
164
+
165
+ @property
166
+ def symbol(self) -> SymbolId:
167
+ digest = hashlib.sha1(self.pattern.encode("utf-8")).hexdigest()[:12]
168
+ return SymbolId(f"python.base.p{digest}")
169
+
170
+ def matches(self, base: SymbolId) -> bool:
171
+ return re.search(self.pattern, base.canonical_name) is not None
172
+
173
+
148
174
  @dataclass(frozen=True)
149
175
  class RouteRegistrar:
150
176
  """A call registering a handler elsewhere (``path('login/', views.log_in)``): the
@@ -251,6 +277,7 @@ Model = (
251
277
  | TemplateRender
252
278
  | Members
253
279
  | RequestObject
280
+ | BasePattern
254
281
  )
255
282
 
256
283
 
@@ -270,6 +297,7 @@ class ModelTable:
270
297
  template_renders: tuple[TemplateRender, ...] = ()
271
298
  members: tuple[Members, ...] = ()
272
299
  request_objects: tuple[RequestObject, ...] = ()
300
+ base_patterns: tuple[BasePattern, ...] = ()
273
301
  _by_symbol: dict[type[Model], dict[SymbolId, Model]] = field(
274
302
  init=False, repr=False, compare=False
275
303
  )
@@ -287,6 +315,7 @@ class ModelTable:
287
315
  SafeArgument: {m.symbol: m for m in self.safe_arguments},
288
316
  TemplateRender: {m.symbol: m for m in self.template_renders},
289
317
  RequestObject: {m.symbol: m for m in self.request_objects},
318
+ BasePattern: {m.symbol: m for m in self.base_patterns},
290
319
  }
291
320
  object.__setattr__(self, "_by_symbol", MappingProxyType(index))
292
321
 
@@ -356,8 +385,20 @@ class ModelTable:
356
385
  self.template_renders,
357
386
  self.members,
358
387
  self.request_objects,
388
+ self.base_patterns,
359
389
  )
360
390
 
391
+ def base_pattern(self, base: SymbolId) -> BasePattern | None:
392
+ """The pattern model the canonical symbol of a class's ``base`` matches, if any."""
393
+
394
+ return next((m for m in self.base_patterns if m.matches(base)), None)
395
+
396
+ def signatures(self) -> tuple[Signature, ...]:
397
+ """What the methods of the classes the base patterns match receive, by position,
398
+ for the call graph to type them."""
399
+
400
+ return tuple(Signature(m.pattern, m.parameters) for m in self.base_patterns)
401
+
361
402
  def sanitizer(self, symbol: SymbolId) -> Sanitizer | None:
362
403
  found = self._by_symbol[Sanitizer].get(symbol)
363
404
  return found if isinstance(found, Sanitizer) else None
@@ -451,6 +492,7 @@ class SecurityModelRegistry:
451
492
  template_renders=tuple(m for m in models if isinstance(m, TemplateRender)),
452
493
  members=tuple(m for m in models if isinstance(m, Members)),
453
494
  request_objects=tuple(m for m in models if isinstance(m, RequestObject)),
495
+ base_patterns=tuple(m for m in models if isinstance(m, BasePattern)),
454
496
  )
455
497
 
456
498
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: coretrace-python-analyzer
3
- Version: 0.16.0
3
+ Version: 0.17.0
4
4
  Summary: Static security analysis infrastructure for Python code
5
5
  Project-URL: Homepage, https://github.com/CoreTrace/coretrace-python-analyzer
6
6
  Project-URL: Repository, https://github.com/CoreTrace/coretrace-python-analyzer
@@ -1,8 +1,8 @@
1
- coretrace_python/__init__.py,sha256=9j69Wzj9GHgyyRtQTj2wS0rZy93WHE76rEZoEt9NUD0,76
1
+ coretrace_python/__init__.py,sha256=HRmDGjpSkbWNTv_zUrVcohlicTxeBUblXGvOBz0lia4,76
2
2
  coretrace_python/__main__.py,sha256=V8DnYtRboISK2VCKm7DGHLREKvqLbqApyWlKBOs26wU,65
3
3
  coretrace_python/cache.py,sha256=-pZv-ELm4jMCTXQWSZIobHaT9UHIjFu7IlMkOM0i4LI,13607
4
4
  coretrace_python/cli.py,sha256=G5jhb6g6RgSRSjjS7DBgziIjUM1vTFwalJGvFHVKxrg,11225
5
- coretrace_python/engine.py,sha256=MBudcPfzzoP3dybO6LvfOXs0scT1L4gE4yUraGaj6aM,33592
5
+ coretrace_python/engine.py,sha256=13lCa7rJTI6Q4Icyvs8gZpcJhW9WxO1poWXGjWCDHT0,33922
6
6
  coretrace_python/abstract/__init__.py,sha256=n5FNkV8Z4LmwG0r06KWdLj4N2CPSgAKwY3896tdmRgM,999
7
7
  coretrace_python/abstract/constants.py,sha256=z4-e7IzysxzGi58wFFff1MlEoV8l7AZsB9EL-q6b7vY,9071
8
8
  coretrace_python/abstract/heap.py,sha256=OaESXFGC0qzyhAr76xrCu4skeDVzZM4wlenQqfMTkdk,9642
@@ -113,10 +113,10 @@ coretrace_python/frontend/parser.py,sha256=6-CG7rWxUYeOGeDP206SJWy4BMQUP9Mr6Jf-t
113
113
  coretrace_python/hir/__init__.py,sha256=xMpvj-RSp6bd78a_hhkqbe99-snjERkH-_Lv5o9ASbw,180
114
114
  coretrace_python/hir/nodes.py,sha256=4BI0f3UhKbnz9ZIxMoKXM7ujav0BmRpD0OXaoblRxIk,12364
115
115
  coretrace_python/hir/visitors.py,sha256=JFnX09hK6trLyRcWgZ5ehOG2ywX3VvkqQ1h82nahYNg,885
116
- coretrace_python/interprocedural/__init__.py,sha256=TNZQLta5sEglu6c2Nf2ygXsjDRlYZfKOu-yHaL7O6B0,1484
117
- coretrace_python/interprocedural/callgraph.py,sha256=3phhsJQ4pnpDullBluROSCbuz4AKaZsvycxrvq4UM7c,19898
116
+ coretrace_python/interprocedural/__init__.py,sha256=HvV9zibV_VX8cfIYzWXVEDGkkMZzDywx-lKJioYSFtg,1566
117
+ coretrace_python/interprocedural/callgraph.py,sha256=a7fTvciUjMkEO0TsJqZm6L0OFyARmLQ1P2cjAnBTENk,21948
118
118
  coretrace_python/interprocedural/modulegraph.py,sha256=4sB7OKjBYfxtm7aMtHm2jRlqFVUNUsdnLhnv9UZ1BWA,8846
119
- coretrace_python/interprocedural/summaries.py,sha256=xrbld2keuz1kam40vZFuzET5sCm8pRbGwxp7hwJNBv4,33602
119
+ coretrace_python/interprocedural/summaries.py,sha256=6lybEynjtptZGGBw_3WKXx9ZZZqN96xL-r-tzo8fbMI,33862
120
120
  coretrace_python/ir/__init__.py,sha256=ShBPYYqoQFePP-mgBjGezQ2acel0-ReOHF9vCC-G_4Q,232
121
121
  coretrace_python/ir/defuse.py,sha256=CZEPnlgntRp4MqwR7kLldd2ZlIlBnr-V9VJAxXxwm0c,2616
122
122
  coretrace_python/ir/lowering.py,sha256=kIVB1HlIW6AMW7-2x9z7wcdhObWj8rjP_eKqOKtgxoM,31442
@@ -143,15 +143,15 @@ coretrace_python/semantic/symbols.py,sha256=G0jwsWFo2346Y1R2sztsB8HuZZm_aHfHSJXX
143
143
  coretrace_python/source/__init__.py,sha256=0Y8fvtbkETnNCJR9Zq7RS5TSgF9c22pz3SSk1KdAXF0,301
144
144
  coretrace_python/source/manager.py,sha256=JRmMOcWfS1nocbVrdcvfQTqEfIkmnb5JP857TpGywN4,2736
145
145
  coretrace_python/source/model.py,sha256=FZnN5mlir3tzbIpWoxnn6YtRi9UcJ_y0sZM60tKr8U4,1727
146
- coretrace_python/taint/__init__.py,sha256=UGGxGnaWqgKqyN_XIJW0fiLqRJdVB9L9CpjxSiaApts,1791
147
- coretrace_python/taint/engine.py,sha256=aNVEOvKTlNoFBcLn3LV8nWS2gXtf6F71uw0PWW9FyV8,47318
148
- coretrace_python/taint/models.py,sha256=uEXSKk0yp-VQ_1L12npBn0xjF3wGi4NdsWmpuj9128Y,18091
146
+ coretrace_python/taint/__init__.py,sha256=nKpD33_4IRneAkd3Dt-j7Q-cHl47rDA_eLZFDHZVH28,1827
147
+ coretrace_python/taint/engine.py,sha256=B3_o8feN0-a6PAfZCyERIxMiZnF50nTMi3rP5uesHOM,48923
148
+ coretrace_python/taint/models.py,sha256=EMzAMY3woBjgDlGyFi9vsVmuE5r2OjnwEvHHoe9IuWE,20026
149
149
  coretrace_python/taint/routes.py,sha256=UAJKXcw_sM9shf58FfDroxVO9bNSm4qrQdZknwUB0lo,6110
150
150
  coretrace_python/taint/templates.py,sha256=cxa2PC-Md0pAPu0NxrIUJ5XMs26zck7O-dDH30TTB2I,31023
151
151
  coretrace_python/taint/urls.py,sha256=kb0-uOT12ww7R3Jzs_lPKg9lFs74JI-bpa9pXX105xM,3166
152
- coretrace_python_analyzer-0.16.0.dist-info/METADATA,sha256=u_7qn4ixLqW-gJbUPggep7tRdDh3ogsp33A6h1-AEhc,3217
153
- coretrace_python_analyzer-0.16.0.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
154
- coretrace_python_analyzer-0.16.0.dist-info/entry_points.txt,sha256=wdozemiraOkbt65g_Y_zgspuZpoLxJdaCVMJt1Ft3c0,72
155
- coretrace_python_analyzer-0.16.0.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
156
- coretrace_python_analyzer-0.16.0.dist-info/licenses/NOTICE,sha256=s3VHj5ngV0ozjW_kZJpg_35ne6JwoBK0ysOjbqVtA0w,113
157
- coretrace_python_analyzer-0.16.0.dist-info/RECORD,,
152
+ coretrace_python_analyzer-0.17.0.dist-info/METADATA,sha256=LCZjkte2jNcPz06rsm7jMwboXtkbiwbyrIQh9Ij4nR8,3217
153
+ coretrace_python_analyzer-0.17.0.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
154
+ coretrace_python_analyzer-0.17.0.dist-info/entry_points.txt,sha256=wdozemiraOkbt65g_Y_zgspuZpoLxJdaCVMJt1Ft3c0,72
155
+ coretrace_python_analyzer-0.17.0.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
156
+ coretrace_python_analyzer-0.17.0.dist-info/licenses/NOTICE,sha256=s3VHj5ngV0ozjW_kZJpg_35ne6JwoBK0ysOjbqVtA0w,113
157
+ coretrace_python_analyzer-0.17.0.dist-info/RECORD,,