circle-ir 4.15.0 → 4.16.1

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 +127 -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 +25 -0
  37. package/dist/analysis/passes/csharp-sanitizer-credit.d.ts.map +1 -1
  38. package/dist/analysis/passes/csharp-sanitizer-credit.js +157 -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 +1234 -127
  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 +326 -34
  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 +1376 -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 +24432 -19928
  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,422 @@
1
+ import { firstRebind } from './rust-literal-guard-rebind.js';
2
+ const CREDITED_TYPES = [
3
+ 'command_injection', 'path_traversal', 'sql_injection', 'ssrf', 'open_redirect',
4
+ 'xss', 'code_injection', 'ldap_injection', 'xpath_injection', 'log_injection',
5
+ 'trust_boundary', 'external_taint_escape',
6
+ ];
7
+ /** `code` with comments blanked and string / char literal bodies replaced by spaces (same length). */
8
+ function maskRust(code) {
9
+ const out = code.split('');
10
+ const n = code.length;
11
+ const blank = (from, to) => {
12
+ for (let k = from; k < to; k++)
13
+ if (out[k] !== '\n')
14
+ out[k] = ' ';
15
+ };
16
+ let i = 0;
17
+ while (i < n) {
18
+ const c = code[i];
19
+ if (c === '/' && code[i + 1] === '/') {
20
+ let j = i;
21
+ while (j < n && code[j] !== '\n')
22
+ j++;
23
+ blank(i, j);
24
+ i = j;
25
+ }
26
+ else if (c === '/' && code[i + 1] === '*') {
27
+ let j = i + 2;
28
+ let depth = 1;
29
+ while (j < n && depth > 0) {
30
+ if (code[j] === '/' && code[j + 1] === '*') {
31
+ depth++;
32
+ j += 2;
33
+ }
34
+ else if (code[j] === '*' && code[j + 1] === '/') {
35
+ depth--;
36
+ j += 2;
37
+ }
38
+ else
39
+ j++;
40
+ }
41
+ blank(i, j);
42
+ i = j;
43
+ }
44
+ else if (c === 'r' && /^r#*"/.test(code.slice(i, i + 12)) && !/[\w]/.test(code[i - 1] ?? ' ')) {
45
+ const hashes = /^r(#*)"/.exec(code.slice(i, i + 12))[1].length;
46
+ const close = '"' + '#'.repeat(hashes);
47
+ const end = code.indexOf(close, i + 2 + hashes);
48
+ const j = end === -1 ? n : end + close.length;
49
+ blank(i + 2 + hashes, Math.max(i + 2 + hashes, j - close.length));
50
+ i = j;
51
+ }
52
+ else if (c === '"') {
53
+ let j = i + 1;
54
+ while (j < n && code[j] !== '"')
55
+ j += code[j] === '\\' ? 2 : 1;
56
+ blank(i + 1, j);
57
+ i = j + 1;
58
+ }
59
+ else if (c === "'") {
60
+ // A char literal ('x', '\n', '\u{..}'), not a lifetime ('a).
61
+ const m = /^'(?:\\(?:u\{[0-9a-fA-F]+\}|x[0-9a-fA-F]{2}|.)|[^\\'])'/.exec(code.slice(i, i + 14));
62
+ if (m) {
63
+ blank(i + 1, i + m[0].length - 1);
64
+ i += m[0].length;
65
+ }
66
+ else
67
+ i++;
68
+ }
69
+ else
70
+ i++;
71
+ }
72
+ return out.join('');
73
+ }
74
+ /** Index of the `}` matching the `{` at `open` in `masked`, or -1. */
75
+ function matchBrace(masked, open) {
76
+ let depth = 0;
77
+ for (let i = open; i < masked.length; i++) {
78
+ if (masked[i] === '{')
79
+ depth++;
80
+ else if (masked[i] === '}' && --depth === 0)
81
+ return i;
82
+ }
83
+ return -1;
84
+ }
85
+ const STR = String.raw `"(?:[^"\\]|\\.)*"`;
86
+ const VAR = String.raw `([A-Za-z_]\w*)(?:\s*\.\s*as_str\s*\(\s*\))?`;
87
+ /** The guarded variable when `cond` is a literal allow-list rejection condition, else null. */
88
+ function guardedVariable(cond) {
89
+ const c = cond.trim();
90
+ let m;
91
+ // `!matches!(x, "a" | "b")`
92
+ if ((m = new RegExp(String.raw `^!\s*matches!\s*\(\s*${VAR}\s*,\s*((?:\|\s*)?${STR}(?:\s*\|\s*${STR})*)\s*,?\s*\)$`).exec(c))) {
93
+ return m[1];
94
+ }
95
+ // `!["a", "b"].contains(&x)`
96
+ if ((m = new RegExp(String.raw `^!\s*\[\s*${STR}(?:\s*,\s*${STR})*\s*,?\s*\]\s*\.\s*contains\s*\(\s*&\s*${VAR}\s*\)$`).exec(c))) {
97
+ return m[1];
98
+ }
99
+ // `!(x == "a" || x == "b")`
100
+ if ((m = /^!\s*\(([\s\S]*)\)$/.exec(c))) {
101
+ return chain(m[1], '||', '==');
102
+ }
103
+ // `x != "a" && x != "b"`
104
+ return chain(c, '&&', '!=');
105
+ }
106
+ /** Terms joined by `joiner`, each `V op "lit"` or `"lit" op V` with one shared V. */
107
+ function chain(text, joiner, op) {
108
+ const other = joiner === '||' ? '&&' : '||';
109
+ if (text.includes(other) || /[()]/.test(text.replace(/\.\s*as_str\s*\(\s*\)/g, '').replace(new RegExp(STR, 'g'), '""'))) {
110
+ return null;
111
+ }
112
+ let name = null;
113
+ const parts = text.split(joiner);
114
+ for (const part of parts) {
115
+ const t = part.trim();
116
+ const m = new RegExp(String.raw `^(?:${VAR}\s*${op}\s*${STR}|${STR}\s*${op}\s*${VAR})$`).exec(t);
117
+ if (!m)
118
+ return null;
119
+ const v = m[1] ?? m[2];
120
+ if (name !== null && v !== name)
121
+ return null;
122
+ name = v;
123
+ }
124
+ return name;
125
+ }
126
+ const KEYWORDS = new Set([
127
+ 'let', 'mut', 'ref', 'as', 'if', 'else', 'return', 'true', 'false', 'self', 'move', 'in', 'for',
128
+ 'while', 'loop', 'match', 'fn', 'pub', 'use', 'mod', 'const', 'static', 'unsafe', 'where', 'dyn',
129
+ 'impl', 'break', 'continue', 'crate', 'super', 'async', 'await', 'box', 'type', 'struct', 'enum',
130
+ 'str', 'u8', 'u16', 'u32', 'u64', 'usize', 'i8', 'i16', 'i32', 'i64', 'isize', 'bool', 'char', 'f32', 'f64',
131
+ ]);
132
+ /**
133
+ * True when the (masked) `line` reads a value other than `name`: another
134
+ * local, a lower-case free or module-qualified call (`std::env::args()`), or
135
+ * an inline format argument (`{other}`). Method names, associated functions
136
+ * of a type (`Command::new`), macros, type names and closure parameters are
137
+ * not values.
138
+ */
139
+ function readsOtherValue(original, masked, name) {
140
+ for (const m of original.matchAll(new RegExp(STR, 'g'))) {
141
+ for (const f of m[0].matchAll(/(?<!\{)\{([A-Za-z_]\w*)(?:[:}])/g))
142
+ if (f[1] !== name)
143
+ return true;
144
+ }
145
+ const closureParams = new Set();
146
+ for (const m of masked.matchAll(/\|\s*([\w\s,&:()]*?)\s*\|/g)) {
147
+ for (const p of m[1].matchAll(/[A-Za-z_]\w*/g))
148
+ closureParams.add(p[0]);
149
+ }
150
+ const re = /[A-Za-z_]\w*/g;
151
+ let m;
152
+ while ((m = re.exec(masked)) !== null) {
153
+ const id = m[0];
154
+ const before = masked.slice(0, m.index);
155
+ const after = masked.slice(m.index + id.length);
156
+ if (id === name || KEYWORDS.has(id) || closureParams.has(id))
157
+ continue;
158
+ if (/\.\s*$/.test(before))
159
+ continue; // method or field
160
+ if (/^\s*!/.test(after) && !/^\s*!=/.test(after))
161
+ continue; // macro
162
+ if (/[A-Z]/.test(id[0]))
163
+ continue; // type, variant, constant
164
+ if (/(?:\blet\s+(?:mut\s+)?)$/.test(before))
165
+ continue; // the binding being introduced
166
+ if (/::\s*$/.test(before))
167
+ continue; // path tail (`io::stdin` handled by its head)
168
+ return true; // other local, free call, module path
169
+ }
170
+ return false;
171
+ }
172
+ /**
173
+ * `&mut` parameter only: the bare name passed as a call argument can be
174
+ * mutated by the callee (checked per line).
175
+ */
176
+ function passesMutParam(line, n) {
177
+ if (!new RegExp(String.raw `(?<![\w.])(?:[A-Za-z_]\w*(?:\s*::\s*[A-Za-z_]\w*)*)\s*\((?:[^)]*,\s*)?${n}\b`).test(line))
178
+ return false;
179
+ // Exclude method calls on name itself (`name.foo(`), handled by firstRebind.
180
+ return !new RegExp(String.raw `\b${n}\s*\.\s*\w+\s*\(`).test(line) || new RegExp(String.raw `(?<![\w.])\w+\s*\(\s*${n}\b`).test(line);
181
+ }
182
+ export function findRustLiteralEqualityGuardSanitizers(code) {
183
+ const masked = maskRust(code);
184
+ const origLines = code.split('\n');
185
+ const maskedLines = masked.split('\n');
186
+ const lineStarts = [];
187
+ for (let i = 0, off = 0; i < origLines.length; i++) {
188
+ lineStarts.push(off);
189
+ off += origLines[i].length + 1;
190
+ }
191
+ const lineOf = (idx) => {
192
+ let lo = 0, hi = lineStarts.length - 1;
193
+ while (lo < hi) {
194
+ const mid = (lo + hi + 1) >> 1;
195
+ if (lineStarts[mid] <= idx)
196
+ lo = mid;
197
+ else
198
+ hi = mid - 1;
199
+ }
200
+ return lo; // 0-based
201
+ };
202
+ const out = [];
203
+ for (const ifm of masked.matchAll(/\bif\b/g)) {
204
+ const at = ifm.index;
205
+ if (/\belse\s*$/.test(masked.slice(Math.max(0, at - 12), at)))
206
+ continue;
207
+ if (/\blet\b/.test(masked.slice(at + 2, at + 8)))
208
+ continue; // `if let`
209
+ // Condition: up to the `{` that opens the block, at bracket depth 0.
210
+ let depth = 0;
211
+ let open = -1;
212
+ for (let i = at + 2; i < masked.length; i++) {
213
+ const ch = masked[i];
214
+ if (ch === '(' || ch === '[')
215
+ depth++;
216
+ else if (ch === ')' || ch === ']')
217
+ depth--;
218
+ else if (ch === '{' && depth === 0) {
219
+ open = i;
220
+ break;
221
+ }
222
+ else if (ch === ';' || ch === '}')
223
+ break;
224
+ }
225
+ if (open < 0)
226
+ continue;
227
+ const name = guardedVariable(code.slice(at + 2, open));
228
+ if (name === null)
229
+ continue;
230
+ const close = matchBrace(masked, open);
231
+ if (close < 0)
232
+ continue;
233
+ if (/^\s*else\b/.test(masked.slice(close + 1, close + 12)))
234
+ continue;
235
+ // The block must reject at its own top level (not inside an inner branch).
236
+ // Strip nested braces and braceless closure bodies (`|…| expr`) so a
237
+ // `return` inside a closure does not count as the guard rejecting.
238
+ const body = masked.slice(open + 1, close).split('');
239
+ for (let i = 0, d = 0; i < body.length; i++) {
240
+ if (body[i] === '{') {
241
+ d++;
242
+ body[i] = ' ';
243
+ }
244
+ else if (body[i] === '}') {
245
+ d--;
246
+ body[i] = ' ';
247
+ }
248
+ else if (d > 0 && body[i] !== '\n')
249
+ body[i] = ' ';
250
+ }
251
+ let bodyText = body.join('');
252
+ bodyText = bodyText.replace(/\|\s*[\w\s,&:()]*?\s*\|\s*[^;{}]*/g, ' ');
253
+ if (!/(?<![\w.#])(?:return\b|panic\s*!|unreachable\s*!|bail\s*!|(?:std\s*::\s*)?process\s*::\s*exit\s*\()/.test(bodyText))
254
+ continue;
255
+ // Credit region: after the guard block to the end of the enclosing block.
256
+ let end = masked.length;
257
+ for (let i = close + 1, d = 0; i < masked.length; i++) {
258
+ if (masked[i] === '{')
259
+ d++;
260
+ else if (masked[i] === '}' && --d < 0) {
261
+ end = i;
262
+ break;
263
+ }
264
+ }
265
+ // Is the guarded binding a `&mut` parameter of the enclosing function?
266
+ let mutParam = false;
267
+ {
268
+ const before = masked.slice(0, at);
269
+ let fnOpen = -1;
270
+ for (const m of before.matchAll(/\bfn\s+\w+\s*(?:<[^>]*>)?\s*\(/g))
271
+ fnOpen = m.index + m[0].length - 1;
272
+ if (fnOpen >= 0) {
273
+ let depth = 1, fnClose = -1;
274
+ for (let i = fnOpen + 1; i < at; i++) {
275
+ if (masked[i] === '(')
276
+ depth++;
277
+ else if (masked[i] === ')' && --depth === 0) {
278
+ fnClose = i;
279
+ break;
280
+ }
281
+ }
282
+ if (fnClose > fnOpen) {
283
+ const params = masked.slice(fnOpen + 1, fnClose);
284
+ mutParam = new RegExp(String.raw `\b${name}\s*:\s*&(?:\s*'\w+)?\s*mut\b`).test(params);
285
+ }
286
+ }
287
+ }
288
+ // Could the binding be `mut`? Any `mut name` / `name: &mut` before the
289
+ // guard counts (wider than needed, which only ends the credit sooner).
290
+ const mutBinding = mutParam || new RegExp(String.raw `\bmut\s+${name}\b|\b${name}\s*:\s*&(?:\s*'\w+)?\s*mut\b`).test(masked.slice(0, at));
291
+ // Whole lines after the guard's closing line, up to the line before the
292
+ // enclosing block's closing brace (or the end of the file).
293
+ const firstLine = lineOf(close) + 1;
294
+ const lastLine = end === masked.length ? origLines.length - 1 : lineOf(end) - 1;
295
+ let stop = lastLine + 1;
296
+ // A rebind or mutation ends the credit (scanned over the whole region, so a
297
+ // pattern or parameter list wrapped over lines is seen in one piece);
298
+ // inside a later loop it ends at the loop.
299
+ let rebindLine = lastLine + 1;
300
+ const rb = firstRebind(masked, close + 1, end, name, { mutBinding });
301
+ if (rb >= 0)
302
+ rebindLine = lineOf(rb);
303
+ if (mutParam) {
304
+ for (let l = firstLine; l < rebindLine && l <= lastLine; l++) {
305
+ if (passesMutParam(maskedLines[l], name)) {
306
+ rebindLine = l;
307
+ break;
308
+ }
309
+ }
310
+ }
311
+ if (rebindLine <= lastLine) {
312
+ const l = rebindLine;
313
+ stop = l;
314
+ for (const lp of masked.slice(close + 1, end).matchAll(/\b(?:for|while|loop)\b[^{;]*\{/g)) {
315
+ const lpOpen = close + 1 + lp.index + lp[0].length - 1;
316
+ const lpClose = matchBrace(masked, lpOpen);
317
+ const lpLine = lineOf(lpOpen);
318
+ if (lpClose >= 0 && lineOf(lpClose) >= l && lpLine <= l)
319
+ stop = Math.min(stop, lpLine);
320
+ }
321
+ }
322
+ const mention = new RegExp(String.raw `(?<![\w.])${name}\b`);
323
+ for (let l = firstLine; l < stop && l <= lastLine; l++) {
324
+ if (!mention.test(maskedLines[l]))
325
+ continue;
326
+ // Evaluate "reads another value" over the whole statement that contains
327
+ // this mention (up to a terminating `;` or the matching close of the
328
+ // enclosing call), not only the single line the name sits on.
329
+ // The line itself is checked too, so a second statement on the same
330
+ // line (`a(tool); b(other);`) also ends the credit for that line.
331
+ const stmt = statementSpan(code, masked, lineStarts[l], end);
332
+ if (readsOtherValue(stmt.orig, stmt.masked, name))
333
+ continue;
334
+ if (readsOtherValue(origLines[l], maskedLines[l], name))
335
+ continue;
336
+ out.push({
337
+ type: 'rust_literal_equality_guard',
338
+ method: 'guard',
339
+ line: l + 1,
340
+ sanitizes: CREDITED_TYPES,
341
+ });
342
+ }
343
+ }
344
+ return out;
345
+ }
346
+ /**
347
+ * Exact text of the statement that contains `lineStart` (absolute index),
348
+ * clipped to `endIdx`. Walks back to the previous `;` / `{` / `}` at depth 0
349
+ * and forward to a terminating `;` (or unmatched closer), so a multi-line
350
+ * `format!(…, tool, extra)` is considered as one statement without pulling in
351
+ * the enclosing function signature.
352
+ */
353
+ function statementSpan(code, masked, lineStart, endIdx) {
354
+ // Walk back to the previous statement boundary at bracket depth 0.
355
+ let start = lineStart;
356
+ let depth = 0;
357
+ for (let i = lineStart - 1; i >= 0; i--) {
358
+ const ch = masked[i];
359
+ if (ch === ')' || ch === ']')
360
+ depth++;
361
+ else if (ch === '(' || ch === '[') {
362
+ if (depth === 0) {
363
+ start = i + 1;
364
+ break;
365
+ }
366
+ depth--;
367
+ }
368
+ else if (ch === '}') {
369
+ if (depth === 0) {
370
+ start = i + 1;
371
+ break;
372
+ }
373
+ depth++; // matching an earlier `{` when walking back through nested blocks
374
+ }
375
+ else if (ch === '{') {
376
+ if (depth === 0) {
377
+ start = i + 1;
378
+ break;
379
+ }
380
+ depth--;
381
+ }
382
+ else if (ch === ';' && depth === 0) {
383
+ start = i + 1;
384
+ break;
385
+ }
386
+ if (i === 0)
387
+ start = 0;
388
+ }
389
+ // Walk forward to terminating `;` at depth 0, or stop at `endIdx` / unmatched `}`.
390
+ depth = 0;
391
+ let stop = Math.min(endIdx, masked.length);
392
+ for (let i = start; i < stop; i++) {
393
+ const ch = masked[i];
394
+ if (ch === '(' || ch === '[')
395
+ depth++;
396
+ else if (ch === ')' || ch === ']') {
397
+ if (depth === 0) {
398
+ stop = i;
399
+ break;
400
+ }
401
+ depth--;
402
+ }
403
+ else if (ch === '{')
404
+ depth++;
405
+ else if (ch === '}') {
406
+ if (depth === 0) {
407
+ stop = i;
408
+ break;
409
+ }
410
+ depth--;
411
+ }
412
+ else if (ch === ';' && depth === 0) {
413
+ stop = i + 1;
414
+ break;
415
+ }
416
+ }
417
+ return {
418
+ orig: code.slice(start, stop),
419
+ masked: masked.slice(start, stop),
420
+ };
421
+ }
422
+ //# sourceMappingURL=rust-literal-guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rust-literal-guard.js","sourceRoot":"","sources":["../../src/analysis/rust-literal-guard.ts"],"names":[],"mappings":"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"}
@@ -22,4 +22,12 @@ export declare function isScalarDerivation(rhs: string, language: string): boole
22
22
  * by a whole-expression measure or test. Taint does not flow into these defs.
23
23
  */
24
24
  export declare function scalarDerivedDefIds(defs: readonly DFGDef[], code: string, language: string): Set<number>;
25
+ /**
26
+ * DFG def ids of a Go local initialised by `make(<type>, <len>[, <cap>])` whose
27
+ * every size argument is an integer literal or a variable rejected above a
28
+ * constant earlier in the same function (`if n > K { return }`). The buffer
29
+ * holds zero values; its size is bounded, so the request text that chose the
30
+ * size does not reach a sink through it. An unbounded size is not credited.
31
+ */
32
+ export declare function boundedMakeDefIds(defs: readonly DFGDef[], code: string, language: string): Set<number>;
25
33
  //# sourceMappingURL=scalar-derivation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"scalar-derivation.d.ts","sourceRoot":"","sources":["../../src/analysis/scalar-derivation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAyGhD,wEAAwE;AACxE,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAkBzE;AAgBD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAaxG"}
1
+ {"version":3,"file":"scalar-derivation.d.ts","sourceRoot":"","sources":["../../src/analysis/scalar-derivation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAyGhD,wEAAwE;AACxE,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAkBzE;AAgBD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAaxG;AA0ID;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAsBtG"}
@@ -193,4 +193,176 @@ export function scalarDerivedDefIds(defs, code, language) {
193
193
  }
194
194
  return out;
195
195
  }
196
+ /** An integer literal, optionally with `_` separators or a hex/binary/octal prefix. */
197
+ const GO_INT_LITERAL = /^(?:0[xX][0-9a-fA-F_]+|0[bB][01_]+|0[oO]?[0-7_]+|[1-9][0-9_]*|0)$/;
198
+ /** Braces in a Go line, with string, rune and raw-string literals blanked out. */
199
+ function goBraceText(text) {
200
+ return text.replace(/"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|`[^`]*`/g, '""');
201
+ }
202
+ /**
203
+ * Names `n` bounded by `if <... n > K | n >= K ...> { ...; return|panic|continue }`
204
+ * in `lines[from .. to)` where the guard still dominates line `to`. The condition
205
+ * may join the bound with `||` only: under `&&` the branch would not reject every
206
+ * large value. K is an integer literal or a name in `consts` (a same-file integer
207
+ * `const`, see `goIntConstNames`).
208
+ *
209
+ * A guard only holds while the block it sits in is open: once the brace depth
210
+ * falls below the guard's depth (the enclosing `if`, loop, closure or `else`
211
+ * branch closed), or a new `case`/`default` clause of the same switch starts,
212
+ * other paths reach `to` without passing the guard. A write to `n` after the
213
+ * guard (`n = …`, `n op= …`, `n++`, `n--`, or `&n` handed to a callee such as
214
+ * `fmt.Sscanf`) voids every bound on it.
215
+ */
216
+ function goUpperBoundGuardedAt(lines, from, to, name, consts) {
217
+ const esc = name.replace(/[$]/g, '\\$');
218
+ const bound = new RegExp(`^\\(*\\s*${esc}\\s*>=?\\s*([\\w]+)\\s*\\)*$`);
219
+ const reassign = new RegExp(`(?:^|[\\s,;(])${esc}(?:\\s*,\\s*\\w+)*\\s*(?::=|=(?!=)|\\+=|-=|\\*=|/=|%=|&=|\\|=|\\^=|&\\^=|<<=|>>=)` +
220
+ `|(?<![\\w.])${esc}\\s*(?:\\+\\+|--)` +
221
+ `|(?<![&\\w])&\\s*${esc}\\b`);
222
+ // Depth (in braces) of each guard still in force, in source order.
223
+ let guards = [];
224
+ let depth = 0;
225
+ for (let i = from; i < to; i++) {
226
+ const text = lines[i].replace(/\s*\/\/.*$/, '').trim();
227
+ if (guards.length > 0 && reassign.test(text))
228
+ guards = [];
229
+ const ifm = /^if\s+(.+?)\s*\{$/.exec(text);
230
+ if (ifm && i + 1 < to) {
231
+ const cond = ifm[1];
232
+ if (!cond.includes('&&')) {
233
+ const parts = cond.split('||').map((p) => p.trim());
234
+ const hit = parts.some((p) => {
235
+ const m = bound.exec(p);
236
+ return m !== null && (GO_INT_LITERAL.test(m[1]) || consts.has(m[1]));
237
+ });
238
+ if (hit) {
239
+ // The guard block must end in an exit before its closing brace.
240
+ let inner = 1;
241
+ let last = '';
242
+ let j = i + 1;
243
+ for (; j < to; j++) {
244
+ const t = lines[j].replace(/\s*\/\/.*$/, '').trim();
245
+ for (const ch of goBraceText(t))
246
+ inner += ch === '{' ? 1 : ch === '}' ? -1 : 0;
247
+ if (inner <= 0)
248
+ break;
249
+ if (t)
250
+ last = t;
251
+ }
252
+ if (inner <= 0 && /^(?:return\b|panic\(|continue\b)/.test(last)) {
253
+ // The block opened and closed on lines i..j; depth is unchanged.
254
+ guards.push(depth);
255
+ i = j;
256
+ continue;
257
+ }
258
+ }
259
+ }
260
+ }
261
+ if (guards.length > 0 && /^(?:case\b.*|default\s*):$/.test(text)) {
262
+ guards = guards.filter((d) => d < depth);
263
+ }
264
+ for (const ch of goBraceText(text)) {
265
+ if (ch === '{')
266
+ depth++;
267
+ else if (ch === '}') {
268
+ depth--;
269
+ if (guards.length > 0)
270
+ guards = guards.filter((d) => d <= depth);
271
+ }
272
+ }
273
+ }
274
+ return guards.length > 0;
275
+ }
276
+ /**
277
+ * Names declared exactly once in the file, as a package- or function-level
278
+ * `const NAME [type] = <integer literal>` (alone or inside a `const ( … )` block),
279
+ * and never otherwise defined: no `:=` or `var` of the same name, no parameter,
280
+ * result or range variable of that name, no second `const` of it. A name that
281
+ * could be shadowed by a variable is not a constant bound.
282
+ */
283
+ function goIntConstNames(lines) {
284
+ const decl = /^(?:const\s+)?([A-Za-z_]\w*)(?:\s+[\w.]+)?\s*=\s*([\w]+)\s*$/;
285
+ const found = new Map();
286
+ let inBlock = false;
287
+ const declLines = new Set();
288
+ for (let i = 0; i < lines.length; i++) {
289
+ const text = lines[i].replace(/\s*\/\/.*$/, '').trim();
290
+ if (inBlock) {
291
+ if (text === ')') {
292
+ inBlock = false;
293
+ continue;
294
+ }
295
+ const m = decl.exec(text);
296
+ if (m && GO_INT_LITERAL.test(m[2]) && !/^const\b/.test(text)) {
297
+ found.set(m[1], (found.get(m[1]) ?? 0) + 1);
298
+ declLines.add(i);
299
+ }
300
+ continue;
301
+ }
302
+ if (/^const\s*\($/.test(text)) {
303
+ inBlock = true;
304
+ continue;
305
+ }
306
+ if (/^const\s/.test(text)) {
307
+ const m = decl.exec(text);
308
+ if (m && GO_INT_LITERAL.test(m[2])) {
309
+ found.set(m[1], (found.get(m[1]) ?? 0) + 1);
310
+ declLines.add(i);
311
+ }
312
+ }
313
+ }
314
+ const out = new Set();
315
+ for (const [name, count] of found) {
316
+ if (count !== 1)
317
+ continue;
318
+ const esc = name.replace(/[$]/g, '\\$');
319
+ const other = new RegExp(`(?:^|[\\s,(])${esc}(?:\\s*,\\s*[\\w]+)*\\s*(?::=|=(?!=))` +
320
+ `|\\b(?:var|const|type|func)\\s+${esc}\\b` +
321
+ `|[(,]\\s*${esc}(?:\\s*,\\s*\\w+)*\\s+[\\w*\\[.]`);
322
+ const shadowed = lines.some((l, i) => {
323
+ if (declLines.has(i))
324
+ return false;
325
+ const t = l.replace(/\s*\/\/.*$/, '');
326
+ return new RegExp(`(?<![\\w.])${esc}(?![\\w])`).test(t) && other.test(t);
327
+ });
328
+ if (!shadowed)
329
+ out.add(name);
330
+ }
331
+ return out;
332
+ }
333
+ /**
334
+ * DFG def ids of a Go local initialised by `make(<type>, <len>[, <cap>])` whose
335
+ * every size argument is an integer literal or a variable rejected above a
336
+ * constant earlier in the same function (`if n > K { return }`). The buffer
337
+ * holds zero values; its size is bounded, so the request text that chose the
338
+ * size does not reach a sink through it. An unbounded size is not credited.
339
+ */
340
+ export function boundedMakeDefIds(defs, code, language) {
341
+ const out = new Set();
342
+ if (language !== 'go')
343
+ return out;
344
+ const lines = code.split('\n');
345
+ const consts = goIntConstNames(lines);
346
+ for (const def of defs) {
347
+ if (def.kind !== 'local')
348
+ continue;
349
+ const text = lines[def.line - 1];
350
+ if (text === undefined)
351
+ continue;
352
+ const rhs = initializerOf(text, def.variable, 'go');
353
+ const mk = rhs === null ? null : /^make\(\s*(\[\][\w.*]+|map\[[^\]]+\][\w.*]+)\s*,\s*([^()]*?)\s*\)$/.exec(rhs);
354
+ if (!mk)
355
+ continue;
356
+ const sizes = mk[2].split(',').map((s) => s.trim());
357
+ if (sizes.length > 2 || sizes.some((s) => s === ''))
358
+ continue;
359
+ let fnStart = def.line - 1;
360
+ while (fnStart > 0 && !/^func\b/.test(lines[fnStart]))
361
+ fnStart--;
362
+ const ok = sizes.every((s) => GO_INT_LITERAL.test(s) || (/^[A-Za-z_]\w*$/.test(s) && goUpperBoundGuardedAt(lines, fnStart, def.line - 1, s, consts)));
363
+ if (ok)
364
+ out.add(def.id);
365
+ }
366
+ return out;
367
+ }
196
368
  //# sourceMappingURL=scalar-derivation.js.map