circle-ir 3.9.7 → 3.9.10
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/dist/analysis/passes/broad-catch-pass.d.ts +29 -0
- package/dist/analysis/passes/broad-catch-pass.js +79 -0
- package/dist/analysis/passes/broad-catch-pass.js.map +1 -0
- package/dist/analysis/passes/deep-inheritance-pass.d.ts +30 -0
- package/dist/analysis/passes/deep-inheritance-pass.js +82 -0
- package/dist/analysis/passes/deep-inheritance-pass.js.map +1 -0
- package/dist/analysis/passes/double-close-pass.d.ts +33 -0
- package/dist/analysis/passes/double-close-pass.js +109 -0
- package/dist/analysis/passes/double-close-pass.js.map +1 -0
- package/dist/analysis/passes/infinite-loop-pass.d.ts +31 -0
- package/dist/analysis/passes/infinite-loop-pass.js +126 -0
- package/dist/analysis/passes/infinite-loop-pass.js.map +1 -0
- package/dist/analysis/passes/react-inline-jsx-pass.d.ts +36 -0
- package/dist/analysis/passes/react-inline-jsx-pass.js +140 -0
- package/dist/analysis/passes/react-inline-jsx-pass.js.map +1 -0
- package/dist/analysis/passes/redundant-loop-pass.d.ts +30 -0
- package/dist/analysis/passes/redundant-loop-pass.js +146 -0
- package/dist/analysis/passes/redundant-loop-pass.js.map +1 -0
- package/dist/analysis/passes/serial-await-pass.d.ts +36 -0
- package/dist/analysis/passes/serial-await-pass.js +132 -0
- package/dist/analysis/passes/serial-await-pass.js.map +1 -0
- package/dist/analysis/passes/sink-filter-pass.js +7 -1
- package/dist/analysis/passes/sink-filter-pass.js.map +1 -1
- package/dist/analysis/passes/swallowed-exception-pass.d.ts +35 -0
- package/dist/analysis/passes/swallowed-exception-pass.js +103 -0
- package/dist/analysis/passes/swallowed-exception-pass.js.map +1 -0
- package/dist/analysis/passes/unbounded-collection-pass.d.ts +32 -0
- package/dist/analysis/passes/unbounded-collection-pass.js +128 -0
- package/dist/analysis/passes/unbounded-collection-pass.js.map +1 -0
- package/dist/analysis/passes/unhandled-exception-pass.d.ts +34 -0
- package/dist/analysis/passes/unhandled-exception-pass.js +123 -0
- package/dist/analysis/passes/unhandled-exception-pass.js.map +1 -0
- package/dist/analysis/passes/use-after-close-pass.d.ts +30 -0
- package/dist/analysis/passes/use-after-close-pass.js +100 -0
- package/dist/analysis/passes/use-after-close-pass.js.map +1 -0
- package/dist/analysis/taint-matcher.js +1 -0
- package/dist/analysis/taint-matcher.js.map +1 -1
- package/dist/analyzer.d.ts +12 -1
- package/dist/analyzer.js +34 -1
- package/dist/analyzer.js.map +1 -1
- package/dist/browser/circle-ir.js +1035 -3
- package/dist/core/circle-ir-core.cjs +2 -1
- package/dist/core/circle-ir-core.js +2 -1
- package/dist/graph/dominator-graph.d.ts +53 -0
- package/dist/graph/dominator-graph.js +256 -0
- package/dist/graph/dominator-graph.js.map +1 -0
- package/dist/graph/exception-flow-graph.d.ts +44 -0
- package/dist/graph/exception-flow-graph.js +75 -0
- package/dist/graph/exception-flow-graph.js.map +1 -0
- package/dist/graph/index.d.ts +2 -0
- package/dist/graph/index.js +2 -0
- package/dist/graph/index.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -10591,7 +10591,8 @@ function findSinks(calls, patterns) {
|
|
|
10591
10591
|
cwe: pattern.cwe,
|
|
10592
10592
|
location,
|
|
10593
10593
|
line: call.location.line,
|
|
10594
|
-
confidence
|
|
10594
|
+
confidence,
|
|
10595
|
+
method: call.method_name
|
|
10595
10596
|
});
|
|
10596
10597
|
}
|
|
10597
10598
|
}
|
|
@@ -10526,7 +10526,8 @@ function findSinks(calls, patterns) {
|
|
|
10526
10526
|
cwe: pattern.cwe,
|
|
10527
10527
|
location,
|
|
10528
10528
|
line: call.location.line,
|
|
10529
|
-
confidence
|
|
10529
|
+
confidence,
|
|
10530
|
+
method: call.method_name
|
|
10530
10531
|
});
|
|
10531
10532
|
}
|
|
10532
10533
|
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DominatorGraph
|
|
3
|
+
*
|
|
4
|
+
* Computes the dominator tree for a control-flow graph using the
|
|
5
|
+
* Cooper et al. "A Simple, Fast Dominance Algorithm" (2001).
|
|
6
|
+
*
|
|
7
|
+
* Chosen over Lengauer-Tarjan because typical intra-procedural CFGs have
|
|
8
|
+
* fewer than 100 blocks — O(n²) worst-case is negligible and the algorithm
|
|
9
|
+
* is straightforward to verify correct.
|
|
10
|
+
*
|
|
11
|
+
* Reference:
|
|
12
|
+
* Cooper, K.D., Harvey, T.J., Kennedy, K. (2001). "A Simple, Fast Dominance
|
|
13
|
+
* Algorithm". Software Practice & Experience, 4, 1–10.
|
|
14
|
+
*
|
|
15
|
+
* Design invariants:
|
|
16
|
+
* - No Node.js-specific APIs. Browser + Node.js + Cloudflare Workers safe.
|
|
17
|
+
* - Does not mutate the input CFG.
|
|
18
|
+
* - Unreachable blocks are excluded from all dominator queries.
|
|
19
|
+
*/
|
|
20
|
+
import type { CFG } from '../types/index.js';
|
|
21
|
+
/**
|
|
22
|
+
* Dominator tree for a CFG, computed with the Cooper et al. algorithm.
|
|
23
|
+
*
|
|
24
|
+
* Entry blocks have no immediate dominator (immediateDominator returns null).
|
|
25
|
+
* Only blocks reachable from the entry are included.
|
|
26
|
+
*/
|
|
27
|
+
export declare class DominatorGraph {
|
|
28
|
+
private readonly idom;
|
|
29
|
+
private readonly rpoIndex;
|
|
30
|
+
private readonly entryId;
|
|
31
|
+
/** Cached reverse map: blockId → all blockIds it strictly dominates. */
|
|
32
|
+
private _dominated;
|
|
33
|
+
constructor(cfg: CFG, entryId?: number);
|
|
34
|
+
/**
|
|
35
|
+
* Returns true if block `a` dominates block `b`.
|
|
36
|
+
* A block dominates itself (reflexive).
|
|
37
|
+
*/
|
|
38
|
+
dominates(a: number, b: number): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Returns true if block `a` strictly dominates block `b` (a ≠ b and a dom b).
|
|
41
|
+
*/
|
|
42
|
+
strictlyDominates(a: number, b: number): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Returns the immediate dominator of `blockId`, or null for the entry block
|
|
45
|
+
* (or any block not in the dominator tree).
|
|
46
|
+
*/
|
|
47
|
+
immediateDominator(blockId: number): number | null;
|
|
48
|
+
/**
|
|
49
|
+
* Returns all block IDs strictly dominated by `blockId`.
|
|
50
|
+
* (Computed lazily and cached on first call.)
|
|
51
|
+
*/
|
|
52
|
+
dominated(blockId: number): number[];
|
|
53
|
+
}
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DominatorGraph
|
|
3
|
+
*
|
|
4
|
+
* Computes the dominator tree for a control-flow graph using the
|
|
5
|
+
* Cooper et al. "A Simple, Fast Dominance Algorithm" (2001).
|
|
6
|
+
*
|
|
7
|
+
* Chosen over Lengauer-Tarjan because typical intra-procedural CFGs have
|
|
8
|
+
* fewer than 100 blocks — O(n²) worst-case is negligible and the algorithm
|
|
9
|
+
* is straightforward to verify correct.
|
|
10
|
+
*
|
|
11
|
+
* Reference:
|
|
12
|
+
* Cooper, K.D., Harvey, T.J., Kennedy, K. (2001). "A Simple, Fast Dominance
|
|
13
|
+
* Algorithm". Software Practice & Experience, 4, 1–10.
|
|
14
|
+
*
|
|
15
|
+
* Design invariants:
|
|
16
|
+
* - No Node.js-specific APIs. Browser + Node.js + Cloudflare Workers safe.
|
|
17
|
+
* - Does not mutate the input CFG.
|
|
18
|
+
* - Unreachable blocks are excluded from all dominator queries.
|
|
19
|
+
*/
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
// Internal helpers
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
/**
|
|
24
|
+
* Compute Reverse Post-Order starting from `entryId`.
|
|
25
|
+
* Returns the RPO traversal order and a map from blockId → RPO position.
|
|
26
|
+
* Blocks unreachable from `entryId` are excluded.
|
|
27
|
+
*/
|
|
28
|
+
function computeRPO(cfg, entryId) {
|
|
29
|
+
// Build outgoing adjacency
|
|
30
|
+
const outgoing = new Map();
|
|
31
|
+
for (const edge of cfg.edges) {
|
|
32
|
+
const list = outgoing.get(edge.from) ?? [];
|
|
33
|
+
list.push(edge.to);
|
|
34
|
+
outgoing.set(edge.from, list);
|
|
35
|
+
}
|
|
36
|
+
// Iterative DFS to compute post-order, then reverse
|
|
37
|
+
const visited = new Set();
|
|
38
|
+
const postOrder = [];
|
|
39
|
+
const stack = [{ id: entryId, childIndex: 0 }];
|
|
40
|
+
visited.add(entryId);
|
|
41
|
+
while (stack.length > 0) {
|
|
42
|
+
const top = stack[stack.length - 1];
|
|
43
|
+
const children = outgoing.get(top.id) ?? [];
|
|
44
|
+
// Find next unvisited child
|
|
45
|
+
let pushed = false;
|
|
46
|
+
while (top.childIndex < children.length) {
|
|
47
|
+
const child = children[top.childIndex++];
|
|
48
|
+
if (!visited.has(child)) {
|
|
49
|
+
visited.add(child);
|
|
50
|
+
stack.push({ id: child, childIndex: 0 });
|
|
51
|
+
pushed = true;
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (!pushed) {
|
|
56
|
+
// All children visited — add to post-order
|
|
57
|
+
postOrder.push(top.id);
|
|
58
|
+
stack.pop();
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
const rpoOrder = postOrder.reverse();
|
|
62
|
+
const rpoIndex = new Map();
|
|
63
|
+
for (let i = 0; i < rpoOrder.length; i++) {
|
|
64
|
+
rpoIndex.set(rpoOrder[i], i);
|
|
65
|
+
}
|
|
66
|
+
return { rpoOrder, rpoIndex };
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Cooper et al. intersect function.
|
|
70
|
+
* Walks up the idom tree from b1 and b2 until a common ancestor is found.
|
|
71
|
+
* Uses RPO positions for comparisons (smaller RPO index = earlier in RPO = closer to entry).
|
|
72
|
+
*
|
|
73
|
+
* IMPORTANT: The entry block must have idom[entry] = entry (self-loop sentinel)
|
|
74
|
+
* so the walk terminates. This sentinel is removed from the public idom map after
|
|
75
|
+
* computation, but must be present during computation.
|
|
76
|
+
*/
|
|
77
|
+
function intersect(b1, b2, idom, rpoIndex) {
|
|
78
|
+
let finger1 = b1;
|
|
79
|
+
let finger2 = b2;
|
|
80
|
+
while (finger1 !== finger2) {
|
|
81
|
+
// Walk finger1 up while its RPO position is deeper (larger index) than finger2
|
|
82
|
+
while ((rpoIndex.get(finger1) ?? Number.MAX_SAFE_INTEGER) >
|
|
83
|
+
(rpoIndex.get(finger2) ?? Number.MAX_SAFE_INTEGER)) {
|
|
84
|
+
const parent = idom.get(finger1);
|
|
85
|
+
if (parent === undefined || parent === finger1)
|
|
86
|
+
break; // at root or self-loop
|
|
87
|
+
finger1 = parent;
|
|
88
|
+
}
|
|
89
|
+
// Walk finger2 up while its RPO position is deeper than finger1
|
|
90
|
+
while ((rpoIndex.get(finger2) ?? Number.MAX_SAFE_INTEGER) >
|
|
91
|
+
(rpoIndex.get(finger1) ?? Number.MAX_SAFE_INTEGER)) {
|
|
92
|
+
const parent = idom.get(finger2);
|
|
93
|
+
if (parent === undefined || parent === finger2)
|
|
94
|
+
break; // at root or self-loop
|
|
95
|
+
finger2 = parent;
|
|
96
|
+
}
|
|
97
|
+
// If neither changed (both at root or unreachable), break
|
|
98
|
+
if (finger1 === finger2)
|
|
99
|
+
break;
|
|
100
|
+
// Safety: if both are at positions we can't walk further, break
|
|
101
|
+
const rpo1 = rpoIndex.get(finger1) ?? Number.MAX_SAFE_INTEGER;
|
|
102
|
+
const rpo2 = rpoIndex.get(finger2) ?? Number.MAX_SAFE_INTEGER;
|
|
103
|
+
if (rpo1 === rpo2 && finger1 !== finger2)
|
|
104
|
+
break; // can't converge further
|
|
105
|
+
}
|
|
106
|
+
return finger1;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Cooper et al. iterative idom computation.
|
|
110
|
+
* Requires rpoOrder and rpoIndex from computeRPO.
|
|
111
|
+
* Returns a map: blockId → immediate dominator blockId.
|
|
112
|
+
* Entry block has idom[entry] = entry (sentinel) during computation;
|
|
113
|
+
* callers remove this after the function returns.
|
|
114
|
+
*/
|
|
115
|
+
function computeIdom(cfg, rpoOrder, rpoIndex, entryId) {
|
|
116
|
+
// Build incoming adjacency
|
|
117
|
+
const incoming = new Map();
|
|
118
|
+
for (const edge of cfg.edges) {
|
|
119
|
+
const list = incoming.get(edge.to) ?? [];
|
|
120
|
+
list.push(edge.from);
|
|
121
|
+
incoming.set(edge.to, list);
|
|
122
|
+
}
|
|
123
|
+
const idom = new Map();
|
|
124
|
+
// Initialise: entry block idom = itself (sentinel for termination)
|
|
125
|
+
idom.set(entryId, entryId);
|
|
126
|
+
// Iterate until stable
|
|
127
|
+
let changed = true;
|
|
128
|
+
while (changed) {
|
|
129
|
+
changed = false;
|
|
130
|
+
// Process in RPO order, skip entry (index 0)
|
|
131
|
+
for (let i = 1; i < rpoOrder.length; i++) {
|
|
132
|
+
const b = rpoOrder[i];
|
|
133
|
+
const preds = incoming.get(b) ?? [];
|
|
134
|
+
// Pick the first predecessor that already has an idom computed
|
|
135
|
+
// (i.e., already processed in RPO order)
|
|
136
|
+
let newIdom;
|
|
137
|
+
for (const p of preds) {
|
|
138
|
+
if (idom.has(p)) {
|
|
139
|
+
newIdom = p;
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
if (newIdom === undefined)
|
|
144
|
+
continue;
|
|
145
|
+
// Intersect with all other processed predecessors
|
|
146
|
+
for (const p of preds) {
|
|
147
|
+
if (p === newIdom)
|
|
148
|
+
continue;
|
|
149
|
+
if (idom.has(p)) {
|
|
150
|
+
newIdom = intersect(p, newIdom, idom, rpoIndex);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
if (idom.get(b) !== newIdom) {
|
|
154
|
+
idom.set(b, newIdom);
|
|
155
|
+
changed = true;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return idom;
|
|
160
|
+
}
|
|
161
|
+
// ---------------------------------------------------------------------------
|
|
162
|
+
// Public class
|
|
163
|
+
// ---------------------------------------------------------------------------
|
|
164
|
+
/**
|
|
165
|
+
* Dominator tree for a CFG, computed with the Cooper et al. algorithm.
|
|
166
|
+
*
|
|
167
|
+
* Entry blocks have no immediate dominator (immediateDominator returns null).
|
|
168
|
+
* Only blocks reachable from the entry are included.
|
|
169
|
+
*/
|
|
170
|
+
export class DominatorGraph {
|
|
171
|
+
idom;
|
|
172
|
+
rpoIndex;
|
|
173
|
+
entryId;
|
|
174
|
+
/** Cached reverse map: blockId → all blockIds it strictly dominates. */
|
|
175
|
+
_dominated = null;
|
|
176
|
+
constructor(cfg, entryId) {
|
|
177
|
+
if (cfg.blocks.length === 0) {
|
|
178
|
+
this.entryId = entryId ?? 0;
|
|
179
|
+
this.idom = new Map();
|
|
180
|
+
this.rpoIndex = new Map();
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
// Determine entry: prefer provided entryId, then type='entry' block,
|
|
184
|
+
// then the block with the smallest id.
|
|
185
|
+
this.entryId =
|
|
186
|
+
entryId ??
|
|
187
|
+
cfg.blocks.find(b => b.type === 'entry')?.id ??
|
|
188
|
+
cfg.blocks.reduce((a, b) => (a.id < b.id ? a : b)).id;
|
|
189
|
+
const { rpoOrder, rpoIndex } = computeRPO(cfg, this.entryId);
|
|
190
|
+
this.rpoIndex = rpoIndex;
|
|
191
|
+
this.idom = computeIdom(cfg, rpoOrder, rpoIndex, this.entryId);
|
|
192
|
+
// Remove the sentinel self-reference for the entry block
|
|
193
|
+
// so immediateDominator(entryId) returns null
|
|
194
|
+
this.idom.delete(this.entryId);
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Returns true if block `a` dominates block `b`.
|
|
198
|
+
* A block dominates itself (reflexive).
|
|
199
|
+
*/
|
|
200
|
+
dominates(a, b) {
|
|
201
|
+
if (a === b)
|
|
202
|
+
return true;
|
|
203
|
+
return this.strictlyDominates(a, b);
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Returns true if block `a` strictly dominates block `b` (a ≠ b and a dom b).
|
|
207
|
+
*/
|
|
208
|
+
strictlyDominates(a, b) {
|
|
209
|
+
if (a === b)
|
|
210
|
+
return false;
|
|
211
|
+
// Walk up the idom chain from b; if we reach a, then a dom b.
|
|
212
|
+
const visited = new Set();
|
|
213
|
+
let cur = this.idom.get(b);
|
|
214
|
+
while (cur !== undefined && !visited.has(cur)) {
|
|
215
|
+
if (cur === a)
|
|
216
|
+
return true;
|
|
217
|
+
visited.add(cur);
|
|
218
|
+
cur = this.idom.get(cur);
|
|
219
|
+
}
|
|
220
|
+
return false;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Returns the immediate dominator of `blockId`, or null for the entry block
|
|
224
|
+
* (or any block not in the dominator tree).
|
|
225
|
+
*/
|
|
226
|
+
immediateDominator(blockId) {
|
|
227
|
+
return this.idom.get(blockId) ?? null;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Returns all block IDs strictly dominated by `blockId`.
|
|
231
|
+
* (Computed lazily and cached on first call.)
|
|
232
|
+
*/
|
|
233
|
+
dominated(blockId) {
|
|
234
|
+
if (!this._dominated) {
|
|
235
|
+
this._dominated = new Map();
|
|
236
|
+
for (const [child, parent] of this.idom.entries()) {
|
|
237
|
+
// Walk up from child to find all ancestors (blocks that dominate child)
|
|
238
|
+
const ancestors = [];
|
|
239
|
+
const seen = new Set();
|
|
240
|
+
let cur = parent;
|
|
241
|
+
while (cur !== undefined && !seen.has(cur)) {
|
|
242
|
+
seen.add(cur);
|
|
243
|
+
ancestors.push(cur);
|
|
244
|
+
cur = this.idom.get(cur);
|
|
245
|
+
}
|
|
246
|
+
for (const anc of ancestors) {
|
|
247
|
+
const list = this._dominated.get(anc) ?? [];
|
|
248
|
+
list.push(child);
|
|
249
|
+
this._dominated.set(anc, list);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
return this._dominated.get(blockId) ?? [];
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
//# sourceMappingURL=dominator-graph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dominator-graph.js","sourceRoot":"","sources":["../../src/graph/dominator-graph.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ExceptionFlowGraph — lightweight wrapper over CFG exception edges.
|
|
3
|
+
*
|
|
4
|
+
* The CFG builder emits edges with `type === 'exception'` connecting the
|
|
5
|
+
* first block of a try body (`from`) to the first block of the corresponding
|
|
6
|
+
* catch handler (`to`). This class indexes those edges so exception-aware
|
|
7
|
+
* passes can query try/catch structure without re-scanning the edge list.
|
|
8
|
+
*/
|
|
9
|
+
import type { CFG, CFGBlock } from '../types/index.js';
|
|
10
|
+
export interface TryCatchInfo {
|
|
11
|
+
tryEntryId: number;
|
|
12
|
+
catchEntryId: number;
|
|
13
|
+
/** First block of the try body. */
|
|
14
|
+
tryBlock: CFGBlock;
|
|
15
|
+
/** First block of the catch handler. */
|
|
16
|
+
catchBlock: CFGBlock;
|
|
17
|
+
}
|
|
18
|
+
export declare class ExceptionFlowGraph {
|
|
19
|
+
/** All try/catch pairs found in the CFG. */
|
|
20
|
+
readonly pairs: TryCatchInfo[];
|
|
21
|
+
/** Block IDs that are catch-handler entry blocks. */
|
|
22
|
+
readonly catchEntryIds: Set<number>;
|
|
23
|
+
/** Block IDs that are try-body entry blocks. */
|
|
24
|
+
readonly tryEntryIds: Set<number>;
|
|
25
|
+
private readonly tryCatchMap;
|
|
26
|
+
private readonly catchTryMap;
|
|
27
|
+
constructor(cfg: CFG, blockById: Map<number, CFGBlock>);
|
|
28
|
+
/** True if at least one try/catch pair was found. */
|
|
29
|
+
get hasTryCatch(): boolean;
|
|
30
|
+
/** True if the given block ID is a catch-handler entry block. */
|
|
31
|
+
isCatchEntry(blockId: number): boolean;
|
|
32
|
+
/** True if the given block ID is a try-body entry block. */
|
|
33
|
+
isTryEntry(blockId: number): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Returns the catch-entry block IDs for the given try-entry block.
|
|
36
|
+
* Multiple values mean multiple catch clauses for the same try.
|
|
37
|
+
*/
|
|
38
|
+
catchBlocksFor(tryEntryId: number): number[];
|
|
39
|
+
/**
|
|
40
|
+
* Returns the try-entry block ID corresponding to a catch-entry block,
|
|
41
|
+
* or `undefined` if the block is not a catch entry.
|
|
42
|
+
*/
|
|
43
|
+
tryBlockFor(catchEntryId: number): number | undefined;
|
|
44
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ExceptionFlowGraph — lightweight wrapper over CFG exception edges.
|
|
3
|
+
*
|
|
4
|
+
* The CFG builder emits edges with `type === 'exception'` connecting the
|
|
5
|
+
* first block of a try body (`from`) to the first block of the corresponding
|
|
6
|
+
* catch handler (`to`). This class indexes those edges so exception-aware
|
|
7
|
+
* passes can query try/catch structure without re-scanning the edge list.
|
|
8
|
+
*/
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
// ExceptionFlowGraph
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
export class ExceptionFlowGraph {
|
|
13
|
+
/** All try/catch pairs found in the CFG. */
|
|
14
|
+
pairs;
|
|
15
|
+
/** Block IDs that are catch-handler entry blocks. */
|
|
16
|
+
catchEntryIds;
|
|
17
|
+
/** Block IDs that are try-body entry blocks. */
|
|
18
|
+
tryEntryIds;
|
|
19
|
+
tryCatchMap; // tryEntryId → [catchEntryId, …]
|
|
20
|
+
catchTryMap; // catchEntryId → tryEntryId
|
|
21
|
+
constructor(cfg, blockById) {
|
|
22
|
+
this.pairs = [];
|
|
23
|
+
this.catchEntryIds = new Set();
|
|
24
|
+
this.tryEntryIds = new Set();
|
|
25
|
+
this.tryCatchMap = new Map();
|
|
26
|
+
this.catchTryMap = new Map();
|
|
27
|
+
for (const edge of cfg.edges) {
|
|
28
|
+
if (edge.type !== 'exception')
|
|
29
|
+
continue;
|
|
30
|
+
const tryBlock = blockById.get(edge.from);
|
|
31
|
+
const catchBlock = blockById.get(edge.to);
|
|
32
|
+
if (!tryBlock || !catchBlock)
|
|
33
|
+
continue;
|
|
34
|
+
this.tryEntryIds.add(edge.from);
|
|
35
|
+
this.catchEntryIds.add(edge.to);
|
|
36
|
+
const catches = this.tryCatchMap.get(edge.from) ?? [];
|
|
37
|
+
catches.push(edge.to);
|
|
38
|
+
this.tryCatchMap.set(edge.from, catches);
|
|
39
|
+
this.catchTryMap.set(edge.to, edge.from);
|
|
40
|
+
this.pairs.push({
|
|
41
|
+
tryEntryId: edge.from,
|
|
42
|
+
catchEntryId: edge.to,
|
|
43
|
+
tryBlock,
|
|
44
|
+
catchBlock,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/** True if at least one try/catch pair was found. */
|
|
49
|
+
get hasTryCatch() {
|
|
50
|
+
return this.pairs.length > 0;
|
|
51
|
+
}
|
|
52
|
+
/** True if the given block ID is a catch-handler entry block. */
|
|
53
|
+
isCatchEntry(blockId) {
|
|
54
|
+
return this.catchEntryIds.has(blockId);
|
|
55
|
+
}
|
|
56
|
+
/** True if the given block ID is a try-body entry block. */
|
|
57
|
+
isTryEntry(blockId) {
|
|
58
|
+
return this.tryEntryIds.has(blockId);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Returns the catch-entry block IDs for the given try-entry block.
|
|
62
|
+
* Multiple values mean multiple catch clauses for the same try.
|
|
63
|
+
*/
|
|
64
|
+
catchBlocksFor(tryEntryId) {
|
|
65
|
+
return this.tryCatchMap.get(tryEntryId) ?? [];
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Returns the try-entry block ID corresponding to a catch-entry block,
|
|
69
|
+
* or `undefined` if the block is not a catch entry.
|
|
70
|
+
*/
|
|
71
|
+
tryBlockFor(catchEntryId) {
|
|
72
|
+
return this.catchTryMap.get(catchEntryId);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=exception-flow-graph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exception-flow-graph.js","sourceRoot":"","sources":["../../src/graph/exception-flow-graph.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAiBH,8EAA8E;AAC9E,qBAAqB;AACrB,8EAA8E;AAE9E,MAAM,OAAO,kBAAkB;IAC7B,4CAA4C;IACnC,KAAK,CAAiB;IAE/B,qDAAqD;IAC5C,aAAa,CAAc;IAEpC,gDAAgD;IACvC,WAAW,CAAc;IAEjB,WAAW,CAAwB,CAAC,iCAAiC;IACrE,WAAW,CAAsB,CAAG,4BAA4B;IAEjF,YAAY,GAAQ,EAAE,SAAgC;QACpD,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QAChB,IAAI,CAAC,aAAa,GAAG,IAAI,GAAG,EAAE,CAAC;QAC/B,IAAI,CAAC,WAAW,GAAG,IAAI,GAAG,EAAE,CAAC;QAC7B,IAAI,CAAC,WAAW,GAAG,IAAI,GAAG,EAAE,CAAC;QAC7B,IAAI,CAAC,WAAW,GAAG,IAAI,GAAG,EAAE,CAAC;QAE7B,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;YAC7B,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW;gBAAE,SAAS;YAExC,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC1C,MAAM,UAAU,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC1C,IAAI,CAAC,QAAQ,IAAI,CAAC,UAAU;gBAAE,SAAS;YAEvC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAChC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAEhC,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACtD,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACtB,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YAEzC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;YAEzC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;gBACd,UAAU,EAAE,IAAI,CAAC,IAAI;gBACrB,YAAY,EAAE,IAAI,CAAC,EAAE;gBACrB,QAAQ;gBACR,UAAU;aACX,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,qDAAqD;IACrD,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;IAC/B,CAAC;IAED,iEAAiE;IACjE,YAAY,CAAC,OAAe;QAC1B,OAAO,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACzC,CAAC;IAED,4DAA4D;IAC5D,UAAU,CAAC,OAAe;QACxB,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACvC,CAAC;IAED;;;OAGG;IACH,cAAc,CAAC,UAAkB;QAC/B,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;IAChD,CAAC;IAED;;;OAGG;IACH,WAAW,CAAC,YAAoB;QAC9B,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IAC5C,CAAC;CACF"}
|
package/dist/graph/index.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export { CodeGraph } from './code-graph.js';
|
|
2
2
|
export { ProjectGraph } from './project-graph.js';
|
|
3
3
|
export { ImportGraph } from './import-graph.js';
|
|
4
|
+
export { DominatorGraph } from './dominator-graph.js';
|
|
5
|
+
export { ExceptionFlowGraph, type TryCatchInfo } from './exception-flow-graph.js';
|
|
4
6
|
export { AnalysisPipeline, type AnalysisPass, type PassContext, type PipelineRunResult, } from './analysis-pass.js';
|
package/dist/graph/index.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export { CodeGraph } from './code-graph.js';
|
|
2
2
|
export { ProjectGraph } from './project-graph.js';
|
|
3
3
|
export { ImportGraph } from './import-graph.js';
|
|
4
|
+
export { DominatorGraph } from './dominator-graph.js';
|
|
5
|
+
export { ExceptionFlowGraph } from './exception-flow-graph.js';
|
|
4
6
|
export { AnalysisPipeline, } from './analysis-pass.js';
|
|
5
7
|
//# sourceMappingURL=index.js.map
|
package/dist/graph/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/graph/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EACL,gBAAgB,GAIjB,MAAM,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/graph/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAqB,MAAM,2BAA2B,CAAC;AAClF,OAAO,EACL,gBAAgB,GAIjB,MAAM,oBAAoB,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -10,6 +10,8 @@ export { initParser, parse, walkTree, findNodes, findAncestor, getNodeText, coll
|
|
|
10
10
|
export { extractMeta, extractTypes, extractCalls, extractImports, extractExports, buildCFG, buildDFG, } from './core/index.js';
|
|
11
11
|
export { getDefaultConfig, createTaintConfig, analyzeTaint, detectUnresolved, propagateTaint, generateFindings, analyzeConstantPropagation, ConstantPropagator, isKnown, createUnknown, getNodeLine, DEFAULT_SOURCES, DEFAULT_SINKS, DEFAULT_SANITIZERS, type ConstantValue, type ConstantPropagatorResult, type TaintPropagationResult, type TaintedVariable, type TaintFlow, } from './analysis/index.js';
|
|
12
12
|
export { getRuleInfo, RULE_DEFINITIONS, type RuleInfo, } from './analysis/rules.js';
|
|
13
|
+
export { DominatorGraph } from './graph/dominator-graph.js';
|
|
14
|
+
export { ExceptionFlowGraph, type TryCatchInfo } from './graph/exception-flow-graph.js';
|
|
13
15
|
export { TypeHierarchyResolver, createWithJdkTypes, SymbolTable, buildSymbolTable, CrossFileResolver, buildCrossFileResolver, } from './resolution/index.js';
|
|
14
16
|
export { getLanguageRegistry, registerLanguage, getLanguagePlugin, getLanguageForFile, detectLanguage, isLanguageSupported, registerBuiltinPlugins, JavaPlugin, JavaScriptPlugin, PythonPlugin, RustPlugin, BaseLanguagePlugin, } from './languages/index.js';
|
|
15
17
|
export type { LanguagePlugin, LanguageRegistry, LanguageNodeTypes, ExtractionContext, FrameworkInfo, TaintSourcePattern, TaintSinkPattern, } from './languages/index.js';
|
package/dist/index.js
CHANGED
|
@@ -13,6 +13,9 @@ export { extractMeta, extractTypes, extractCalls, extractImports, extractExports
|
|
|
13
13
|
export { getDefaultConfig, createTaintConfig, analyzeTaint, detectUnresolved, propagateTaint, generateFindings, analyzeConstantPropagation, ConstantPropagator, isKnown, createUnknown, getNodeLine, DEFAULT_SOURCES, DEFAULT_SINKS, DEFAULT_SANITIZERS, } from './analysis/index.js';
|
|
14
14
|
// Rule definitions
|
|
15
15
|
export { getRuleInfo, RULE_DEFINITIONS, } from './analysis/rules.js';
|
|
16
|
+
// Graph utilities
|
|
17
|
+
export { DominatorGraph } from './graph/dominator-graph.js';
|
|
18
|
+
export { ExceptionFlowGraph } from './graph/exception-flow-graph.js';
|
|
16
19
|
// Resolution utilities
|
|
17
20
|
export { TypeHierarchyResolver, createWithJdkTypes, SymbolTable, buildSymbolTable, CrossFileResolver, buildCrossFileResolver, } from './resolution/index.js';
|
|
18
21
|
// Language plugins
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,gBAAgB;AAChB,OAAO,EACL,YAAY,EACZ,OAAO,EACP,aAAa,EACb,cAAc,EACd,qBAAqB,EACrB,aAAa,GAEd,MAAM,eAAe,CAAC;AAuEvB,sCAAsC;AACtC,OAAO,EACL,UAAU,EACV,KAAK,EACL,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,WAAW,EACX,eAAe,GAMhB,MAAM,iBAAiB,CAAC;AAEzB,kBAAkB;AAClB,OAAO,EACL,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,cAAc,EACd,cAAc,EACd,QAAQ,EACR,QAAQ,GACT,MAAM,iBAAiB,CAAC;AAEzB,qBAAqB;AACrB,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,YAAY,EACZ,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,0BAA0B,EAC1B,kBAAkB,EAClB,OAAO,EACP,aAAa,EACb,WAAW,EACX,eAAe,EACf,aAAa,EACb,kBAAkB,GAMnB,MAAM,qBAAqB,CAAC;AAE7B,mBAAmB;AACnB,OAAO,EACL,WAAW,EACX,gBAAgB,GAEjB,MAAM,qBAAqB,CAAC;AAE7B,uBAAuB;AACvB,OAAO,EACL,qBAAqB,EACrB,kBAAkB,EAClB,WAAW,EACX,gBAAgB,EAChB,iBAAiB,EACjB,sBAAsB,GACvB,MAAM,uBAAuB,CAAC;AAE/B,mBAAmB;AACnB,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EAClB,cAAc,EACd,mBAAmB,EACnB,sBAAsB,EACtB,UAAU,EACV,gBAAgB,EAChB,YAAY,EACZ,UAAU,EACV,kBAAkB,GACnB,MAAM,sBAAsB,CAAC;AAY9B,gCAAgC;AAChC,OAAO,EACL,MAAM,EACN,SAAS,EACT,eAAe,EACf,WAAW,EACX,WAAW,GAIZ,MAAM,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,gBAAgB;AAChB,OAAO,EACL,YAAY,EACZ,OAAO,EACP,aAAa,EACb,cAAc,EACd,qBAAqB,EACrB,aAAa,GAEd,MAAM,eAAe,CAAC;AAuEvB,sCAAsC;AACtC,OAAO,EACL,UAAU,EACV,KAAK,EACL,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,WAAW,EACX,eAAe,GAMhB,MAAM,iBAAiB,CAAC;AAEzB,kBAAkB;AAClB,OAAO,EACL,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,cAAc,EACd,cAAc,EACd,QAAQ,EACR,QAAQ,GACT,MAAM,iBAAiB,CAAC;AAEzB,qBAAqB;AACrB,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,YAAY,EACZ,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,0BAA0B,EAC1B,kBAAkB,EAClB,OAAO,EACP,aAAa,EACb,WAAW,EACX,eAAe,EACf,aAAa,EACb,kBAAkB,GAMnB,MAAM,qBAAqB,CAAC;AAE7B,mBAAmB;AACnB,OAAO,EACL,WAAW,EACX,gBAAgB,GAEjB,MAAM,qBAAqB,CAAC;AAE7B,kBAAkB;AAClB,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAqB,MAAM,iCAAiC,CAAC;AAExF,uBAAuB;AACvB,OAAO,EACL,qBAAqB,EACrB,kBAAkB,EAClB,WAAW,EACX,gBAAgB,EAChB,iBAAiB,EACjB,sBAAsB,GACvB,MAAM,uBAAuB,CAAC;AAE/B,mBAAmB;AACnB,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EAClB,cAAc,EACd,mBAAmB,EACnB,sBAAsB,EACtB,UAAU,EACV,gBAAgB,EAChB,YAAY,EACZ,UAAU,EACV,kBAAkB,GACnB,MAAM,sBAAsB,CAAC;AAY9B,gCAAgC;AAChC,OAAO,EACL,MAAM,EACN,SAAS,EACT,eAAe,EACf,WAAW,EACX,WAAW,GAIZ,MAAM,mBAAmB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "circle-ir",
|
|
3
|
-
"version": "3.9.
|
|
3
|
+
"version": "3.9.10",
|
|
4
4
|
"description": "High-performance Static Application Security Testing (SAST) library for detecting security vulnerabilities through taint analysis",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.js",
|