circle-ir 4.14.2 → 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.
- package/configs/sinks/golang.json +4 -4
- package/dist/analysis/config-loader.d.ts.map +1 -1
- package/dist/analysis/config-loader.js +11 -7
- package/dist/analysis/config-loader.js.map +1 -1
- package/dist/analysis/const-table-lookup.d.ts +29 -0
- package/dist/analysis/const-table-lookup.d.ts.map +1 -0
- package/dist/analysis/const-table-lookup.js +145 -0
- package/dist/analysis/const-table-lookup.js.map +1 -0
- package/dist/analysis/constant-caller-gate.d.ts +39 -0
- package/dist/analysis/constant-caller-gate.d.ts.map +1 -0
- package/dist/analysis/constant-caller-gate.js +298 -0
- package/dist/analysis/constant-caller-gate.js.map +1 -0
- package/dist/analysis/constant-propagation/evaluator.d.ts.map +1 -1
- package/dist/analysis/constant-propagation/evaluator.js +3 -1
- package/dist/analysis/constant-propagation/evaluator.js.map +1 -1
- package/dist/analysis/constant-propagation/patterns.d.ts +19 -0
- package/dist/analysis/constant-propagation/patterns.d.ts.map +1 -1
- package/dist/analysis/constant-propagation/patterns.js +33 -0
- package/dist/analysis/constant-propagation/patterns.js.map +1 -1
- package/dist/analysis/constant-propagation/propagator.d.ts +59 -0
- package/dist/analysis/constant-propagation/propagator.d.ts.map +1 -1
- package/dist/analysis/constant-propagation/propagator.js +396 -49
- package/dist/analysis/constant-propagation/propagator.js.map +1 -1
- package/dist/analysis/constant-propagation/types.d.ts +9 -0
- package/dist/analysis/constant-propagation/types.d.ts.map +1 -1
- package/dist/analysis/findings.d.ts.map +1 -1
- package/dist/analysis/findings.js +149 -4
- package/dist/analysis/findings.js.map +1 -1
- package/dist/analysis/go-strings-replacer.d.ts +21 -0
- package/dist/analysis/go-strings-replacer.d.ts.map +1 -0
- package/dist/analysis/go-strings-replacer.js +145 -0
- package/dist/analysis/go-strings-replacer.js.map +1 -0
- package/dist/analysis/interprocedural.d.ts.map +1 -1
- package/dist/analysis/interprocedural.js +148 -0
- package/dist/analysis/interprocedural.js.map +1 -1
- package/dist/analysis/java-array-element-keys.d.ts +14 -0
- package/dist/analysis/java-array-element-keys.d.ts.map +1 -0
- package/dist/analysis/java-array-element-keys.js +36 -0
- package/dist/analysis/java-array-element-keys.js.map +1 -0
- package/dist/analysis/java-canonical-prefix.d.ts +42 -0
- package/dist/analysis/java-canonical-prefix.d.ts.map +1 -0
- package/dist/analysis/java-canonical-prefix.js +145 -0
- package/dist/analysis/java-canonical-prefix.js.map +1 -0
- package/dist/analysis/java-crlf-strip.d.ts +30 -0
- package/dist/analysis/java-crlf-strip.d.ts.map +1 -0
- package/dist/analysis/java-crlf-strip.js +195 -0
- package/dist/analysis/java-crlf-strip.js.map +1 -0
- package/dist/analysis/js-crlf-strip.d.ts +26 -0
- package/dist/analysis/js-crlf-strip.d.ts.map +1 -0
- package/dist/analysis/js-crlf-strip.js +244 -0
- package/dist/analysis/js-crlf-strip.js.map +1 -0
- package/dist/analysis/passes/cleartext-credential-transport-pass.d.ts +2 -0
- package/dist/analysis/passes/cleartext-credential-transport-pass.d.ts.map +1 -1
- package/dist/analysis/passes/cleartext-credential-transport-pass.js +64 -12
- package/dist/analysis/passes/cleartext-credential-transport-pass.js.map +1 -1
- package/dist/analysis/passes/cross-file-pass.d.ts.map +1 -1
- package/dist/analysis/passes/cross-file-pass.js +43 -0
- package/dist/analysis/passes/cross-file-pass.js.map +1 -1
- package/dist/analysis/passes/csharp-sanitizer-credit.d.ts +12 -0
- package/dist/analysis/passes/csharp-sanitizer-credit.d.ts.map +1 -1
- package/dist/analysis/passes/csharp-sanitizer-credit.js +127 -12
- package/dist/analysis/passes/csharp-sanitizer-credit.js.map +1 -1
- package/dist/analysis/passes/interprocedural-pass.d.ts +28 -0
- package/dist/analysis/passes/interprocedural-pass.d.ts.map +1 -1
- package/dist/analysis/passes/interprocedural-pass.js +20 -1
- package/dist/analysis/passes/interprocedural-pass.js.map +1 -1
- package/dist/analysis/passes/language-sources-pass.d.ts +76 -2
- package/dist/analysis/passes/language-sources-pass.d.ts.map +1 -1
- package/dist/analysis/passes/language-sources-pass.js +2045 -156
- package/dist/analysis/passes/language-sources-pass.js.map +1 -1
- package/dist/analysis/passes/param-source-flow-gate-pass.d.ts +8 -0
- package/dist/analysis/passes/param-source-flow-gate-pass.d.ts.map +1 -1
- package/dist/analysis/passes/param-source-flow-gate-pass.js +214 -6
- package/dist/analysis/passes/param-source-flow-gate-pass.js.map +1 -1
- package/dist/analysis/passes/plaintext-password-storage-pass.d.ts +6 -0
- package/dist/analysis/passes/plaintext-password-storage-pass.d.ts.map +1 -1
- package/dist/analysis/passes/plaintext-password-storage-pass.js +160 -0
- package/dist/analysis/passes/plaintext-password-storage-pass.js.map +1 -1
- package/dist/analysis/passes/scan-secrets-pass.d.ts +1 -1
- package/dist/analysis/passes/scan-secrets-pass.d.ts.map +1 -1
- package/dist/analysis/passes/scan-secrets-pass.js +7 -1
- package/dist/analysis/passes/scan-secrets-pass.js.map +1 -1
- package/dist/analysis/passes/sink-filter-pass.d.ts +1 -1
- package/dist/analysis/passes/sink-filter-pass.d.ts.map +1 -1
- package/dist/analysis/passes/sink-filter-pass.js +509 -27
- package/dist/analysis/passes/sink-filter-pass.js.map +1 -1
- package/dist/analysis/passes/taint-matcher-pass.d.ts.map +1 -1
- package/dist/analysis/passes/taint-matcher-pass.js +2 -2
- package/dist/analysis/passes/taint-matcher-pass.js.map +1 -1
- package/dist/analysis/passes/taint-propagation-pass.d.ts.map +1 -1
- package/dist/analysis/passes/taint-propagation-pass.js +1606 -60
- package/dist/analysis/passes/taint-propagation-pass.js.map +1 -1
- package/dist/analysis/passes/weak-hash-pass.d.ts +6 -0
- package/dist/analysis/passes/weak-hash-pass.d.ts.map +1 -1
- package/dist/analysis/passes/weak-hash-pass.js +191 -4
- package/dist/analysis/passes/weak-hash-pass.js.map +1 -1
- package/dist/analysis/passes/weak-random-pass.d.ts +5 -0
- package/dist/analysis/passes/weak-random-pass.d.ts.map +1 -1
- package/dist/analysis/passes/weak-random-pass.js +30 -0
- package/dist/analysis/passes/weak-random-pass.js.map +1 -1
- package/dist/analysis/project-callee-escape-gate.d.ts +40 -0
- package/dist/analysis/project-callee-escape-gate.d.ts.map +1 -0
- package/dist/analysis/project-callee-escape-gate.js +243 -0
- package/dist/analysis/project-callee-escape-gate.js.map +1 -0
- package/dist/analysis/rust-literal-guard-rebind.d.ts +34 -0
- package/dist/analysis/rust-literal-guard-rebind.d.ts.map +1 -0
- package/dist/analysis/rust-literal-guard-rebind.js +197 -0
- package/dist/analysis/rust-literal-guard-rebind.js.map +1 -0
- package/dist/analysis/rust-literal-guard.d.ts +33 -0
- package/dist/analysis/rust-literal-guard.d.ts.map +1 -0
- package/dist/analysis/rust-literal-guard.js +422 -0
- package/dist/analysis/rust-literal-guard.js.map +1 -0
- package/dist/analysis/scalar-derivation.d.ts +33 -0
- package/dist/analysis/scalar-derivation.d.ts.map +1 -0
- package/dist/analysis/scalar-derivation.js +368 -0
- package/dist/analysis/scalar-derivation.js.map +1 -0
- package/dist/analysis/taint-matcher.d.ts +2 -2
- package/dist/analysis/taint-matcher.d.ts.map +1 -1
- package/dist/analysis/taint-matcher.js +695 -34
- package/dist/analysis/taint-matcher.js.map +1 -1
- package/dist/analysis/taint-propagation.d.ts +26 -1
- package/dist/analysis/taint-propagation.d.ts.map +1 -1
- package/dist/analysis/taint-propagation.js +375 -24
- package/dist/analysis/taint-propagation.js.map +1 -1
- package/dist/analyzer.d.ts +16 -2
- package/dist/analyzer.d.ts.map +1 -1
- package/dist/analyzer.js +19 -2
- package/dist/analyzer.js.map +1 -1
- package/dist/browser/circle-ir.js +25539 -19200
- package/dist/core/circle-ir-core.cjs +3945 -2126
- package/dist/core/circle-ir-core.js +3945 -2126
- package/dist/core/extractors/calls.d.ts +12 -1
- package/dist/core/extractors/calls.d.ts.map +1 -1
- package/dist/core/extractors/calls.js +332 -22
- package/dist/core/extractors/calls.js.map +1 -1
- package/dist/core/extractors/dfg.js +336 -10
- package/dist/core/extractors/dfg.js.map +1 -1
- package/dist/core/extractors/types.d.ts +5 -1
- package/dist/core/extractors/types.d.ts.map +1 -1
- package/dist/core/extractors/types.js +62 -0
- package/dist/core/extractors/types.js.map +1 -1
- package/dist/graph/analysis-pass.d.ts +6 -1
- package/dist/graph/analysis-pass.d.ts.map +1 -1
- package/dist/graph/analysis-pass.js +2 -1
- package/dist/graph/analysis-pass.js.map +1 -1
- package/dist/graph/code-graph.d.ts +9 -0
- package/dist/graph/code-graph.d.ts.map +1 -1
- package/dist/graph/code-graph.js +11 -0
- package/dist/graph/code-graph.js.map +1 -1
- package/dist/navigation/navigation-index.d.ts +134 -14
- package/dist/navigation/navigation-index.d.ts.map +1 -1
- package/dist/navigation/navigation-index.js +1158 -104
- package/dist/navigation/navigation-index.js.map +1 -1
- package/dist/navigation/types.d.ts +59 -2
- package/dist/navigation/types.d.ts.map +1 -1
- package/dist/resolution/cross-file.d.ts +16 -0
- package/dist/resolution/cross-file.d.ts.map +1 -1
- package/dist/resolution/cross-file.js +110 -42
- package/dist/resolution/cross-file.js.map +1 -1
- package/dist/resolution/type-hierarchy.d.ts +3 -0
- package/dist/resolution/type-hierarchy.d.ts.map +1 -1
- package/dist/resolution/type-hierarchy.js +45 -1
- package/dist/resolution/type-hierarchy.js.map +1 -1
- package/dist/types/index.d.ts +33 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js.map +1 -1
- package/dist/wasm/web-tree-sitter.wasm +0 -0
- package/package.json +3 -3
|
@@ -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"}
|