circle-ir 4.15.0 → 4.16.0

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 (135) hide show
  1. package/configs/sinks/golang.json +4 -4
  2. package/dist/analysis/config-loader.d.ts.map +1 -1
  3. package/dist/analysis/config-loader.js +11 -7
  4. package/dist/analysis/config-loader.js.map +1 -1
  5. package/dist/analysis/constant-caller-gate.d.ts +39 -0
  6. package/dist/analysis/constant-caller-gate.d.ts.map +1 -0
  7. package/dist/analysis/constant-caller-gate.js +298 -0
  8. package/dist/analysis/constant-caller-gate.js.map +1 -0
  9. package/dist/analysis/constant-propagation/evaluator.d.ts.map +1 -1
  10. package/dist/analysis/constant-propagation/evaluator.js +3 -1
  11. package/dist/analysis/constant-propagation/evaluator.js.map +1 -1
  12. package/dist/analysis/constant-propagation/patterns.d.ts +19 -0
  13. package/dist/analysis/constant-propagation/patterns.d.ts.map +1 -1
  14. package/dist/analysis/constant-propagation/patterns.js +33 -0
  15. package/dist/analysis/constant-propagation/patterns.js.map +1 -1
  16. package/dist/analysis/constant-propagation/propagator.d.ts +59 -0
  17. package/dist/analysis/constant-propagation/propagator.d.ts.map +1 -1
  18. package/dist/analysis/constant-propagation/propagator.js +396 -49
  19. package/dist/analysis/constant-propagation/propagator.js.map +1 -1
  20. package/dist/analysis/constant-propagation/types.d.ts +9 -0
  21. package/dist/analysis/constant-propagation/types.d.ts.map +1 -1
  22. package/dist/analysis/findings.d.ts.map +1 -1
  23. package/dist/analysis/findings.js +134 -0
  24. package/dist/analysis/findings.js.map +1 -1
  25. package/dist/analysis/interprocedural.d.ts.map +1 -1
  26. package/dist/analysis/interprocedural.js +98 -3
  27. package/dist/analysis/interprocedural.js.map +1 -1
  28. package/dist/analysis/java-array-element-keys.d.ts +14 -0
  29. package/dist/analysis/java-array-element-keys.d.ts.map +1 -0
  30. package/dist/analysis/java-array-element-keys.js +36 -0
  31. package/dist/analysis/java-array-element-keys.js.map +1 -0
  32. package/dist/analysis/js-crlf-strip.d.ts +26 -0
  33. package/dist/analysis/js-crlf-strip.d.ts.map +1 -0
  34. package/dist/analysis/js-crlf-strip.js +244 -0
  35. package/dist/analysis/js-crlf-strip.js.map +1 -0
  36. package/dist/analysis/passes/csharp-sanitizer-credit.d.ts +12 -0
  37. package/dist/analysis/passes/csharp-sanitizer-credit.d.ts.map +1 -1
  38. package/dist/analysis/passes/csharp-sanitizer-credit.js +109 -12
  39. package/dist/analysis/passes/csharp-sanitizer-credit.js.map +1 -1
  40. package/dist/analysis/passes/language-sources-pass.d.ts +38 -3
  41. package/dist/analysis/passes/language-sources-pass.d.ts.map +1 -1
  42. package/dist/analysis/passes/language-sources-pass.js +1176 -119
  43. package/dist/analysis/passes/language-sources-pass.js.map +1 -1
  44. package/dist/analysis/passes/param-source-flow-gate-pass.d.ts.map +1 -1
  45. package/dist/analysis/passes/param-source-flow-gate-pass.js +53 -1
  46. package/dist/analysis/passes/param-source-flow-gate-pass.js.map +1 -1
  47. package/dist/analysis/passes/plaintext-password-storage-pass.d.ts +6 -0
  48. package/dist/analysis/passes/plaintext-password-storage-pass.d.ts.map +1 -1
  49. package/dist/analysis/passes/plaintext-password-storage-pass.js +160 -0
  50. package/dist/analysis/passes/plaintext-password-storage-pass.js.map +1 -1
  51. package/dist/analysis/passes/scan-secrets-pass.d.ts +1 -1
  52. package/dist/analysis/passes/scan-secrets-pass.d.ts.map +1 -1
  53. package/dist/analysis/passes/scan-secrets-pass.js +7 -1
  54. package/dist/analysis/passes/scan-secrets-pass.js.map +1 -1
  55. package/dist/analysis/passes/sink-filter-pass.d.ts +1 -1
  56. package/dist/analysis/passes/sink-filter-pass.d.ts.map +1 -1
  57. package/dist/analysis/passes/sink-filter-pass.js +307 -31
  58. package/dist/analysis/passes/sink-filter-pass.js.map +1 -1
  59. package/dist/analysis/passes/taint-matcher-pass.d.ts.map +1 -1
  60. package/dist/analysis/passes/taint-matcher-pass.js +2 -2
  61. package/dist/analysis/passes/taint-matcher-pass.js.map +1 -1
  62. package/dist/analysis/passes/taint-propagation-pass.d.ts.map +1 -1
  63. package/dist/analysis/passes/taint-propagation-pass.js +1349 -58
  64. package/dist/analysis/passes/taint-propagation-pass.js.map +1 -1
  65. package/dist/analysis/passes/weak-hash-pass.d.ts +6 -0
  66. package/dist/analysis/passes/weak-hash-pass.d.ts.map +1 -1
  67. package/dist/analysis/passes/weak-hash-pass.js +191 -4
  68. package/dist/analysis/passes/weak-hash-pass.js.map +1 -1
  69. package/dist/analysis/passes/weak-random-pass.d.ts +5 -0
  70. package/dist/analysis/passes/weak-random-pass.d.ts.map +1 -1
  71. package/dist/analysis/passes/weak-random-pass.js +30 -0
  72. package/dist/analysis/passes/weak-random-pass.js.map +1 -1
  73. package/dist/analysis/project-callee-escape-gate.d.ts +40 -0
  74. package/dist/analysis/project-callee-escape-gate.d.ts.map +1 -0
  75. package/dist/analysis/project-callee-escape-gate.js +243 -0
  76. package/dist/analysis/project-callee-escape-gate.js.map +1 -0
  77. package/dist/analysis/rust-literal-guard-rebind.d.ts +34 -0
  78. package/dist/analysis/rust-literal-guard-rebind.d.ts.map +1 -0
  79. package/dist/analysis/rust-literal-guard-rebind.js +197 -0
  80. package/dist/analysis/rust-literal-guard-rebind.js.map +1 -0
  81. package/dist/analysis/rust-literal-guard.d.ts +33 -0
  82. package/dist/analysis/rust-literal-guard.d.ts.map +1 -0
  83. package/dist/analysis/rust-literal-guard.js +422 -0
  84. package/dist/analysis/rust-literal-guard.js.map +1 -0
  85. package/dist/analysis/scalar-derivation.d.ts +8 -0
  86. package/dist/analysis/scalar-derivation.d.ts.map +1 -1
  87. package/dist/analysis/scalar-derivation.js +172 -0
  88. package/dist/analysis/scalar-derivation.js.map +1 -1
  89. package/dist/analysis/taint-matcher.d.ts +2 -2
  90. package/dist/analysis/taint-matcher.d.ts.map +1 -1
  91. package/dist/analysis/taint-matcher.js +531 -31
  92. package/dist/analysis/taint-matcher.js.map +1 -1
  93. package/dist/analysis/taint-propagation.d.ts +26 -1
  94. package/dist/analysis/taint-propagation.d.ts.map +1 -1
  95. package/dist/analysis/taint-propagation.js +234 -13
  96. package/dist/analysis/taint-propagation.js.map +1 -1
  97. package/dist/analyzer.d.ts +16 -2
  98. package/dist/analyzer.d.ts.map +1 -1
  99. package/dist/analyzer.js +13 -3
  100. package/dist/analyzer.js.map +1 -1
  101. package/dist/browser/circle-ir.js +24319 -19934
  102. package/dist/core/circle-ir-core.cjs +4936 -3575
  103. package/dist/core/circle-ir-core.js +4936 -3575
  104. package/dist/core/extractors/calls.d.ts +12 -1
  105. package/dist/core/extractors/calls.d.ts.map +1 -1
  106. package/dist/core/extractors/calls.js +332 -22
  107. package/dist/core/extractors/calls.js.map +1 -1
  108. package/dist/core/extractors/dfg.js +102 -10
  109. package/dist/core/extractors/dfg.js.map +1 -1
  110. package/dist/core/extractors/types.d.ts +5 -1
  111. package/dist/core/extractors/types.d.ts.map +1 -1
  112. package/dist/core/extractors/types.js +62 -0
  113. package/dist/core/extractors/types.js.map +1 -1
  114. package/dist/graph/analysis-pass.d.ts +6 -1
  115. package/dist/graph/analysis-pass.d.ts.map +1 -1
  116. package/dist/graph/analysis-pass.js +2 -1
  117. package/dist/graph/analysis-pass.js.map +1 -1
  118. package/dist/navigation/navigation-index.d.ts +134 -14
  119. package/dist/navigation/navigation-index.d.ts.map +1 -1
  120. package/dist/navigation/navigation-index.js +1158 -104
  121. package/dist/navigation/navigation-index.js.map +1 -1
  122. package/dist/navigation/types.d.ts +59 -2
  123. package/dist/navigation/types.d.ts.map +1 -1
  124. package/dist/resolution/cross-file.d.ts +9 -0
  125. package/dist/resolution/cross-file.d.ts.map +1 -1
  126. package/dist/resolution/cross-file.js +102 -43
  127. package/dist/resolution/cross-file.js.map +1 -1
  128. package/dist/resolution/type-hierarchy.d.ts +3 -0
  129. package/dist/resolution/type-hierarchy.d.ts.map +1 -1
  130. package/dist/resolution/type-hierarchy.js +45 -1
  131. package/dist/resolution/type-hierarchy.js.map +1 -1
  132. package/dist/types/index.d.ts +33 -0
  133. package/dist/types/index.d.ts.map +1 -1
  134. package/dist/types/index.js.map +1 -1
  135. package/package.json +1 -1
@@ -0,0 +1,243 @@
1
+ /**
2
+ * Project-callee escape gate (cognium-dev#637, C#).
3
+ *
4
+ * A file analysed on its own cannot see a method defined in another file, so
5
+ * a tainted argument passed to it is reported as an `external_taint_escape`
6
+ * (data handed to an unknown method). Inside `analyzeProject` the callee is
7
+ * known: the call is project code, not data leaving the program, and whether
8
+ * the value reaches a sink is decided by the cross-file phase and its callee
9
+ * reach check. With both classes in one file the same call reports nothing,
10
+ * so this step makes the project result agree with it.
11
+ *
12
+ * Runs after the per-file analyses and before the cross-file phase, so no
13
+ * cross-file path is built from the dropped sink. A sink is dropped only when
14
+ * every call at its line to that method name resolves exactly to a method
15
+ * declared in a different project file AND that method contains a registered
16
+ * sink and does not forward any of its parameters (directly, through an
17
+ * identity local alias, a field/property store, a return of a non-void method,
18
+ * or an interpolated-string hole): the cross-file phase and its callee-reach
19
+ * check then decide what is reported. A callee with no registered sink is a
20
+ * shape the registry does not know (for example a header or cookie write), and
21
+ * one that forwards the parameter elsewhere leaks it there; in both the escape
22
+ * is the only signal. An unresolved, inferred or polymorphic call also keeps
23
+ * it. When the call's receiver is a type-like name it must match the resolved
24
+ * class, so a second same-line call such as `Unknown.Run(data)` cannot inherit
25
+ * another call's cached resolution.
26
+ *
27
+ * The decision is transitive for a pure forwarder: a callee with no sink of its
28
+ * own whose only use of the parameter is to pass it to calls that each resolve
29
+ * exactly to a method in another project file is decided by those methods, to a
30
+ * depth of four hops with a visited set (so a loop stops). Any hop that does not
31
+ * resolve, ends without a sink, forwards elsewhere as well, stores or returns the
32
+ * value, or lies beyond the depth keeps the escape.
33
+ */
34
+ const ESCAPE = 'external_taint_escape';
35
+ /**
36
+ * Blank string literals but keep the contents of `{...}` holes in interpolated
37
+ * strings (`$"…"`, `$@"…"`), so `Sender.Post($"hello {data}")` still sees `data`.
38
+ */
39
+ function textOf(expr) {
40
+ return expr.replace(/\$@?"(?:[^"\\]|\\.|\{[^}]*\})*"|\$?"(?:[^"\\]|\\.|\{[^}]*\})*"|@?"(?:[^"\\]|\\.)*"/g, (lit) => {
41
+ if (lit.startsWith('$')) {
42
+ const holes = [...lit.matchAll(/\{([^}]*)\}/g)].map(m => m[1]).join(' ');
43
+ return ` ${holes} `;
44
+ }
45
+ return ' ';
46
+ });
47
+ }
48
+ function mentionsName(expr, name) {
49
+ return new RegExp(`(?<![\\w.])${name}(?!\\w)`).test(textOf(expr));
50
+ }
51
+ /**
52
+ * Identity aliases of parameters (`string x = data`), not transforms
53
+ * (`data.Split(...)`). A local chained from a known name counts only when its
54
+ * def line has a use of that name and no call with that name as receiver.
55
+ */
56
+ function identityAliases(ir, methodStart, methodEnd, params) {
57
+ const names = new Set(params);
58
+ const defs = ir.dfg?.defs ?? [];
59
+ const uses = ir.dfg?.uses ?? [];
60
+ const chains = ir.dfg?.chains ?? [];
61
+ const inMethod = (d) => d.line >= methodStart && d.line <= methodEnd;
62
+ let grew = true;
63
+ while (grew) {
64
+ grew = false;
65
+ const nameDefIds = new Set(defs.filter(d => inMethod(d) && names.has(d.variable)).map(d => d.id));
66
+ for (const ch of chains) {
67
+ if (!nameDefIds.has(ch.from_def))
68
+ continue;
69
+ const from = defs.find(d => d.id === ch.from_def);
70
+ const to = defs.find(d => d.id === ch.to_def);
71
+ if (!from || !to || !inMethod(to) || to.kind !== 'local')
72
+ continue;
73
+ if (names.has(to.variable))
74
+ continue;
75
+ if (!uses.some(u => u.line === to.line && u.variable === from.variable))
76
+ continue;
77
+ const transform = ir.calls.some(c => c.location.line === to.line && c.receiver === from.variable);
78
+ if (transform)
79
+ continue;
80
+ names.add(to.variable);
81
+ grew = true;
82
+ }
83
+ }
84
+ return names;
85
+ }
86
+ function fieldNamesOf(ir) {
87
+ return new Set(ir.types.flatMap(t => (t.fields ?? []).map(f => f.name)));
88
+ }
89
+ function isVoidReturn(m) {
90
+ const t = (m.return_type ?? 'void').trim().toLowerCase();
91
+ return t === '' || t === 'void';
92
+ }
93
+ /**
94
+ * True when every method named like `targetFqn` in `ir` contains a registered
95
+ * sink and does not forward a parameter elsewhere. A parameter bound with
96
+ * `x.Parameters.Add*(...)` is a binding, and a call on a registered sink line
97
+ * is covered by the reach check. Forwarding includes: a call argument that
98
+ * mentions the parameter or an identity local alias of it (including `{data}`
99
+ * holes in interpolated strings), a store into a field/property, and a return
100
+ * of the parameter from a non-void method. Null-checks and transforms like
101
+ * `data.Split(...)` are not forwarding.
102
+ */
103
+ const MAX_FORWARD_DEPTH = 4;
104
+ function calleeDecidedBySinks(projectGraph, file, targetFqn, depth = 0, visited = new Set()) {
105
+ const ir = projectGraph.getIR(file);
106
+ if (!ir)
107
+ return false;
108
+ const visitKey = `${file}#${targetFqn}`;
109
+ if (visited.has(visitKey))
110
+ return false;
111
+ visited.add(visitKey);
112
+ const name = targetFqn.split('.').pop();
113
+ const methods = ir.types.flatMap(t => t.methods).filter(m => m.name === name);
114
+ if (methods.length === 0)
115
+ return false;
116
+ const sinks = ir.taint?.sinks ?? [];
117
+ const sinkLines = new Set(sinks.filter(k => k.type !== ESCAPE).map(k => k.line));
118
+ const fields = fieldNamesOf(ir);
119
+ const defs = ir.dfg?.defs ?? [];
120
+ const uses = ir.dfg?.uses ?? [];
121
+ return methods.every(m => {
122
+ const hasSink = sinks.some(k => k.type !== ESCAPE && k.line >= m.start_line && k.line <= m.end_line);
123
+ const params = m.parameters.map(p => p.name).filter(Boolean);
124
+ if (params.length === 0)
125
+ return hasSink;
126
+ const aliases = identityAliases(ir, m.start_line, m.end_line, params);
127
+ // Call-argument forwarding (direct, identity alias, or interpolated hole).
128
+ const forwards = ir.calls.filter(c => c.location.line >= m.start_line && c.location.line <= m.end_line
129
+ && !sinkLines.has(c.location.line)
130
+ && !/(?:^|\.)Parameters$/.test(c.receiver ?? '')
131
+ && c.arguments.some(a => [...aliases].some(p => mentionsName(a.expression ?? '', p))));
132
+ if (forwards.length > 0) {
133
+ // A callee with its own sink that forwards elsewhere leaks there. One without
134
+ // a sink is decided by the methods it forwards to, when every forward resolves
135
+ // exactly to a method in another project file and that method is decided.
136
+ if (hasSink || depth >= MAX_FORWARD_DEPTH)
137
+ return false;
138
+ // Only a bare parameter handed on as an argument counts: a transform, alias or
139
+ // interpolation of it is not followed (the cross-file phase does not either).
140
+ const bare = forwards.every(c => c.arguments.every(a => {
141
+ const e = (a.expression ?? '').trim();
142
+ return params.includes(e) || ![...aliases].some(p => mentionsName(e, p));
143
+ }));
144
+ if (!bare)
145
+ return false;
146
+ const resolver = projectGraph.resolver;
147
+ const chained = forwards.every(call => {
148
+ const r = resolver.resolveCall(call, file);
149
+ return !!r && r.resolution === 'exact' && r.targetFile !== file
150
+ && receiverMatchesTarget(call, r.targetClass)
151
+ && calleeDecidedBySinks(projectGraph, r.targetFile, r.targetMethod, depth + 1, new Set(visited));
152
+ });
153
+ if (!chained)
154
+ return false;
155
+ }
156
+ else if (!hasSink) {
157
+ return false;
158
+ }
159
+ // Field/property store: `saved = data` / `this.saved = data` / `Prop = data`.
160
+ for (const u of uses) {
161
+ if (u.line < m.start_line || u.line > m.end_line)
162
+ continue;
163
+ if (!aliases.has(u.variable))
164
+ continue;
165
+ if (sinkLines.has(u.line))
166
+ continue;
167
+ const lineDefs = defs.filter(d => d.line === u.line);
168
+ if (lineDefs.some(d => d.kind === 'field' || fields.has(d.variable)))
169
+ return false;
170
+ if (uses.some(o => o.line === u.line && o.variable !== u.variable && fields.has(o.variable)))
171
+ return false;
172
+ }
173
+ // Return of a parameter/alias from a non-void method: use on a line with
174
+ // no calls and no new local def (null-checks in void methods stay silent).
175
+ if (!isVoidReturn(m)) {
176
+ for (const u of uses) {
177
+ if (u.line < m.start_line || u.line > m.end_line)
178
+ continue;
179
+ if (!aliases.has(u.variable))
180
+ continue;
181
+ if (sinkLines.has(u.line))
182
+ continue;
183
+ if (ir.calls.some(c => c.location.line === u.line))
184
+ continue;
185
+ if (defs.some(d => d.line === u.line && d.kind === 'local'))
186
+ continue;
187
+ return false;
188
+ }
189
+ }
190
+ return true;
191
+ });
192
+ }
193
+ /** Receiver looks like a type name and must match the resolved target class. */
194
+ function receiverMatchesTarget(call, targetClass) {
195
+ const recv = call.receiver;
196
+ if (!recv || !/^[A-Z]/.test(recv))
197
+ return true;
198
+ if (recv.includes('.'))
199
+ return true; // namespace-qualified / member chain: leave to resolver
200
+ const simple = targetClass.split('.').pop() ?? targetClass;
201
+ return recv === simple || recv === targetClass;
202
+ }
203
+ export function dropEscapesToProjectCallees(fileAnalyses, projectGraph) {
204
+ const resolver = projectGraph.resolver;
205
+ for (const fa of fileAnalyses) {
206
+ const ir = fa.analysis;
207
+ if (ir.meta.language !== 'csharp')
208
+ continue;
209
+ const sinks = ir.taint?.sinks ?? [];
210
+ if (!sinks.some(s => s.type === ESCAPE))
211
+ continue;
212
+ const dropped = new Set();
213
+ for (const sink of sinks) {
214
+ if (sink.type !== ESCAPE || !sink.method)
215
+ continue;
216
+ const calls = ir.calls.filter(c => c.location.line === sink.line && c.method_name === sink.method);
217
+ if (calls.length === 0)
218
+ continue;
219
+ const projectCall = calls.every(call => {
220
+ const r = resolver.resolveCall(call, fa.file);
221
+ return !!r && r.resolution === 'exact' && r.targetFile !== fa.file
222
+ && receiverMatchesTarget(call, r.targetClass)
223
+ && calleeDecidedBySinks(projectGraph, r.targetFile, r.targetMethod);
224
+ });
225
+ if (projectCall)
226
+ dropped.add(sink.line);
227
+ }
228
+ if (dropped.size === 0)
229
+ continue;
230
+ const isDropped = (type, line) => type === ESCAPE && dropped.has(line);
231
+ // In place: the project graph holds the same arrays.
232
+ for (let i = sinks.length - 1; i >= 0; i--) {
233
+ if (isDropped(sinks[i].type, sinks[i].line))
234
+ sinks.splice(i, 1);
235
+ }
236
+ const flows = ir.taint.flows ?? [];
237
+ for (let i = flows.length - 1; i >= 0; i--) {
238
+ if (isDropped(flows[i].sink_type, flows[i].sink_line))
239
+ flows.splice(i, 1);
240
+ }
241
+ }
242
+ }
243
+ //# sourceMappingURL=project-callee-escape-gate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-callee-escape-gate.js","sourceRoot":"","sources":["../../src/analysis/project-callee-escape-gate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Where a Rust literal-equality guard credit ends (cognium-dev#293): the first
3
+ * rebind or possible mutation of the guarded name after the guard.
4
+ *
5
+ * Works on masked text (comments and string bodies blanked) over the whole
6
+ * credit region, not line by line, so a rustfmt-wrapped pattern or parameter
7
+ * list is seen in one piece. When in doubt it reports a rebind: ending the
8
+ * credit early only keeps a finding, never hides one.
9
+ *
10
+ * Ends the credit:
11
+ * - the left side of any `=` / `op=` that names it (`x = ..`, `let (x, _) = ..`,
12
+ * `if let W { f: x } = ..`, `(x, n) = ..`, `W { x, .. } = ..`, `*x = ..`),
13
+ * a bare `let x;`,
14
+ * - a `for … in` head or a match-arm head (`… =>`) that names it,
15
+ * - a nested `fn` or closure whose parameter list names it (any pattern),
16
+ * - `&mut x`, `write!(x, ..)`, `mem::swap/replace/take(.. x ..)`,
17
+ * - a method call `x.m(..)`: when the binding is `mut` (or `&mut`) any method
18
+ * outside a short read-only list; otherwise a known `&mut self` method.
19
+ *
20
+ * Known limits (not guard bugs; the engine does not carry these flows even
21
+ * without a guard): a derived value mutated later
22
+ * (`let mut c = String::from(x); c.push_str(other)`) and a struct field of
23
+ * another value reassigned.
24
+ */
25
+ export interface RebindOptions {
26
+ /** The guarded binding is `mut x` or `x: &mut T`, so any non-read-only method may mutate it. */
27
+ mutBinding: boolean;
28
+ }
29
+ /**
30
+ * Absolute index (first non-space char of the statement or head) of the
31
+ * earliest rebind or possible mutation of `name` in `m[from, to)`, or -1.
32
+ */
33
+ export declare function firstRebind(m: string, from: number, to: number, name: string, opts: RebindOptions): number;
34
+ //# sourceMappingURL=rust-literal-guard-rebind.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rust-literal-guard-rebind.d.ts","sourceRoot":"","sources":["../../src/analysis/rust-literal-guard-rebind.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAiFH,MAAM,WAAW,aAAa;IAC5B,gGAAgG;IAChG,UAAU,EAAE,OAAO,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,MAAM,CA4D1G"}
@@ -0,0 +1,197 @@
1
+ /**
2
+ * Where a Rust literal-equality guard credit ends (cognium-dev#293): the first
3
+ * rebind or possible mutation of the guarded name after the guard.
4
+ *
5
+ * Works on masked text (comments and string bodies blanked) over the whole
6
+ * credit region, not line by line, so a rustfmt-wrapped pattern or parameter
7
+ * list is seen in one piece. When in doubt it reports a rebind: ending the
8
+ * credit early only keeps a finding, never hides one.
9
+ *
10
+ * Ends the credit:
11
+ * - the left side of any `=` / `op=` that names it (`x = ..`, `let (x, _) = ..`,
12
+ * `if let W { f: x } = ..`, `(x, n) = ..`, `W { x, .. } = ..`, `*x = ..`),
13
+ * a bare `let x;`,
14
+ * - a `for … in` head or a match-arm head (`… =>`) that names it,
15
+ * - a nested `fn` or closure whose parameter list names it (any pattern),
16
+ * - `&mut x`, `write!(x, ..)`, `mem::swap/replace/take(.. x ..)`,
17
+ * - a method call `x.m(..)`: when the binding is `mut` (or `&mut`) any method
18
+ * outside a short read-only list; otherwise a known `&mut self` method.
19
+ *
20
+ * Known limits (not guard bugs; the engine does not carry these flows even
21
+ * without a guard): a derived value mutated later
22
+ * (`let mut c = String::from(x); c.push_str(other)`) and a struct field of
23
+ * another value reassigned.
24
+ */
25
+ /** `name` used as a bare identifier: not a field (`.x`), not a path segment (`a::x`, `x::b`). */
26
+ function bareRe(name) {
27
+ return new RegExp(String.raw `(?<![\w.]|::)${name}\b(?!\s*::)`);
28
+ }
29
+ /** Index of the `{` matching the `}` at `close` (walking back), or -1. */
30
+ function openOf(m, close, floor) {
31
+ let d = 0;
32
+ for (let i = close; i >= floor; i--) {
33
+ if (m[i] === '}')
34
+ d++;
35
+ else if (m[i] === '{' && --d === 0)
36
+ return i;
37
+ }
38
+ return -1;
39
+ }
40
+ /**
41
+ * Start of the pattern / assignee that ends just before `idx` (an `=` or `=>`):
42
+ * walks back to the previous `;`, `,`, `=>` or unmatched opener at depth 0.
43
+ * A `{ … }` preceded by a type name (`W { .. }`) is a struct pattern and is
44
+ * stepped over; any other `}` is the end of the previous statement or arm.
45
+ */
46
+ function headStart(m, idx, floor) {
47
+ let depth = 0;
48
+ for (let i = idx - 1; i >= floor; i--) {
49
+ const ch = m[i];
50
+ if (ch === ')' || ch === ']')
51
+ depth++;
52
+ else if (ch === '(' || ch === '[' || ch === '{') {
53
+ if (depth === 0)
54
+ return i + 1;
55
+ depth--;
56
+ }
57
+ else if (ch === '}') {
58
+ if (depth > 0) {
59
+ depth++;
60
+ continue;
61
+ }
62
+ const open = openOf(m, i, floor);
63
+ if (open > floor && /(?:[A-Z]\w*|::)\s*$/.test(m.slice(Math.max(floor, open - 80), open))) {
64
+ i = open;
65
+ continue;
66
+ }
67
+ return i + 1;
68
+ }
69
+ else if (depth === 0 && (ch === ';' || ch === ','))
70
+ return i + 1;
71
+ else if (depth === 0 && ch === '>' && m[i - 1] === '=')
72
+ return i + 1;
73
+ }
74
+ return floor;
75
+ }
76
+ /** Index just past the `)`/`|` that closes the list opened at `open`, or -1. */
77
+ function closeParen(m, open, to) {
78
+ let d = 0;
79
+ for (let i = open; i < to; i++) {
80
+ if (m[i] === '(' || m[i] === '[' || m[i] === '{')
81
+ d++;
82
+ else if ((m[i] === ')' || m[i] === ']' || m[i] === '}') && --d === 0)
83
+ return i + 1;
84
+ }
85
+ return -1;
86
+ }
87
+ /** True when the `=` at `i` is an assignment (`=`, `+=`, `<<=`, …), not `==`, `!=`, `<=`, `>=`, `=>`, `..=`. */
88
+ function isAssign(m, i) {
89
+ const next = m[i + 1];
90
+ const prev = m[i - 1];
91
+ if (next === '=' || next === '>')
92
+ return false;
93
+ if (prev === '=' || prev === '!' || prev === '.')
94
+ return false;
95
+ if (prev === '<' || prev === '>')
96
+ return m[i - 2] === prev; // `<<=` / `>>=`
97
+ return true;
98
+ }
99
+ /** `&self` methods on str / String / &str that never change the value. */
100
+ const READ_ONLY = new Set([
101
+ 'as_str', 'as_bytes', 'as_ref', 'as_os_str', 'as_path', 'as_deref', 'borrow', 'deref', 'len', 'is_empty',
102
+ 'to_string', 'to_owned', 'clone', 'into', 'chars', 'char_indices', 'bytes', 'lines', 'trim', 'trim_start',
103
+ 'trim_end', 'trim_matches', 'trim_start_matches', 'trim_end_matches', 'starts_with', 'ends_with', 'contains',
104
+ 'find', 'rfind', 'split', 'splitn', 'rsplit', 'rsplitn', 'split_whitespace', 'split_once', 'rsplit_once',
105
+ 'strip_prefix', 'strip_suffix', 'eq', 'ne', 'cmp', 'partial_cmp', 'eq_ignore_ascii_case', 'to_lowercase',
106
+ 'to_uppercase', 'to_ascii_lowercase', 'to_ascii_uppercase', 'replace', 'replacen', 'repeat', 'parse',
107
+ 'capacity', 'get', 'iter', 'is_char_boundary', 'matches', 'to_str', 'to_string_lossy', 'is_ascii',
108
+ ]);
109
+ /** `&mut self` methods, used when the binding is not known to be `mut`. */
110
+ const MUTATORS = new Set([
111
+ 'push', 'push_str', 'clear', 'insert_str', 'insert', 'extend', 'extend_from_slice', 'truncate', 'remove',
112
+ 'retain', 'drain', 'replace_range', 'make_ascii_lowercase', 'make_ascii_uppercase', 'clone_from',
113
+ 'write_fmt', 'write_str', 'write_char', 'add_assign', 'pop', 'split_off', 'as_mut_str', 'as_mut_vec',
114
+ 'as_mut', 'get_mut', 'iter_mut', 'append', 'resize', 'reserve',
115
+ ]);
116
+ /**
117
+ * Absolute index (first non-space char of the statement or head) of the
118
+ * earliest rebind or possible mutation of `name` in `m[from, to)`, or -1.
119
+ */
120
+ export function firstRebind(m, from, to, name, opts) {
121
+ const region = m.slice(from, to);
122
+ const bare = bareRe(name);
123
+ let best = -1;
124
+ const hit = (abs) => {
125
+ while (abs < to && /\s/.test(m[abs]))
126
+ abs++;
127
+ if (best < 0 || abs < best)
128
+ best = abs;
129
+ };
130
+ const scan = (re, f) => {
131
+ for (const mm of region.matchAll(re))
132
+ f(mm);
133
+ };
134
+ // Left side of an assignment, a `let` pattern, a destructuring assignment.
135
+ for (let i = from; i < to; i++) {
136
+ if (m[i] !== '=' || !isAssign(m, i))
137
+ continue;
138
+ const hs = headStart(m, i, from);
139
+ if (bare.test(m.slice(hs, i)))
140
+ hit(hs);
141
+ }
142
+ scan(new RegExp(String.raw `\blet\s+(?:mut\s+)?${name}\s*(?::[^;=]*)?;`, 'g'), (mm) => hit(from + mm.index));
143
+ // Match-arm heads.
144
+ scan(/=>/g, (mm) => {
145
+ const at = from + mm.index;
146
+ const hs = headStart(m, at, from);
147
+ if (bare.test(m.slice(hs, at)))
148
+ hit(hs);
149
+ });
150
+ // `for PATTERN in`.
151
+ scan(/\bfor\b(?!\s*<)([\s\S]*?)\bin\b/g, (mm) => { if (bare.test(mm[1]))
152
+ hit(from + mm.index); });
153
+ // Nested fn parameter lists (any pattern, any number of lines).
154
+ scan(/\bfn\s+\w+\s*/g, (mm) => {
155
+ let i = from + mm.index + mm[0].length;
156
+ if (m[i] === '<') {
157
+ let d = 0;
158
+ for (; i < to; i++) {
159
+ if (m[i] === '<')
160
+ d++;
161
+ else if (m[i] === '>' && m[i - 1] !== '-' && --d === 0) {
162
+ i++;
163
+ break;
164
+ }
165
+ }
166
+ while (i < to && /\s/.test(m[i]))
167
+ i++;
168
+ }
169
+ if (m[i] !== '(')
170
+ return;
171
+ const end = closeParen(m, i, to);
172
+ if (bare.test(m.slice(i, end < 0 ? to : end)))
173
+ hit(from + mm.index);
174
+ });
175
+ // Closure parameter lists `|…|` (opening bar in expression position).
176
+ scan(/(?:^|[(,=>{;]|\bmove)\s*\|/gm, (mm) => {
177
+ const open = from + mm.index + mm[0].length - 1;
178
+ const close = m.indexOf('|', open + 1);
179
+ if (close < 0 || close >= to)
180
+ return;
181
+ const params = m.slice(open + 1, close);
182
+ if (!params.includes(';') && bare.test(params))
183
+ hit(open);
184
+ });
185
+ // `&mut x`, `write!(x, ..)`, `mem::swap/replace/take(.. x ..)`.
186
+ scan(new RegExp(String.raw `&\s*mut\s+${name}\b`, 'g'), (mm) => hit(from + mm.index));
187
+ scan(new RegExp(String.raw `\b(?:write|writeln)\s*!\s*\(\s*${name}\b`, 'g'), (mm) => hit(from + mm.index));
188
+ scan(new RegExp(String.raw `\bmem\s*::\s*(?:swap|replace|take)\s*\([^;]*?\b${name}\b`, 'g'), (mm) => hit(from + mm.index));
189
+ // Method calls on the name, including a call on the next line (`x\n.write_str(..)`).
190
+ scan(new RegExp(String.raw `(?<![\w.]|::)${name}\s*\.\s*(\w+)\s*(?:::\s*<[^>]*>\s*)?\(`, 'g'), (mm) => {
191
+ const method = mm[1];
192
+ if (opts.mutBinding ? !READ_ONLY.has(method) : MUTATORS.has(method))
193
+ hit(from + mm.index);
194
+ });
195
+ return best;
196
+ }
197
+ //# sourceMappingURL=rust-literal-guard-rebind.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rust-literal-guard-rebind.js","sourceRoot":"","sources":["../../src/analysis/rust-literal-guard-rebind.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,iGAAiG;AACjG,SAAS,MAAM,CAAC,IAAY;IAC1B,OAAO,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG,CAAA,gBAAgB,IAAI,aAAa,CAAC,CAAC;AACjE,CAAC;AAED,0EAA0E;AAC1E,SAAS,MAAM,CAAC,CAAS,EAAE,KAAa,EAAE,KAAa;IACrD,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,KAAK,IAAI,CAAC,GAAG,KAAK,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;QACpC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG;YAAE,CAAC,EAAE,CAAC;aACjB,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,EAAE,CAAC,KAAK,CAAC;YAAE,OAAO,CAAC,CAAC;IAC/C,CAAC;IACD,OAAO,CAAC,CAAC,CAAC;AACZ,CAAC;AAED;;;;;GAKG;AACH,SAAS,SAAS,CAAC,CAAS,EAAE,GAAW,EAAE,KAAa;IACtD,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAChB,IAAI,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,GAAG;YAAE,KAAK,EAAE,CAAC;aACjC,IAAI,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YAChD,IAAI,KAAK,KAAK,CAAC;gBAAE,OAAO,CAAC,GAAG,CAAC,CAAC;YAC9B,KAAK,EAAE,CAAC;QACV,CAAC;aAAM,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YACtB,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;gBAAC,KAAK,EAAE,CAAC;gBAAC,SAAS;YAAC,CAAC;YACrC,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;YACjC,IAAI,IAAI,GAAG,KAAK,IAAI,qBAAqB,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,GAAG,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC;gBAAC,CAAC,GAAG,IAAI,CAAC;gBAAC,SAAS;YAAC,CAAC;YAClH,OAAO,CAAC,GAAG,CAAC,CAAC;QACf,CAAC;aAAM,IAAI,KAAK,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,GAAG,CAAC;YAAE,OAAO,CAAC,GAAG,CAAC,CAAC;aAC9D,IAAI,KAAK,KAAK,CAAC,IAAI,EAAE,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG;YAAE,OAAO,CAAC,GAAG,CAAC,CAAC;IACvE,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,gFAAgF;AAChF,SAAS,UAAU,CAAC,CAAS,EAAE,IAAY,EAAE,EAAU;IACrD,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,KAAK,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;QAC/B,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG;YAAE,CAAC,EAAE,CAAC;aACjD,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;YAAE,OAAO,CAAC,GAAG,CAAC,CAAC;IACrF,CAAC;IACD,OAAO,CAAC,CAAC,CAAC;AACZ,CAAC;AAED,gHAAgH;AAChH,SAAS,QAAQ,CAAC,CAAS,EAAE,CAAS;IACpC,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACtB,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACtB,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG;QAAE,OAAO,KAAK,CAAC;IAC/C,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG;QAAE,OAAO,KAAK,CAAC;IAC/D,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG;QAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,gBAAgB;IAC5E,OAAO,IAAI,CAAC;AACd,CAAC;AAED,0EAA0E;AAC1E,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC;IACxB,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU;IACxG,WAAW,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY;IACzG,UAAU,EAAE,cAAc,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,aAAa,EAAE,WAAW,EAAE,UAAU;IAC5G,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,kBAAkB,EAAE,YAAY,EAAE,aAAa;IACxG,cAAc,EAAE,cAAc,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,aAAa,EAAE,sBAAsB,EAAE,cAAc;IACxG,cAAc,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO;IACpG,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,kBAAkB,EAAE,SAAS,EAAE,QAAQ,EAAE,iBAAiB,EAAE,UAAU;CAClG,CAAC,CAAC;AAEH,2EAA2E;AAC3E,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC;IACvB,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,mBAAmB,EAAE,UAAU,EAAE,QAAQ;IACxG,QAAQ,EAAE,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,YAAY;IAChG,WAAW,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY;IACpG,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS;CAC/D,CAAC,CAAC;AAOH;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,CAAS,EAAE,IAAY,EAAE,EAAU,EAAE,IAAY,EAAE,IAAmB;IAChG,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACjC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAC1B,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC;IACd,MAAM,GAAG,GAAG,CAAC,GAAW,EAAE,EAAE;QAC1B,OAAO,GAAG,GAAG,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YAAE,GAAG,EAAE,CAAC;QAC5C,IAAI,IAAI,GAAG,CAAC,IAAI,GAAG,GAAG,IAAI;YAAE,IAAI,GAAG,GAAG,CAAC;IACzC,CAAC,CAAC;IACF,MAAM,IAAI,GAAG,CAAC,EAAU,EAAE,CAAgC,EAAE,EAAE;QAC5D,KAAK,MAAM,EAAE,IAAI,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;YAAE,CAAC,CAAC,EAAqB,CAAC,CAAC;IACjE,CAAC,CAAC;IAEF,2EAA2E;IAC3E,KAAK,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;QAC/B,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC;YAAE,SAAS;QAC9C,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;QACjC,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;YAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IACzC,CAAC;IACD,IAAI,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG,CAAA,sBAAsB,IAAI,kBAAkB,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAC5G,mBAAmB;IACnB,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE;QACjB,MAAM,EAAE,GAAG,IAAI,GAAG,EAAE,CAAC,KAAK,CAAC;QAC3B,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC;QAClC,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IACH,oBAAoB;IACpB,IAAI,CAAC,kCAAkC,EAAE,CAAC,EAAE,EAAE,EAAE,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAAE,GAAG,CAAC,IAAI,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAClG,gEAAgE;IAChE,IAAI,CAAC,gBAAgB,EAAE,CAAC,EAAE,EAAE,EAAE;QAC5B,IAAI,CAAC,GAAG,IAAI,GAAG,EAAE,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QACvC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YACjB,IAAI,CAAC,GAAG,CAAC,CAAC;YACV,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;gBACnB,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG;oBAAE,CAAC,EAAE,CAAC;qBACjB,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,IAAI,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;oBAAC,CAAC,EAAE,CAAC;oBAAC,MAAM;gBAAC,CAAC;YACzE,CAAC;YACD,OAAO,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAAE,CAAC,EAAE,CAAC;QACxC,CAAC;QACD,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG;YAAE,OAAO;QACzB,MAAM,GAAG,GAAG,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QACjC,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YAAE,GAAG,CAAC,IAAI,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC;IACtE,CAAC,CAAC,CAAC;IACH,sEAAsE;IACtE,IAAI,CAAC,8BAA8B,EAAE,CAAC,EAAE,EAAE,EAAE;QAC1C,MAAM,IAAI,GAAG,IAAI,GAAG,EAAE,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;QAChD,MAAM,KAAK,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC;QACvC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,IAAI,EAAE;YAAE,OAAO;QACrC,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC;QACxC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;YAAE,GAAG,CAAC,IAAI,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IACH,gEAAgE;IAChE,IAAI,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG,CAAA,aAAa,IAAI,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IACrF,IAAI,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG,CAAA,kCAAkC,IAAI,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAC1G,IAAI,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG,CAAA,kDAAkD,IAAI,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAC1H,qFAAqF;IACrF,IAAI,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG,CAAA,gBAAgB,IAAI,wCAAwC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE;QACnG,MAAM,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;QACrB,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC;YAAE,GAAG,CAAC,IAAI,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC;IAC5F,CAAC,CAAC,CAAC;IACH,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Rust literal-equality reject guard credit (cognium-dev#293, Rust cell).
3
+ *
4
+ * if tool != "uptime" && tool != "whoami" { return Err("not allowed".into()); }
5
+ * Command::new(tool).output() // `tool` is one of the two literals
6
+ *
7
+ * A guard whose block always rejects, written over string literals only,
8
+ * proves the guarded variable is one of those literals for the rest of the
9
+ * enclosing block. Recognised conditions (all compared values must be string
10
+ * literals, the guarded value one plain local or parameter):
11
+ *
12
+ * - `x != "a" && x != "b" …` (also `"a" != x`)
13
+ * - `!(x == "a" || x == "b" …)`
14
+ * - `!matches!(x, "a" | "b" …)`
15
+ * - `!["a", "b"].contains(&x)`
16
+ *
17
+ * Not credited: an `||` of `!=` (or an `&&` of `==`), a comparison to a
18
+ * non-literal, a guard on another variable, a guard that falls through or
19
+ * rejects only inside an inner branch, a guard with an `else`, and any
20
+ * `matches!` arm that is not a plain string literal.
21
+ *
22
+ * The credit is line-keyed. It starts after the guard block, ends with the
23
+ * enclosing block (so never reaches another function), stops at the line of
24
+ * the first rebind or possible mutation of the variable (or at the start of a
25
+ * loop that contains it; see `rust-literal-guard-rebind.ts`, which scans the
26
+ * whole region so wrapped patterns and parameter lists count), and skips a
27
+ * mention whose statement or line also reads another value
28
+ * (`Command::new(x).arg(other)`, an operand on a later line of the same
29
+ * statement, or a second statement on the same line).
30
+ */
31
+ import type { TaintSanitizer } from '../types/index.js';
32
+ export declare function findRustLiteralEqualityGuardSanitizers(code: string): TaintSanitizer[];
33
+ //# sourceMappingURL=rust-literal-guard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rust-literal-guard.d.ts","sourceRoot":"","sources":["../../src/analysis/rust-literal-guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AA6JxD,wBAAgB,sCAAsC,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,EAAE,CA2HrF"}