gitnexus 1.6.8-rc.8 → 1.6.8
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/README.md +3 -3
- package/dist/_shared/graph/types.d.ts +31 -1
- package/dist/_shared/graph/types.d.ts.map +1 -1
- package/dist/_shared/language-detection.d.ts.map +1 -1
- package/dist/_shared/language-detection.js +11 -1
- package/dist/_shared/language-detection.js.map +1 -1
- package/dist/_shared/lbug/schema-constants.d.ts +1 -1
- package/dist/_shared/lbug/schema-constants.d.ts.map +1 -1
- package/dist/_shared/lbug/schema-constants.js +6 -0
- package/dist/_shared/lbug/schema-constants.js.map +1 -1
- package/dist/_shared/scope-resolution/parsed-file.d.ts +21 -0
- package/dist/_shared/scope-resolution/parsed-file.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/symbol-definition.d.ts +6 -0
- package/dist/_shared/scope-resolution/symbol-definition.d.ts.map +1 -1
- package/dist/cli/ai-context.d.ts +31 -1
- package/dist/cli/ai-context.js +18 -16
- package/dist/cli/analyze-config.js +11 -0
- package/dist/cli/analyze.d.ts +14 -0
- package/dist/cli/analyze.js +98 -0
- package/dist/cli/embedding-dims.d.ts +33 -0
- package/dist/cli/embedding-dims.js +39 -0
- package/dist/cli/eval-server.d.ts +8 -0
- package/dist/cli/eval-server.js +242 -2
- package/dist/cli/help-i18n.js +19 -0
- package/dist/cli/i18n/en.d.ts +15 -1
- package/dist/cli/i18n/en.js +15 -1
- package/dist/cli/i18n/resources.d.ts +29 -1
- package/dist/cli/i18n/zh-CN.d.ts +14 -0
- package/dist/cli/i18n/zh-CN.js +15 -1
- package/dist/cli/index.js +89 -1
- package/dist/cli/mcp.d.ts +6 -1
- package/dist/cli/mcp.js +26 -1
- package/dist/cli/optional-grammars.d.ts +6 -8
- package/dist/cli/optional-grammars.js +8 -11
- package/dist/cli/setup.d.ts +3 -1
- package/dist/cli/setup.js +67 -17
- package/dist/cli/skill-gen.js +2 -1
- package/dist/cli/tool.d.ts +19 -1
- package/dist/cli/tool.js +96 -3
- package/dist/core/embeddings/hf-env.d.ts +0 -66
- package/dist/core/embeddings/http-client.d.ts +7 -0
- package/dist/core/embeddings/http-client.js +5 -3
- package/dist/core/embeddings/server-mapping.d.ts +1 -1
- package/dist/core/embeddings/server-mapping.js +7 -3
- package/dist/core/graph/import-cycles.d.ts +10 -0
- package/dist/core/graph/import-cycles.js +103 -0
- package/dist/core/group/cross-impact.d.ts +2 -1
- package/dist/core/group/cross-impact.js +5 -1
- package/dist/core/group/extractors/grpc-patterns/proto.js +10 -6
- package/dist/core/group/extractors/http-patterns/kotlin.js +7 -7
- package/dist/core/group/extractors/http-route-extractor.d.ts +24 -0
- package/dist/core/group/extractors/http-route-extractor.js +22 -4
- package/dist/core/group/extractors/include-extractor.js +22 -13
- package/dist/core/group/sync.d.ts +27 -1
- package/dist/core/group/sync.js +0 -0
- package/dist/core/incremental/subgraph-extract.js +18 -1
- package/dist/core/ingestion/cfg/cfg-builder.d.ts +114 -0
- package/dist/core/ingestion/cfg/cfg-builder.js +196 -0
- package/dist/core/ingestion/cfg/collect.d.ts +51 -0
- package/dist/core/ingestion/cfg/collect.js +77 -0
- package/dist/core/ingestion/cfg/control-dependence.d.ts +58 -0
- package/dist/core/ingestion/cfg/control-dependence.js +182 -0
- package/dist/core/ingestion/cfg/control-flow-context.d.ts +106 -0
- package/dist/core/ingestion/cfg/control-flow-context.js +124 -0
- package/dist/core/ingestion/cfg/emit.d.ts +293 -0
- package/dist/core/ingestion/cfg/emit.js +646 -0
- package/dist/core/ingestion/cfg/post-dominators.d.ts +79 -0
- package/dist/core/ingestion/cfg/post-dominators.js +176 -0
- package/dist/core/ingestion/cfg/reaching-def-reason-codec.d.ts +106 -0
- package/dist/core/ingestion/cfg/reaching-def-reason-codec.js +133 -0
- package/dist/core/ingestion/cfg/reaching-defs-graph.d.ts +18 -0
- package/dist/core/ingestion/cfg/reaching-defs-graph.js +312 -0
- package/dist/core/ingestion/cfg/reaching-defs.d.ts +162 -0
- package/dist/core/ingestion/cfg/reaching-defs.js +785 -0
- package/dist/core/ingestion/cfg/synthetic-escape.d.ts +124 -0
- package/dist/core/ingestion/cfg/synthetic-escape.js +300 -0
- package/dist/core/ingestion/cfg/traversal-result.d.ts +20 -0
- package/dist/core/ingestion/cfg/traversal-result.js +2 -0
- package/dist/core/ingestion/cfg/types.d.ts +274 -0
- package/dist/core/ingestion/cfg/types.js +13 -0
- package/dist/core/ingestion/cfg/visitors/c-cpp-harvest.d.ts +111 -0
- package/dist/core/ingestion/cfg/visitors/c-cpp-harvest.js +541 -0
- package/dist/core/ingestion/cfg/visitors/c-cpp.d.ts +74 -0
- package/dist/core/ingestion/cfg/visitors/c-cpp.js +584 -0
- package/dist/core/ingestion/cfg/visitors/call-site-harvest.d.ts +195 -0
- package/dist/core/ingestion/cfg/visitors/call-site-harvest.js +350 -0
- package/dist/core/ingestion/cfg/visitors/csharp-harvest.d.ts +124 -0
- package/dist/core/ingestion/cfg/visitors/csharp-harvest.js +589 -0
- package/dist/core/ingestion/cfg/visitors/csharp.d.ts +87 -0
- package/dist/core/ingestion/cfg/visitors/csharp.js +867 -0
- package/dist/core/ingestion/cfg/visitors/dart-harvest.d.ts +278 -0
- package/dist/core/ingestion/cfg/visitors/dart-harvest.js +870 -0
- package/dist/core/ingestion/cfg/visitors/dart.d.ts +119 -0
- package/dist/core/ingestion/cfg/visitors/dart.js +836 -0
- package/dist/core/ingestion/cfg/visitors/go-harvest.d.ts +160 -0
- package/dist/core/ingestion/cfg/visitors/go-harvest.js +621 -0
- package/dist/core/ingestion/cfg/visitors/go.d.ts +108 -0
- package/dist/core/ingestion/cfg/visitors/go.js +638 -0
- package/dist/core/ingestion/cfg/visitors/java-harvest.d.ts +108 -0
- package/dist/core/ingestion/cfg/visitors/java-harvest.js +513 -0
- package/dist/core/ingestion/cfg/visitors/java.d.ts +101 -0
- package/dist/core/ingestion/cfg/visitors/java.js +812 -0
- package/dist/core/ingestion/cfg/visitors/kotlin-harvest.d.ts +253 -0
- package/dist/core/ingestion/cfg/visitors/kotlin-harvest.js +719 -0
- package/dist/core/ingestion/cfg/visitors/kotlin.d.ts +121 -0
- package/dist/core/ingestion/cfg/visitors/kotlin.js +809 -0
- package/dist/core/ingestion/cfg/visitors/php-harvest.d.ts +172 -0
- package/dist/core/ingestion/cfg/visitors/php-harvest.js +626 -0
- package/dist/core/ingestion/cfg/visitors/php.d.ts +96 -0
- package/dist/core/ingestion/cfg/visitors/php.js +721 -0
- package/dist/core/ingestion/cfg/visitors/python-harvest.d.ts +212 -0
- package/dist/core/ingestion/cfg/visitors/python-harvest.js +739 -0
- package/dist/core/ingestion/cfg/visitors/python.d.ts +103 -0
- package/dist/core/ingestion/cfg/visitors/python.js +558 -0
- package/dist/core/ingestion/cfg/visitors/ruby-harvest.d.ts +223 -0
- package/dist/core/ingestion/cfg/visitors/ruby-harvest.js +587 -0
- package/dist/core/ingestion/cfg/visitors/ruby.d.ts +112 -0
- package/dist/core/ingestion/cfg/visitors/ruby.js +756 -0
- package/dist/core/ingestion/cfg/visitors/rust-harvest.d.ts +324 -0
- package/dist/core/ingestion/cfg/visitors/rust-harvest.js +873 -0
- package/dist/core/ingestion/cfg/visitors/rust.d.ts +95 -0
- package/dist/core/ingestion/cfg/visitors/rust.js +558 -0
- package/dist/core/ingestion/cfg/visitors/scope-tree-harvest.d.ts +87 -0
- package/dist/core/ingestion/cfg/visitors/scope-tree-harvest.js +116 -0
- package/dist/core/ingestion/cfg/visitors/swift-harvest.d.ts +255 -0
- package/dist/core/ingestion/cfg/visitors/swift-harvest.js +679 -0
- package/dist/core/ingestion/cfg/visitors/swift.d.ts +116 -0
- package/dist/core/ingestion/cfg/visitors/swift.js +787 -0
- package/dist/core/ingestion/cfg/visitors/typescript-harvest.d.ts +149 -0
- package/dist/core/ingestion/cfg/visitors/typescript-harvest.js +1056 -0
- package/dist/core/ingestion/cfg/visitors/typescript.d.ts +66 -0
- package/dist/core/ingestion/cfg/visitors/typescript.js +583 -0
- package/dist/core/ingestion/import-resolvers/utils.js +2 -0
- package/dist/core/ingestion/language-provider.d.ts +23 -2
- package/dist/core/ingestion/languages/c-cpp.js +17 -5
- package/dist/core/ingestion/languages/cobol.js +4 -0
- package/dist/core/ingestion/languages/cpp/arity-metadata.js +41 -2
- package/dist/core/ingestion/languages/cpp/captures.js +50 -1
- package/dist/core/ingestion/languages/cpp/conversion-rank.d.ts +2 -0
- package/dist/core/ingestion/languages/cpp/conversion-rank.js +89 -0
- package/dist/core/ingestion/languages/cpp/header-scan.d.ts +1 -1
- package/dist/core/ingestion/languages/cpp/header-scan.js +2 -2
- package/dist/core/ingestion/languages/cpp/inline-namespaces.js +7 -2
- package/dist/core/ingestion/languages/cpp/member-lookup.js +2 -1
- package/dist/core/ingestion/languages/cpp/query.js +23 -0
- package/dist/core/ingestion/languages/cpp/scope-resolver.js +2 -1
- package/dist/core/ingestion/languages/csharp.js +2 -0
- package/dist/core/ingestion/languages/dart.js +2 -0
- package/dist/core/ingestion/languages/go.js +2 -0
- package/dist/core/ingestion/languages/java.js +3 -0
- package/dist/core/ingestion/languages/kotlin/query.js +3 -2
- package/dist/core/ingestion/languages/kotlin.js +8 -1
- package/dist/core/ingestion/languages/php.js +2 -0
- package/dist/core/ingestion/languages/python.js +2 -0
- package/dist/core/ingestion/languages/ruby.js +2 -0
- package/dist/core/ingestion/languages/rust.js +2 -0
- package/dist/core/ingestion/languages/swift.js +2 -0
- package/dist/core/ingestion/languages/typescript.js +5 -0
- package/dist/core/ingestion/languages/vue.js +6 -0
- package/dist/core/ingestion/method-extractors/configs/c-cpp.js +6 -13
- package/dist/core/ingestion/method-extractors/generic.js +1 -0
- package/dist/core/ingestion/method-types.d.ts +2 -0
- package/dist/core/ingestion/model/symbol-table.d.ts +1 -0
- package/dist/core/ingestion/model/symbol-table.js +1 -0
- package/dist/core/ingestion/mro-processor.js +109 -0
- package/dist/core/ingestion/parsing-processor.js +44 -0
- package/dist/core/ingestion/pipeline-phases/call-summaries.d.ts +26 -0
- package/dist/core/ingestion/pipeline-phases/call-summaries.js +46 -0
- package/dist/core/ingestion/pipeline-phases/index.d.ts +2 -0
- package/dist/core/ingestion/pipeline-phases/index.js +2 -0
- package/dist/core/ingestion/pipeline-phases/parse-impl.d.ts +0 -21
- package/dist/core/ingestion/pipeline-phases/parse-impl.js +18 -1
- package/dist/core/ingestion/pipeline-phases/routes.d.ts +10 -0
- package/dist/core/ingestion/pipeline-phases/routes.js +30 -1
- package/dist/core/ingestion/pipeline-phases/taint-summaries.d.ts +30 -0
- package/dist/core/ingestion/pipeline-phases/taint-summaries.js +81 -0
- package/dist/core/ingestion/pipeline.d.ts +92 -10
- package/dist/core/ingestion/pipeline.js +11 -2
- package/dist/core/ingestion/scope-extractor.js +12 -2
- package/dist/core/ingestion/scope-resolution/contract/scope-resolver.d.ts +9 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/callee-id-sink.d.ts +75 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/callee-id-sink.js +67 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/edges.d.ts +12 -2
- package/dist/core/ingestion/scope-resolution/graph-bridge/edges.js +14 -2
- package/dist/core/ingestion/scope-resolution/graph-bridge/references-to-edges.d.ts +6 -1
- package/dist/core/ingestion/scope-resolution/graph-bridge/references-to-edges.js +13 -1
- package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.d.ts +9 -1
- package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.js +28 -2
- package/dist/core/ingestion/scope-resolution/passes/overload-narrowing.d.ts +4 -0
- package/dist/core/ingestion/scope-resolution/passes/overload-narrowing.js +9 -0
- package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.d.ts +6 -1
- package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.js +174 -40
- package/dist/core/ingestion/scope-resolution/pipeline/phase.d.ts +24 -0
- package/dist/core/ingestion/scope-resolution/pipeline/phase.js +276 -190
- package/dist/core/ingestion/scope-resolution/pipeline/reconcile-ownership.js +43 -3
- package/dist/core/ingestion/scope-resolution/pipeline/run.d.ts +75 -0
- package/dist/core/ingestion/scope-resolution/pipeline/run.js +349 -1
- package/dist/core/ingestion/scope-resolution/resolution-outcome.d.ts +1 -1
- package/dist/core/ingestion/taint/call-summary-codec.d.ts +75 -0
- package/dist/core/ingestion/taint/call-summary-codec.js +128 -0
- package/dist/core/ingestion/taint/call-summary-emit.d.ts +43 -0
- package/dist/core/ingestion/taint/call-summary-emit.js +70 -0
- package/dist/core/ingestion/taint/call-summary-harvest.d.ts +77 -0
- package/dist/core/ingestion/taint/call-summary-harvest.js +179 -0
- package/dist/core/ingestion/taint/call-summary-model.d.ts +47 -0
- package/dist/core/ingestion/taint/call-summary-model.js +25 -0
- package/dist/core/ingestion/taint/emit.d.ts +125 -0
- package/dist/core/ingestion/taint/emit.js +208 -0
- package/dist/core/ingestion/taint/interproc-emit.d.ts +50 -0
- package/dist/core/ingestion/taint/interproc-emit.js +88 -0
- package/dist/core/ingestion/taint/interproc-solver.d.ts +110 -0
- package/dist/core/ingestion/taint/interproc-solver.js +312 -0
- package/dist/core/ingestion/taint/match.d.ts +153 -0
- package/dist/core/ingestion/taint/match.js +278 -0
- package/dist/core/ingestion/taint/path-codec.d.ts +134 -0
- package/dist/core/ingestion/taint/path-codec.js +190 -0
- package/dist/core/ingestion/taint/propagate.d.ts +216 -0
- package/dist/core/ingestion/taint/propagate.js +659 -0
- package/dist/core/ingestion/taint/site-safety.d.ts +29 -0
- package/dist/core/ingestion/taint/site-safety.js +98 -0
- package/dist/core/ingestion/taint/source-sink-config.d.ts +107 -23
- package/dist/core/ingestion/taint/source-sink-config.js +35 -12
- package/dist/core/ingestion/taint/source-sink-registry.d.ts +6 -4
- package/dist/core/ingestion/taint/source-sink-registry.js +6 -4
- package/dist/core/ingestion/taint/summary-harvest-driver.d.ts +80 -0
- package/dist/core/ingestion/taint/summary-harvest-driver.js +179 -0
- package/dist/core/ingestion/taint/summary-harvest.d.ts +89 -0
- package/dist/core/ingestion/taint/summary-harvest.js +537 -0
- package/dist/core/ingestion/taint/summary-model.d.ts +200 -0
- package/dist/core/ingestion/taint/summary-model.js +86 -0
- package/dist/core/ingestion/taint/typescript-model.d.ts +38 -0
- package/dist/core/ingestion/taint/typescript-model.js +102 -0
- package/dist/core/ingestion/type-extractors/c-cpp.js +21 -0
- package/dist/core/ingestion/utils/env.d.ts +7 -0
- package/dist/core/ingestion/utils/env.js +12 -0
- package/dist/core/ingestion/utils/method-props.js +1 -0
- package/dist/core/ingestion/workers/clone-safety.d.ts +109 -0
- package/dist/core/ingestion/workers/clone-safety.js +465 -0
- package/dist/core/ingestion/workers/parse-worker.d.ts +23 -0
- package/dist/core/ingestion/workers/parse-worker.js +81 -53
- package/dist/core/ingestion/workers/post-result.d.ts +22 -0
- package/dist/core/ingestion/workers/post-result.js +87 -0
- package/dist/core/ingestion/workers/result-merge.d.ts +20 -0
- package/dist/core/ingestion/workers/result-merge.js +43 -0
- package/dist/core/ingestion/workers/worker-pool.d.ts +15 -40
- package/dist/core/ingestion/workers/worker-pool.js +43 -16
- package/dist/core/lbug/csv-generator.d.ts +51 -3
- package/dist/core/lbug/csv-generator.js +369 -255
- package/dist/core/lbug/lbug-adapter.d.ts +58 -18
- package/dist/core/lbug/lbug-adapter.js +346 -84
- package/dist/core/lbug/lbug-config.d.ts +19 -0
- package/dist/core/lbug/lbug-config.js +29 -0
- package/dist/core/lbug/pdg-emit-sink.d.ts +127 -0
- package/dist/core/lbug/pdg-emit-sink.js +358 -0
- package/dist/core/lbug/pool-adapter.d.ts +35 -0
- package/dist/core/lbug/pool-adapter.js +90 -1
- package/dist/core/lbug/rel-pair-routing.d.ts +54 -0
- package/dist/core/lbug/rel-pair-routing.js +140 -0
- package/dist/core/lbug/schema.d.ts +2 -2
- package/dist/core/lbug/schema.js +3 -0
- package/dist/core/logger.d.ts +0 -5
- package/dist/core/run-analyze.d.ts +96 -0
- package/dist/core/run-analyze.js +207 -3
- package/dist/core/tree-sitter/parser-loader.js +5 -4
- package/dist/core/tree-sitter/safe-parse.d.ts +0 -5
- package/dist/core/tree-sitter/vendored-grammars.d.ts +39 -0
- package/dist/core/tree-sitter/vendored-grammars.js +57 -0
- package/dist/core/wiki/generator.js +3 -1
- package/dist/core/wiki/graph-queries.d.ts +6 -0
- package/dist/core/wiki/graph-queries.js +9 -1
- package/dist/mcp/http-transport.d.ts +134 -0
- package/dist/mcp/http-transport.js +503 -0
- package/dist/mcp/local/local-backend.d.ts +110 -24
- package/dist/mcp/local/local-backend.js +1225 -19
- package/dist/mcp/local/pdg-impact.d.ts +384 -0
- package/dist/mcp/local/pdg-impact.js +1972 -0
- package/dist/mcp/resources.js +13 -1
- package/dist/mcp/tools.d.ts +12 -0
- package/dist/mcp/tools.js +214 -7
- package/dist/server/analyze-launch.d.ts +29 -0
- package/dist/server/analyze-launch.js +137 -0
- package/dist/server/analyze-upload.d.ts +33 -0
- package/dist/server/analyze-upload.js +123 -0
- package/dist/server/analyze-worker-ipc.d.ts +58 -0
- package/dist/server/analyze-worker-ipc.js +16 -0
- package/dist/server/analyze-worker.d.ts +17 -1
- package/dist/server/analyze-worker.js +7 -1
- package/dist/server/api.d.ts +17 -0
- package/dist/server/api.js +132 -168
- package/dist/server/git-clone.d.ts +43 -2
- package/dist/server/git-clone.js +211 -16
- package/dist/server/mcp-http.d.ts +5 -6
- package/dist/server/mcp-http.js +9 -82
- package/dist/server/middleware.d.ts +40 -0
- package/dist/server/middleware.js +92 -0
- package/dist/server/private-ip.d.ts +1 -0
- package/dist/server/private-ip.js +15 -0
- package/dist/server/upload-ingest.d.ts +56 -0
- package/dist/server/upload-ingest.js +276 -0
- package/dist/server/upload-paths.d.ts +37 -0
- package/dist/server/upload-paths.js +57 -0
- package/dist/server/upload-sweep.d.ts +20 -0
- package/dist/server/upload-sweep.js +57 -0
- package/dist/storage/git.js +5 -8
- package/dist/storage/parse-cache.d.ts +22 -1
- package/dist/storage/parse-cache.js +44 -10
- package/dist/storage/repo-manager.d.ts +121 -10
- package/dist/storage/repo-manager.js +43 -5
- package/dist/types/pipeline.d.ts +9 -0
- package/hooks/antigravity/gitnexus-antigravity-hook.cjs +110 -10
- package/hooks/claude/gitnexus-hook.cjs +110 -13
- package/hooks/claude/hook-db-lock-probe.cjs +513 -26
- package/package.json +8 -2
- package/scripts/assert-publish-grammar-coverage.cjs +31 -0
- package/scripts/build-tree-sitter-grammars.cjs +16 -10
- package/scripts/cross-platform-tests.ts +1 -0
- package/skills/gitnexus-debugging.md +16 -4
- package/skills/gitnexus-exploring.md +3 -3
- package/skills/gitnexus-guide.md +33 -0
- package/skills/gitnexus-pdg-query.md +89 -0
- package/skills/gitnexus-refactoring.md +1 -1
- package/skills/gitnexus-taint-analysis.md +178 -0
- package/vendor/tree-sitter-c/package.json +1 -1
- package/vendor/tree-sitter-dart/package.json +1 -1
- package/vendor/tree-sitter-kotlin/package.json +1 -1
- package/vendor/tree-sitter-proto/package.json +1 -1
- package/vendor/tree-sitter-swift/package.json +1 -1
- package/web/assets/{agent-CKPMqImC.js → agent-D3Xd7zZE.js} +123 -123
- package/web/assets/architecture-7EHR7CIX-6QZW5X65-DxJw65fT.js +1 -0
- package/web/assets/architectureDiagram-UL44E2DR-ChH9xW-N.js +36 -0
- package/web/assets/{blockDiagram-7IZFK4PR-B4niSLvR.js → blockDiagram-7IZFK4PR-BkWhpzWB.js} +1 -1
- package/web/assets/{c4Diagram-Y2BXMSZH-DIzEXalR.js → c4Diagram-Y2BXMSZH-DtBvpzWD.js} +1 -1
- package/web/assets/{chunk-3SSMPTDK-BzGeeheI.js → chunk-3SSMPTDK-B4_etUhr.js} +2 -2
- package/web/assets/{chunk-5IMINLNL-CnTLsXIV.js → chunk-5IMINLNL-DOdTeQri.js} +1 -1
- package/web/assets/{chunk-5VCL7Z4A-w1BCx98Z.js → chunk-5VCL7Z4A-CQ-2dYWj.js} +1 -1
- package/web/assets/chunk-6764PJDD-DpIS7hxD.js +1 -0
- package/web/assets/{chunk-67TQ5CYL-CChC2cAv.js → chunk-67TQ5CYL-4sNPJU1q.js} +3 -3
- package/web/assets/{chunk-7W6UQGC5-CgFyfZ6k.js → chunk-7W6UQGC5-KyEG0HQg.js} +1 -1
- package/web/assets/{chunk-AZZRMDJM-5E9ARdDQ.js → chunk-AZZRMDJM-y-xJBuMz.js} +1 -1
- package/web/assets/{chunk-INKRHTLW-ELpfuk9h.js → chunk-INKRHTLW-Nu4ri9P-.js} +1 -1
- package/web/assets/{chunk-JQRUD6KW-Dcq_Qnyy.js → chunk-JQRUD6KW-Dbva2Z17.js} +1 -1
- package/web/assets/{chunk-KGFNY3KK-W-VR57xb.js → chunk-KGFNY3KK-JGMJvKCK.js} +1 -1
- package/web/assets/chunk-KGYTTC2M-CWC_c3H9.js +161 -0
- package/web/assets/{chunk-KNLZD3CH-BuZBOcso.js → chunk-KNLZD3CH-BGlP6X9R.js} +1 -1
- package/web/assets/{chunk-KRXBNO2N-DH2NPM7I.js → chunk-KRXBNO2N-BW5o0KUN.js} +1 -1
- package/web/assets/{chunk-LCXTWHL2-Dfmux4m1.js → chunk-LCXTWHL2-zoomRtWX.js} +1 -1
- package/web/assets/{chunk-LII3EMHJ-3X33tCpU.js → chunk-LII3EMHJ-D-jm-dLa.js} +1 -1
- package/web/assets/{chunk-QA3QBVWF-D5Ha3GgB.js → chunk-QA3QBVWF-BgRW3SXd.js} +1 -1
- package/web/assets/{chunk-RG4AUYOV-CAkzcoRj.js → chunk-RG4AUYOV-DD0B2N2B.js} +1 -1
- package/web/assets/{chunk-T2UQINTJ-kGYG7ppP.js → chunk-T2UQINTJ-DSBqkzH7.js} +1 -1
- package/web/assets/chunk-T5OCTHI4-DdZvN-9i.js +1 -0
- package/web/assets/{chunk-UY5QBCOK-Du-c56gs.js → chunk-UY5QBCOK-DyF0vyGd.js} +1 -1
- package/web/assets/{chunk-W44A43WB-lrCpuupA.js → chunk-W44A43WB-JqMLIpR0.js} +1 -1
- package/web/assets/{chunk-ZXARS5L4-CSZRiyOf.js → chunk-ZXARS5L4-CxN8oiwI.js} +1 -1
- package/web/assets/classDiagram-KGZ6W3CR-DJm9BgF-.js +1 -0
- package/web/assets/classDiagram-v2-72OJOZXJ-DJm9BgF-.js +1 -0
- package/web/assets/{context-builder-_HS0v2ma.js → context-builder-BHiFUA8O.js} +10 -2
- package/web/assets/{cose-bilkent-UX7MHV2Q-BHv2bbtl.js → cose-bilkent-UX7MHV2Q-D71wNYRJ.js} +1 -1
- package/web/assets/dagre-ND4H6XIP-BIkxmhcu.js +4 -0
- package/web/assets/diagram-3NCE3AQN-BTa6iH0T.js +43 -0
- package/web/assets/diagram-GF46GFSD-DZDV0vBj.js +24 -0
- package/web/assets/{diagram-HNR7UZ2L-fUWreZzx.js → diagram-HNR7UZ2L-DFCfd5LI.js} +2 -2
- package/web/assets/diagram-QXG6HAR7-BzM--Jj0.js +24 -0
- package/web/assets/diagram-WEQXMOUZ-DFFwz0k4.js +10 -0
- package/web/assets/{erDiagram-L5TCEMPS-QN2eEP1e.js → erDiagram-L5TCEMPS-CfHMJJqo.js} +1 -1
- package/web/assets/eventmodeling-FCH6USID-MREXMVOE-BQm9QzEa.js +1 -0
- package/web/assets/{flowDiagram-H6V6AXG4-CXbXImlN.js → flowDiagram-H6V6AXG4-Be805QiJ.js} +3 -3
- package/web/assets/{ganttDiagram-JCBTUEKG-BHQssTz6.js → ganttDiagram-JCBTUEKG-D3iL2Aet.js} +1 -1
- package/web/assets/gitGraph-WXDBUCRP-R675I2BI-Cr_Bm2Nb.js +1 -0
- package/web/assets/gitGraphDiagram-S2ZK5IYY-CPIDgxGm.js +106 -0
- package/web/assets/index-BvYev1UJ.js +635 -0
- package/web/assets/index-_lgn7hs5.css +2 -0
- package/web/assets/info-J43DQDTF-KCYPFFUO-Cs4p2oyk.js +1 -0
- package/web/assets/infoDiagram-3YFTVSEB-Y7BKSoke.js +2 -0
- package/web/assets/{ishikawaDiagram-BNXS4ZKH-6LKOvBfp.js → ishikawaDiagram-BNXS4ZKH-CT4SHFuI.js} +1 -1
- package/web/assets/{journeyDiagram-M6C3CM3L-DNPYCpvq.js → journeyDiagram-M6C3CM3L-CvArszLo.js} +1 -1
- package/web/assets/{kanban-definition-75IXJCU3-DgDi9oJT.js → kanban-definition-75IXJCU3-C6yDxr7N.js} +3 -3
- package/web/assets/{katex-K3KEBU37-CrVLz8l7.js → katex-K3KEBU37-CTc5BslQ.js} +1 -1
- package/web/assets/{mindmap-definition-2TDM6QVE-CwR5sBB-.js → mindmap-definition-2TDM6QVE-BOc2WEne.js} +1 -1
- package/web/assets/packet-YPE3B663-LP52Z2RK-CKCrztD2.js +1 -0
- package/web/assets/pie-LRSECV5Y-TCRJHUBD-BB7pHqoD.js +1 -0
- package/web/assets/{pieDiagram-CU6KROY3-By8g6f6B.js → pieDiagram-CU6KROY3-Cvc0f_Pd.js} +1 -1
- package/web/assets/{quadrantDiagram-VICAPDV7-bAm6Hi_5.js → quadrantDiagram-VICAPDV7-yXSZ2lLz.js} +1 -1
- package/web/assets/radar-GUYGQ44K-RDLRG3WG-DhoTOcuK.js +1 -0
- package/web/assets/{requirementDiagram-JXO7QTGE-7oDcJ1_J.js → requirementDiagram-JXO7QTGE-BRcZvHs4.js} +1 -1
- package/web/assets/{sankeyDiagram-URQDO5SZ-LFJz53u5.js → sankeyDiagram-URQDO5SZ-1qEjlFIB.js} +1 -1
- package/web/assets/{sequenceDiagram-VS2MUI6T-FySeKCUy.js → sequenceDiagram-VS2MUI6T-PcSCuvrB.js} +3 -3
- package/web/assets/stateDiagram-7D4R322I-D6qYSV1E.js +1 -0
- package/web/assets/stateDiagram-v2-36443NZ5-Bg-ImOSX.js +1 -0
- package/web/assets/{timeline-definition-O6YCAMPW-Ds2CnVZK.js → timeline-definition-O6YCAMPW-QWkh01xw.js} +1 -1
- package/web/assets/treeView-BLDUP644-QA4HXRO3-ODehyGKL.js +1 -0
- package/web/assets/treemap-LRROVOQU-LLAWBHMP-BfpgC-7o.js +1 -0
- package/web/assets/{vennDiagram-MWXL3ELB-DUIEwXWp.js → vennDiagram-MWXL3ELB-ak4DfwuM.js} +3 -3
- package/web/assets/wardley-L42UT6IY-5TKZOOLJ-CNeL6VHE.js +1 -0
- package/web/assets/{wardleyDiagram-CUQ6CDDI-DEiFPQih.js → wardleyDiagram-CUQ6CDDI-CTzR4Loq.js} +1 -1
- package/web/assets/{xychartDiagram-N2JHSOCM-BUbayhST.js → xychartDiagram-N2JHSOCM-DA1BEaQz.js} +1 -1
- package/web/index.html +13 -15
- package/scripts/materialize-vendor-grammars.cjs +0 -97
- package/web/assets/architecture-7EHR7CIX-6QZW5X65-BETj2x4g.js +0 -1
- package/web/assets/architectureDiagram-UL44E2DR-D1EXI0zA.js +0 -36
- package/web/assets/chunk-2T2R6R2M-n6s9JZqv.js +0 -4
- package/web/assets/chunk-2UTLFMKG-CMBB1TMN.js +0 -1
- package/web/assets/chunk-4R4BOZG6-mKhL59ul.js +0 -159
- package/web/assets/chunk-6764PJDD-ChwMM2z4.js +0 -1
- package/web/assets/chunk-7J6CGLKN-DT-b53FT.js +0 -10
- package/web/assets/chunk-C62D2QBJ-CDAWj26E.js +0 -1
- package/web/assets/chunk-CEXFNPSA-D68Tk6ls.js +0 -1
- package/web/assets/chunk-CilyBKbf.js +0 -1
- package/web/assets/chunk-J5EP6P6S-DxWW0yvu.js +0 -1
- package/web/assets/chunk-KGYTTC2M-C6PHeuay.js +0 -1
- package/web/assets/chunk-RERM46MO-DQNbXtfw.js +0 -1
- package/web/assets/chunk-RKZBBQEN-BmTPLSyv.js +0 -1
- package/web/assets/chunk-RLI5ZMPA-DExu2DOK.js +0 -1
- package/web/assets/chunk-T5OCTHI4--9wWpVws.js +0 -1
- package/web/assets/chunk-UP6H54XL-DsKdC6jC.js +0 -1
- package/web/assets/chunk-UXSXWOXI-DR81EqLr.js +0 -1
- package/web/assets/classDiagram-KGZ6W3CR-Bv93af_b.js +0 -1
- package/web/assets/classDiagram-v2-72OJOZXJ-CLfEqHUa.js +0 -1
- package/web/assets/dagre-ND4H6XIP-DsIr9MOv.js +0 -4
- package/web/assets/diagram-3NCE3AQN-BqAtKUpW.js +0 -43
- package/web/assets/diagram-GF46GFSD-CaBG6n6o.js +0 -24
- package/web/assets/diagram-QXG6HAR7-CZ-O3rcV.js +0 -24
- package/web/assets/diagram-WEQXMOUZ-P4lSL4GH.js +0 -10
- package/web/assets/eventmodeling-FCH6USID-MREXMVOE-B3myHUst.js +0 -1
- package/web/assets/gitGraph-WXDBUCRP-R675I2BI-DF3rtf4A.js +0 -1
- package/web/assets/gitGraphDiagram-S2ZK5IYY-CCwVLT__.js +0 -106
- package/web/assets/index-BKWA-m7o.css +0 -2
- package/web/assets/index-CG6q8eTs.js +0 -626
- package/web/assets/info-J43DQDTF-KCYPFFUO-R4XV_akJ.js +0 -1
- package/web/assets/infoDiagram-3YFTVSEB-DmLICZx1.js +0 -2
- package/web/assets/packet-YPE3B663-LP52Z2RK-CgQPdNZa.js +0 -1
- package/web/assets/pie-LRSECV5Y-TCRJHUBD-BzWOwc_c.js +0 -1
- package/web/assets/radar-GUYGQ44K-RDLRG3WG-B7KG0FN7.js +0 -1
- package/web/assets/stateDiagram-7D4R322I-CB2nABwH.js +0 -1
- package/web/assets/stateDiagram-v2-36443NZ5-COBGd2RL.js +0 -1
- package/web/assets/treeView-BLDUP644-QA4HXRO3-CRSxEwLO.js +0 -1
- package/web/assets/treemap-LRROVOQU-LLAWBHMP-a0PfKoVn.js +0 -1
- package/web/assets/wardley-L42UT6IY-5TKZOOLJ-BKQ6e5mC.js +0 -1
- /package/web/assets/{chunk-AQ6EADP3-CCFje6lL.js → chunk-AQ6EADP3-CZhslHi-.js} +0 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
const SITE_KINDS = new Set(['call', 'new', 'member-read']);
|
|
2
|
+
/**
|
|
3
|
+
* Whether a structurally-valid CFG's M3 `sites` annotations are safe to feed
|
|
4
|
+
* to the taint matcher/propagator. `true` when no statement carries sites
|
|
5
|
+
* (pre-M3 channel, or no calls) — absence is the well-formed empty case.
|
|
6
|
+
*/
|
|
7
|
+
export const hasTaintSafeSites = (cfg) => {
|
|
8
|
+
// Sites carry binding indices — a channel with sites but no binding table
|
|
9
|
+
// has nothing to range-check them against: reject (checked per statement).
|
|
10
|
+
const bindingCount = Array.isArray(cfg.bindings) ? cfg.bindings.length : -1;
|
|
11
|
+
for (const block of cfg.blocks) {
|
|
12
|
+
const stmts = block.statements;
|
|
13
|
+
if (stmts === undefined)
|
|
14
|
+
continue;
|
|
15
|
+
if (!Array.isArray(stmts))
|
|
16
|
+
return false;
|
|
17
|
+
for (const s of stmts) {
|
|
18
|
+
if (s?.sites === undefined)
|
|
19
|
+
continue;
|
|
20
|
+
if (bindingCount < 0)
|
|
21
|
+
return false;
|
|
22
|
+
if (!isSafeSiteList(s.sites, bindingCount))
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return true;
|
|
27
|
+
};
|
|
28
|
+
const isSafeSiteList = (sites, bindingCount) => {
|
|
29
|
+
if (!Array.isArray(sites))
|
|
30
|
+
return false;
|
|
31
|
+
const siteCount = sites.length;
|
|
32
|
+
const bindingInRange = (i) => Number.isInteger(i) && i >= 0 && i < bindingCount;
|
|
33
|
+
const siteInRange = (i) => Number.isInteger(i) && i >= 0 && i < siteCount;
|
|
34
|
+
for (const site of sites) {
|
|
35
|
+
if (site === null || typeof site !== 'object')
|
|
36
|
+
return false;
|
|
37
|
+
if (typeof site.kind !== 'string' || !SITE_KINDS.has(site.kind))
|
|
38
|
+
return false;
|
|
39
|
+
if (site.callee !== undefined && typeof site.callee !== 'string')
|
|
40
|
+
return false;
|
|
41
|
+
if (site.receiver !== undefined && !bindingInRange(site.receiver))
|
|
42
|
+
return false;
|
|
43
|
+
if (site.requireArg !== undefined && typeof site.requireArg !== 'string')
|
|
44
|
+
return false;
|
|
45
|
+
if (site.template !== undefined && typeof site.template !== 'boolean')
|
|
46
|
+
return false;
|
|
47
|
+
if (site.spread !== undefined &&
|
|
48
|
+
(!Number.isInteger(site.spread) || site.spread < 0)) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
if (site.parent !== undefined) {
|
|
52
|
+
const p = site.parent;
|
|
53
|
+
if (!Array.isArray(p) || p.length !== 2)
|
|
54
|
+
return false;
|
|
55
|
+
if (!siteInRange(p[0]))
|
|
56
|
+
return false;
|
|
57
|
+
if (!Number.isInteger(p[1]) || p[1] < 0)
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
if (site.resultDefs !== undefined) {
|
|
61
|
+
if (!Array.isArray(site.resultDefs) || !site.resultDefs.every(bindingInRange))
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
if (site.args !== undefined) {
|
|
65
|
+
if (!Array.isArray(site.args))
|
|
66
|
+
return false;
|
|
67
|
+
for (const position of site.args) {
|
|
68
|
+
if (!Array.isArray(position))
|
|
69
|
+
return false;
|
|
70
|
+
for (const entry of position) {
|
|
71
|
+
if (typeof entry === 'number') {
|
|
72
|
+
if (!bindingInRange(entry))
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
else if (Array.isArray(entry) && entry.length === 2) {
|
|
76
|
+
if (!bindingInRange(entry[0]) || !siteInRange(entry[1]))
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
if (site.kind === 'member-read') {
|
|
86
|
+
// The matcher dereferences both unconditionally on member reads.
|
|
87
|
+
if (!bindingInRange(site.object) || typeof site.property !== 'string')
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
if (site.object !== undefined && !bindingInRange(site.object))
|
|
92
|
+
return false;
|
|
93
|
+
if (site.property !== undefined && typeof site.property !== 'string')
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return true;
|
|
98
|
+
};
|
|
@@ -1,36 +1,120 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Source/sink/sanitizer config model (issue #2080,
|
|
2
|
+
* Source/sink/sanitizer config model (issue #2080 M0 seam, extended by #2083
|
|
3
|
+
* M3 U2).
|
|
3
4
|
*
|
|
4
|
-
* The per-language taint configuration *shape*. M0
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* The per-language taint configuration *shape*. M0 shipped only the bare
|
|
6
|
+
* `{name, args?}` callable matcher and an empty registry seam; M3 U2 extends
|
|
7
|
+
* it with the `kind` taxonomy and the resolution-mechanism fields the
|
|
8
|
+
* import-aware matcher (`taint/match.ts`) needs, and fills the registry with
|
|
9
|
+
* the built-in TS/JS model (`taint/typescript-model.ts`).
|
|
8
10
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* when M3 makes contact with real flows; that is a forward-declared-interface
|
|
14
|
-
* design choice, not a finished contract.
|
|
11
|
+
* Design rule: entries describe WHAT a callable is (category + how its name
|
|
12
|
+
* resolves), never HOW matching works — matching semantics (import joins,
|
|
13
|
+
* shadow checks, spread/template position rules) live in the matcher so the
|
|
14
|
+
* spec stays declarative data that can hash into `taintModelVersion`.
|
|
15
15
|
*/
|
|
16
|
+
/** Categories of taint sources. M3 ships remote HTTP input only. */
|
|
17
|
+
export type SourceKind = 'remote-input';
|
|
16
18
|
/**
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
19
|
+
* Vulnerability categories for sinks. Sanitizers reference the SAME taxonomy
|
|
20
|
+
* via {@link TaintSanitizerEntry.neutralizes}: a sanitizer kill applies only
|
|
21
|
+
* when it neutralizes the matched sink's kind (`path.basename` strips
|
|
22
|
+
* directories, not shell metacharacters — a kind-blind kill is a suppressed
|
|
23
|
+
* live command injection, the forbidden false-negative direction).
|
|
22
24
|
*/
|
|
23
|
-
export
|
|
25
|
+
export type SinkKind = 'command-injection' | 'code-injection' | 'path-traversal' | 'sql-injection' | 'xss';
|
|
26
|
+
/**
|
|
27
|
+
* Identifies a callable that participates in taint flow. `name` is the
|
|
28
|
+
* callable's own (unqualified) name — qualification comes from the
|
|
29
|
+
* resolution-mechanism fields on the extending entry types, not from dotted
|
|
30
|
+
* `name` strings. `args` optionally narrows to specific 0-based argument
|
|
31
|
+
* positions that carry taint into a sink (or are cleared by a sanitizer);
|
|
32
|
+
* omit to mean "all positions".
|
|
33
|
+
*/
|
|
34
|
+
export interface TaintCallableMatcher<K extends string = string> {
|
|
35
|
+
readonly name: string;
|
|
36
|
+
readonly args?: readonly number[];
|
|
37
|
+
/** Category label — drives finding classification and sanitizer kind-compat. */
|
|
38
|
+
readonly kind: K;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* A sink callable. Exactly one resolution mechanism should be set per entry:
|
|
42
|
+
*
|
|
43
|
+
* - `module` — the callable lives in a package/builtin module; the matcher
|
|
44
|
+
* resolves call sites against it import-aware (ESM `parsedImports` aliases,
|
|
45
|
+
* namespace handles, and the CommonJS `require('<literal>')` join). `name`
|
|
46
|
+
* is the exported member (`'exec'` of `'child_process'`); the pseudo-name
|
|
47
|
+
* `'default'` denotes invoking the module's default export / the module
|
|
48
|
+
* handle itself.
|
|
49
|
+
* - `global` — a true ECMAScript global (`eval`, `Function`); matched by bare
|
|
50
|
+
* name only when the name is not shadowed by an in-function declaration and
|
|
51
|
+
* not bound by an import. `newOnly` further restricts to `new` expressions
|
|
52
|
+
* (`new Function(body)`).
|
|
53
|
+
* - `anyReceiver` — a method matched on ANY receiver chain by its final
|
|
54
|
+
* segment (`.query(sql)` / `.execute(sql)` on whatever the DB handle is
|
|
55
|
+
* named) — deliberately name-conventional, like Semgrep's default rules.
|
|
56
|
+
* - `receivers` — a method matched only on the listed conventional receiver
|
|
57
|
+
* names (`res.send` / `res.write`); exactly `<receiver>.<name>`, name-based.
|
|
58
|
+
*/
|
|
59
|
+
export interface TaintSinkEntry extends TaintCallableMatcher<SinkKind> {
|
|
60
|
+
readonly module?: string;
|
|
61
|
+
readonly global?: boolean;
|
|
62
|
+
/** Only meaningful with `global`: match `new <name>(…)` sites only. */
|
|
63
|
+
readonly newOnly?: boolean;
|
|
64
|
+
readonly anyReceiver?: boolean;
|
|
65
|
+
readonly receivers?: readonly string[];
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* A sanitizer callable. Carries the sink kinds it `neutralizes` instead of a
|
|
69
|
+
* `kind` of its own. STRICTER resolution than sinks by design: only the
|
|
70
|
+
* `module` (import-aware) and `global` mechanisms exist — never a bare-name
|
|
71
|
+
* convention — because a sanitizer mis-match is a false KILL (a user's own
|
|
72
|
+
* `escape` helper must not suppress findings), while a sink mis-match is
|
|
73
|
+
* merely noise. `args` narrows which argument positions are cleared (omit =
|
|
74
|
+
* all).
|
|
75
|
+
*/
|
|
76
|
+
export interface TaintSanitizerEntry {
|
|
24
77
|
readonly name: string;
|
|
25
78
|
readonly args?: readonly number[];
|
|
79
|
+
readonly neutralizes: readonly SinkKind[];
|
|
80
|
+
readonly module?: string;
|
|
81
|
+
readonly global?: boolean;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* A member-read taint source: reading `<object>.<property>` where the object
|
|
85
|
+
* is one of the conventional receiver `objects` names (`req`/`request`) and
|
|
86
|
+
* the property is one of `properties` (`body`, `query`, …). Matching is
|
|
87
|
+
* name-based on the harvested `member-read` site (Semgrep-convention, not
|
|
88
|
+
* type-aware — the accepted M3 FP/FN trade recorded in the plan's risk
|
|
89
|
+
* table). One entry fans out over the objects × properties product.
|
|
90
|
+
*/
|
|
91
|
+
export interface TaintMemberSourceEntry {
|
|
92
|
+
readonly kind: SourceKind;
|
|
93
|
+
readonly objects: readonly string[];
|
|
94
|
+
readonly properties: readonly string[];
|
|
26
95
|
}
|
|
27
96
|
/**
|
|
28
|
-
* The taint configuration for a single language: which
|
|
29
|
-
* taint (sources), which are dangerous to reach with tainted input
|
|
30
|
-
* and which clear
|
|
97
|
+
* The taint configuration for a single language: which member reads introduce
|
|
98
|
+
* taint (sources), which callables are dangerous to reach with tainted input
|
|
99
|
+
* (sinks), and which callables clear it (sanitizers). M3 sources are
|
|
100
|
+
* member-read entries only; call-result sources are a forward extension
|
|
101
|
+
* (add a union variant), not a missing case.
|
|
31
102
|
*/
|
|
32
103
|
export interface SourceSinkSanitizerSpec {
|
|
33
|
-
readonly sources: readonly
|
|
34
|
-
readonly sinks: readonly
|
|
35
|
-
readonly sanitizers: readonly
|
|
104
|
+
readonly sources: readonly TaintMemberSourceEntry[];
|
|
105
|
+
readonly sinks: readonly TaintSinkEntry[];
|
|
106
|
+
readonly sanitizers: readonly TaintSanitizerEntry[];
|
|
36
107
|
}
|
|
108
|
+
/**
|
|
109
|
+
* Canonical deterministic ordering of {@link SinkKind} values. The single
|
|
110
|
+
* source of this order — the intra-procedural propagation engine
|
|
111
|
+
* (`propagate.ts`) and the M4 summary harvest (`summary-harvest.ts`) both sort
|
|
112
|
+
* `neutralized`/exclusion sets by it so their deterministic outputs (and the
|
|
113
|
+
* summary version stamp) stay stable. Lives here, next to the `SinkKind`
|
|
114
|
+
* union, so the two consumers never drift.
|
|
115
|
+
*/
|
|
116
|
+
export declare const SINK_KIND_ORDER: readonly SinkKind[];
|
|
117
|
+
/** Dedupe + sort sink kinds by {@link SINK_KIND_ORDER} (deterministic). */
|
|
118
|
+
export declare function sortSinkKinds(kinds: Iterable<SinkKind>): SinkKind[];
|
|
119
|
+
/** Rank of a sink kind in {@link SINK_KIND_ORDER} (for comparator chaining). */
|
|
120
|
+
export declare function sinkKindRank(kind: SinkKind): number;
|
|
@@ -1,16 +1,39 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Source/sink/sanitizer config model (issue #2080,
|
|
2
|
+
* Source/sink/sanitizer config model (issue #2080 M0 seam, extended by #2083
|
|
3
|
+
* M3 U2).
|
|
3
4
|
*
|
|
4
|
-
* The per-language taint configuration *shape*. M0
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* The per-language taint configuration *shape*. M0 shipped only the bare
|
|
6
|
+
* `{name, args?}` callable matcher and an empty registry seam; M3 U2 extends
|
|
7
|
+
* it with the `kind` taxonomy and the resolution-mechanism fields the
|
|
8
|
+
* import-aware matcher (`taint/match.ts`) needs, and fills the registry with
|
|
9
|
+
* the built-in TS/JS model (`taint/typescript-model.ts`).
|
|
8
10
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* when M3 makes contact with real flows; that is a forward-declared-interface
|
|
14
|
-
* design choice, not a finished contract.
|
|
11
|
+
* Design rule: entries describe WHAT a callable is (category + how its name
|
|
12
|
+
* resolves), never HOW matching works — matching semantics (import joins,
|
|
13
|
+
* shadow checks, spread/template position rules) live in the matcher so the
|
|
14
|
+
* spec stays declarative data that can hash into `taintModelVersion`.
|
|
15
15
|
*/
|
|
16
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Canonical deterministic ordering of {@link SinkKind} values. The single
|
|
18
|
+
* source of this order — the intra-procedural propagation engine
|
|
19
|
+
* (`propagate.ts`) and the M4 summary harvest (`summary-harvest.ts`) both sort
|
|
20
|
+
* `neutralized`/exclusion sets by it so their deterministic outputs (and the
|
|
21
|
+
* summary version stamp) stay stable. Lives here, next to the `SinkKind`
|
|
22
|
+
* union, so the two consumers never drift.
|
|
23
|
+
*/
|
|
24
|
+
export const SINK_KIND_ORDER = [
|
|
25
|
+
'code-injection',
|
|
26
|
+
'command-injection',
|
|
27
|
+
'path-traversal',
|
|
28
|
+
'sql-injection',
|
|
29
|
+
'xss',
|
|
30
|
+
];
|
|
31
|
+
const SINK_KIND_RANK = new Map(SINK_KIND_ORDER.map((k, i) => [k, i]));
|
|
32
|
+
/** Dedupe + sort sink kinds by {@link SINK_KIND_ORDER} (deterministic). */
|
|
33
|
+
export function sortSinkKinds(kinds) {
|
|
34
|
+
return [...new Set(kinds)].sort((a, b) => (SINK_KIND_RANK.get(a) ?? 99) - (SINK_KIND_RANK.get(b) ?? 99));
|
|
35
|
+
}
|
|
36
|
+
/** Rank of a sink kind in {@link SINK_KIND_ORDER} (for comparator chaining). */
|
|
37
|
+
export function sinkKindRank(kind) {
|
|
38
|
+
return SINK_KIND_RANK.get(kind) ?? 99;
|
|
39
|
+
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Per-language source/sink/sanitizer registry seam (issue #2080).
|
|
3
3
|
*
|
|
4
|
-
* A keyed registry of {@link SourceSinkSanitizerSpec} by language id. M0
|
|
5
|
-
* up the empty seam
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* A keyed registry of {@link SourceSinkSanitizerSpec} by language id. M0 stood
|
|
5
|
+
* up the empty seam; M3 U2 (#2083) fills it with the built-in TS/JS model via
|
|
6
|
+
* the EXPLICIT `registerBuiltinTaintModels()` seam in `typescript-model.ts` —
|
|
7
|
+
* deliberately not an import side-effect. The U4 taint emit path must call it
|
|
8
|
+
* once before the pdg window consumes the registry (idempotent; the registry
|
|
9
|
+
* itself stays empty until then, preserving default-run parity).
|
|
8
10
|
*
|
|
9
11
|
* The store is module-level (matching the codebase's other per-language
|
|
10
12
|
* registries). {@link clearSourceSinkRegistry} resets it for test isolation.
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Per-language source/sink/sanitizer registry seam (issue #2080).
|
|
3
3
|
*
|
|
4
|
-
* A keyed registry of {@link SourceSinkSanitizerSpec} by language id. M0
|
|
5
|
-
* up the empty seam
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* A keyed registry of {@link SourceSinkSanitizerSpec} by language id. M0 stood
|
|
5
|
+
* up the empty seam; M3 U2 (#2083) fills it with the built-in TS/JS model via
|
|
6
|
+
* the EXPLICIT `registerBuiltinTaintModels()` seam in `typescript-model.ts` —
|
|
7
|
+
* deliberately not an import side-effect. The U4 taint emit path must call it
|
|
8
|
+
* once before the pdg window consumes the registry (idempotent; the registry
|
|
9
|
+
* itself stays empty until then, preserving default-run parity).
|
|
8
10
|
*
|
|
9
11
|
* The store is module-level (matching the codebase's other per-language
|
|
10
12
|
* registries). {@link clearSourceSinkRegistry} resets it for test isolation.
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Summary-harvest driver (#2084 M4 U1) — the in-phase orchestration that turns
|
|
3
|
+
* per-function CFGs into call-graph-keyed {@link FunctionSummary} objects.
|
|
4
|
+
*
|
|
5
|
+
* Runs inside the scope-resolution pdg window (alongside `emitFileTaint`),
|
|
6
|
+
* where both the live CFG side channel AND the structure-phase `Function` /
|
|
7
|
+
* `Method` graph nodes are available. For each emit-safe CFG it:
|
|
8
|
+
*
|
|
9
|
+
* 1. resolves the CFG's source anchor `(filePath, functionStartLine)` to its
|
|
10
|
+
* graph node id, so the summary speaks the call graph's language directly —
|
|
11
|
+
* the interprocedural fixpoint then joins summaries to `CALLS` edges by node
|
|
12
|
+
* id with no fragile re-derivation;
|
|
13
|
+
* 2. runs the pure {@link harvestFunctionSummary} over the same RD facts +
|
|
14
|
+
* matched sites the M3 taint pass uses;
|
|
15
|
+
* 3. stamps the own-facts `version` (#2084 review P1-1: callee-version
|
|
16
|
+
* composition is RESERVED — the fixpoint does not recompute it today).
|
|
17
|
+
*
|
|
18
|
+
* ## The Function↔CFG join (load-bearing)
|
|
19
|
+
*
|
|
20
|
+
* `FunctionCfg.functionStartLine` is 1-based (the TS visitor's `row + 1`);
|
|
21
|
+
* `Function`/`Method` node `startLine` is 0-based (`startPosition.row`). The
|
|
22
|
+
* join therefore looks up node start line `functionStartLine - 1`
|
|
23
|
+
* ({@link NODE_TO_CFG_LINE_OFFSET}). Function nodes carry no start column, so a
|
|
24
|
+
* `(filePath, startLine)` collision — two functions opening on one line,
|
|
25
|
+
* `{ a: () => x(), b: () => y() }` — is ambiguous: the CFG disambiguates with
|
|
26
|
+
* `functionStartColumn` but the node does not, so a colliding anchor is DROPPED
|
|
27
|
+
* (counted as `unresolved`) rather than risk attaching a summary to the wrong
|
|
28
|
+
* function. Rare in practice; the alternative (cross-wired summaries) is unsound.
|
|
29
|
+
*/
|
|
30
|
+
import type { ParsedImport } from '../../../_shared/index.js';
|
|
31
|
+
import type { KnowledgeGraph } from '../../graph/types.js';
|
|
32
|
+
import { type ReachingDefsSolver } from '../cfg/reaching-defs.js';
|
|
33
|
+
import type { FunctionCfg } from '../cfg/types.js';
|
|
34
|
+
import type { SourceSinkSanitizerSpec } from './source-sink-config.js';
|
|
35
|
+
import { type FunctionSummary } from './summary-model.js';
|
|
36
|
+
import type { CallSummary } from './call-summary-model.js';
|
|
37
|
+
/** `cfg.functionStartLine` (1-based) − this = the node's 0-based `startLine`. */
|
|
38
|
+
export declare const NODE_TO_CFG_LINE_OFFSET = 1;
|
|
39
|
+
/**
|
|
40
|
+
* Index of functionish graph nodes by `filePath → startLine(0-based) → ids`.
|
|
41
|
+
* Built ONCE per scope-resolution pass (the graph is whole-repo); reused across
|
|
42
|
+
* every file's harvest.
|
|
43
|
+
*/
|
|
44
|
+
export type FunctionNodeIndex = ReadonlyMap<string, ReadonlyMap<number, readonly string[]>>;
|
|
45
|
+
export declare function buildFunctionNodeIndex(graph: KnowledgeGraph): FunctionNodeIndex;
|
|
46
|
+
export interface FileSummaryResult {
|
|
47
|
+
readonly summaries: readonly FunctionSummary[];
|
|
48
|
+
/** CFGs whose anchor resolved to no unique graph node (collision / missing). */
|
|
49
|
+
readonly unresolved: number;
|
|
50
|
+
/** CFGs whose reaching-defs were not `computed` (no summary produced). */
|
|
51
|
+
readonly gaps: number;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Harvest summaries for one file's emit-safe CFGs. `cfgs` MUST already be
|
|
55
|
+
* `isEmitSafeCfg`-filtered (the same `wellFormed` array fed to `emitFileTaint`).
|
|
56
|
+
* Pure aside from the read-only graph lookup; never throws on valid input.
|
|
57
|
+
*/
|
|
58
|
+
export declare function harvestFileSummaries(fnIndex: FunctionNodeIndex, cfgs: readonly FunctionCfg[], parsedImports: readonly ParsedImport[], spec: SourceSinkSanitizerSpec, maxFacts?: number, solve?: ReachingDefsSolver): FileSummaryResult;
|
|
59
|
+
export interface FileCallSummaryResult {
|
|
60
|
+
readonly summaries: readonly CallSummary[];
|
|
61
|
+
/** CFGs whose anchor resolved to no unique graph node (collision / missing). */
|
|
62
|
+
readonly unresolved: number;
|
|
63
|
+
/** CFGs whose reaching-defs were not `computed` (no summary produced). */
|
|
64
|
+
readonly gaps: number;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Harvest per-function RETURN-VALUE ASCENT summaries (PDG FU-C, U-C2) for one
|
|
68
|
+
* file's emit-safe CFGs — the dependence-engine SIBLING of
|
|
69
|
+
* {@link harvestFileSummaries}. `cfgs` MUST already be `isEmitSafeCfg`-filtered.
|
|
70
|
+
* Pure aside from the read-only graph lookup; never throws on valid input.
|
|
71
|
+
*
|
|
72
|
+
* Unlike the taint harvest, this needs NO source/sink model — return-value
|
|
73
|
+
* ascent is purely data-dependence over the RD facts — so it runs for every
|
|
74
|
+
* `--pdg` language (not just those with a registered taint spec). It reuses the
|
|
75
|
+
* SAME per-function RD facts (recomputed via the same pure solver + cap the RD
|
|
76
|
+
* emit used; the persisted REACHING_DEF projection is a lossy subset, so the
|
|
77
|
+
* harvest re-derives in-phase exactly as the taint harvest does — no new
|
|
78
|
+
* worker/CFG work, no parse-cache bump).
|
|
79
|
+
*/
|
|
80
|
+
export declare function harvestFileCallSummaries(fnIndex: FunctionNodeIndex, cfgs: readonly FunctionCfg[], maxFacts?: number, solve?: ReachingDefsSolver): FileCallSummaryResult;
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Summary-harvest driver (#2084 M4 U1) — the in-phase orchestration that turns
|
|
3
|
+
* per-function CFGs into call-graph-keyed {@link FunctionSummary} objects.
|
|
4
|
+
*
|
|
5
|
+
* Runs inside the scope-resolution pdg window (alongside `emitFileTaint`),
|
|
6
|
+
* where both the live CFG side channel AND the structure-phase `Function` /
|
|
7
|
+
* `Method` graph nodes are available. For each emit-safe CFG it:
|
|
8
|
+
*
|
|
9
|
+
* 1. resolves the CFG's source anchor `(filePath, functionStartLine)` to its
|
|
10
|
+
* graph node id, so the summary speaks the call graph's language directly —
|
|
11
|
+
* the interprocedural fixpoint then joins summaries to `CALLS` edges by node
|
|
12
|
+
* id with no fragile re-derivation;
|
|
13
|
+
* 2. runs the pure {@link harvestFunctionSummary} over the same RD facts +
|
|
14
|
+
* matched sites the M3 taint pass uses;
|
|
15
|
+
* 3. stamps the own-facts `version` (#2084 review P1-1: callee-version
|
|
16
|
+
* composition is RESERVED — the fixpoint does not recompute it today).
|
|
17
|
+
*
|
|
18
|
+
* ## The Function↔CFG join (load-bearing)
|
|
19
|
+
*
|
|
20
|
+
* `FunctionCfg.functionStartLine` is 1-based (the TS visitor's `row + 1`);
|
|
21
|
+
* `Function`/`Method` node `startLine` is 0-based (`startPosition.row`). The
|
|
22
|
+
* join therefore looks up node start line `functionStartLine - 1`
|
|
23
|
+
* ({@link NODE_TO_CFG_LINE_OFFSET}). Function nodes carry no start column, so a
|
|
24
|
+
* `(filePath, startLine)` collision — two functions opening on one line,
|
|
25
|
+
* `{ a: () => x(), b: () => y() }` — is ambiguous: the CFG disambiguates with
|
|
26
|
+
* `functionStartColumn` but the node does not, so a colliding anchor is DROPPED
|
|
27
|
+
* (counted as `unresolved`) rather than risk attaching a summary to the wrong
|
|
28
|
+
* function. Rare in practice; the alternative (cross-wired summaries) is unsound.
|
|
29
|
+
*/
|
|
30
|
+
import { computeReachingDefs } from '../cfg/reaching-defs.js';
|
|
31
|
+
import { DEFAULT_PDG_MAX_REACHING_DEF_FACTS_PER_FUNCTION } from '../cfg/emit.js';
|
|
32
|
+
import { buildTaintImportIndex, matchFunctionSites } from './match.js';
|
|
33
|
+
import { harvestFunctionSummary } from './summary-harvest.js';
|
|
34
|
+
import { ownFactsDigest, summaryVersion } from './summary-model.js';
|
|
35
|
+
import { harvestCallSummary } from './call-summary-harvest.js';
|
|
36
|
+
/** `cfg.functionStartLine` (1-based) − this = the node's 0-based `startLine`. */
|
|
37
|
+
export const NODE_TO_CFG_LINE_OFFSET = 1;
|
|
38
|
+
/**
|
|
39
|
+
* Node labels that can own a CFG / be a `CALLS` endpoint AND receive a
|
|
40
|
+
* return-value-ascent summary. `Constructor` is INTENTIONALLY excluded: a
|
|
41
|
+
* constructor's "return" is the freshly-allocated instance, not a user-flowed
|
|
42
|
+
* value, so a formal→return ascent is not meaningful for it. A Constructor CFG
|
|
43
|
+
* therefore resolves to no functionish node (counted `unresolved`) and emits no
|
|
44
|
+
* CALL_SUMMARY edge — a sound recall miss, never a false ascent. The impact
|
|
45
|
+
* consumer may still DESCEND into a Constructor; it just never learns a
|
|
46
|
+
* constructor's return-flow. (#2227 tri-review.)
|
|
47
|
+
*/
|
|
48
|
+
const FUNCTIONISH_LABELS = new Set(['Function', 'Method']);
|
|
49
|
+
export function buildFunctionNodeIndex(graph) {
|
|
50
|
+
const index = new Map();
|
|
51
|
+
const add = (node) => {
|
|
52
|
+
if (!FUNCTIONISH_LABELS.has(node.label))
|
|
53
|
+
return;
|
|
54
|
+
const filePath = node.properties.filePath;
|
|
55
|
+
const startLine = node.properties.startLine;
|
|
56
|
+
if (typeof filePath !== 'string' || typeof startLine !== 'number')
|
|
57
|
+
return;
|
|
58
|
+
let byLine = index.get(filePath);
|
|
59
|
+
if (!byLine) {
|
|
60
|
+
byLine = new Map();
|
|
61
|
+
index.set(filePath, byLine);
|
|
62
|
+
}
|
|
63
|
+
const ids = byLine.get(startLine);
|
|
64
|
+
if (ids)
|
|
65
|
+
ids.push(node.id);
|
|
66
|
+
else
|
|
67
|
+
byLine.set(startLine, [node.id]);
|
|
68
|
+
};
|
|
69
|
+
for (const node of graph.iterNodes())
|
|
70
|
+
add(node);
|
|
71
|
+
return index;
|
|
72
|
+
}
|
|
73
|
+
/** Resolve a CFG anchor to a unique functionish node id, or undefined. */
|
|
74
|
+
function resolveFnId(fnIndex, cfg) {
|
|
75
|
+
const byLine = fnIndex.get(cfg.filePath);
|
|
76
|
+
if (!byLine)
|
|
77
|
+
return undefined;
|
|
78
|
+
const ids = byLine.get(cfg.functionStartLine - NODE_TO_CFG_LINE_OFFSET);
|
|
79
|
+
// Unique match only — a same-line collision is unresolvable (no node column).
|
|
80
|
+
return ids && ids.length === 1 ? ids[0] : undefined;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Harvest summaries for one file's emit-safe CFGs. `cfgs` MUST already be
|
|
84
|
+
* `isEmitSafeCfg`-filtered (the same `wellFormed` array fed to `emitFileTaint`).
|
|
85
|
+
* Pure aside from the read-only graph lookup; never throws on valid input.
|
|
86
|
+
*/
|
|
87
|
+
export function harvestFileSummaries(fnIndex, cfgs, parsedImports, spec, maxFacts = DEFAULT_PDG_MAX_REACHING_DEF_FACTS_PER_FUNCTION,
|
|
88
|
+
// U12: shared per-file memoized solver (harvest/taint bucket — no maxBlockVisits).
|
|
89
|
+
solve = computeReachingDefs) {
|
|
90
|
+
const importIndex = buildTaintImportIndex(parsedImports);
|
|
91
|
+
const summaries = [];
|
|
92
|
+
let unresolved = 0;
|
|
93
|
+
let gaps = 0;
|
|
94
|
+
for (const cfg of cfgs) {
|
|
95
|
+
const fnId = resolveFnId(fnIndex, cfg);
|
|
96
|
+
if (fnId === undefined) {
|
|
97
|
+
unresolved++;
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
const defUse = solve(cfg, { maxFacts });
|
|
101
|
+
const matches = matchFunctionSites(cfg, spec, importIndex);
|
|
102
|
+
const harvested = harvestFunctionSummary(cfg, defUse, matches);
|
|
103
|
+
if (harvested.status !== 'computed') {
|
|
104
|
+
gaps++;
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
const facts = harvested.facts;
|
|
108
|
+
// Skip functions with NO taint behaviour at all — they cannot participate
|
|
109
|
+
// in any flow and would only bloat the fixpoint's working set.
|
|
110
|
+
if (facts.paramToReturn.length === 0 &&
|
|
111
|
+
facts.paramToCallArg.length === 0 &&
|
|
112
|
+
facts.paramToSink.length === 0 &&
|
|
113
|
+
facts.sourceToReturn.length === 0 &&
|
|
114
|
+
facts.sourceToCallArg.length === 0 &&
|
|
115
|
+
facts.callResults.length === 0) {
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
const digest = ownFactsDigest(facts);
|
|
119
|
+
summaries.push({
|
|
120
|
+
fnId,
|
|
121
|
+
filePath: cfg.filePath,
|
|
122
|
+
startLine: cfg.functionStartLine,
|
|
123
|
+
...facts,
|
|
124
|
+
// Provisional own-only version; the fixpoint recomputes with callee
|
|
125
|
+
// versions once the call graph is condensed.
|
|
126
|
+
version: summaryVersion(digest, []),
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
return { summaries, unresolved, gaps };
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Harvest per-function RETURN-VALUE ASCENT summaries (PDG FU-C, U-C2) for one
|
|
133
|
+
* file's emit-safe CFGs — the dependence-engine SIBLING of
|
|
134
|
+
* {@link harvestFileSummaries}. `cfgs` MUST already be `isEmitSafeCfg`-filtered.
|
|
135
|
+
* Pure aside from the read-only graph lookup; never throws on valid input.
|
|
136
|
+
*
|
|
137
|
+
* Unlike the taint harvest, this needs NO source/sink model — return-value
|
|
138
|
+
* ascent is purely data-dependence over the RD facts — so it runs for every
|
|
139
|
+
* `--pdg` language (not just those with a registered taint spec). It reuses the
|
|
140
|
+
* SAME per-function RD facts (recomputed via the same pure solver + cap the RD
|
|
141
|
+
* emit used; the persisted REACHING_DEF projection is a lossy subset, so the
|
|
142
|
+
* harvest re-derives in-phase exactly as the taint harvest does — no new
|
|
143
|
+
* worker/CFG work, no parse-cache bump).
|
|
144
|
+
*/
|
|
145
|
+
export function harvestFileCallSummaries(fnIndex, cfgs, maxFacts = DEFAULT_PDG_MAX_REACHING_DEF_FACTS_PER_FUNCTION,
|
|
146
|
+
// U12: shared per-file memoized solver (harvest/taint bucket — no maxBlockVisits).
|
|
147
|
+
solve = computeReachingDefs) {
|
|
148
|
+
const summaries = [];
|
|
149
|
+
let unresolved = 0;
|
|
150
|
+
let gaps = 0;
|
|
151
|
+
for (const cfg of cfgs) {
|
|
152
|
+
const fnId = resolveFnId(fnIndex, cfg);
|
|
153
|
+
if (fnId === undefined) {
|
|
154
|
+
unresolved++;
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
const defUse = solve(cfg, { maxFacts });
|
|
158
|
+
const harvested = harvestCallSummary(cfg, defUse);
|
|
159
|
+
if (harvested.status !== 'computed') {
|
|
160
|
+
gaps++;
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
const facts = harvested.facts;
|
|
164
|
+
// Skip functions with NO return-flow at all — an empty summary records no
|
|
165
|
+
// ascent fact, so persisting it would only bloat the edge set. (The consumer
|
|
166
|
+
// treats an absent CALL_SUMMARY as "no known ascent", identical to an empty
|
|
167
|
+
// one.) A 0-param function or a void function therefore emits no edge.
|
|
168
|
+
if (facts.returnFlowParams.length === 0)
|
|
169
|
+
continue;
|
|
170
|
+
summaries.push({
|
|
171
|
+
fnId,
|
|
172
|
+
filePath: cfg.filePath,
|
|
173
|
+
startLine: cfg.functionStartLine,
|
|
174
|
+
paramCount: facts.paramCount,
|
|
175
|
+
returnFlowParams: facts.returnFlowParams,
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
return { summaries, unresolved, gaps };
|
|
179
|
+
}
|