@clear-capabilities/agentic-security-scanner 0.74.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/CHANGELOG.md +1580 -0
- package/bin/.agentic-security/findings.json +1577 -0
- package/bin/.agentic-security/last-scan.json +1577 -0
- package/bin/.agentic-security/last-scan.json.sig +1 -0
- package/bin/.agentic-security/scan-history.json +465 -0
- package/bin/.agentic-security/streak.json +25 -0
- package/bin/agentic-security-audit.js +198 -0
- package/bin/agentic-security-consistency.js +80 -0
- package/bin/agentic-security-diff.js +136 -0
- package/bin/agentic-security-lsp.js +12 -0
- package/bin/agentic-security-mcp.js +40 -0
- package/bin/agentic-security-rule.js +153 -0
- package/bin/agentic-security.js +1683 -0
- package/dist/117.index.js +207 -0
- package/dist/178.index.js +250 -0
- package/dist/218.index.js +793 -0
- package/dist/227.index.js +192 -0
- package/dist/301.index.js +167 -0
- package/dist/384.index.js +18 -0
- package/dist/476.index.js +126 -0
- package/dist/513.index.js +373 -0
- package/dist/520.index.js +13 -0
- package/dist/601.index.js +1038 -0
- package/dist/634.index.js +1892 -0
- package/dist/637.index.js +216 -0
- package/dist/660.index.js +131 -0
- package/dist/675.index.js +451 -0
- package/dist/826.index.js +188 -0
- package/dist/830.index.js +133 -0
- package/dist/agentic-security.mjs +272 -0
- package/dist/agentic-security.mjs.sha256 +1 -0
- package/dist/calibration-seed.json +27 -0
- package/package.json +77 -0
- package/src/.agentic-security/findings.json +80844 -0
- package/src/.agentic-security/last-scan.json +80844 -0
- package/src/.agentic-security/last-scan.json.sig +1 -0
- package/src/.agentic-security/scan-history.json +8408 -0
- package/src/.agentic-security/streak.json +26 -0
- package/src/badge.js +188 -0
- package/src/compare.js +203 -0
- package/src/dataflow/.agentic-security/findings.json +3487 -0
- package/src/dataflow/.agentic-security/last-scan.json +3487 -0
- package/src/dataflow/.agentic-security/last-scan.json.sig +1 -0
- package/src/dataflow/.agentic-security/scan-history.json +735 -0
- package/src/dataflow/.agentic-security/streak.json +24 -0
- package/src/dataflow/CLAUDE.md +38 -0
- package/src/dataflow/access-paths.js +172 -0
- package/src/dataflow/async-sequencing.js +177 -0
- package/src/dataflow/backward.js +201 -0
- package/src/dataflow/catalog-expanded.js +485 -0
- package/src/dataflow/catalog.js +659 -0
- package/src/dataflow/cross-repo.js +219 -0
- package/src/dataflow/engine.js +588 -0
- package/src/dataflow/exception-flow.js +116 -0
- package/src/dataflow/exploit-prover.js +187 -0
- package/src/dataflow/higher-order.js +221 -0
- package/src/dataflow/ifds.js +347 -0
- package/src/dataflow/implicit-flow.js +129 -0
- package/src/dataflow/incremental.js +229 -0
- package/src/dataflow/index.js +181 -0
- package/src/dataflow/numeric-domain.js +192 -0
- package/src/dataflow/path-feasibility.js +114 -0
- package/src/dataflow/points-to.js +337 -0
- package/src/dataflow/polyglot.js +190 -0
- package/src/dataflow/proven-clean.js +159 -0
- package/src/dataflow/receiver-context.js +76 -0
- package/src/dataflow/sanitizer-proof.js +154 -0
- package/src/dataflow/soft-taint.js +140 -0
- package/src/dataflow/string-domain.js +234 -0
- package/src/dataflow/stub-aware-filter.js +100 -0
- package/src/dataflow/summaries.js +132 -0
- package/src/dataflow/symbolic-exec.js +238 -0
- package/src/dataflow/tabulation.js +135 -0
- package/src/engine.js +7763 -0
- package/src/history-scan.js +229 -0
- package/src/index.js +3 -0
- package/src/integrations/.agentic-security/findings.json +1504 -0
- package/src/integrations/.agentic-security/last-scan.json +1504 -0
- package/src/integrations/.agentic-security/scan-history.json +40 -0
- package/src/integrations/.agentic-security/streak.json +21 -0
- package/src/integrations/index.js +321 -0
- package/src/integrations/tickets.js +200 -0
- package/src/ir/.agentic-security/findings.json +3036 -0
- package/src/ir/.agentic-security/last-scan.json +3036 -0
- package/src/ir/.agentic-security/last-scan.json.sig +1 -0
- package/src/ir/.agentic-security/scan-history.json +364 -0
- package/src/ir/.agentic-security/streak.json +23 -0
- package/src/ir/CLAUDE.md +172 -0
- package/src/ir/callgraph.js +73 -0
- package/src/ir/class-hierarchy.js +195 -0
- package/src/ir/index.js +152 -0
- package/src/ir/parser-cs.js +260 -0
- package/src/ir/parser-java.js +286 -0
- package/src/ir/parser-js.js +413 -0
- package/src/ir/parser-kt.js +258 -0
- package/src/ir/parser-py-cst.js +136 -0
- package/src/ir/parser-py.helper.py +501 -0
- package/src/ir/parser-py.js +312 -0
- package/src/ir/ssa.js +315 -0
- package/src/ir/type-stubs.js +288 -0
- package/src/leaderboard.js +152 -0
- package/src/llm-validator/.agentic-security/findings.json +1891 -0
- package/src/llm-validator/.agentic-security/last-scan.json +1891 -0
- package/src/llm-validator/.agentic-security/last-scan.json.sig +1 -0
- package/src/llm-validator/.agentic-security/scan-history.json +168 -0
- package/src/llm-validator/.agentic-security/streak.json +20 -0
- package/src/llm-validator/consistency.js +141 -0
- package/src/llm-validator/index.js +437 -0
- package/src/lsp/.agentic-security/findings.json +28 -0
- package/src/lsp/.agentic-security/last-scan.json +28 -0
- package/src/lsp/.agentic-security/scan-history.json +79 -0
- package/src/lsp/.agentic-security/streak.json +22 -0
- package/src/lsp/server.js +275 -0
- package/src/mcp/.agentic-security/findings.json +8358 -0
- package/src/mcp/.agentic-security/last-scan.json +8358 -0
- package/src/mcp/.agentic-security/last-scan.json.sig +1 -0
- package/src/mcp/.agentic-security/scan-history.json +1125 -0
- package/src/mcp/.agentic-security/streak.json +22 -0
- package/src/mcp/CLAUDE.md +54 -0
- package/src/mcp/audit.js +136 -0
- package/src/mcp/redact.js +75 -0
- package/src/mcp/server.js +158 -0
- package/src/mcp/stdio.js +83 -0
- package/src/mcp/tools.js +940 -0
- package/src/mcp/validate.js +49 -0
- package/src/personality.js +164 -0
- package/src/poc-video.js +239 -0
- package/src/posture/.agentic-security/findings.json +51239 -0
- package/src/posture/.agentic-security/last-scan.json +51239 -0
- package/src/posture/.agentic-security/last-scan.json.sig +1 -0
- package/src/posture/.agentic-security/scan-history.json +5557 -0
- package/src/posture/.agentic-security/streak.json +24 -0
- package/src/posture/CLAUDE.md +42 -0
- package/src/posture/adversarial-self-test.js +114 -0
- package/src/posture/adversary-agent.js +204 -0
- package/src/posture/agents-memory.js +135 -0
- package/src/posture/ai-code-fingerprint.js +171 -0
- package/src/posture/aibom.js +284 -0
- package/src/posture/api-inventory.js +96 -0
- package/src/posture/attack-playbooks.js +305 -0
- package/src/posture/auditor-agent.js +115 -0
- package/src/posture/auth-posture-import.js +135 -0
- package/src/posture/baseline-compare.js +114 -0
- package/src/posture/blast-radius.js +836 -0
- package/src/posture/bounty-prediction.js +141 -0
- package/src/posture/business-logic.js +239 -0
- package/src/posture/calibration-drift.js +93 -0
- package/src/posture/calibration-seed.json +27 -0
- package/src/posture/calibration.js +204 -0
- package/src/posture/clustering.js +75 -0
- package/src/posture/concurrency-checker.js +265 -0
- package/src/posture/confidence.js +65 -0
- package/src/posture/container-runtime.js +149 -0
- package/src/posture/counterfactual.js +109 -0
- package/src/posture/cross-lang-graphql.js +165 -0
- package/src/posture/cross-lang-grpc.js +166 -0
- package/src/posture/cross-lang-meta.js +101 -0
- package/src/posture/cross-lang-openapi.js +187 -0
- package/src/posture/cross-lang-orm.js +153 -0
- package/src/posture/cross-lang-queues.js +210 -0
- package/src/posture/crown-jewels.js +110 -0
- package/src/posture/custom-rules.js +361 -0
- package/src/posture/cve-alert-daemon.js +433 -0
- package/src/posture/cve-lookup.js +129 -0
- package/src/posture/dead-code.js +430 -0
- package/src/posture/defender-agent.js +158 -0
- package/src/posture/deploy-platform.js +204 -0
- package/src/posture/detector-fuzz.js +61 -0
- package/src/posture/deterministic.js +99 -0
- package/src/posture/drift.js +165 -0
- package/src/posture/epss.js +156 -0
- package/src/posture/exploitability-probability.js +212 -0
- package/src/posture/exploitability.js +121 -0
- package/src/posture/feature-flags.js +110 -0
- package/src/posture/finding-defaults.js +132 -0
- package/src/posture/fix-history.js +411 -0
- package/src/posture/fix-plan.js +121 -0
- package/src/posture/fix-verify-loop.js +157 -0
- package/src/posture/fix-verify.js +130 -0
- package/src/posture/flow-narration.js +105 -0
- package/src/posture/grader-calibration.js +156 -0
- package/src/posture/harness-discovery.js +113 -0
- package/src/posture/holdout-eval.js +144 -0
- package/src/posture/iac-reachability.js +163 -0
- package/src/posture/iam-policy.js +128 -0
- package/src/posture/integrity.js +97 -0
- package/src/posture/learning.js +166 -0
- package/src/posture/license-policy.js +109 -0
- package/src/posture/llm-redteam-prompts.js +418 -0
- package/src/posture/llm-redteam.js +303 -0
- package/src/posture/material-change.js +163 -0
- package/src/posture/mitigation-composite.js +55 -0
- package/src/posture/mttr.js +91 -0
- package/src/posture/network-policy-import.js +126 -0
- package/src/posture/path-predicates.js +99 -0
- package/src/posture/persona-prioritization.js +153 -0
- package/src/posture/poc-cwe-map.js +51 -0
- package/src/posture/poc-generator.js +500 -0
- package/src/posture/policy-gate.js +174 -0
- package/src/posture/pre-incident-archaeology.js +110 -0
- package/src/posture/profile.js +93 -0
- package/src/posture/reachability-filter.js +42 -0
- package/src/posture/regression-test-gen.js +200 -0
- package/src/posture/reverse-blast-radius.js +110 -0
- package/src/posture/router.js +109 -0
- package/src/posture/rule-overrides.js +198 -0
- package/src/posture/rule-pack-signing.js +209 -0
- package/src/posture/rule-packs.js +143 -0
- package/src/posture/rule-synthesis.js +108 -0
- package/src/posture/ruleset-version.js +71 -0
- package/src/posture/sbom.js +129 -0
- package/src/posture/schema-aware-bridge.js +207 -0
- package/src/posture/security-trend.js +87 -0
- package/src/posture/semantic-clone.js +114 -0
- package/src/posture/specification-mining.js +170 -0
- package/src/posture/stable-id.js +75 -0
- package/src/posture/stack-playbook.js +229 -0
- package/src/posture/streak.js +249 -0
- package/src/posture/suppressions.js +135 -0
- package/src/posture/telemetry-ingest.js +112 -0
- package/src/posture/threat-model.js +145 -0
- package/src/posture/three-agent-pipeline.js +74 -0
- package/src/posture/triage.js +146 -0
- package/src/posture/trust-boundary-diagram.js +115 -0
- package/src/posture/type-narrowing.js +129 -0
- package/src/posture/validator-metrics.js +179 -0
- package/src/posture/verifier-ephemeral.js +118 -0
- package/src/posture/verifier-target.js +147 -0
- package/src/posture/verifier.js +257 -0
- package/src/posture/version.js +75 -0
- package/src/posture/waf-ingest.js +200 -0
- package/src/posture/why-fired.js +141 -0
- package/src/pr-comment.js +172 -0
- package/src/pr-delta.js +198 -0
- package/src/report/.agentic-security/findings.json +79 -0
- package/src/report/.agentic-security/last-scan.json +79 -0
- package/src/report/.agentic-security/last-scan.json.sig +1 -0
- package/src/report/.agentic-security/scan-history.json +332 -0
- package/src/report/.agentic-security/streak.json +23 -0
- package/src/report/index.js +1136 -0
- package/src/report/mascot.js +42 -0
- package/src/runScan.js +141 -0
- package/src/sast/.agentic-security/findings.json +5051 -0
- package/src/sast/.agentic-security/last-scan.json +5051 -0
- package/src/sast/.agentic-security/last-scan.json.sig +1 -0
- package/src/sast/.agentic-security/scan-history.json +788 -0
- package/src/sast/.agentic-security/streak.json +23 -0
- package/src/sast/CLAUDE.md +39 -0
- package/src/sast/_comment-strip.js +46 -0
- package/src/sast/agent-tool-escalation.js +131 -0
- package/src/sast/auth-provider.js +171 -0
- package/src/sast/authz.js +236 -0
- package/src/sast/bench-shape/.agentic-security/findings.json +28 -0
- package/src/sast/bench-shape/.agentic-security/last-scan.json +28 -0
- package/src/sast/bench-shape/.agentic-security/scan-history.json +24 -0
- package/src/sast/bench-shape/.agentic-security/streak.json +22 -0
- package/src/sast/bench-shape/index.js +62 -0
- package/src/sast/claude-hook-injection.js +199 -0
- package/src/sast/claude-md-prompt-injection.js +170 -0
- package/src/sast/claude-settings.js +165 -0
- package/src/sast/client-side.js +149 -0
- package/src/sast/cpp-bench-extras.js +122 -0
- package/src/sast/cpp-dataflow.js +430 -0
- package/src/sast/cpp.js +248 -0
- package/src/sast/csharp.js +152 -0
- package/src/sast/csrf.js +82 -0
- package/src/sast/dart-flutter.js +173 -0
- package/src/sast/db-rls.js +147 -0
- package/src/sast/db-taint.js +215 -0
- package/src/sast/defi-deep.js +242 -0
- package/src/sast/deserialization-gadgets.js +113 -0
- package/src/sast/django-hardening.js +230 -0
- package/src/sast/env-hygiene.js +125 -0
- package/src/sast/fastapi-hardening.js +145 -0
- package/src/sast/go-extended.js +84 -0
- package/src/sast/host-header.js +106 -0
- package/src/sast/index.js +17 -0
- package/src/sast/java-ast-folding.js +561 -0
- package/src/sast/java-bench-extras.js +708 -0
- package/src/sast/java-collection-passthrough.js +178 -0
- package/src/sast/java-constant-fold.js +244 -0
- package/src/sast/java-deserialization.js +125 -0
- package/src/sast/jndi.js +104 -0
- package/src/sast/juliet-shape.js +324 -0
- package/src/sast/jwt-exp.js +104 -0
- package/src/sast/kotlin.js +82 -0
- package/src/sast/laravel-hardening.js +198 -0
- package/src/sast/ldap-injection.js +100 -0
- package/src/sast/llm-owasp.js +465 -0
- package/src/sast/llm-stored-prompt.js +103 -0
- package/src/sast/llm-trading-agent.js +161 -0
- package/src/sast/llm.js +308 -0
- package/src/sast/logic.js +140 -0
- package/src/sast/mass-assignment.js +101 -0
- package/src/sast/mcp-audit.js +242 -0
- package/src/sast/mobile-manifest.js +195 -0
- package/src/sast/model-load.js +164 -0
- package/src/sast/mutation-xss.js +87 -0
- package/src/sast/nosql-injection.js +82 -0
- package/src/sast/open-redirect.js +119 -0
- package/src/sast/php.js +91 -0
- package/src/sast/pipeline.js +122 -0
- package/src/sast/primary-cwe-java.js +155 -0
- package/src/sast/prompt-firewall.js +151 -0
- package/src/sast/prompt-template.js +157 -0
- package/src/sast/prototype-pollution.js +112 -0
- package/src/sast/python-sinks.js +195 -0
- package/src/sast/quarkus-hardening.js +102 -0
- package/src/sast/rag-poisoning.js +118 -0
- package/src/sast/rate-limit.js +128 -0
- package/src/sast/response-splitting.js +138 -0
- package/src/sast/ruby.js +108 -0
- package/src/sast/rust.js +105 -0
- package/src/sast/solidity.js +167 -0
- package/src/sast/springboot-hardening.js +186 -0
- package/src/sast/ssrf-cloud-metadata.js +80 -0
- package/src/sast/ssti.js +116 -0
- package/src/sast/swift.js +162 -0
- package/src/sast/toctou.js +95 -0
- package/src/sast/webhook.js +101 -0
- package/src/sast/xpath-injection.js +51 -0
- package/src/sast/xxe.js +140 -0
- package/src/sast/zip-slip.js +200 -0
- package/src/sca/base-images.json +45 -0
- package/src/sca/container.js +107 -0
- package/src/sca/dep-confusion.js +134 -0
- package/src/sca/index.js +6 -0
- package/src/sca/popular-packages.json +41 -0
- package/src/sca/sarif-ingest.js +187 -0
- package/src/sca/vuln-function-hints.json +89 -0
- package/src/secrets/index.js +4 -0
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
// Java IR frontend (P2.3).
|
|
2
|
+
//
|
|
3
|
+
// Converts the java-parser AST into our unified IR shape. The dataflow
|
|
4
|
+
// engine consumes the same node kinds as the JS frontend (assign / call /
|
|
5
|
+
// return / if / loop-header / throw / entry / exit / noop).
|
|
6
|
+
//
|
|
7
|
+
// v1 scope:
|
|
8
|
+
// - Method declarations → IR functions with CFG
|
|
9
|
+
// - Field declarations → top-level assigns
|
|
10
|
+
// - Local variable declarations + assignments → assign nodes
|
|
11
|
+
// - Method invocations → call nodes
|
|
12
|
+
// - Return / throw / if-else / while / for → corresponding IR nodes
|
|
13
|
+
// - Try / catch → exception-flow scaffolding (P3.4 will model)
|
|
14
|
+
// - Lambdas → captured as function-value (P1.3 helpers consume)
|
|
15
|
+
//
|
|
16
|
+
// Out of scope for v1: generics resolution, annotation introspection beyond
|
|
17
|
+
// shallow name capture, varargs unpacking, switch expressions.
|
|
18
|
+
//
|
|
19
|
+
// The implementation is line-aware: java-parser produces an exhaustive CST,
|
|
20
|
+
// which we walk to extract just the dataflow-relevant nodes. v1 is
|
|
21
|
+
// conservative — we recover what we can, and fall back to a single noop
|
|
22
|
+
// when the shape is unfamiliar.
|
|
23
|
+
|
|
24
|
+
import { blankComments } from '../sast/_comment-strip.js';
|
|
25
|
+
|
|
26
|
+
let _nodeIdSeq = 0;
|
|
27
|
+
function nextNodeId() { return 'jn' + (++_nodeIdSeq); }
|
|
28
|
+
|
|
29
|
+
let _javaParser = null;
|
|
30
|
+
async function _loadJavaParser() {
|
|
31
|
+
if (_javaParser) return _javaParser;
|
|
32
|
+
try {
|
|
33
|
+
const mod = await import('java-parser');
|
|
34
|
+
_javaParser = mod.parse || mod.default;
|
|
35
|
+
return _javaParser;
|
|
36
|
+
} catch {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Walk a java-parser CST node and emit our exprDesc shape.
|
|
43
|
+
*/
|
|
44
|
+
function exprFromCst(node) {
|
|
45
|
+
if (!node) return { kind: 'unknown' };
|
|
46
|
+
if (Array.isArray(node)) {
|
|
47
|
+
return node.length === 1 ? exprFromCst(node[0]) : { kind: 'unknown' };
|
|
48
|
+
}
|
|
49
|
+
if (node.image) {
|
|
50
|
+
// Token leaf — number, string, ident.
|
|
51
|
+
const img = node.image;
|
|
52
|
+
if (/^['"]/.test(img)) return { kind: 'literal', value: img };
|
|
53
|
+
if (/^-?\d/.test(img)) return { kind: 'literal', value: Number(img) || img };
|
|
54
|
+
if (/^(?:true|false|null)$/.test(img)) return { kind: 'literal', value: img };
|
|
55
|
+
return { kind: 'ident', name: img };
|
|
56
|
+
}
|
|
57
|
+
if (node.children) {
|
|
58
|
+
// CST node with named children — recurse into the most informative one.
|
|
59
|
+
// Method invocation
|
|
60
|
+
if (node.children.methodInvocation) return _methodInvocation(node.children.methodInvocation[0]);
|
|
61
|
+
// FQN ref
|
|
62
|
+
if (node.children.fqnOrRefType) return _fqnExpr(node.children.fqnOrRefType[0]);
|
|
63
|
+
if (node.children.unqualifiedClassInstanceCreationExpression) {
|
|
64
|
+
const ci = node.children.unqualifiedClassInstanceCreationExpression[0];
|
|
65
|
+
const callee = (ci.children?.classOrInterfaceTypeToInstantiate?.[0]?.children?.Identifier?.[0]?.image) || 'new';
|
|
66
|
+
return { kind: 'call', callee, isNew: true, args: [] };
|
|
67
|
+
}
|
|
68
|
+
if (node.children.literal) return exprFromCst(node.children.literal[0]);
|
|
69
|
+
if (node.children.Identifier) return { kind: 'ident', name: node.children.Identifier[0].image };
|
|
70
|
+
// Binary expression
|
|
71
|
+
if (node.children.BinaryOperator || node.children.binaryExpression) {
|
|
72
|
+
// Best-effort: take the two operands.
|
|
73
|
+
const kids = node.children.unaryExpression || node.children.expression || [];
|
|
74
|
+
if (kids.length >= 2) {
|
|
75
|
+
return {
|
|
76
|
+
kind: 'binary',
|
|
77
|
+
op: '?',
|
|
78
|
+
left: exprFromCst(kids[0]),
|
|
79
|
+
right: exprFromCst(kids[1]),
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// Fall through: recurse the first child
|
|
84
|
+
for (const k of Object.keys(node.children)) {
|
|
85
|
+
const arr = node.children[k];
|
|
86
|
+
if (Array.isArray(arr) && arr.length) return exprFromCst(arr[0]);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return { kind: 'unknown' };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function _fqnExpr(node) {
|
|
93
|
+
// java-parser fqnOrRefType has children { Identifier: [...] } sometimes
|
|
94
|
+
// and Dot tokens between them.
|
|
95
|
+
if (!node || !node.children) return { kind: 'unknown' };
|
|
96
|
+
const ids = node.children.Identifier;
|
|
97
|
+
if (!ids || !ids.length) return { kind: 'unknown' };
|
|
98
|
+
let cur = { kind: 'ident', name: ids[0].image };
|
|
99
|
+
for (let i = 1; i < ids.length; i++) {
|
|
100
|
+
cur = { kind: 'member', object: cur, prop: ids[i].image };
|
|
101
|
+
}
|
|
102
|
+
return cur;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function _methodInvocation(node) {
|
|
106
|
+
// node.children typically: fqnOrRefType (callee) + argumentList (args).
|
|
107
|
+
const callee = node.children?.fqnOrRefType
|
|
108
|
+
? _flattenFqnToString(node.children.fqnOrRefType[0])
|
|
109
|
+
: (node.children?.Identifier?.[0]?.image || 'unknown');
|
|
110
|
+
const args = [];
|
|
111
|
+
if (node.children?.argumentList) {
|
|
112
|
+
const al = node.children.argumentList[0];
|
|
113
|
+
if (al && al.children?.expression) {
|
|
114
|
+
for (const e of al.children.expression) args.push(exprFromCst(e));
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return { kind: 'call', callee, args };
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function _flattenFqnToString(node) {
|
|
121
|
+
if (!node || !node.children) return 'unknown';
|
|
122
|
+
const ids = node.children.Identifier;
|
|
123
|
+
if (!ids) return 'unknown';
|
|
124
|
+
return ids.map(t => t.image).join('.');
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Build a function's CFG from its method-body CST.
|
|
129
|
+
*
|
|
130
|
+
* v1: a simple sequential walk — every statement becomes one IR node,
|
|
131
|
+
* connected linearly. Branches (`if/else`, `while`, `for`) emit an
|
|
132
|
+
* `if` / `loop-header` node and the body falls through linearly. This is
|
|
133
|
+
* coarser than the JS frontend; v2 will branch the succ array.
|
|
134
|
+
*/
|
|
135
|
+
function buildCfgFromBody(bodyNode, line) {
|
|
136
|
+
const nodes = {};
|
|
137
|
+
const entry = nextNodeId();
|
|
138
|
+
const exit = nextNodeId();
|
|
139
|
+
nodes[entry] = { id: entry, kind: 'entry', succ: [] };
|
|
140
|
+
nodes[exit] = { id: exit, kind: 'exit', succ: [] };
|
|
141
|
+
let prev = entry;
|
|
142
|
+
|
|
143
|
+
function emit(node) {
|
|
144
|
+
const id = nextNodeId();
|
|
145
|
+
node.id = id;
|
|
146
|
+
nodes[id] = node;
|
|
147
|
+
if (nodes[prev]) {
|
|
148
|
+
nodes[prev].succ = nodes[prev].succ || [];
|
|
149
|
+
nodes[prev].succ.push(id);
|
|
150
|
+
}
|
|
151
|
+
prev = id;
|
|
152
|
+
return id;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
walkStmts(bodyNode);
|
|
156
|
+
|
|
157
|
+
function walkStmts(stmtNode) {
|
|
158
|
+
if (!stmtNode || !stmtNode.children) return;
|
|
159
|
+
const kids = stmtNode.children;
|
|
160
|
+
// Block statement children
|
|
161
|
+
if (kids.blockStatement) {
|
|
162
|
+
for (const bs of kids.blockStatement) walkStmts(bs);
|
|
163
|
+
}
|
|
164
|
+
if (kids.localVariableDeclarationStatement) {
|
|
165
|
+
for (const lv of kids.localVariableDeclarationStatement) {
|
|
166
|
+
const vdecl = lv.children?.localVariableDeclaration?.[0];
|
|
167
|
+
const declarators = vdecl?.children?.variableDeclaratorList?.[0]?.children?.variableDeclarator;
|
|
168
|
+
if (declarators) {
|
|
169
|
+
for (const d of declarators) {
|
|
170
|
+
const target = d.children?.variableDeclaratorId?.[0]?.children?.Identifier?.[0]?.image;
|
|
171
|
+
const initExpr = d.children?.variableInitializer?.[0]?.children?.expression?.[0];
|
|
172
|
+
if (target) {
|
|
173
|
+
emit({ kind: 'assign', target, source: initExpr ? exprFromCst(initExpr) : { kind: 'unknown' }, line: line || 0, succ: [] });
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
if (kids.statement) {
|
|
180
|
+
for (const s of kids.statement) walkStmts(s);
|
|
181
|
+
}
|
|
182
|
+
if (kids.statementWithoutTrailingSubstatement) {
|
|
183
|
+
for (const s of kids.statementWithoutTrailingSubstatement) walkStmts(s);
|
|
184
|
+
}
|
|
185
|
+
if (kids.expressionStatement) {
|
|
186
|
+
const e = kids.expressionStatement[0]?.children?.statementExpression?.[0]?.children?.expression?.[0];
|
|
187
|
+
if (e) {
|
|
188
|
+
const expr = exprFromCst(e);
|
|
189
|
+
if (expr.kind === 'call') emit({ ...expr, line: line || 0, succ: [] });
|
|
190
|
+
else if (expr.kind === 'binary' && expr.op === '=') {
|
|
191
|
+
// assignment expr `x = y;`
|
|
192
|
+
emit({ kind: 'assign', target: expr.left?.name || null, source: expr.right, line: line || 0, succ: [] });
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
if (kids.returnStatement) {
|
|
197
|
+
const r = kids.returnStatement[0];
|
|
198
|
+
const expr = r.children?.expression?.[0];
|
|
199
|
+
emit({ kind: 'return', value: expr ? exprFromCst(expr) : null, line: line || 0, succ: [] });
|
|
200
|
+
}
|
|
201
|
+
if (kids.throwStatement) {
|
|
202
|
+
const t = kids.throwStatement[0];
|
|
203
|
+
const expr = t.children?.expression?.[0];
|
|
204
|
+
emit({ kind: 'throw', value: expr ? exprFromCst(expr) : null, line: line || 0, succ: [] });
|
|
205
|
+
}
|
|
206
|
+
if (kids.ifStatement) {
|
|
207
|
+
const i = kids.ifStatement[0];
|
|
208
|
+
const cond = i.children?.expression?.[0];
|
|
209
|
+
emit({ kind: 'if', cond: cond ? exprFromCst(cond) : null, line: line || 0, succ: [] });
|
|
210
|
+
// Then branch body falls through linearly; v1 simplification.
|
|
211
|
+
for (const sub of (i.children?.statement || [])) walkStmts(sub);
|
|
212
|
+
}
|
|
213
|
+
if (kids.whileStatement) {
|
|
214
|
+
const w = kids.whileStatement[0];
|
|
215
|
+
const cond = w.children?.expression?.[0];
|
|
216
|
+
emit({ kind: 'loop-header', cond: cond ? exprFromCst(cond) : null, line: line || 0, succ: [] });
|
|
217
|
+
for (const sub of (w.children?.statement || [])) walkStmts(sub);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (nodes[prev]) {
|
|
222
|
+
nodes[prev].succ = nodes[prev].succ || [];
|
|
223
|
+
nodes[prev].succ.push(exit);
|
|
224
|
+
}
|
|
225
|
+
return { entry, exit, nodes };
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Top-level: parse one .java file. Returns the perFileIR shape (same as
|
|
230
|
+
* parser-js.js). Returns null when java-parser is unavailable OR the
|
|
231
|
+
* file fails to parse.
|
|
232
|
+
*
|
|
233
|
+
* Async because we lazy-import java-parser.
|
|
234
|
+
*/
|
|
235
|
+
export async function parseJavaFile(file, raw) {
|
|
236
|
+
if (!file || !raw || typeof raw !== 'string') return null;
|
|
237
|
+
if (!/\.java$/i.test(file)) return null;
|
|
238
|
+
if (raw.length > 1_000_000) return null;
|
|
239
|
+
const parser = await _loadJavaParser();
|
|
240
|
+
if (!parser) return null;
|
|
241
|
+
|
|
242
|
+
let cst;
|
|
243
|
+
try { cst = parser(raw); } catch { return null; }
|
|
244
|
+
if (!cst) return null;
|
|
245
|
+
|
|
246
|
+
const functions = [];
|
|
247
|
+
// Walk the CST for methodDeclaration nodes.
|
|
248
|
+
function walkForMethods(node, className) {
|
|
249
|
+
if (!node || !node.children) return;
|
|
250
|
+
for (const k of Object.keys(node.children)) {
|
|
251
|
+
const arr = node.children[k];
|
|
252
|
+
if (!Array.isArray(arr)) continue;
|
|
253
|
+
for (const child of arr) {
|
|
254
|
+
if (k === 'classDeclaration' || k === 'normalClassDeclaration') {
|
|
255
|
+
const newClassName = child.children?.typeIdentifier?.[0]?.children?.Identifier?.[0]?.image
|
|
256
|
+
|| child.children?.Identifier?.[0]?.image
|
|
257
|
+
|| className;
|
|
258
|
+
walkForMethods(child, newClassName);
|
|
259
|
+
continue;
|
|
260
|
+
}
|
|
261
|
+
if (k === 'methodDeclaration' || k === 'methodHeader') {
|
|
262
|
+
const md = child;
|
|
263
|
+
const name = md.children?.methodHeader?.[0]?.children?.methodDeclarator?.[0]?.children?.Identifier?.[0]?.image
|
|
264
|
+
|| md.children?.methodDeclarator?.[0]?.children?.Identifier?.[0]?.image
|
|
265
|
+
|| 'anonymous';
|
|
266
|
+
const params = []; // params extraction deferred
|
|
267
|
+
const body = md.children?.methodBody?.[0]?.children?.block?.[0];
|
|
268
|
+
if (body) {
|
|
269
|
+
functions.push({
|
|
270
|
+
qid: `${file}::${className || 'class'}::${name}`,
|
|
271
|
+
name: className ? `${className}.${name}` : name,
|
|
272
|
+
line: 0,
|
|
273
|
+
params,
|
|
274
|
+
cfg: buildCfgFromBody(body, 0),
|
|
275
|
+
file,
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
walkForMethods(child, className);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
walkForMethods(cst, null);
|
|
284
|
+
|
|
285
|
+
return { file, functions, topLevel: null };
|
|
286
|
+
}
|