codeanalyzer-python 1.5.3__py3-none-any.whl → 1.5.4__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.
@@ -142,6 +142,26 @@ class _FunctionAssembler:
142
142
 
143
143
  # ---------------------------------------------------------------- formals
144
144
 
145
+ def formal_for(self, var: str) -> Optional[int]:
146
+ """The ``formal_in`` vertex that defines ``var`` in this callable.
147
+
148
+ A parameter, a capture and a read global are all defined at a
149
+ ``formal_in`` port, not at the synthetic CFG ENTRY node. Reaching-def
150
+ analysis reports ENTRY as the source for all three, so every place that
151
+ consumes a raw def source has to remap it here, or the SDG loses the
152
+ hop from the parameter to whatever uses it. Returns ``None`` when
153
+ ``var`` is not one of this callable's formals, so a caller can keep the
154
+ original source.
155
+ """
156
+ b = base_of(var)
157
+ if b in self.formal_in:
158
+ return self.formal_in[b]
159
+ if CAPTURE_PREFIX + b in self.formal_in:
160
+ return self.formal_in[CAPTURE_PREFIX + b]
161
+ if "::" in b and GLOBAL_PREFIX + b in self.formal_in:
162
+ return self.formal_in[GLOBAL_PREFIX + b]
163
+ return None
164
+
145
165
  def build_formals(self) -> None:
146
166
  scope, summary = self.scope, self.summary
147
167
  params = list(scope.params)
@@ -168,14 +188,8 @@ class _FunctionAssembler:
168
188
  for e in self.ddg:
169
189
  if e.source != entry:
170
190
  continue
171
- b = base_of(e.var)
172
- if b in self.formal_in:
173
- fid = self.formal_in[b]
174
- elif CAPTURE_PREFIX + b in self.formal_in:
175
- fid = self.formal_in[CAPTURE_PREFIX + b]
176
- elif "::" in b and GLOBAL_PREFIX + b in self.formal_in:
177
- fid = self.formal_in[GLOBAL_PREFIX + b]
178
- else:
191
+ fid = self.formal_for(e.var)
192
+ if fid is None:
179
193
  continue
180
194
  self.extra.append(PDGEdge(source=fid, target=e.target, type="DDG", var=e.var))
181
195
 
@@ -268,6 +282,8 @@ class _FunctionAssembler:
268
282
  for src, var in self._defs_reaching_call_matching(
269
283
  cs.node_id, path
270
284
  ):
285
+ if src == self.cfg.entry_id:
286
+ src = self.formal_for(var) or src
271
287
  self.extra.append(
272
288
  PDGEdge(source=src, target=aid, type="DDG", var=var)
273
289
  )
@@ -296,6 +312,8 @@ class _FunctionAssembler:
296
312
  for src, var in self._defs_reaching_call_matching(
297
313
  cs.node_id, g
298
314
  ):
315
+ if src == self.cfg.entry_id:
316
+ src = self.formal_for(var) or src
299
317
  self.extra.append(
300
318
  PDGEdge(source=src, target=aid, type="DDG", var=var)
301
319
  )
@@ -104,8 +104,12 @@ def _methods_of(dec, spec: Optional[Dict[str, Any]], qualified: Optional[str] =
104
104
  return []
105
105
  source = spec.get("from")
106
106
  if source == "match_suffix":
107
+ # Only a real verb: `heuristic.http-verb` also matches `.websocket`, and a
108
+ # rule may accept any suffix, but `http_methods` is what a consumer filters
109
+ # on to enumerate methods -- a value that is not one is worse there than an
110
+ # empty list (#213). The dispatch path below already filters the same way.
107
111
  verb = (qualified or dec.qualified_name or "").rsplit(".", 1)[-1]
108
- return [verb.upper()]
112
+ return [verb.upper()] if verb.lower() in _HTTP_VERBS else []
109
113
  if source == "keyword":
110
114
  raw = (dec.keyword_arguments or {}).get(spec.get("name", ""))
111
115
  value = _literal(raw)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: codeanalyzer-python
3
- Version: 1.5.3
3
+ Version: 1.5.4
4
4
  Summary: Static analysis for Python — canonical schema v2 (symbol table, call graph, and native CFG/PDG/SDG dataflow) as analysis.json or a Neo4j property graph.
5
5
  Author-email: Rahul Krishna <i.m.ralk@gmail.com>
6
6
  License-File: LICENSE
@@ -21,7 +21,7 @@ codeanalyzer/dataflow/identity.py,sha256=6aAz3iPSOpoS7l_moC7XGr2RS_GqJp_FlsWGglM
21
21
  codeanalyzer/dataflow/pdg.py,sha256=1Bm7AnoRqXBryZulII2idPw0feV8eZQ1VqqprQ8PW-g,3731
22
22
  codeanalyzer/dataflow/scalpel_oracle.py,sha256=FxRadKrTWar0VKHyQJM40n3cq25sld3Sj4lMdOm5NFk,11494
23
23
  codeanalyzer/dataflow/scc.py,sha256=Doa_0-5f3agCu_5UmeEDlCUErg34TtniKIv8Uqd7Jiw,3493
24
- codeanalyzer/dataflow/sdg.py,sha256=taDXkIg0BZUtDEJUjRJB_dxrFl6tKNOUdFyj0zCiso0,18533
24
+ codeanalyzer/dataflow/sdg.py,sha256=_dcR6nNc0ZTETaLHbmliEMeTG-AcQU0x-7DiB1cvoPs,19445
25
25
  codeanalyzer/dataflow/slicing.py,sha256=lWZ7jHhlR8m7rECWJQXvwfs5GNZeJY55Cud3Ji5UbNU,3654
26
26
  codeanalyzer/dataflow/summaries.py,sha256=TLtc5h4bLBC4lViuMhMlEp5rp_nBpDPOl4_wfBuRUY4,9210
27
27
  codeanalyzer/dataflow/syntactic.py,sha256=AbHyXjKX_1xkGgKH48BpXYCWBauActGUwSMF_OD-uys,1124
@@ -38,7 +38,7 @@ codeanalyzer/dataflow/scalpel/core/func_call_visitor.py,sha256=ps0snjTchBXilhor3
38
38
  codeanalyzer/dataflow/scalpel/core/vars_visitor.py,sha256=gE5fNyJS6jslD6vsMRbFLoy3n1xTwH-b54mBcNYO72M,5660
39
39
  codeanalyzer/entrypoints/__init__.py,sha256=VaMd4mSEPLuPlRxxAve_nTJ9ZH62stXZGTPNwU_BQ50,99
40
40
  codeanalyzer/entrypoints/detect.py,sha256=fsWRQz1njvB9d3LIJEHxsNFE1GrB7q52KCvozw_UIUQ,4594
41
- codeanalyzer/entrypoints/matching.py,sha256=rQeY_w2dyG36DBUjle7GLXxqDKsoMhJYPjN4s11OGtM,7948
41
+ codeanalyzer/entrypoints/matching.py,sha256=fppta04o1_HWBEHe6boV_7T964cdLuZlOoQHAW4yt0Q,8321
42
42
  codeanalyzer/entrypoints/pipeline.py,sha256=vVSdttMfSAWour2fsC3LomMtwFLzRqmJHixJS82VY1I,7828
43
43
  codeanalyzer/entrypoints/rules.py,sha256=yG772JHmNc2L10jIpxfg1xTh-QouJa6lNU9ubo3EZYg,6003
44
44
  codeanalyzer/entrypoints/rules.yml,sha256=sguICRfDDNGjJPfZz-JSwkI_hzbTJaau1liHV_y4rTA,4637
@@ -70,9 +70,9 @@ codeanalyzer/syntactic_analysis/symbol_table_builder.py,sha256=tKed-VCSd_albMeZf
70
70
  codeanalyzer/utils/__init__.py,sha256=hC6VWdR5rerSqBxzu9KQHTASWqwrrYJv-CMDwrTlzkc,137
71
71
  codeanalyzer/utils/logging.py,sha256=Fw0tattPAOMs3o0JMjjXhRVLIF64f-SCcygUXF9jqeg,904
72
72
  codeanalyzer/utils/progress_bar.py,sha256=C9JtzVdd10lIxTv-KA6PebqjKWueC_vMGwVzAtHuHIw,2818
73
- codeanalyzer_python-1.5.3.dist-info/METADATA,sha256=mYN0yUedKfOOzWquD1DxyaoE3c9yUpK9Prs9AXqj6d0,44845
74
- codeanalyzer_python-1.5.3.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
75
- codeanalyzer_python-1.5.3.dist-info/entry_points.txt,sha256=v4Vux0Nnx7sOntVk_CH7W9RX6SkIkvR1FQYq73oVlCQ,105
76
- codeanalyzer_python-1.5.3.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
77
- codeanalyzer_python-1.5.3.dist-info/licenses/NOTICE,sha256=MdVkNYqHJ20on2FmWvgD4WpMsX5mir33xdyPvTXd0A0,1223
78
- codeanalyzer_python-1.5.3.dist-info/RECORD,,
73
+ codeanalyzer_python-1.5.4.dist-info/METADATA,sha256=pky-NFu9SoPYS5JNaPnJF4J-9yTTp02bDGA0qxkorpA,44845
74
+ codeanalyzer_python-1.5.4.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
75
+ codeanalyzer_python-1.5.4.dist-info/entry_points.txt,sha256=v4Vux0Nnx7sOntVk_CH7W9RX6SkIkvR1FQYq73oVlCQ,105
76
+ codeanalyzer_python-1.5.4.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
77
+ codeanalyzer_python-1.5.4.dist-info/licenses/NOTICE,sha256=MdVkNYqHJ20on2FmWvgD4WpMsX5mir33xdyPvTXd0A0,1223
78
+ codeanalyzer_python-1.5.4.dist-info/RECORD,,