From d7eac32820edd4a38fc8e04225b15b1d0f76b093 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 13 Aug 2026 17:23:24 +0000 Subject: [PATCH 1/9] Rename module to github.com/bytevet/godzilla so `go install` works go.mod declared a bare `module godzilla`, which is not a resolvable module path: the install command README documented failed with "malformed module path: missing dot in first path element". With no goreleaser config and a container-only release workflow, that left no source-install channel at all. Mechanical apart from the protobuf. The four .pb.go files are REGENERATED rather than edited: go_package is embedded in each serialized FileDescriptorProto behind byte length prefixes, so rewriting the string in place would desynchronise them and corrupt the descriptor at init. Three godzilla-prefixed strings are deliberately left alone, none of which is an import path: - the proto package godzilla.ir.v1 (wire identity, not a Go path) - sarif.go's "godzilla/v1" partialFingerprints key (changing it would invalidate every consumer's code-scanning dedup history) - taint_test.go's "godzilla/test/go/sql_injection" gIR fixtures, which mirror the sample module's own name, not the root module's Verified: build clean, 20 test packages pass, TestCorpus/js passes. The only failures are TestCorpus/java/* and converters/java, all from this environment having JDK 21 where the Java frontend requires 24 -- pre-existing and unrelated. `go install github.com/bytevet/godzilla/cmd/godzilla@latest` now resolves and fetches; it completes once this reaches the default branch. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01Rao1GBomZ53fL2ydytD96r --- README.md | 2 +- cmd/godzilla/main.go | 24 +++++++++++------------ cmd/godzilla/main_test.go | 2 +- cmd/godzilla/rules.go | 6 +++--- converters/cpp/converter.go | 8 ++++---- converters/cpp/converter_stub.go | 4 ++-- converters/frontend/frontend.go | 4 ++-- converters/go/converter.go | 2 +- converters/go/converter_test.go | 2 +- converters/go/format_marker_test.go | 2 +- converters/java/branchmerge_test.go | 6 +++--- converters/java/converter.go | 8 ++++---- converters/java/converter_test.go | 6 +++--- converters/java/lower.go | 4 ++-- converters/javascript/collect.go | 2 +- converters/javascript/converter.go | 8 ++++---- converters/javascript/converter_test.go | 10 +++++----- converters/javascript/lower.go | 4 ++-- converters/javascript/sfc.go | 2 +- converters/javascript/transform.go | 2 +- converters/javascript/typescript_test.go | 2 +- converters/llvm/cfg_test.go | 2 +- converters/llvm/llvm.go | 4 ++-- converters/python/constglobal.go | 2 +- converters/python/constglobal_test.go | 2 +- converters/python/converter.go | 10 +++++----- converters/python/converter_test.go | 10 +++++----- converters/python/lower.go | 4 ++-- converters/python/timeout_test.go | 4 ++-- converters/ruby/converter.go | 8 ++++---- converters/ruby/converter_test.go | 6 +++--- converters/ruby/lower.go | 4 ++-- converters/rust/converter.go | 10 +++++----- converters/rust/converter_test.go | 10 +++++----- converters/rust/format_marker_test.go | 2 +- converters/rust/mir.go | 4 ++-- converters/rust/smoke.go | 4 ++-- converters/ssabuild/scaffold.go | 2 +- converters/ssabuild/scaffold_test.go | 2 +- converters/ssabuild/ssabuild.go | 2 +- converters/ssabuild/ssabuild_test.go | 2 +- converters/ssabuild/values.go | 2 +- go.mod | 2 +- internal/analysis/bench_test.go | 4 ++-- internal/analysis/callgraph.go | 4 ++-- internal/analysis/callgraph_test.go | 4 ++-- internal/analysis/dangerous.go | 6 +++--- internal/analysis/dangerous_test.go | 4 ++-- internal/analysis/dynamicsink_test.go | 4 ++-- internal/analysis/edgecases_test.go | 4 ++-- internal/analysis/fieldsense_test.go | 6 +++--- internal/analysis/finding.go | 4 ++-- internal/analysis/finding_compare_test.go | 4 ++-- internal/analysis/fingerprint.go | 2 +- internal/analysis/flow.go | 2 +- internal/analysis/flow_test.go | 4 ++-- internal/analysis/global_taint_test.go | 4 ++-- internal/analysis/guards.go | 4 ++-- internal/analysis/guards_test.go | 6 +++--- internal/analysis/interproc.go | 6 +++--- internal/analysis/interproc_test.go | 4 ++-- internal/analysis/return_flow_test.go | 6 +++--- internal/analysis/sanitizer_test.go | 4 ++-- internal/analysis/secrets.go | 8 ++++---- internal/analysis/secrets_test.go | 2 +- internal/analysis/sinkargs_test.go | 4 ++-- internal/analysis/ssrf.go | 4 ++-- internal/analysis/ssrf_report_test.go | 4 ++-- internal/analysis/ssrf_test.go | 2 +- internal/analysis/taint.go | 4 ++-- internal/analysis/taint_test.go | 8 ++++---- internal/analysis/testrules_test.go | 4 ++-- internal/config/config.go | 4 ++-- internal/config/config_test.go | 6 +++--- internal/irwalk/irwalk.go | 2 +- internal/llm/anthropic.go | 2 +- internal/llm/anthropic_loop_test.go | 4 ++-- internal/llm/config_test.go | 2 +- internal/llm/openai.go | 2 +- internal/llm/openai_test.go | 4 ++-- internal/llm/review.go | 6 +++--- internal/llm/review_test.go | 6 +++--- internal/llm/tools.go | 6 +++--- internal/llm/tools_test.go | 2 +- internal/report/html.go | 8 ++++---- internal/report/html_test.go | 6 +++--- internal/report/json.go | 4 ++-- internal/report/json_test.go | 6 +++--- internal/report/sarif.go | 6 +++--- internal/report/sarif_test.go | 6 +++--- internal/report/suppression_test.go | 6 +++--- internal/report/version_test.go | 4 ++-- internal/rules/loader/loader.go | 4 ++-- internal/rules/loader/loader_test.go | 2 +- internal/ruletest/ruletest.go | 6 +++--- internal/ruletest/ruletest_test.go | 2 +- internal/scan/bench_test.go | 4 ++-- internal/scan/scan.go | 22 ++++++++++----------- internal/scan/scan_test.go | 10 +++++----- internal/testsupport/testsupport.go | 4 ++-- internal/triage/triage.go | 4 ++-- internal/triage/triage_test.go | 4 ++-- pkg/ir/v1/common.pb.go | 2 +- pkg/ir/v1/function.pb.go | 2 +- pkg/ir/v1/generate.go | 2 +- pkg/ir/v1/instruction.pb.go | 2 +- pkg/ir/v1/module.pb.go | 2 +- proto/common.proto | 2 +- proto/function.proto | 2 +- proto/instruction.proto | 2 +- proto/module.proto | 2 +- test/corpus/corpus_test.go | 4 ++-- test/corpus/differential_test.go | 4 ++-- test/corpus/manifest.go | 2 +- test/corpus/metrics_test.go | 6 +++--- test/corpus/multilang_test.go | 4 ++-- test/corpus/regen_test.go | 4 ++-- 117 files changed, 265 insertions(+), 265 deletions(-) diff --git a/README.md b/README.md index 421f715a..47460309 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ flowchart LR ## Install ```bash -go install godzilla/cmd/godzilla@latest # or, from a clone: +go install github.com/bytevet/godzilla/cmd/godzilla@latest # or, from a clone: go build -o godzilla ./cmd/godzilla ``` diff --git a/cmd/godzilla/main.go b/cmd/godzilla/main.go index 766dcfed..8d595771 100644 --- a/cmd/godzilla/main.go +++ b/cmd/godzilla/main.go @@ -17,18 +17,18 @@ import ( "slices" "strings" - "godzilla/internal/analysis" - "godzilla/internal/buildpolicy" - "godzilla/internal/config" - "godzilla/internal/llm" - "godzilla/internal/memlimit" - "godzilla/internal/proc" - "godzilla/internal/report" - "godzilla/internal/rules" - "godzilla/internal/rules/loader" - "godzilla/internal/scan" - "godzilla/internal/triage" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/internal/analysis" + "github.com/bytevet/godzilla/internal/buildpolicy" + "github.com/bytevet/godzilla/internal/config" + "github.com/bytevet/godzilla/internal/llm" + "github.com/bytevet/godzilla/internal/memlimit" + "github.com/bytevet/godzilla/internal/proc" + "github.com/bytevet/godzilla/internal/report" + "github.com/bytevet/godzilla/internal/rules" + "github.com/bytevet/godzilla/internal/rules/loader" + "github.com/bytevet/godzilla/internal/scan" + "github.com/bytevet/godzilla/internal/triage" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // version is the tool version, overridable at build time via diff --git a/cmd/godzilla/main_test.go b/cmd/godzilla/main_test.go index 0ade7b2b..391e41ed 100644 --- a/cmd/godzilla/main_test.go +++ b/cmd/godzilla/main_test.go @@ -7,7 +7,7 @@ import ( "strings" "testing" - "godzilla/internal/testsupport" + "github.com/bytevet/godzilla/internal/testsupport" ) // runCLI builds and runs the godzilla CLI (via `go run .`) with args, returning diff --git a/cmd/godzilla/rules.go b/cmd/godzilla/rules.go index 93269998..2e71a6ad 100644 --- a/cmd/godzilla/rules.go +++ b/cmd/godzilla/rules.go @@ -8,9 +8,9 @@ import ( "slices" "strings" - "godzilla/internal/rules" - "godzilla/internal/rules/loader" - "godzilla/internal/ruletest" + "github.com/bytevet/godzilla/internal/rules" + "github.com/bytevet/godzilla/internal/rules/loader" + "github.com/bytevet/godzilla/internal/ruletest" ) const rulesUsageText = `usage: godzilla rules [args] diff --git a/converters/cpp/converter.go b/converters/cpp/converter.go index 91e3ee93..22051da1 100644 --- a/converters/cpp/converter.go +++ b/converters/cpp/converter.go @@ -14,10 +14,10 @@ import ( "path/filepath" "strings" - "godzilla/converters/frontend" - llvm_converter "godzilla/converters/llvm" - "godzilla/internal/proc" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/converters/frontend" + llvm_converter "github.com/bytevet/godzilla/converters/llvm" + "github.com/bytevet/godzilla/internal/proc" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // Converter lowers C/C++ sources into gIR: the shared frontend.Driver surface diff --git a/converters/cpp/converter_stub.go b/converters/cpp/converter_stub.go index 7ef75d87..0aee68a3 100644 --- a/converters/cpp/converter_stub.go +++ b/converters/cpp/converter_stub.go @@ -7,8 +7,8 @@ package cpp_converter import ( "fmt" - "godzilla/internal/walkignore" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/internal/walkignore" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) type Converter struct{} diff --git a/converters/frontend/frontend.go b/converters/frontend/frontend.go index f0ad6502..e38b73a3 100644 --- a/converters/frontend/frontend.go +++ b/converters/frontend/frontend.go @@ -23,8 +23,8 @@ import ( "strings" "sync" - "godzilla/internal/walkignore" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/internal/walkignore" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // Driver is the embeddable front half of a Batch-based Converter: the diff --git a/converters/go/converter.go b/converters/go/converter.go index cd86ee7e..fc5ab59c 100644 --- a/converters/go/converter.go +++ b/converters/go/converter.go @@ -13,7 +13,7 @@ import ( "strings" "sync" - ir "godzilla/pkg/ir/v1" + ir "github.com/bytevet/godzilla/pkg/ir/v1" "golang.org/x/tools/go/packages" "golang.org/x/tools/go/ssa" "golang.org/x/tools/go/ssa/ssautil" diff --git a/converters/go/converter_test.go b/converters/go/converter_test.go index b923fb96..13166731 100644 --- a/converters/go/converter_test.go +++ b/converters/go/converter_test.go @@ -6,7 +6,7 @@ import ( "strings" "testing" - ir "godzilla/pkg/ir/v1" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) func TestConvertFile(t *testing.T) { diff --git a/converters/go/format_marker_test.go b/converters/go/format_marker_test.go index 027c3a5d..a5a5f350 100644 --- a/converters/go/format_marker_test.go +++ b/converters/go/format_marker_test.go @@ -5,7 +5,7 @@ import ( "path/filepath" "testing" - ir "godzilla/pkg/ir/v1" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // TestFormatMarkerExactCalleeMatch is the regression guard for the diff --git a/converters/java/branchmerge_test.go b/converters/java/branchmerge_test.go index ab84cffb..345042be 100644 --- a/converters/java/branchmerge_test.go +++ b/converters/java/branchmerge_test.go @@ -3,9 +3,9 @@ package java_converter import ( "testing" - "godzilla/internal/analysis" - "godzilla/internal/rules" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/internal/analysis" + "github.com/bytevet/godzilla/internal/rules" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // TestBranchMerge_TernaryKeepsTaint is a hermetic guard (no JDK) for FE-4. It diff --git a/converters/java/converter.go b/converters/java/converter.go index 43ed70b7..c17f602a 100644 --- a/converters/java/converter.go +++ b/converters/java/converter.go @@ -29,10 +29,10 @@ import ( "strings" "sync" - "godzilla/internal/buildpolicy" - "godzilla/internal/proc" - "godzilla/internal/walkignore" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/internal/buildpolicy" + "github.com/bytevet/godzilla/internal/proc" + "github.com/bytevet/godzilla/internal/walkignore" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) //go:embed JavaDump.java diff --git a/converters/java/converter_test.go b/converters/java/converter_test.go index ef16d46b..57c53d91 100644 --- a/converters/java/converter_test.go +++ b/converters/java/converter_test.go @@ -6,9 +6,9 @@ import ( "strings" "testing" - "godzilla/internal/irwalk" - "godzilla/internal/testsupport" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/internal/irwalk" + "github.com/bytevet/godzilla/internal/testsupport" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // requireJava skips when no JDK `java` launcher is on PATH (the frontend runs diff --git a/converters/java/lower.go b/converters/java/lower.go index 8117b383..13870d9d 100644 --- a/converters/java/lower.go +++ b/converters/java/lower.go @@ -6,8 +6,8 @@ import ( "slices" "strings" - "godzilla/converters/ssabuild" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/converters/ssabuild" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // convertClass turns one dumped class into a gIR module (one function per method). diff --git a/converters/javascript/collect.go b/converters/javascript/collect.go index 5027d61b..aa372db7 100644 --- a/converters/javascript/collect.go +++ b/converters/javascript/collect.go @@ -7,7 +7,7 @@ import ( "github.com/dop251/goja/ast" "github.com/dop251/goja/file" - ir "godzilla/pkg/ir/v1" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // pendingFunc is a function AST node discovered by the collector, queued for diff --git a/converters/javascript/converter.go b/converters/javascript/converter.go index 5353ed56..3e620e4a 100644 --- a/converters/javascript/converter.go +++ b/converters/javascript/converter.go @@ -79,10 +79,10 @@ import ( "github.com/dop251/goja/parser" "github.com/go-sourcemap/sourcemap" - "godzilla/converters/frontend" - "godzilla/internal/irwalk" - "godzilla/internal/walkignore" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/converters/frontend" + "github.com/bytevet/godzilla/internal/irwalk" + "github.com/bytevet/godzilla/internal/walkignore" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // Converter lowers JavaScript source files/directories into gIR: the shared diff --git a/converters/javascript/converter_test.go b/converters/javascript/converter_test.go index c59260a8..d82a747e 100644 --- a/converters/javascript/converter_test.go +++ b/converters/javascript/converter_test.go @@ -9,11 +9,11 @@ import ( "github.com/dop251/goja/file" "github.com/dop251/goja/parser" - "godzilla/internal/analysis" - "godzilla/internal/irwalk" - "godzilla/internal/rules" - "godzilla/internal/testsupport" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/internal/analysis" + "github.com/bytevet/godzilla/internal/irwalk" + "github.com/bytevet/godzilla/internal/rules" + "github.com/bytevet/godzilla/internal/testsupport" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // reqSources is the untrusted-HTTP-request source glob set shared by every diff --git a/converters/javascript/lower.go b/converters/javascript/lower.go index acf84ff4..1874229f 100644 --- a/converters/javascript/lower.go +++ b/converters/javascript/lower.go @@ -8,8 +8,8 @@ import ( "github.com/dop251/goja/file" "github.com/dop251/goja/token" - "godzilla/converters/ssabuild" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/converters/ssabuild" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // funcState holds the per-function lowering state. Variable values and the diff --git a/converters/javascript/sfc.go b/converters/javascript/sfc.go index b4066204..f1fb1bc4 100644 --- a/converters/javascript/sfc.go +++ b/converters/javascript/sfc.go @@ -10,7 +10,7 @@ import ( "github.com/go-sourcemap/sourcemap" "golang.org/x/net/html" - ir "godzilla/pkg/ir/v1" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // Component single-file formats (Vue `.vue`, Svelte `.svelte`) put their JS/TS in diff --git a/converters/javascript/transform.go b/converters/javascript/transform.go index 0a12f00b..588607c6 100644 --- a/converters/javascript/transform.go +++ b/converters/javascript/transform.go @@ -8,7 +8,7 @@ import ( "github.com/evanw/esbuild/pkg/api" "github.com/go-sourcemap/sourcemap" - ir "godzilla/pkg/ir/v1" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // IsJSFamily reports whether path is a JavaScript-family source file the frontend diff --git a/converters/javascript/typescript_test.go b/converters/javascript/typescript_test.go index c0f2d1df..61fd1b13 100644 --- a/converters/javascript/typescript_test.go +++ b/converters/javascript/typescript_test.go @@ -7,7 +7,7 @@ import ( "strings" "testing" - ir "godzilla/pkg/ir/v1" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // calleeNames returns every call/invoke callee in a converted program. diff --git a/converters/llvm/cfg_test.go b/converters/llvm/cfg_test.go index 736bfa55..4f9de586 100644 --- a/converters/llvm/cfg_test.go +++ b/converters/llvm/cfg_test.go @@ -7,7 +7,7 @@ import ( "path/filepath" "testing" - ir "godzilla/pkg/ir/v1" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // lowerLL writes src to a temp .ll and lowers it as C, failing the test on error. diff --git a/converters/llvm/llvm.go b/converters/llvm/llvm.go index 5b42bbfe..d55c3e7b 100644 --- a/converters/llvm/llvm.go +++ b/converters/llvm/llvm.go @@ -13,8 +13,8 @@ package llvm_converter import ( "fmt" - "godzilla/converters/ssabuild" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/converters/ssabuild" + ir "github.com/bytevet/godzilla/pkg/ir/v1" "tinygo.org/x/go-llvm" ) diff --git a/converters/python/constglobal.go b/converters/python/constglobal.go index 63e1f6b5..af0aa17d 100644 --- a/converters/python/constglobal.go +++ b/converters/python/constglobal.go @@ -3,7 +3,7 @@ package py_converter import ( "strings" - ir "godzilla/pkg/ir/v1" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // Module-level string constants are INLINED at their use sites (see diff --git a/converters/python/constglobal_test.go b/converters/python/constglobal_test.go index b33cec47..04c4e686 100644 --- a/converters/python/constglobal_test.go +++ b/converters/python/constglobal_test.go @@ -5,7 +5,7 @@ import ( "path/filepath" "testing" - ir "godzilla/pkg/ir/v1" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // usesBase is appended to every case so the module actually READS BASE; without diff --git a/converters/python/converter.go b/converters/python/converter.go index 3446fe9b..e51faa3c 100644 --- a/converters/python/converter.go +++ b/converters/python/converter.go @@ -34,11 +34,11 @@ import ( "os/exec" "strings" - "godzilla/converters/frontend" - "godzilla/internal/irwalk" - "godzilla/internal/proc" - "godzilla/internal/walkignore" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/converters/frontend" + "github.com/bytevet/godzilla/internal/irwalk" + "github.com/bytevet/godzilla/internal/proc" + "github.com/bytevet/godzilla/internal/walkignore" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) //go:embed pyast.py diff --git a/converters/python/converter_test.go b/converters/python/converter_test.go index 4875ddab..875606cd 100644 --- a/converters/python/converter_test.go +++ b/converters/python/converter_test.go @@ -6,11 +6,11 @@ import ( "strings" "testing" - "godzilla/converters/ssabuild" - "godzilla/internal/analysis" - "godzilla/internal/rules" - "godzilla/internal/testsupport" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/converters/ssabuild" + "github.com/bytevet/godzilla/internal/analysis" + "github.com/bytevet/godzilla/internal/rules" + "github.com/bytevet/godzilla/internal/testsupport" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // requirePython3 skips the test if python3 is not on PATH, since ConvertFile diff --git a/converters/python/lower.go b/converters/python/lower.go index 9a21c4c8..bbbce0e4 100644 --- a/converters/python/lower.go +++ b/converters/python/lower.go @@ -6,8 +6,8 @@ import ( "maps" "strings" - "godzilla/converters/ssabuild" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/converters/ssabuild" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // modCtx bundles the file-scoped facts every lowered function in a module needs: diff --git a/converters/python/timeout_test.go b/converters/python/timeout_test.go index 3bae3b69..52d437d1 100644 --- a/converters/python/timeout_test.go +++ b/converters/python/timeout_test.go @@ -6,8 +6,8 @@ import ( "testing" "time" - "godzilla/internal/proc" - "godzilla/internal/testsupport" + "github.com/bytevet/godzilla/internal/proc" + "github.com/bytevet/godzilla/internal/testsupport" ) // TestParseTimeoutKillsSubprocess is the PERF-4 guard: with a 1ms parse timeout, diff --git a/converters/ruby/converter.go b/converters/ruby/converter.go index 9118ae06..65c746d8 100644 --- a/converters/ruby/converter.go +++ b/converters/ruby/converter.go @@ -28,10 +28,10 @@ import ( "slices" "strings" - "godzilla/converters/frontend" - "godzilla/internal/proc" - "godzilla/internal/walkignore" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/converters/frontend" + "github.com/bytevet/godzilla/internal/proc" + "github.com/bytevet/godzilla/internal/walkignore" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) //go:embed rbdump.rb diff --git a/converters/ruby/converter_test.go b/converters/ruby/converter_test.go index 6fc3282b..50eae07a 100644 --- a/converters/ruby/converter_test.go +++ b/converters/ruby/converter_test.go @@ -4,9 +4,9 @@ import ( "strings" "testing" - "godzilla/internal/analysis" - "godzilla/internal/rules" - "godzilla/internal/testsupport" + "github.com/bytevet/godzilla/internal/analysis" + "github.com/bytevet/godzilla/internal/rules" + "github.com/bytevet/godzilla/internal/testsupport" ) // requireRuby skips when no ruby is on PATH (the frontend shells out to it for diff --git a/converters/ruby/lower.go b/converters/ruby/lower.go index 950d0c94..89a88ff2 100644 --- a/converters/ruby/lower.go +++ b/converters/ruby/lower.go @@ -4,8 +4,8 @@ import ( "encoding/json" "fmt" - "godzilla/converters/ssabuild" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/converters/ssabuild" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // A Ripper sexp node is a JSON value: a list (`[]interface{}` whose head is a diff --git a/converters/rust/converter.go b/converters/rust/converter.go index 83788e89..200af710 100644 --- a/converters/rust/converter.go +++ b/converters/rust/converter.go @@ -29,11 +29,11 @@ import ( "path/filepath" "strings" - "godzilla/converters/frontend" - "godzilla/internal/buildpolicy" - "godzilla/internal/proc" - "godzilla/internal/walkignore" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/converters/frontend" + "github.com/bytevet/godzilla/internal/buildpolicy" + "github.com/bytevet/godzilla/internal/proc" + "github.com/bytevet/godzilla/internal/walkignore" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // Converter lowers Rust source files/directories into gIR: the shared diff --git a/converters/rust/converter_test.go b/converters/rust/converter_test.go index b3643a7f..8767d26e 100644 --- a/converters/rust/converter_test.go +++ b/converters/rust/converter_test.go @@ -4,11 +4,11 @@ import ( "strings" "testing" - "godzilla/internal/analysis" - "godzilla/internal/irwalk" - "godzilla/internal/rules/loader" - "godzilla/internal/testsupport" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/internal/analysis" + "github.com/bytevet/godzilla/internal/irwalk" + "github.com/bytevet/godzilla/internal/rules/loader" + "github.com/bytevet/godzilla/internal/testsupport" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // requireRustc skips when no rustc is on PATH (the frontend shells out to it to diff --git a/converters/rust/format_marker_test.go b/converters/rust/format_marker_test.go index 8708ce90..057793ff 100644 --- a/converters/rust/format_marker_test.go +++ b/converters/rust/format_marker_test.go @@ -5,7 +5,7 @@ import ( "path/filepath" "testing" - ir "godzilla/pkg/ir/v1" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // calleeMarks walks every CALL in a module and returns callee -> the set of diff --git a/converters/rust/mir.go b/converters/rust/mir.go index 6eaa579a..5a1aa501 100644 --- a/converters/rust/mir.go +++ b/converters/rust/mir.go @@ -8,8 +8,8 @@ import ( "strings" "unicode/utf8" - "godzilla/converters/ssabuild" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/converters/ssabuild" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // This file lowers rustc's textual MIR (Mid-level IR) to gIR. MIR is the right diff --git a/converters/rust/smoke.go b/converters/rust/smoke.go index 4fb3baf3..3f2894c6 100644 --- a/converters/rust/smoke.go +++ b/converters/rust/smoke.go @@ -5,8 +5,8 @@ import ( "os" "sync" - "godzilla/internal/irwalk" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/internal/irwalk" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // FE-10: rustc's textual MIR is an explicitly unstable format that this frontend diff --git a/converters/ssabuild/scaffold.go b/converters/ssabuild/scaffold.go index 599f22f7..4261bc8f 100644 --- a/converters/ssabuild/scaffold.go +++ b/converters/ssabuild/scaffold.go @@ -1,7 +1,7 @@ package ssabuild import ( - ir "godzilla/pkg/ir/v1" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // This file holds the CFG scaffolds shared by the AST-walking frontends diff --git a/converters/ssabuild/scaffold_test.go b/converters/ssabuild/scaffold_test.go index b249213c..75bb8ef0 100644 --- a/converters/ssabuild/scaffold_test.go +++ b/converters/ssabuild/scaffold_test.go @@ -3,7 +3,7 @@ package ssabuild import ( "testing" - ir "godzilla/pkg/ir/v1" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // sameCFG asserts two materialized CFGs are structurally identical: block diff --git a/converters/ssabuild/ssabuild.go b/converters/ssabuild/ssabuild.go index ca17ca06..9a03bff7 100644 --- a/converters/ssabuild/ssabuild.go +++ b/converters/ssabuild/ssabuild.go @@ -59,7 +59,7 @@ import ( "sort" "strconv" - ir "godzilla/pkg/ir/v1" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // BlockID identifies a basic block within one Builder. Ids are sequential ints diff --git a/converters/ssabuild/ssabuild_test.go b/converters/ssabuild/ssabuild_test.go index 078aa936..417f55bc 100644 --- a/converters/ssabuild/ssabuild_test.go +++ b/converters/ssabuild/ssabuild_test.go @@ -3,7 +3,7 @@ package ssabuild import ( "testing" - ir "godzilla/pkg/ir/v1" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) func constInt(n int64) *ir.Value { diff --git a/converters/ssabuild/values.go b/converters/ssabuild/values.go index 2bf7d718..3d829c12 100644 --- a/converters/ssabuild/values.go +++ b/converters/ssabuild/values.go @@ -1,6 +1,6 @@ package ssabuild -import ir "godzilla/pkg/ir/v1" +import ir "github.com/bytevet/godzilla/pkg/ir/v1" // gIR value constructors shared by every frontend. Each is a one-liner, but // before living here the same one-liners were re-declared privately in six diff --git a/go.mod b/go.mod index 21e0b96d..dcbc7d1e 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module godzilla +module github.com/bytevet/godzilla go 1.26.5 diff --git a/internal/analysis/bench_test.go b/internal/analysis/bench_test.go index 7adbfec0..6a245a26 100644 --- a/internal/analysis/bench_test.go +++ b/internal/analysis/bench_test.go @@ -4,8 +4,8 @@ import ( "fmt" "testing" - "godzilla/internal/rules" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/internal/rules" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // buildScaleProgram builds a synthetic program of nFunc functions, each a diff --git a/internal/analysis/callgraph.go b/internal/analysis/callgraph.go index e5216ed5..5b729773 100644 --- a/internal/analysis/callgraph.go +++ b/internal/analysis/callgraph.go @@ -1,12 +1,12 @@ package analysis import ( - "godzilla/internal/irwalk" + "github.com/bytevet/godzilla/internal/irwalk" "maps" "slices" "strings" - ir "godzilla/pkg/ir/v1" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // CallGraph is a whole-program call graph over gIR functions. The diff --git a/internal/analysis/callgraph_test.go b/internal/analysis/callgraph_test.go index d5e98fbf..c7e652e1 100644 --- a/internal/analysis/callgraph_test.go +++ b/internal/analysis/callgraph_test.go @@ -4,8 +4,8 @@ import ( "strings" "testing" - go_converter "godzilla/converters/go" - ir "godzilla/pkg/ir/v1" + go_converter "github.com/bytevet/godzilla/converters/go" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // convertSQLInjectionSampleForCallGraph loads and converts the sql_injection diff --git a/internal/analysis/dangerous.go b/internal/analysis/dangerous.go index 8ed69739..617960ab 100644 --- a/internal/analysis/dangerous.go +++ b/internal/analysis/dangerous.go @@ -1,11 +1,11 @@ package analysis import ( - "godzilla/internal/irwalk" + "github.com/bytevet/godzilla/internal/irwalk" "regexp" - "godzilla/internal/rules" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/internal/rules" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // ScanDangerousCalls evaluates every `kind: dangerous-call` rule (COV-4) diff --git a/internal/analysis/dangerous_test.go b/internal/analysis/dangerous_test.go index 76c12b3e..2aadcebd 100644 --- a/internal/analysis/dangerous_test.go +++ b/internal/analysis/dangerous_test.go @@ -3,8 +3,8 @@ package analysis import ( "testing" - "godzilla/internal/rules" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/internal/rules" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // callInstAt builds a CALL instruction to callee with the given constant-string diff --git a/internal/analysis/dynamicsink_test.go b/internal/analysis/dynamicsink_test.go index 8f8d2e90..80f98739 100644 --- a/internal/analysis/dynamicsink_test.go +++ b/internal/analysis/dynamicsink_test.go @@ -4,8 +4,8 @@ import ( "strings" "testing" - "godzilla/internal/rules" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/internal/rules" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // TestArgVals checks the IR->Arg skeleton bridge a dynamic guard evaluates over: diff --git a/internal/analysis/edgecases_test.go b/internal/analysis/edgecases_test.go index 60ac4fdc..c2d238eb 100644 --- a/internal/analysis/edgecases_test.go +++ b/internal/analysis/edgecases_test.go @@ -3,8 +3,8 @@ package analysis import ( "testing" - go_converter "godzilla/converters/go" - "godzilla/internal/rules" + go_converter "github.com/bytevet/godzilla/converters/go" + "github.com/bytevet/godzilla/internal/rules" ) // TestAnalyze_DeferAndMapFlows is a regression test for two taint blind spots diff --git a/internal/analysis/fieldsense_test.go b/internal/analysis/fieldsense_test.go index c7233a2e..9c2bb6ed 100644 --- a/internal/analysis/fieldsense_test.go +++ b/internal/analysis/fieldsense_test.go @@ -4,9 +4,9 @@ import ( "strings" "testing" - go_converter "godzilla/converters/go" - "godzilla/internal/rules" - "godzilla/internal/testsupport" + go_converter "github.com/bytevet/godzilla/converters/go" + "github.com/bytevet/godzilla/internal/rules" + "github.com/bytevet/godzilla/internal/testsupport" ) func cmdiRuleSet(t testing.TB, id string) *rules.RuleSet { diff --git a/internal/analysis/finding.go b/internal/analysis/finding.go index 8540199a..6c7ca01f 100644 --- a/internal/analysis/finding.go +++ b/internal/analysis/finding.go @@ -5,8 +5,8 @@ import ( "fmt" "strings" - "godzilla/internal/rules" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/internal/rules" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // Confidence expresses how certain the engine is that a finding is a true diff --git a/internal/analysis/finding_compare_test.go b/internal/analysis/finding_compare_test.go index 5c83b875..72197da8 100644 --- a/internal/analysis/finding_compare_test.go +++ b/internal/analysis/finding_compare_test.go @@ -4,8 +4,8 @@ import ( "slices" "testing" - "godzilla/internal/rules" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/internal/rules" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // TestCompareFindings pins the pipeline-wide display order the CLI and all diff --git a/internal/analysis/fingerprint.go b/internal/analysis/fingerprint.go index f3f07631..02c78a45 100644 --- a/internal/analysis/fingerprint.go +++ b/internal/analysis/fingerprint.go @@ -9,7 +9,7 @@ import ( "strings" "sync" - ir "godzilla/pkg/ir/v1" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // fingerprintCwd memoizes os.Getwd for fingerprinting: the working directory diff --git a/internal/analysis/flow.go b/internal/analysis/flow.go index b780a0d3..5a0bf479 100644 --- a/internal/analysis/flow.go +++ b/internal/analysis/flow.go @@ -4,7 +4,7 @@ import ( "maps" "slices" - ir "godzilla/pkg/ir/v1" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // taintState maps a tainted register (or access-path key) to the source origin diff --git a/internal/analysis/flow_test.go b/internal/analysis/flow_test.go index 13b9416f..43c9ff71 100644 --- a/internal/analysis/flow_test.go +++ b/internal/analysis/flow_test.go @@ -3,8 +3,8 @@ package analysis import ( "testing" - "godzilla/internal/rules" - "godzilla/internal/testsupport" + "github.com/bytevet/godzilla/internal/rules" + "github.com/bytevet/godzilla/internal/testsupport" ) // cmdiRule is a minimal command-injection rule for the flow-sensitivity tests. diff --git a/internal/analysis/global_taint_test.go b/internal/analysis/global_taint_test.go index 33d764a0..3db7fcba 100644 --- a/internal/analysis/global_taint_test.go +++ b/internal/analysis/global_taint_test.go @@ -3,8 +3,8 @@ package analysis import ( "testing" - go_converter "godzilla/converters/go" - "godzilla/internal/rules" + go_converter "github.com/bytevet/godzilla/converters/go" + "github.com/bytevet/godzilla/internal/rules" ) // TestAnalyze_GlobalTaintFlow is the ENG-6(a) regression guard: taint stored diff --git a/internal/analysis/guards.go b/internal/analysis/guards.go index b563a95e..6551a7f1 100644 --- a/internal/analysis/guards.go +++ b/internal/analysis/guards.go @@ -3,8 +3,8 @@ package analysis import ( "maps" - "godzilla/internal/rules" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/internal/rules" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // guardIndex answers, for a rule that declares validators, whether a sink is diff --git a/internal/analysis/guards_test.go b/internal/analysis/guards_test.go index e9631d04..4290d377 100644 --- a/internal/analysis/guards_test.go +++ b/internal/analysis/guards_test.go @@ -5,9 +5,9 @@ import ( "path/filepath" "testing" - go_converter "godzilla/converters/go" - "godzilla/internal/rules" - "godzilla/internal/testsupport" + go_converter "github.com/bytevet/godzilla/converters/go" + "github.com/bytevet/godzilla/internal/rules" + "github.com/bytevet/godzilla/internal/testsupport" ) // pathRule is a path-traversal rule with a filepath.IsLocal validator, matching diff --git a/internal/analysis/interproc.go b/internal/analysis/interproc.go index 1a56ad89..fbd0b8a0 100644 --- a/internal/analysis/interproc.go +++ b/internal/analysis/interproc.go @@ -2,7 +2,7 @@ package analysis import ( "fmt" - "godzilla/internal/irwalk" + "github.com/bytevet/godzilla/internal/irwalk" "maps" "runtime" "slices" @@ -11,8 +11,8 @@ import ( "sync" "sync/atomic" - "godzilla/internal/rules" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/internal/rules" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // Analyze runs inter-procedural taint analysis over prog for every rule in the diff --git a/internal/analysis/interproc_test.go b/internal/analysis/interproc_test.go index dfd95ecc..2a496ddf 100644 --- a/internal/analysis/interproc_test.go +++ b/internal/analysis/interproc_test.go @@ -3,8 +3,8 @@ package analysis import ( "testing" - go_converter "godzilla/converters/go" - "godzilla/internal/rules" + go_converter "github.com/bytevet/godzilla/converters/go" + "github.com/bytevet/godzilla/internal/rules" ) // TestAnalyze_Interprocedural validates that taint is tracked across a function diff --git a/internal/analysis/return_flow_test.go b/internal/analysis/return_flow_test.go index b11b9d46..5d8ccc5b 100644 --- a/internal/analysis/return_flow_test.go +++ b/internal/analysis/return_flow_test.go @@ -3,9 +3,9 @@ package analysis import ( "testing" - go_converter "godzilla/converters/go" - "godzilla/internal/rules" - "godzilla/internal/rules/loader" + go_converter "github.com/bytevet/godzilla/converters/go" + "github.com/bytevet/godzilla/internal/rules" + "github.com/bytevet/godzilla/internal/rules/loader" ) // TestAnalyze_ReturnFlowIsMedium is the ENG-7 regression guard. In diff --git a/internal/analysis/sanitizer_test.go b/internal/analysis/sanitizer_test.go index 30193cfd..d10b7ea9 100644 --- a/internal/analysis/sanitizer_test.go +++ b/internal/analysis/sanitizer_test.go @@ -3,8 +3,8 @@ package analysis import ( "testing" - go_converter "godzilla/converters/go" - "godzilla/internal/rules" + go_converter "github.com/bytevet/godzilla/converters/go" + "github.com/bytevet/godzilla/internal/rules" ) // TestAnalyze_SanitizerSuppressesReturnFlow is the ENG-1 regression guard. In diff --git a/internal/analysis/secrets.go b/internal/analysis/secrets.go index e5a07faf..f8566738 100644 --- a/internal/analysis/secrets.go +++ b/internal/analysis/secrets.go @@ -8,10 +8,10 @@ import ( "strconv" "strings" - "godzilla/internal/irwalk" - "godzilla/internal/rules" - "godzilla/internal/walkignore" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/internal/irwalk" + "github.com/bytevet/godzilla/internal/rules" + "github.com/bytevet/godzilla/internal/walkignore" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // secretDetector is one compiled `kind: secret` rule. Collected once per scan so diff --git a/internal/analysis/secrets_test.go b/internal/analysis/secrets_test.go index 918cad02..87d82976 100644 --- a/internal/analysis/secrets_test.go +++ b/internal/analysis/secrets_test.go @@ -3,7 +3,7 @@ package analysis import ( "testing" - ir "godzilla/pkg/ir/v1" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // progWithConstant builds a minimal gIR program with a single call instruction diff --git a/internal/analysis/sinkargs_test.go b/internal/analysis/sinkargs_test.go index b3f0c95c..7b7a6c5c 100644 --- a/internal/analysis/sinkargs_test.go +++ b/internal/analysis/sinkargs_test.go @@ -4,8 +4,8 @@ import ( "strings" "testing" - go_converter "godzilla/converters/go" - "godzilla/internal/rules/loader" + go_converter "github.com/bytevet/godzilla/converters/go" + "github.com/bytevet/godzilla/internal/rules/loader" ) // TestAnalyze_ParameterizedQueryNoFalsePositive is a regression test for the diff --git a/internal/analysis/ssrf.go b/internal/analysis/ssrf.go index 6ddb0f65..6737ae13 100644 --- a/internal/analysis/ssrf.go +++ b/internal/analysis/ssrf.go @@ -3,8 +3,8 @@ package analysis import ( "strings" - "godzilla/internal/rules" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/internal/rules" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // SSRF (CWE-918) false-positive reduction. diff --git a/internal/analysis/ssrf_report_test.go b/internal/analysis/ssrf_report_test.go index e5151b66..e4929ab3 100644 --- a/internal/analysis/ssrf_report_test.go +++ b/internal/analysis/ssrf_report_test.go @@ -3,8 +3,8 @@ package analysis import ( "testing" - "godzilla/internal/rules" - "godzilla/internal/testsupport" + "github.com/bytevet/godzilla/internal/rules" + "github.com/bytevet/godzilla/internal/testsupport" ) // ssrfRule is a minimal CWE-918 rule over net/http.Get for the ENG-8 tests. diff --git a/internal/analysis/ssrf_test.go b/internal/analysis/ssrf_test.go index 693384da..87f9da6b 100644 --- a/internal/analysis/ssrf_test.go +++ b/internal/analysis/ssrf_test.go @@ -3,7 +3,7 @@ package analysis import ( "testing" - ir "godzilla/pkg/ir/v1" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // --- constructors ------------------------------------------------------------ diff --git a/internal/analysis/taint.go b/internal/analysis/taint.go index 381b9aeb..48341bf5 100644 --- a/internal/analysis/taint.go +++ b/internal/analysis/taint.go @@ -4,8 +4,8 @@ import ( "strconv" "strings" - "godzilla/internal/rules" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/internal/rules" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // Engine runs taint analysis over a gIR program for a fixed set of rules. diff --git a/internal/analysis/taint_test.go b/internal/analysis/taint_test.go index 4a6fda6a..77b63b53 100644 --- a/internal/analysis/taint_test.go +++ b/internal/analysis/taint_test.go @@ -4,10 +4,10 @@ import ( "sort" "testing" - go_converter "godzilla/converters/go" - "godzilla/internal/rules" - "godzilla/internal/testsupport" - ir "godzilla/pkg/ir/v1" + go_converter "github.com/bytevet/godzilla/converters/go" + "github.com/bytevet/godzilla/internal/rules" + "github.com/bytevet/godzilla/internal/testsupport" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // convertSQLInjectionSample loads and converts the sql_injection sample used diff --git a/internal/analysis/testrules_test.go b/internal/analysis/testrules_test.go index 78120e72..ebbb2a20 100644 --- a/internal/analysis/testrules_test.go +++ b/internal/analysis/testrules_test.go @@ -3,8 +3,8 @@ package analysis import ( "testing" - "godzilla/internal/rules" - "godzilla/internal/rules/loader" + "github.com/bytevet/godzilla/internal/rules" + "github.com/bytevet/godzilla/internal/rules/loader" ) // builtinRuleSet returns the shipped rule set, compiled. Tests that need what diff --git a/internal/config/config.go b/internal/config/config.go index dfba6612..da64a405 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -12,8 +12,8 @@ import ( "regexp" "strings" - "godzilla/internal/analysis" - "godzilla/internal/rules" + "github.com/bytevet/godzilla/internal/analysis" + "github.com/bytevet/godzilla/internal/rules" "gopkg.in/yaml.v3" ) diff --git a/internal/config/config_test.go b/internal/config/config_test.go index c026521b..4ece69a0 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -5,9 +5,9 @@ import ( "path/filepath" "testing" - "godzilla/internal/analysis" - "godzilla/internal/rules" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/internal/analysis" + "github.com/bytevet/godzilla/internal/rules" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) func TestPathMatches(t *testing.T) { diff --git a/internal/irwalk/irwalk.go b/internal/irwalk/irwalk.go index 416e03e3..ab338608 100644 --- a/internal/irwalk/irwalk.go +++ b/internal/irwalk/irwalk.go @@ -12,7 +12,7 @@ package irwalk import ( "iter" - ir "godzilla/pkg/ir/v1" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // Funcs yields every non-nil function in prog with its owning module. diff --git a/internal/llm/anthropic.go b/internal/llm/anthropic.go index d94f11eb..fc288d66 100644 --- a/internal/llm/anthropic.go +++ b/internal/llm/anthropic.go @@ -7,7 +7,7 @@ import ( "github.com/anthropics/anthropic-sdk-go" - "godzilla/internal/analysis" + "github.com/bytevet/godzilla/internal/analysis" ) // AnthropicReviewer is a Reviewer backed by the Anthropic Messages API. It is diff --git a/internal/llm/anthropic_loop_test.go b/internal/llm/anthropic_loop_test.go index b2e9da70..65fff005 100644 --- a/internal/llm/anthropic_loop_test.go +++ b/internal/llm/anthropic_loop_test.go @@ -13,8 +13,8 @@ import ( "github.com/anthropics/anthropic-sdk-go" "github.com/anthropics/anthropic-sdk-go/option" - "godzilla/internal/analysis" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/internal/analysis" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // TestAgenticLoop_ToolThenVerdict drives the full agentic reviewer against a diff --git a/internal/llm/config_test.go b/internal/llm/config_test.go index 4884668b..3b454290 100644 --- a/internal/llm/config_test.go +++ b/internal/llm/config_test.go @@ -6,7 +6,7 @@ import ( "testing" "time" - "godzilla/internal/analysis" + "github.com/bytevet/godzilla/internal/analysis" ) // concurrencyProbe records the maximum number of concurrent Review calls, to diff --git a/internal/llm/openai.go b/internal/llm/openai.go index 0bd80ae4..3e73eda8 100644 --- a/internal/llm/openai.go +++ b/internal/llm/openai.go @@ -12,7 +12,7 @@ import ( "strings" "time" - "godzilla/internal/analysis" + "github.com/bytevet/godzilla/internal/analysis" ) // OpenAIReviewer is a Reviewer backed by any OpenAI-compatible /chat/completions diff --git a/internal/llm/openai_test.go b/internal/llm/openai_test.go index 8ad24996..8d0ef19e 100644 --- a/internal/llm/openai_test.go +++ b/internal/llm/openai_test.go @@ -9,8 +9,8 @@ import ( "strings" "testing" - "godzilla/internal/analysis" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/internal/analysis" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // TestOpenAIReviewer_ParsesVerdict drives the OpenAI-compatible reviewer against diff --git a/internal/llm/review.go b/internal/llm/review.go index 71ee22f9..6075c72d 100644 --- a/internal/llm/review.go +++ b/internal/llm/review.go @@ -18,9 +18,9 @@ import ( "sync" "time" - "godzilla/internal/analysis" - "godzilla/internal/srclines" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/internal/analysis" + "github.com/bytevet/godzilla/internal/srclines" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // Verdict is a reviewer's judgment about a single finding. Beyond the binary diff --git a/internal/llm/review_test.go b/internal/llm/review_test.go index f240b6c2..b2b73d7b 100644 --- a/internal/llm/review_test.go +++ b/internal/llm/review_test.go @@ -9,9 +9,9 @@ import ( "sync" "testing" - "godzilla/internal/analysis" - "godzilla/internal/srclines" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/internal/analysis" + "github.com/bytevet/godzilla/internal/srclines" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // mockReviewer marks findings whose RuleID is in fp as false positives, and diff --git a/internal/llm/tools.go b/internal/llm/tools.go index fee2ecaf..a3ff1d50 100644 --- a/internal/llm/tools.go +++ b/internal/llm/tools.go @@ -9,9 +9,9 @@ import ( "regexp" "strings" - "godzilla/internal/irwalk" - "godzilla/internal/walkignore" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/internal/irwalk" + "github.com/bytevet/godzilla/internal/walkignore" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // ToolBox is the read-only capability set the agentic reviewer (LLM-4) can call diff --git a/internal/llm/tools_test.go b/internal/llm/tools_test.go index 2e35bb9c..35144b67 100644 --- a/internal/llm/tools_test.go +++ b/internal/llm/tools_test.go @@ -7,7 +7,7 @@ import ( "strings" "testing" - ir "godzilla/pkg/ir/v1" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // writeTree lays out files under a temp dir and returns the root. diff --git a/internal/report/html.go b/internal/report/html.go index 447b2e51..7a85f9b6 100644 --- a/internal/report/html.go +++ b/internal/report/html.go @@ -19,10 +19,10 @@ import ( "time" "unicode/utf8" - "godzilla/internal/analysis" - "godzilla/internal/rules" - "godzilla/internal/srclines" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/internal/analysis" + "github.com/bytevet/godzilla/internal/rules" + "github.com/bytevet/godzilla/internal/srclines" + ir "github.com/bytevet/godzilla/pkg/ir/v1" "html/template" ) diff --git a/internal/report/html_test.go b/internal/report/html_test.go index f0e15e34..56f31921 100644 --- a/internal/report/html_test.go +++ b/internal/report/html_test.go @@ -5,9 +5,9 @@ import ( "strings" "testing" - "godzilla/internal/analysis" - "godzilla/internal/rules" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/internal/analysis" + "github.com/bytevet/godzilla/internal/rules" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) func TestWriteHTML(t *testing.T) { diff --git a/internal/report/json.go b/internal/report/json.go index 9d828258..31cb7516 100644 --- a/internal/report/json.go +++ b/internal/report/json.go @@ -4,8 +4,8 @@ import ( "encoding/json" "io" - "godzilla/internal/analysis" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/internal/analysis" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // Version is the tool version stamped into machine-readable reports (SARIF and diff --git a/internal/report/json_test.go b/internal/report/json_test.go index 69ac934f..13e0b5f2 100644 --- a/internal/report/json_test.go +++ b/internal/report/json_test.go @@ -5,9 +5,9 @@ import ( "encoding/json" "testing" - "godzilla/internal/analysis" - "godzilla/internal/rules" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/internal/analysis" + "github.com/bytevet/godzilla/internal/rules" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) func sampleFindings() []analysis.Finding { diff --git a/internal/report/sarif.go b/internal/report/sarif.go index de5d18ee..61711074 100644 --- a/internal/report/sarif.go +++ b/internal/report/sarif.go @@ -7,9 +7,9 @@ import ( "path/filepath" "strings" - "godzilla/internal/analysis" - "godzilla/internal/rules" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/internal/analysis" + "github.com/bytevet/godzilla/internal/rules" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // SARIF 2.1.0 document structs. Only the fields Godzilla populates are diff --git a/internal/report/sarif_test.go b/internal/report/sarif_test.go index 475ef0cd..5969a9dc 100644 --- a/internal/report/sarif_test.go +++ b/internal/report/sarif_test.go @@ -8,9 +8,9 @@ import ( "strings" "testing" - "godzilla/internal/analysis" - "godzilla/internal/rules" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/internal/analysis" + "github.com/bytevet/godzilla/internal/rules" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) func TestWriteSARIF(t *testing.T) { diff --git a/internal/report/suppression_test.go b/internal/report/suppression_test.go index aaf4b9ee..48d8c9e5 100644 --- a/internal/report/suppression_test.go +++ b/internal/report/suppression_test.go @@ -6,9 +6,9 @@ import ( "strings" "testing" - "godzilla/internal/analysis" - "godzilla/internal/rules" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/internal/analysis" + "github.com/bytevet/godzilla/internal/rules" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // suppressedFinding is a finding the LLM reviewer judged a false positive: it is diff --git a/internal/report/version_test.go b/internal/report/version_test.go index 9b407b13..a640aae2 100644 --- a/internal/report/version_test.go +++ b/internal/report/version_test.go @@ -5,8 +5,8 @@ import ( "strings" "testing" - "godzilla/internal/analysis" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/internal/analysis" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // TestReportsStampVersion verifies the tool version and schema version reach both diff --git a/internal/rules/loader/loader.go b/internal/rules/loader/loader.go index 3886cdf0..04ddc85a 100644 --- a/internal/rules/loader/loader.go +++ b/internal/rules/loader/loader.go @@ -26,8 +26,8 @@ import ( "gopkg.in/yaml.v3" - "godzilla/internal/rules" - "godzilla/rulepacks" + "github.com/bytevet/godzilla/internal/rules" + "github.com/bytevet/godzilla/rulepacks" ) // LoadFile reads a single YAML rule file and unmarshals it into a RuleSet, diff --git a/internal/rules/loader/loader_test.go b/internal/rules/loader/loader_test.go index 48a1bdb8..c950ea04 100644 --- a/internal/rules/loader/loader_test.go +++ b/internal/rules/loader/loader_test.go @@ -6,7 +6,7 @@ import ( "slices" "testing" - "godzilla/internal/rules" + "github.com/bytevet/godzilla/internal/rules" ) func TestBuiltin(t *testing.T) { diff --git a/internal/ruletest/ruletest.go b/internal/ruletest/ruletest.go index a889b1cc..d52514af 100644 --- a/internal/ruletest/ruletest.go +++ b/internal/ruletest/ruletest.go @@ -14,9 +14,9 @@ import ( "slices" "strings" - "godzilla/internal/analysis" - "godzilla/internal/rules" - "godzilla/internal/scan" + "github.com/bytevet/godzilla/internal/analysis" + "github.com/bytevet/godzilla/internal/rules" + "github.com/bytevet/godzilla/internal/scan" "gopkg.in/yaml.v3" ) diff --git a/internal/ruletest/ruletest_test.go b/internal/ruletest/ruletest_test.go index 0f5e0b1b..6fc9adcd 100644 --- a/internal/ruletest/ruletest_test.go +++ b/internal/ruletest/ruletest_test.go @@ -5,7 +5,7 @@ import ( "path/filepath" "testing" - "godzilla/internal/rules/loader" + "github.com/bytevet/godzilla/internal/rules/loader" ) // writeSample lays out a Go sample project (go.mod + main.go + expected.yaml). diff --git a/internal/scan/bench_test.go b/internal/scan/bench_test.go index d7c4690c..6f7c4a68 100644 --- a/internal/scan/bench_test.go +++ b/internal/scan/bench_test.go @@ -4,8 +4,8 @@ import ( "strings" "testing" - "godzilla/internal/rules/loader" - "godzilla/internal/testsupport" + "github.com/bytevet/godzilla/internal/rules/loader" + "github.com/bytevet/godzilla/internal/testsupport" ) // benchScanLang benchmarks a full-pipeline scan of one language's sample so diff --git a/internal/scan/scan.go b/internal/scan/scan.go index f015860d..40056e98 100644 --- a/internal/scan/scan.go +++ b/internal/scan/scan.go @@ -11,17 +11,17 @@ import ( "slices" "sync" - cpp_converter "godzilla/converters/cpp" - go_converter "godzilla/converters/go" - java_converter "godzilla/converters/java" - js_converter "godzilla/converters/javascript" - py_converter "godzilla/converters/python" - ruby_converter "godzilla/converters/ruby" - rust_converter "godzilla/converters/rust" - "godzilla/internal/analysis" - "godzilla/internal/rules" - "godzilla/internal/walkignore" - ir "godzilla/pkg/ir/v1" + cpp_converter "github.com/bytevet/godzilla/converters/cpp" + go_converter "github.com/bytevet/godzilla/converters/go" + java_converter "github.com/bytevet/godzilla/converters/java" + js_converter "github.com/bytevet/godzilla/converters/javascript" + py_converter "github.com/bytevet/godzilla/converters/python" + ruby_converter "github.com/bytevet/godzilla/converters/ruby" + rust_converter "github.com/bytevet/godzilla/converters/rust" + "github.com/bytevet/godzilla/internal/analysis" + "github.com/bytevet/godzilla/internal/rules" + "github.com/bytevet/godzilla/internal/walkignore" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // LangCoverage records what happened to one language frontend during a scan: diff --git a/internal/scan/scan_test.go b/internal/scan/scan_test.go index 1b273144..ba0d5c88 100644 --- a/internal/scan/scan_test.go +++ b/internal/scan/scan_test.go @@ -6,11 +6,11 @@ import ( "slices" "testing" - "godzilla/internal/analysis" - "godzilla/internal/rules" - "godzilla/internal/rules/loader" - "godzilla/internal/testsupport" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/internal/analysis" + "github.com/bytevet/godzilla/internal/rules" + "github.com/bytevet/godzilla/internal/rules/loader" + "github.com/bytevet/godzilla/internal/testsupport" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) // TestResultFailed checks the coverage predicate that drives the strict gate: diff --git a/internal/testsupport/testsupport.go b/internal/testsupport/testsupport.go index 36a8b7b0..38ade18d 100644 --- a/internal/testsupport/testsupport.go +++ b/internal/testsupport/testsupport.go @@ -12,8 +12,8 @@ import ( "os/exec" "testing" - "godzilla/internal/rules" - "godzilla/internal/rules/loader" + "github.com/bytevet/godzilla/internal/rules" + "github.com/bytevet/godzilla/internal/rules/loader" ) // RequireTool skips the test when the named executable (python3, ruby, java, diff --git a/internal/triage/triage.go b/internal/triage/triage.go index aa4a396d..f023b8ab 100644 --- a/internal/triage/triage.go +++ b/internal/triage/triage.go @@ -16,8 +16,8 @@ import ( "slices" "strings" - "godzilla/internal/analysis" - "godzilla/internal/srclines" + "github.com/bytevet/godzilla/internal/analysis" + "github.com/bytevet/godzilla/internal/srclines" ) // ignoreToken is the directive that suppresses a finding when it appears in a diff --git a/internal/triage/triage_test.go b/internal/triage/triage_test.go index 6eb0bef4..749e939e 100644 --- a/internal/triage/triage_test.go +++ b/internal/triage/triage_test.go @@ -6,8 +6,8 @@ import ( "path/filepath" "testing" - "godzilla/internal/analysis" - ir "godzilla/pkg/ir/v1" + "github.com/bytevet/godzilla/internal/analysis" + ir "github.com/bytevet/godzilla/pkg/ir/v1" ) func findingAt(rule, file string, line int32) analysis.Finding { diff --git a/pkg/ir/v1/common.pb.go b/pkg/ir/v1/common.pb.go index 112afcf0..94eb34ee 100644 --- a/pkg/ir/v1/common.pb.go +++ b/pkg/ir/v1/common.pb.go @@ -903,7 +903,7 @@ const file_proto_common_proto_rawDesc = "" + "\x1dBASIC_TYPE_KIND_UNTYPED_FLOAT\x10\x16\x12#\n" + "\x1fBASIC_TYPE_KIND_UNTYPED_COMPLEX\x10\x17\x12\"\n" + "\x1eBASIC_TYPE_KIND_UNTYPED_STRING\x10\x18\x12\x1f\n" + - "\x1bBASIC_TYPE_KIND_UNTYPED_NIL\x10\x19B\x17Z\x15godzilla/pkg/ir/v1;irb\x06proto3" + "\x1bBASIC_TYPE_KIND_UNTYPED_NIL\x10\x19B*Z(github.com/bytevet/godzilla/pkg/ir/v1;irb\x06proto3" var ( file_proto_common_proto_rawDescOnce sync.Once diff --git a/pkg/ir/v1/function.pb.go b/pkg/ir/v1/function.pb.go index dfbac046..77e3de9e 100644 --- a/pkg/ir/v1/function.pb.go +++ b/pkg/ir/v1/function.pb.go @@ -271,7 +271,7 @@ const file_proto_function_proto_rawDesc = "" + " \x03(\v2\x15.godzilla.ir.v1.ValueR\x06locals\x12,\n" + "\x06parent\x18\v \x01(\v2\x14.godzilla.ir.v1.TypeR\x06parent\x12\x1c\n" + "\tsynthetic\x18\f \x01(\bR\tsynthetic\x12%\n" + - "\x0ecanonical_name\x18\r \x01(\tR\rcanonicalNameB\x17Z\x15godzilla/pkg/ir/v1;irb\x06proto3" + "\x0ecanonical_name\x18\r \x01(\tR\rcanonicalNameB*Z(github.com/bytevet/godzilla/pkg/ir/v1;irb\x06proto3" var ( file_proto_function_proto_rawDescOnce sync.Once diff --git a/pkg/ir/v1/generate.go b/pkg/ir/v1/generate.go index 0b2893d0..8762b9fe 100644 --- a/pkg/ir/v1/generate.go +++ b/pkg/ir/v1/generate.go @@ -1,3 +1,3 @@ package ir -//go:generate protoc -I=../../.. --go_out=../../.. --go_opt=module=godzilla proto/common.proto proto/instruction.proto proto/function.proto proto/module.proto +//go:generate protoc -I=../../.. --go_out=../../.. --go_opt=module=github.com/bytevet/godzilla proto/common.proto proto/instruction.proto proto/function.proto proto/module.proto diff --git a/pkg/ir/v1/instruction.pb.go b/pkg/ir/v1/instruction.pb.go index 7c45e9a6..b7cbe5ea 100644 --- a/pkg/ir/v1/instruction.pb.go +++ b/pkg/ir/v1/instruction.pb.go @@ -864,7 +864,7 @@ const file_proto_instruction_proto_rawDesc = "" + "\n" + "UN_OP_ADDR\x10\x05\x12\x0f\n" + "\vUN_OP_DEREF\x10\x06\x12\x0f\n" + - "\vUN_OP_ARROW\x10\aB\x17Z\x15godzilla/pkg/ir/v1;irb\x06proto3" + "\vUN_OP_ARROW\x10\aB*Z(github.com/bytevet/godzilla/pkg/ir/v1;irb\x06proto3" var ( file_proto_instruction_proto_rawDescOnce sync.Once diff --git a/pkg/ir/v1/module.pb.go b/pkg/ir/v1/module.pb.go index 593a41c7..6a61d561 100644 --- a/pkg/ir/v1/module.pb.go +++ b/pkg/ir/v1/module.pb.go @@ -184,7 +184,7 @@ const file_proto_module_proto_rawDesc = "" + "\aProgram\x120\n" + "\amodules\x18\x01 \x03(\v2\x16.godzilla.ir.v1.ModuleR\amodules\x123\n" + "\bmain_pkg\x18\x02 \x01(\v2\x18.godzilla.ir.v1.FunctionR\amainPkg\x12\x12\n" + - "\x04mode\x18\x03 \x01(\tR\x04modeB\x17Z\x15godzilla/pkg/ir/v1;irb\x06proto3" + "\x04mode\x18\x03 \x01(\tR\x04modeB*Z(github.com/bytevet/godzilla/pkg/ir/v1;irb\x06proto3" var ( file_proto_module_proto_rawDescOnce sync.Once diff --git a/proto/common.proto b/proto/common.proto index b044f31b..9ab40c30 100644 --- a/proto/common.proto +++ b/proto/common.proto @@ -2,7 +2,7 @@ syntax = "proto3"; package godzilla.ir.v1; -option go_package = "godzilla/pkg/ir/v1;ir"; +option go_package = "github.com/bytevet/godzilla/pkg/ir/v1;ir"; // Position represents a source code location. message Position { diff --git a/proto/function.proto b/proto/function.proto index 9db34069..bb8c5413 100644 --- a/proto/function.proto +++ b/proto/function.proto @@ -2,7 +2,7 @@ syntax = "proto3"; package godzilla.ir.v1; -option go_package = "godzilla/pkg/ir/v1;ir"; +option go_package = "github.com/bytevet/godzilla/pkg/ir/v1;ir"; import "proto/common.proto"; import "proto/instruction.proto"; diff --git a/proto/instruction.proto b/proto/instruction.proto index 6c0b7d43..5bd7de41 100644 --- a/proto/instruction.proto +++ b/proto/instruction.proto @@ -2,7 +2,7 @@ syntax = "proto3"; package godzilla.ir.v1; -option go_package = "godzilla/pkg/ir/v1;ir"; +option go_package = "github.com/bytevet/godzilla/pkg/ir/v1;ir"; import "proto/common.proto"; diff --git a/proto/module.proto b/proto/module.proto index 077f91cd..b325958f 100644 --- a/proto/module.proto +++ b/proto/module.proto @@ -2,7 +2,7 @@ syntax = "proto3"; package godzilla.ir.v1; -option go_package = "godzilla/pkg/ir/v1;ir"; +option go_package = "github.com/bytevet/godzilla/pkg/ir/v1;ir"; import "proto/common.proto"; import "proto/function.proto"; diff --git a/test/corpus/corpus_test.go b/test/corpus/corpus_test.go index e45c023f..55a26f51 100644 --- a/test/corpus/corpus_test.go +++ b/test/corpus/corpus_test.go @@ -7,8 +7,8 @@ import ( "strings" "testing" - "godzilla/internal/rules/loader" - "godzilla/internal/scan" + "github.com/bytevet/godzilla/internal/rules/loader" + "github.com/bytevet/godzilla/internal/scan" ) // TestCorpus runs the real scan pipeline over every sample under diff --git a/test/corpus/differential_test.go b/test/corpus/differential_test.go index d69404c7..823ccb06 100644 --- a/test/corpus/differential_test.go +++ b/test/corpus/differential_test.go @@ -6,8 +6,8 @@ import ( "path/filepath" "testing" - "godzilla/internal/rules/loader" - "godzilla/internal/scan" + "github.com/bytevet/godzilla/internal/rules/loader" + "github.com/bytevet/godzilla/internal/scan" ) // TestDifferential_CommandInjection is a cross-language differential test for a diff --git a/test/corpus/manifest.go b/test/corpus/manifest.go index 36b71c25..a44f94bc 100644 --- a/test/corpus/manifest.go +++ b/test/corpus/manifest.go @@ -12,7 +12,7 @@ import ( "sort" "strings" - "godzilla/internal/analysis" + "github.com/bytevet/godzilla/internal/analysis" "gopkg.in/yaml.v3" ) diff --git a/test/corpus/metrics_test.go b/test/corpus/metrics_test.go index 00ca71e9..4dd7d785 100644 --- a/test/corpus/metrics_test.go +++ b/test/corpus/metrics_test.go @@ -7,9 +7,9 @@ import ( "strings" "testing" - "godzilla/internal/buildpolicy" - "godzilla/internal/rules/loader" - "godzilla/internal/scan" + "github.com/bytevet/godzilla/internal/buildpolicy" + "github.com/bytevet/godzilla/internal/rules/loader" + "github.com/bytevet/godzilla/internal/scan" ) // sampleEligible reports whether a sample can run in this environment, mirroring diff --git a/test/corpus/multilang_test.go b/test/corpus/multilang_test.go index 5d6caca2..da0205d7 100644 --- a/test/corpus/multilang_test.go +++ b/test/corpus/multilang_test.go @@ -6,8 +6,8 @@ import ( "path/filepath" "testing" - "godzilla/internal/rules/loader" - "godzilla/internal/scan" + "github.com/bytevet/godzilla/internal/rules/loader" + "github.com/bytevet/godzilla/internal/scan" ) // TestMultiLanguageScan exercises Godzilla's headline promise — one scan of a diff --git a/test/corpus/regen_test.go b/test/corpus/regen_test.go index 54bb797c..5f357c9b 100644 --- a/test/corpus/regen_test.go +++ b/test/corpus/regen_test.go @@ -5,8 +5,8 @@ import ( "path/filepath" "testing" - "godzilla/internal/rules/loader" - "godzilla/internal/scan" + "github.com/bytevet/godzilla/internal/rules/loader" + "github.com/bytevet/godzilla/internal/scan" "gopkg.in/yaml.v3" ) From 692ba9a903550ee2a8dfb10682119829caf9b2ac Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 13 Aug 2026 18:09:31 +0000 Subject: [PATCH 2/9] js: parse esbuild's AST directly, removing goja The frontend parsed twice: esbuild's api.Transform normalised TS/JSX/ESM to text, goja reparsed that text, and a sourcemap carried positions back. esbuild had already built an AST and discarded it -- its parser is unreachable under internal/, so github.com/bytevet/esbuild-jsast re-exports it and the lowering now consumes it directly. goja, evanw/esbuild and go-sourcemap all leave go.mod. The round trip cost precision, not just time. Printing was ~79% of the transform, and goja's ragged grammar forced downlevels that rewrote object spread into a helper taint did not survive. Top-level await could not work at all: it is expressible only in ESM output, which a CommonJS-consuming lowering cannot read. It now parses, and its known-gap fixture moves into dialects/. Positions are correct by construction rather than reconstructed. A node's Loc is a byte offset into the buffer as written, so remapPositions and the sourcemap dependency are gone; lineIndex is the one place an offset becomes a position, using ECMAScript's line terminators (LF, lone CR, CRLF as one, U+2028/9) and 1-based byte columns -- goja's exact convention, so nothing moves. Offset 0 is a VALID position, so "no node" is decided by a nil Data, never by a zero offset. The two-axis ladder collapses to one. Loader selection remains driven by parse failure rather than prediction, since one extension covers four dialects, and flowstrip stays its last rung. ESM is now native: import clauses feed the same alias table require() does, so a module-anchored sink rule matches an imported binding. The comma-callee case survives retargeted -- our own pipeline no longer emits `(0, mod.fn)(x)`, but every bundler does. Verified against a position oracle captured from the pre-change build: all 58 test/js findings, byte-identical source and sink line/column. The one delta is esm_module's enclosing function, $anon1 -> $anon0, because esbuild's injected __export helper arrow no longer consumes index 0 -- the new name is the correct one. That oracle is now a permanent gate (TestJSFindingPositions): expected.yaml asserts counts and only nine JS samples assert a line, so a systematic column shift previously passed the corpus in silence. Also pinned: parser options cannot request a transform (Options is two booleans), dead branches and consts survive parsing, lineIndex handles CRLF and U+2028/9, and Skipped() over test/js stays exactly 1. gojacaps_test.go is deleted -- it asserted a goja/esbuild disagreement that no longer exists -- with every construct it covered moved into testdata/dialects/, where TestDialectsAllConvert makes the stronger claim. js.unsupported across test/js and testdata/dialects is zero. 90s of fuzzing, 373k execs, no panic. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01Rao1GBomZ53fL2ydytD96r --- ARCHITECTURE.md | 20 +- BACKLOG.md | 1 + CLAUDE.md | 15 +- README.md | 2 +- converters/javascript/aliases.go | 285 +++-- converters/javascript/collect.go | 400 +++--- converters/javascript/converter.go | 97 +- converters/javascript/converter_test.go | 61 +- converters/javascript/dialect.go | 174 +++ converters/javascript/dialects_test.go | 49 +- converters/javascript/flowstrip.go | 33 +- converters/javascript/fuzz_test.go | 8 +- converters/javascript/gojacaps_test.go | 125 -- converters/javascript/lower.go | 1102 +++++++++-------- converters/javascript/parseopts_test.go | 170 +++ converters/javascript/sfc.go | 78 +- .../testdata/dialects/annotated_commonjs.js | 6 +- .../testdata/dialects/class_esnext.js | 14 + .../testdata/dialects/decorators.ts | 3 + .../javascript/testdata/dialects/esnext.js | 26 + .../testdata/dialects/top_level_await.js | 4 + .../dialects_known_gaps/top_level_await.js | 5 - converters/javascript/transform.go | 237 ---- converters/javascript/typescript_test.go | 37 +- go.mod | 7 +- go.sum | 15 +- test/corpus/positions_test.go | 125 ++ test/corpus/testdata/js_positions.golden | 58 + test/js/decorators_for_await/expected.yaml | 9 + .../service.js | 8 +- test/js/esm_module/app.js | 6 +- test/js/goja_gaps/expected.yaml | 11 - 32 files changed, 1757 insertions(+), 1434 deletions(-) create mode 100644 converters/javascript/dialect.go delete mode 100644 converters/javascript/gojacaps_test.go create mode 100644 converters/javascript/parseopts_test.go create mode 100644 converters/javascript/testdata/dialects/class_esnext.js create mode 100644 converters/javascript/testdata/dialects/esnext.js create mode 100644 converters/javascript/testdata/dialects/top_level_await.js delete mode 100644 converters/javascript/testdata/dialects_known_gaps/top_level_await.js delete mode 100644 converters/javascript/transform.go create mode 100644 test/corpus/positions_test.go create mode 100644 test/corpus/testdata/js_positions.golden create mode 100644 test/js/decorators_for_await/expected.yaml rename test/js/{goja_gaps => decorators_for_await}/service.js (51%) delete mode 100644 test/js/goja_gaps/expected.yaml diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 74bd071a..378902ed 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -43,7 +43,7 @@ all of them. ┌───────── Frontends (in-process Go, one binary) ─────────┐ Go ────► x/tools SSA ───┐ Python ──► python3 ast ──┤ - JS ────► goja AST ──┤ + JS ────► esbuild AST ──┤ Java ────► JVM bytecode ──┤─► lower ─► gIR (core + intrinsics, canonical FQNs) Rust ────► rustc MIR ──┤ │ Ruby ────► ruby Ripper ──┤ │ @@ -177,14 +177,16 @@ Python/Java/Rust/Ruby shelling out to a toolchain on `PATH`. lives in `http.HandleFunc` closures. Emits `go:` names. - **Python** (`converters/python/`) — shells out to `python3` for an `ast` JSON dump, then lowers it to a real CFG (`ssabuild`). Emits `py:` names; requires `python3`. -- **JavaScript** (`converters/javascript/`) — pure-Go parse via **goja**, then - lowers. TS/JSX/ESM are stripped/lowered in-process by esbuild (no Node), with source - maps remapping positions back; a plain `.js` is handed to goja first and only falls - back to esbuild when the parse fails, since one extension covers four dialects. - Flow, which esbuild cannot load at all, is blanked in place beforehand - (`flowstrip.go`) so byte offsets — and therefore positions — are preserved. `.vue`/`.svelte` SFCs are also - handled (`sfc.go`): the ` + + diff --git a/test/js/crossfile_sfc_import/app.js b/test/js/crossfile_sfc_import/app.js new file mode 100644 index 00000000..a94df12d --- /dev/null +++ b/test/js/crossfile_sfc_import/app.js @@ -0,0 +1,16 @@ +// A relative import of a .vue component. The specifier keeps its extension while +// the walk names the module without one, so the two only meet if the resolver +// strips exactly the extensions IsJSFamily recognizes — SFCs included. Get that +// wrong and the cross-module edge silently disappears: no error, no skipped +// file, just a finding that stops being reported. +import express from "express"; +import render from "./Renderer.vue"; + +const app = express(); + +app.get("/r", function (req, res) { + const id = req.query.id; // source + res.send(render("SELECT * FROM users WHERE id = " + id)); // cross-file call into Renderer.vue +}); + +export default app; diff --git a/test/js/crossfile_sfc_import/expected.yaml b/test/js/crossfile_sfc_import/expected.yaml new file mode 100644 index 00000000..6d163609 --- /dev/null +++ b/test/js/crossfile_sfc_import/expected.yaml @@ -0,0 +1,11 @@ +# Expected findings for this sample (see test/README.md). +# The sink is in Renderer.vue but the source is in app.js, so this only fires if +# `./Renderer.vue` resolves to the module the walk named `Renderer`. When it does +# not, both files still convert and coverage still reads ok — the finding just +# vanishes. That is why the assertion is pinned to the file and line. +findings: + - rule: js-sqli + min: 1 + max: 1 + line: 6 + sink: "js:some-db.query" diff --git a/test/js/esmodule/app.mjs b/test/js/esmodule/app.mjs index ab9136bd..cecec0e1 100644 --- a/test/js/esmodule/app.mjs +++ b/test/js/esmodule/app.mjs @@ -1,7 +1,7 @@ -// ES module (import/export) command injection: goja cannot parse top-level -// import, so esbuild lowers it to CommonJS first. The named-import call -// execSync(cmd) becomes an interop call (0, import_child_process.execSync)(cmd); -// the sink must still be recognized. +// ES module (import/export) command injection. A named import binds its sink +// through the import-alias table (aliases.go), not through a require, so the +// call must still canonicalize to js:child_process.execSync -- that table is the +// only thing standing between an ESM project and no module-anchored sinks at all. import { execSync } from "child_process"; export function run(req) { diff --git a/test/js/loop_header_callback/app.js b/test/js/loop_header_callback/app.js new file mode 100644 index 00000000..0b22e454 --- /dev/null +++ b/test/js/loop_header_callback/app.js @@ -0,0 +1,17 @@ +// A function literal in a loop HEADER, not its body. The lowering visits the +// header, so the collector must too: an uncollected literal there is unnamed, +// resolves to nothing, and its body goes unanalyzed while the file still reports +// as converted. Both sinks below live inside such a literal. +const { exec } = require("child_process"); + +function handleBatch(req, res) { + for (const row of req.query.rows.filter((v) => v.ok)) { + exec(row.cmd); + } + for (let i = 0, run = (c) => exec(c); i < 1; i++) { + run(req.query.cmd); + } + res.send("ok"); +} + +module.exports = handleBatch; diff --git a/test/js/loop_header_callback/expected.yaml b/test/js/loop_header_callback/expected.yaml new file mode 100644 index 00000000..afebc920 --- /dev/null +++ b/test/js/loop_header_callback/expected.yaml @@ -0,0 +1,12 @@ +# Expected findings for this sample (see test/README.md). +# The flow itself is ordinary; what this sample guards is that the loop HEADERS +# above it are collected. If they are not, the header literals go unnamed and the +# lowering emits js.unsupported — caught by TestNoUnsupportedInstructions, which +# walks this whole tree — while this finding still fires, so a count alone would +# not notice. +findings: + - rule: js-command-injection + min: 1 + max: 1 + line: 9 + sink: "js:child_process.exec" diff --git a/test/js/typescript/app.ts b/test/js/typescript/app.ts index 86b8fa5e..932a8fa7 100644 --- a/test/js/typescript/app.ts +++ b/test/js/typescript/app.ts @@ -1,6 +1,6 @@ // TypeScript command injection: type annotations (: string, : void, the Request -// interface) must be stripped by esbuild so goja can parse it, and the finding -// must point at THIS .ts file at the correct line. +// interface) are erased by the ladder's TS rung, and the finding must still point +// at THIS .ts file at the correct line -- an erased annotation shifts no offset. const cp = require("child_process"); interface Req { From ec94c1f4f17660f538fb0425ab40a127c2d8905e Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 14 Aug 2026 02:25:54 +0000 Subject: [PATCH 5/9] js: cut duplicated rationale, and pin the half nothing was pinning Comment bloat, not code bloat: the previous commit added 69 comment lines to 19 code lines. This removes 27 comment lines from Go and 9 more from fixtures. "The collector must walk what the lowering lowers" was written in six places. It now has one home in converter.go's package doc; funcRefValue and the loop arms point at it. The addFunction comment stays because it carries a DIFFERENT fact -- nothing lowers a parameter default -- and the fixture headers hand their rationale to expected.yaml, where someone deleting a sample looks. That duplication had already started to disagree with itself. The package doc claimed TestNoUnsupportedInstructions was the alarm for an uncollected literal, which is false for a parameter default: nothing lowers one, so no intrinsic is emitted and the test sees nothing. Half the previous commit's fix was therefore shipped untested. TestCollectsParamDefaultLiteral now covers it, and was verified to fail with the collector loop removed while TestNoUnsupportedInstructions stayed green -- which is the blind spot, demonstrated. Also: - collectStmts(stmtList(x)) is collectStmt(x): collectStmt already flattens SBlock and no-ops on a nil Data. Twelve call sites, one wrapper gone. stmtList stays for lower.go, which genuinely wants a slice. - TestNoUnsupportedInstructions uses irwalk instead of hand-rolling a four-deep Modules/Functions/Blocks/Instrs nest, in a file that already imports it. Net Go LoC is +8, not negative: the new test costs ~25 lines and the trimming saved ~17. Coverage was the right trade, but it is a trade, not a win. SForIn/SForOf stay duplicated -- Go cannot bind a typed value across a multi-type case, and a helper costs more lines than it saves; the file already spells SWhile/SDoWhile the same way. Positions: three findings shift, in exactly the three fixtures whose headers shrank, by exactly the lines removed. Nothing else moved. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01Rao1GBomZ53fL2ydytD96r --- converters/javascript/collect.go | 35 ++++++++---------- converters/javascript/converter.go | 15 ++++---- converters/javascript/converter_test.go | 42 +++++++++++++++------- converters/javascript/lower.go | 12 +++---- test/corpus/testdata/js_positions.golden | 6 ++-- test/js/crossfile_sfc_import/app.js | 7 ++-- test/js/crossfile_sfc_import/expected.yaml | 7 ++-- test/js/esmodule/app.mjs | 7 ++-- test/js/loop_header_callback/app.js | 6 ++-- test/js/loop_header_callback/expected.yaml | 10 +++--- 10 files changed, 73 insertions(+), 74 deletions(-) diff --git a/converters/javascript/collect.go b/converters/javascript/collect.go index e3efc5c7..22f98f0b 100644 --- a/converters/javascript/collect.go +++ b/converters/javascript/collect.go @@ -94,10 +94,8 @@ func (c *collector) addFunction(node fnID, loc jsast.Loc, qualname string, args if _, seen := c.nameOf[node]; seen { return } - // A parameter default is an expression like any other and can hold a function - // literal (`function f(cb = () => {...})`). Nothing lowers it, so an - // uncollected literal there is not merely unnamed -- its body is never - // analyzed, silently. + // Nothing LOWERS a default, so an uncollected literal here emits no + // js.unsupported to notice -- it is simply never analyzed. for _, a := range args { c.collectExpr(a.DefaultOrNil, qualname+".", "") } @@ -173,31 +171,28 @@ func (c *collector) collectStmt(s jsast.Stmt, qualPrefix string) { c.collectExpr(v.Value, qualPrefix, "") case *jsast.SIf: c.collectExpr(v.Test, qualPrefix, "") - c.collectStmts(stmtList(v.Yes), qualPrefix) - c.collectStmts(stmtList(v.NoOrNil), qualPrefix) - // A loop HEADER is lowered like any other expression (lowerFor, lowerForRange), - // so it must be collected like one. Walking only the body leaves a literal in - // the header unnamed, and the lowering then has nothing to resolve: it emits - // js.unsupported and the literal's body is never analyzed at all. + c.collectStmt(v.Yes, qualPrefix) + c.collectStmt(v.NoOrNil, qualPrefix) + // Headers are lowered too (lowerFor/lowerForRange), so they are collected too. case *jsast.SFor: - c.collectStmts(stmtList(v.InitOrNil), qualPrefix) + c.collectStmt(v.InitOrNil, qualPrefix) c.collectExpr(v.TestOrNil, qualPrefix, "") c.collectExpr(v.UpdateOrNil, qualPrefix, "") - c.collectStmts(stmtList(v.Body), qualPrefix) + c.collectStmt(v.Body, qualPrefix) case *jsast.SForIn: - c.collectStmts(stmtList(v.Init), qualPrefix) + c.collectStmt(v.Init, qualPrefix) c.collectExpr(v.Value, qualPrefix, "") - c.collectStmts(stmtList(v.Body), qualPrefix) + c.collectStmt(v.Body, qualPrefix) case *jsast.SForOf: - c.collectStmts(stmtList(v.Init), qualPrefix) + c.collectStmt(v.Init, qualPrefix) c.collectExpr(v.Value, qualPrefix, "") - c.collectStmts(stmtList(v.Body), qualPrefix) + c.collectStmt(v.Body, qualPrefix) case *jsast.SWhile: c.collectExpr(v.Test, qualPrefix, "") - c.collectStmts(stmtList(v.Body), qualPrefix) + c.collectStmt(v.Body, qualPrefix) case *jsast.SDoWhile: c.collectExpr(v.Test, qualPrefix, "") - c.collectStmts(stmtList(v.Body), qualPrefix) + c.collectStmt(v.Body, qualPrefix) case *jsast.SBlock: c.collectStmts(v.Stmts, qualPrefix) case *jsast.STry: @@ -215,10 +210,10 @@ func (c *collector) collectStmt(s jsast.Stmt, qualPrefix string) { c.collectStmts(cs.Body, qualPrefix) } case *jsast.SLabel: - c.collectStmts(stmtList(v.Stmt), qualPrefix) + c.collectStmt(v.Stmt, qualPrefix) case *jsast.SWith: c.collectExpr(v.Value, qualPrefix, "") - c.collectStmts(stmtList(v.Body), qualPrefix) + c.collectStmt(v.Body, qualPrefix) case *jsast.SClass: c.collectClass(v.Class, qualPrefix, "") case *jsast.SExportDefault: diff --git a/converters/javascript/converter.go b/converters/javascript/converter.go index 0d37e775..7a6600be 100644 --- a/converters/javascript/converter.go +++ b/converters/javascript/converter.go @@ -72,13 +72,14 @@ // // # Collector coverage // -// The collector (collect.go) must walk every expression the lowering lowers, -// including loop headers and parameter defaults. A function literal it misses is -// not merely unnamed: the lowering has nothing to resolve, emits js.unsupported, -// and the literal's body goes unanalyzed while the file still reports as -// converted. TestNoUnsupportedInstructions is the alarm, and it walks whole trees -// rather than a named list, because the shapes that go unmodelled are the ones -// nobody thought to name. +// The collector (collect.go) must walk every expression the lowering lowers. A +// literal it misses is not just unnamed -- the lowering resolves nothing, emits +// js.unsupported, and its body goes unanalyzed while the file still reports as +// converted. TestNoUnsupportedInstructions walks whole trees to catch that. +// +// A parameter default is the blind spot: nothing lowers one, so a missed literal +// there emits no intrinsic at all and only TestCollectsParamDefaultLiteral sees +// it. package js_converter import ( diff --git a/converters/javascript/converter_test.go b/converters/javascript/converter_test.go index 789a3dee..f16713ae 100644 --- a/converters/javascript/converter_test.go +++ b/converters/javascript/converter_test.go @@ -295,29 +295,45 @@ func functionNamesForModules(prog *ir.Program) []string { // every instruction in the converted samples must have a real OpCode, never the // generic "js.unsupported" intrinsic. func TestNoUnsupportedInstructions(t *testing.T) { - // Whole trees, not a hand-picked list: a fallback intrinsic marks a construct - // the lowering does not model, and the constructs most likely to produce one - // are the ones nobody thought to name. A hand-maintained list only ever covers - // yesterday's shapes -- a literal in a loop header went unmodelled under one. + // Whole trees, not a hand-picked list: the constructs that trip the fallback + // are the ones nobody thought to name. for _, path := range []string{ "../../test/js", filepath.Join("testdata", "dialects"), } { - prog := mustConvert(t, path) - for _, mod := range prog.Modules { - for _, fn := range mod.Functions { - for _, blk := range fn.Blocks { - for _, inst := range blk.Instrs { - if inst.Op == ir.OpCode_OP_CODE_INTRINSIC && inst.Intrinsic == "js.unsupported" { - t.Errorf("%s: unsupported instruction in %s: %s", path, fn.CanonicalName, inst.Comment) - } - } + for _, fn := range irwalk.Funcs(mustConvert(t, path)) { + for inst := range irwalk.Instrs(fn) { + if inst.Op == ir.OpCode_OP_CODE_INTRINSIC && inst.Intrinsic == "js.unsupported" { + t.Errorf("%s: unsupported instruction in %s: %s", path, fn.CanonicalName, inst.Comment) } } } } } +// TestCollectsParamDefaultLiteral pins the half of collector coverage no +// intrinsic reports: nothing lowers a parameter default, so a literal the +// collector misses there is silently absent rather than flagged. +func TestCollectsParamDefaultLiteral(t *testing.T) { + dir := t.TempDir() + path := filepath.Join(dir, "pdef.js") + if err := os.WriteFile(path, []byte("function f(cb = (c) => eval(c)) { cb(1); }\n"), 0o644); err != nil { + t.Fatal(err) + } + mod, _, err := NewConverter().convertJSFile(path, "pdef") + if err != nil { + t.Fatal(err) + } + for _, fn := range mod.Functions { + for inst := range irwalk.Instrs(fn) { + if inst.GetCall().GetCallee() == "js:eval" { + return + } + } + } + t.Error("no js:eval call lowered — the default's literal was never collected") +} + // TestLogXSSSampleInstructions is a diagnostic test: it converts the XSS // sample and logs every instruction in the handleName function, so the // lowering shape (registers, opcodes, callees, positions) is visible in test diff --git a/converters/javascript/lower.go b/converters/javascript/lower.go index ca5b7cb6..2334c513 100644 --- a/converters/javascript/lower.go +++ b/converters/javascript/lower.go @@ -770,9 +770,8 @@ func (fs *funcState) lowerStmt(s jsast.Stmt) { fs.lowerExpr(v.Value) default: // SClass, SEmpty, SBreak, SContinue, SDebugger, SComment, SDirective, - // SImport and the remaining export forms: dropped. SClass is a no-op HERE - // because collectClass already queued each method as its own function; the - // rest carry no dataflow. + // SImport and the remaining export forms: dropped. collectClass already + // queued each SClass method; the rest carry no dataflow. } } @@ -1058,9 +1057,7 @@ func (fs *funcState) funcRefValue(e jsast.Expr) *ir.Value { if canonical, ok := fs.nameOf[fnID(e.Data)]; ok { return &ir.Value{Kind: &ir.Value_FuncName{FuncName: canonical}} } - // Unreachable: the collector walks every expression tree the lowering lowers, - // loop headers and parameter defaults included. Reaching this means the two - // have drifted apart -- see the Collector coverage note in converter.go. + // Unreachable: see "Collector coverage" in converter.go. return fs.emitUnsupported(e.Loc, "unresolved inline function literal") } @@ -1360,8 +1357,7 @@ const identityIntrinsic = "builtin.identity" // lowerNestedCallees walks a call/new expression's callee along the same // Dot/Index "Target" chain syntacticCallee walks and lowers any call it finds — // e.g. the `require('./x')` inside `new (require('./x').Client)()` — inside-out -// via the ordinary lowerCall path. `new` is the case that needs it: a plain -// method call lowers its receiver through lowerExpr, which already covers this. +// via the ordinary lowerCall path. // // Without it the inner call is never visited at all: syntactic name building is // a pure string walk with no side effects, so the inner call's instruction (and diff --git a/test/corpus/testdata/js_positions.golden b/test/corpus/testdata/js_positions.golden index 105d693d..ba624790 100644 --- a/test/corpus/testdata/js_positions.golden +++ b/test/corpus/testdata/js_positions.golden @@ -7,7 +7,7 @@ js-command-injection|js:command_injection_require/app.$anon0|js:child_pr js-command-injection|js:command_injection_require/app.$anon1|js:child_process.exec|src=test/js/command_injection_require/app.js:11:42|sink=test/js/command_injection_require/app.js:11:37 js-command-injection|js:command_injection_require/app.$anon2|js:child_process.execSync|src=test/js/command_injection_require/app.js:12:40|sink=test/js/command_injection_require/app.js:12:37 js-command-injection|js:esm_module/app.$anon0|js:child_process.exec|src=test/js/esm_module/app.js:11:16|sink=test/js/esm_module/app.js:12:3 -js-command-injection|js:esmodule/app.run|js:child_process.execSync|src=test/js/esmodule/app.mjs:8:17|sink=test/js/esmodule/app.mjs:9:5 +js-command-injection|js:esmodule/app.run|js:child_process.execSync|src=test/js/esmodule/app.mjs:7:17|sink=test/js/esmodule/app.mjs:8:5 js-command-injection|js:fastify/app.$anon1|js:child_process.exec|src=test/js/fastify/app.js:17:16|sink=test/js/fastify/app.js:18:3 js-command-injection|js:handler_destructure/app.$anon0|js:child_process.exec|src=test/js/handler_destructure/app.js:9:18|sink=test/js/handler_destructure/app.js:10:3 js-command-injection|js:handler_destructure/app.$anon1|js:child_process.exec|src=test/js/handler_destructure/app.js:15:20|sink=test/js/handler_destructure/app.js:16:3 @@ -15,7 +15,7 @@ js-command-injection|js:handler_param/app.$anon0|js:child_process.exec|s js-command-injection|js:header_source/app.$anon0|js:child_process.execSync|src=test/js/header_source/app.js:5:17|sink=test/js/header_source/app.js:6:5 js-command-injection|js:koa/app.$anon1|js:child_process.exec|src=test/js/koa/app.js:22:16|sink=test/js/koa/app.js:23:3 js-command-injection|js:loop_carried_command_injection/app.handleRun|js:child_process.exec|src=test/js/loop_carried_command_injection/app.js:21:11|sink=test/js/loop_carried_command_injection/app.js:20:5 -js-command-injection|js:loop_header_callback/app.handleBatch|js:child_process.exec|src=test/js/loop_header_callback/app.js:8:21|sink=test/js/loop_header_callback/app.js:9:5 +js-command-injection|js:loop_header_callback/app.handleBatch|js:child_process.exec|src=test/js/loop_header_callback/app.js:6:21|sink=test/js/loop_header_callback/app.js:7:5 js-command-injection|js:propagator_default/app.$anon0|js:child_process.execSync|src=test/js/propagator_default/app.js:7:17|sink=test/js/propagator_default/app.js:8:5 js-command-injection|js:try_catch_command_injection/app.handleLookup|js:child_process.exec|src=test/js/try_catch_command_injection/app.js:16:12|sink=test/js/try_catch_command_injection/app.js:19:5 js-command-injection|js:typescript/app.$anon0|js:child_process.execSync|src=test/js/typescript/app.ts:11:25|sink=test/js/typescript/app.ts:12:5 @@ -30,7 +30,7 @@ js-path-traversal|js:path_traversal_join/app.handleDownload|js:fs.readFile|src=t js-path-traversal|js:path_traversal_requrl_memfs/app.serve|js:context.outputFileSystem.createReadStream|src=test/js/path_traversal_requrl_memfs/app.js:14:18|sink=test/js/path_traversal_requrl_memfs/app.js:20:5 js-path-traversal|js:path_traversal_requrl_memfs/app.serve|js:context.outputFileSystem.statSync|src=test/js/path_traversal_requrl_memfs/app.js:14:18|sink=test/js/path_traversal_requrl_memfs/app.js:18:15 js-path-traversal|js:wdm_getfilename/getFilenameFromUrl.getFilenameFromUrl|js:outputFileSystem.statSync|src=test/js/wdm_getfilename/middleware.js:14:40|sink=test/js/wdm_getfilename/getFilenameFromUrl.js:21:10 -js-sqli|js:crossfile_sfc_import/Renderer.render|js:some-db.query|src=test/js/crossfile_sfc_import/app.js:12:14|sink=test/js/crossfile_sfc_import/Renderer.vue:6:10 +js-sqli|js:crossfile_sfc_import/Renderer.render|js:some-db.query|src=test/js/crossfile_sfc_import/app.js:9:14|sink=test/js/crossfile_sfc_import/Renderer.vue:6:10 js-sqli|js:fastify/app.$anon0|js:db.query|src=test/js/fastify/app.js:11:14|sink=test/js/fastify/app.js:12:22 js-sqli|js:interproc_local_helper/app.$anon0|js:some-db.query|src=test/js/interproc_local_helper/app.js:17:13|sink=test/js/interproc_local_helper/app.js:19:12 js-sqli|js:koa/app.$anon0|js:db.query|src=test/js/koa/app.js:15:14|sink=test/js/koa/app.js:17:22 diff --git a/test/js/crossfile_sfc_import/app.js b/test/js/crossfile_sfc_import/app.js index a94df12d..da083ae5 100644 --- a/test/js/crossfile_sfc_import/app.js +++ b/test/js/crossfile_sfc_import/app.js @@ -1,8 +1,5 @@ -// A relative import of a .vue component. The specifier keeps its extension while -// the walk names the module without one, so the two only meet if the resolver -// strips exactly the extensions IsJSFamily recognizes — SFCs included. Get that -// wrong and the cross-module edge silently disappears: no error, no skipped -// file, just a finding that stops being reported. +// Cross-file taint into a sink inside a .vue component, imported by a specifier +// that keeps its extension (see expected.yaml). import express from "express"; import render from "./Renderer.vue"; diff --git a/test/js/crossfile_sfc_import/expected.yaml b/test/js/crossfile_sfc_import/expected.yaml index 6d163609..32490b60 100644 --- a/test/js/crossfile_sfc_import/expected.yaml +++ b/test/js/crossfile_sfc_import/expected.yaml @@ -1,8 +1,7 @@ # Expected findings for this sample (see test/README.md). -# The sink is in Renderer.vue but the source is in app.js, so this only fires if -# `./Renderer.vue` resolves to the module the walk named `Renderer`. When it does -# not, both files still convert and coverage still reads ok — the finding just -# vanishes. That is why the assertion is pinned to the file and line. +# Source in app.js, sink in Renderer.vue: fires only if `./Renderer.vue` resolves +# to the module the walk named `Renderer`. When it does not, both files still +# convert and coverage still reads ok, so the file+line pin is the only alarm. findings: - rule: js-sqli min: 1 diff --git a/test/js/esmodule/app.mjs b/test/js/esmodule/app.mjs index cecec0e1..b134051a 100644 --- a/test/js/esmodule/app.mjs +++ b/test/js/esmodule/app.mjs @@ -1,7 +1,6 @@ -// ES module (import/export) command injection. A named import binds its sink -// through the import-alias table (aliases.go), not through a require, so the -// call must still canonicalize to js:child_process.execSync -- that table is the -// only thing standing between an ESM project and no module-anchored sinks at all. +// ES module command injection. A named import binds its sink through the +// import-alias table (aliases.go), not through a require, so the call must still +// canonicalize to js:child_process.execSync. import { execSync } from "child_process"; export function run(req) { diff --git a/test/js/loop_header_callback/app.js b/test/js/loop_header_callback/app.js index 0b22e454..a4e60c29 100644 --- a/test/js/loop_header_callback/app.js +++ b/test/js/loop_header_callback/app.js @@ -1,7 +1,5 @@ -// A function literal in a loop HEADER, not its body. The lowering visits the -// header, so the collector must too: an uncollected literal there is unnamed, -// resolves to nothing, and its body goes unanalyzed while the file still reports -// as converted. Both sinks below live inside such a literal. +// Command injection reached from a function literal in a loop HEADER, not its +// body (see expected.yaml). const { exec } = require("child_process"); function handleBatch(req, res) { diff --git a/test/js/loop_header_callback/expected.yaml b/test/js/loop_header_callback/expected.yaml index afebc920..a2320804 100644 --- a/test/js/loop_header_callback/expected.yaml +++ b/test/js/loop_header_callback/expected.yaml @@ -1,12 +1,10 @@ # Expected findings for this sample (see test/README.md). -# The flow itself is ordinary; what this sample guards is that the loop HEADERS -# above it are collected. If they are not, the header literals go unnamed and the -# lowering emits js.unsupported — caught by TestNoUnsupportedInstructions, which -# walks this whole tree — while this finding still fires, so a count alone would -# not notice. +# The flow is ordinary; what this pins is that the loop HEADERS are collected. If +# they are not, this finding still fires -- the header literals just go unnamed +# and lower to js.unsupported, which only TestNoUnsupportedInstructions sees. findings: - rule: js-command-injection min: 1 max: 1 - line: 9 + line: 7 sink: "js:child_process.exec" From 9a73d5d9266903fe62136f8d5c24000d0c148344 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 14 Aug 2026 05:00:17 +0000 Subject: [PATCH 6/9] Escape the raw U+2060 in the lineIndex test, and lint in `make gate` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CI's Lint & format job has been red since 692ba9a on one staticcheck issue: parseopts_test.go:143: ST1018: string literal contains the Unicode format character U+2060, consider using the '⁠' escape sequence instead The test case is right -- U+2060 (e2 81 a0) shares U+2028's lead byte without being a line break, which is exactly what lineIndex must not confuse -- but writing it as a raw glyph puts an invisible character in the source. It is now the escape. Behaviour is unchanged; the case still asserts {2, 1} at offset 7. A repo-wide scan finds no other category-Cf character in a Go source. The reason it stayed red is the second half of this commit: `make gate` was `fmt vet build test`, so the gate this repo documents could not catch a lint regression, and `go vet` does not include staticcheck. gate now runs lint too. Reproducing CI locally has a sharp edge worth recording in the Makefile: golangci-lint refuses to run at all when built with an older Go than the module targets, and reports it as a config-load error rather than a lint result, so an outdated binary looks like a broken repo. The installed 2.5.0 hit exactly that, and `go install ...@v2.12.2` still does unless GOTOOLCHAIN forces 1.26.5. Verified with CI's own version (2.12.2, built with go1.26.5): 0 issues. The other three CI jobs were already green, including Build & test (Go/Python/JS/Java/Rust) -- so the Java corpus failures seen locally are the JDK 21-vs-24 environment difference and nothing else. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01Rao1GBomZ53fL2ydytD96r --- Makefile | 8 +++++++- converters/javascript/parseopts_test.go | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 46959924..4a07b9e0 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,13 @@ fmt: gofmt -l cmd converters internal test/corpus vet: go vet ./... -gate: fmt vet build test +# CI's blocking check, and a strict superset of `go vet`. golangci-lint refuses to +# run when it was built with an older Go than this module targets, so an outdated +# binary fails closed with a config-load error rather than a clean report: +# GOTOOLCHAIN=go1.26.5 go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.12.2 +lint: + golangci-lint run +gate: fmt vet lint build test # --- with the C/C++/Rust LLVM frontends (cgo + libLLVM) --- build-llvm: diff --git a/converters/javascript/parseopts_test.go b/converters/javascript/parseopts_test.go index e50532d0..6a1924ab 100644 --- a/converters/javascript/parseopts_test.go +++ b/converters/javascript/parseopts_test.go @@ -140,7 +140,7 @@ func TestLineIndexTerminators(t *testing.T) { {"offset zero is line 1 col 1", "function f(){}", 0, [2]int32{1, 1}}, {"column is bytes, not runes", "\"é\";x", 5, [2]int32{1, 6}}, // U+2060 (e2 81 a0) shares U+2028's lead byte but is not a line break. - {"e2 that is not a separator", "\"⁠\";\nx", 7, [2]int32{2, 1}}, + {"e2 that is not a separator", "\"\u2060\";\nx", 7, [2]int32{2, 1}}, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { From 91f502dc7d6978e3ad7ef696eaff990314dd41b3 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 14 Aug 2026 05:05:14 +0000 Subject: [PATCH 7/9] js: stop counting U+2028/U+2029 as reported line breaks lineIndex inherited ECMAScript's line-terminator set from goja, which is right for a GRAMMAR -- U+2028/U+2029 do end a statement -- and wrong for a reported position. Since ES2019 both are legal inside a string literal, and every consumer of the number lineIndex produces splits on "\n": srclines, which feeds the HTML report snippet, the LLM reviewer's context, and godzilla:ignore matching in internal/triage. So one U+2028 in a string shifted every later finding in that file off its own text. Demonstrated before the change: const BANNER = "line-sep:here"; ... exec(req.query.cmd); // \n-split line 4; reported as line 5 The report would render line 5 -- `}` -- as the vulnerable line, the reviewer would adjudicate against `}`, and an ignore directive on the real line would not match. The offsets were never wrong; deriving a line from them was. CRLF still counts once and lone CR still breaks: those agree with a \n split (and with editors), and double-counting CRLF would shift every line of every file written on Windows. That is the case in this function that genuinely earns its keep. No corpus position moves -- no fixture contains either character -- so the position golden is untouched. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01Rao1GBomZ53fL2ydytD96r --- converters/javascript/dialect.go | 18 +++++++++--------- converters/javascript/parseopts_test.go | 11 ++++++----- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/converters/javascript/dialect.go b/converters/javascript/dialect.go index 722c3f98..177baaa6 100644 --- a/converters/javascript/dialect.go +++ b/converters/javascript/dialect.go @@ -111,8 +111,15 @@ func parseError(errs []jsast.Error) error { // the EXACT buffer handed to the parser (flow-stripped or SFC-padded, not the // file on disk), since that is what the offsets index. // -// Line breaks are ECMAScript's four: LF, lone CR, CRLF (ONE break), and U+2028 / -// U+2029. The result is a 1-based line and a 1-based BYTE column. +// A line break is LF, lone CR, or CRLF (ONE break). Result is a 1-based line and +// a 1-based BYTE column. +// +// Deliberately NOT ECMAScript's set: the grammar also ends a line at U+2028 / +// U+2029, but those are legal INSIDE a string literal (ES2019), and every +// consumer of the number this produces -- srclines, which feeds the report +// snippet, the LLM reviewer and godzilla:ignore matching -- splits on "\n". Count +// a separator they do not and a finding after one reports a line whose text is +// some other line, silently. type lineIndex struct { filename string starts []int32 // byte offset of each line's first byte; starts[0] == 0 @@ -129,13 +136,6 @@ func newLineIndex(filename, src string) *lineIndex { if i < len(src) && src[i] == '\n' { i++ } - case 0xe2: // U+2028 / U+2029 are e2 80 a8 / e2 80 a9 - if i+2 < len(src) && src[i+1] == 0x80 && (src[i+2] == 0xa8 || src[i+2] == 0xa9) { - i += 3 - break - } - i++ - continue default: i++ continue diff --git a/converters/javascript/parseopts_test.go b/converters/javascript/parseopts_test.go index 6a1924ab..a502c81e 100644 --- a/converters/javascript/parseopts_test.go +++ b/converters/javascript/parseopts_test.go @@ -135,12 +135,13 @@ func TestLineIndexTerminators(t *testing.T) { {"lf", "a\nbc", 3, [2]int32{2, 2}}, {"crlf counts once", "a\r\nbc", 4, [2]int32{2, 2}}, {"lone cr", "a\rbc", 3, [2]int32{2, 2}}, - {"u2028", "a
bc", 5, [2]int32{2, 2}}, - {"u2029", "a
bc", 5, [2]int32{2, 2}}, {"offset zero is line 1 col 1", "function f(){}", 0, [2]int32{1, 1}}, - {"column is bytes, not runes", "\"é\";x", 5, [2]int32{1, 6}}, - // U+2060 (e2 81 a0) shares U+2028's lead byte but is not a line break. - {"e2 that is not a separator", "\"\u2060\";\nx", 7, [2]int32{2, 1}}, + {"column is bytes, not runes", "\"\u00e9\";x", 5, [2]int32{1, 6}}, + // ECMAScript ends a line at U+2028/U+2029; a REPORTED line does not, because + // srclines and every editor split on "\n". Both are legal inside a string + // literal, so counting them would shift every later finding off its own text. + {"u2028 is not a reported line break", "\"\u2028\";x", 7, [2]int32{1, 8}}, + {"u2029 is not a reported line break", "\"\u2029\";x", 7, [2]int32{1, 8}}, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { From 99737bca8e4b75ea4f74b382669d9dea4ec28bcc Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 14 Aug 2026 05:18:02 +0000 Subject: [PATCH 8/9] js: drop tests whose assertions another test already makes Seven test functions, none of which could fail in a way something else did not already catch. -69 lines in converters/javascript, no coverage lost. TestLogXSSSampleInstructions no assertions at all -- pure t.Logf, so it could never fail TestConvertCommandInjectionSample \ TestConvertSQLInjectionSample | same four samples, same requireFinding TestConvertSSRFSample | call, that TestNewRulePacksDoNotCrossFire TestConvertPathTraversalSample / already makes -- plus a cross-fire check TestConvertDirectory "at least 2 modules from test/js", implied by the same tree converting with 1 skip TestNoUnsupportedInstructions folded, see below TestConvertXSSSample stays: unlike its four siblings it also pins the module count, the language tag and a canonical name. The fallback-intrinsic walk moves into the two tests that were ALREADY converting those trees, as requireNoFallbackIntrinsic. "Skipped is 1" and "no instruction lowered to js.unsupported" are one invariant -- this tree converted completely -- and asserting them over one conversion instead of three drops two full walks of test/js from the package's runtime. Verified the relocation kept its teeth: removing the SForOf header collection again fails TestConvertCorpusTreeSkipsOnlyBroken, naming the same function. test/corpus was reviewed and left alone. Its four suites look overlapping and are not: signal/noise scores the labeled corpus, the differential and multi-language suites cover shapes no single-language sample can, and TestSampleModulesBuild compile-checks the isolated Go modules that `go test ./...` skips entirely. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01Rao1GBomZ53fL2ydytD96r --- converters/javascript/converter_test.go | 102 ++++-------------------- converters/javascript/dialects_test.go | 9 ++- 2 files changed, 21 insertions(+), 90 deletions(-) diff --git a/converters/javascript/converter_test.go b/converters/javascript/converter_test.go index f16713ae..845b3d46 100644 --- a/converters/javascript/converter_test.go +++ b/converters/javascript/converter_test.go @@ -1,7 +1,6 @@ package js_converter import ( - "fmt" "os" "path/filepath" "testing" @@ -84,6 +83,20 @@ func requireFinding(t *testing.T, findings []analysis.Finding, ruleID string) an return analysis.Finding{} } +// requireNoFallbackIntrinsic asserts no instruction lowered to js.unsupported. +// A fallback marks a construct the lowering does not model, and it is silent: +// the file still converts, so only this catches it. +func requireNoFallbackIntrinsic(t *testing.T, prog *ir.Program, what string) { + t.Helper() + for _, fn := range irwalk.Funcs(prog) { + for inst := range irwalk.Instrs(fn) { + if inst.Op == ir.OpCode_OP_CODE_INTRINSIC && inst.Intrinsic == "js.unsupported" { + t.Errorf("%s: unsupported instruction in %s: %s", what, fn.CanonicalName, inst.Comment) + } + } + } +} + func TestConvertXSSSample(t *testing.T) { prog := mustConvert(t, "../../test/js/xss/app.js") @@ -113,14 +126,6 @@ func TestConvertXSSSample(t *testing.T) { requireFinding(t, findings, "js-xss") } -func TestConvertCommandInjectionSample(t *testing.T) { - prog := mustConvert(t, "../../test/js/command_injection/app.js") - - engine := analysis.NewEngine(commandInjectionRuleSet(t)) - findings := engine.Analyze(prog) - requireFinding(t, findings, "js-command-injection") -} - // TestConvertBranchMergeDefault pins the statement-level "default if empty" // pattern (`if (!host) host = "localhost"`, FE-5): without the merge PHI the // reassignment inside the `if` kills the tainted binding on the merge path and @@ -133,22 +138,6 @@ func TestConvertBranchMergeDefault(t *testing.T) { requireFinding(t, findings, "js-command-injection") } -func TestConvertSQLInjectionSample(t *testing.T) { - prog := mustConvert(t, "../../test/js/sql_injection/app.js") - - engine := analysis.NewEngine(sqliRuleSet(t)) - findings := engine.Analyze(prog) - requireFinding(t, findings, "js-sqli") -} - -func TestConvertSSRFSample(t *testing.T) { - prog := mustConvert(t, "../../test/js/ssrf/app.js") - - engine := analysis.NewEngine(ssrfRuleSet(t)) - findings := engine.Analyze(prog) - requireFinding(t, findings, "js-ssrf") -} - // TestConvertChainedAxiosCallSSRF pins the chained-call lowering: a // CallExpression inside another call's *callee* (the `axios.get(url)` in // `axios.get(url).then(cb)`) must get its own OP_CODE_CALL with its own real @@ -203,14 +192,6 @@ module.exports = app; } } -func TestConvertPathTraversalSample(t *testing.T) { - prog := mustConvert(t, "../../test/js/path_traversal/app.js") - - engine := analysis.NewEngine(pathTraversalRuleSet(t)) - findings := engine.Analyze(prog) - requireFinding(t, findings, "js-path-traversal") -} - // TestNewRulePacksDoNotCrossFire pins that the broad `js:*.` sink globs // stay isolated to their own vulnerability class: no pack fires on another // pack's sample. @@ -245,15 +226,6 @@ func TestNewRulePacksDoNotCrossFire(t *testing.T) { } } -// TestConvertDirectory exercises the directory-walk path of ConvertFile -// (both sample directories share a common parent, test/js). -func TestConvertDirectory(t *testing.T) { - prog := mustConvert(t, "../../test/js") - if len(prog.Modules) < 2 { - t.Fatalf("expected at least 2 modules from directory conversion, got %d", len(prog.Modules)) - } -} - // TestConvertDirectorySkipsUnparseableFile pins that a directory conversion // tolerates one unparseable .js file: the batch still succeeds, yields only // app.js's module, and the engine still finds app.js's vulnerability. @@ -291,26 +263,6 @@ func functionNamesForModules(prog *ir.Program) []string { return names } -// TestNoUnsupportedInstructions is the absence-of-fallback check (CLAUDE.md): -// every instruction in the converted samples must have a real OpCode, never the -// generic "js.unsupported" intrinsic. -func TestNoUnsupportedInstructions(t *testing.T) { - // Whole trees, not a hand-picked list: the constructs that trip the fallback - // are the ones nobody thought to name. - for _, path := range []string{ - "../../test/js", - filepath.Join("testdata", "dialects"), - } { - for _, fn := range irwalk.Funcs(mustConvert(t, path)) { - for inst := range irwalk.Instrs(fn) { - if inst.Op == ir.OpCode_OP_CODE_INTRINSIC && inst.Intrinsic == "js.unsupported" { - t.Errorf("%s: unsupported instruction in %s: %s", path, fn.CanonicalName, inst.Comment) - } - } - } - } -} - // TestCollectsParamDefaultLiteral pins the half of collector coverage no // intrinsic reports: nothing lowers a parameter default, so a literal the // collector misses there is silently absent rather than flagged. @@ -334,32 +286,6 @@ func TestCollectsParamDefaultLiteral(t *testing.T) { t.Error("no js:eval call lowered — the default's literal was never collected") } -// TestLogXSSSampleInstructions is a diagnostic test: it converts the XSS -// sample and logs every instruction in the handleName function, so the -// lowering shape (registers, opcodes, callees, positions) is visible in test -// output, mirroring internal/analysis's TestLogSQLInjectionCallees. -func TestLogXSSSampleInstructions(t *testing.T) { - prog := mustConvert(t, "../../test/js/xss/app.js") - for _, mod := range prog.Modules { - for _, fn := range mod.Functions { - t.Logf("function %s (canonical=%s, synthetic=%v)", fn.Name, fn.CanonicalName, fn.Synthetic) - for _, blk := range fn.Blocks { - for _, inst := range blk.Instrs { - pos := "" - if inst.Pos != nil { - pos = fmt.Sprintf("%s:%d:%d", inst.Pos.GetFilename(), inst.Pos.GetLine(), inst.Pos.GetColumn()) - } - callee := "" - if inst.Call != nil { - callee = inst.Call.Callee - } - t.Logf(" name=%-4s op=%-24s callee=%-20s comment=%-20q pos=%s", inst.Name, inst.Op, callee, inst.Comment, pos) - } - } - } - } -} - func functionNames(mod *ir.Module) []string { var names []string for _, fn := range mod.Functions { diff --git a/converters/javascript/dialects_test.go b/converters/javascript/dialects_test.go index 024b3ce4..77c206d7 100644 --- a/converters/javascript/dialects_test.go +++ b/converters/javascript/dialects_test.go @@ -48,12 +48,15 @@ func TestDialectsAllConvert(t *testing.T) { // coverage, which is what makes a partially-dropped project visible. func TestDialectsScanReportsFullCoverage(t *testing.T) { c := NewConverter() - if _, err := c.ConvertFile(filepath.Join("testdata", "dialects")); err != nil { + prog, err := c.ConvertFile(filepath.Join("testdata", "dialects")) + if err != nil { t.Fatalf("ConvertFile(dialects): %v", err) } if c.Skipped() != 0 { t.Errorf("Skipped() = %d, want 0 — a dialect stopped parsing; see parseLadder", c.Skipped()) } + // Converting is half of it: a dialect can parse and still lower to a fallback. + requireNoFallbackIntrinsic(t, prog, "testdata/dialects") } // TestConvertCorpusTreeSkipsOnlyBroken pins the skip count over the whole JS @@ -66,12 +69,14 @@ func TestDialectsScanReportsFullCoverage(t *testing.T) { // still being read, and the dropped one simply has no findings to miss. func TestConvertCorpusTreeSkipsOnlyBroken(t *testing.T) { c := NewConverter() - if _, err := c.ConvertFile(filepath.Join("..", "..", "test", "js")); err != nil { + prog, err := c.ConvertFile(filepath.Join("..", "..", "test", "js")) + if err != nil { t.Fatalf("ConvertFile(test/js): %v", err) } if c.Skipped() != 1 { t.Errorf("Skipped() = %d, want 1 (only resilience/broken.js)", c.Skipped()) } + requireNoFallbackIntrinsic(t, prog, "test/js") } // TestLadderOrderKeepsRelationalArgs pins the rung ORDER, which is load-bearing From a03fc14bdf1a0541f65414b8163f6763f304944e Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 14 Aug 2026 05:21:09 +0000 Subject: [PATCH 9/9] js: fold modern.js into class_esnext.js The last goja-shaped residue in the fixtures. Both files probe class-body syntax, written at different times against goja's ragged ES2022 support, and they overlap: private field and static field appear in each. class_esnext.js now carries modern.js's unique constructs too -- optional chaining, nullish coalescing, `export class` -- so nothing is lost by dropping it. Nothing else in the tree is goja-specific: gojacaps_test.go went with the migration, test/js/goja_gaps was renamed for what it actually pins, and there is no longer a single `goja` reference in the repo outside FE-16's ledger row, which exists to record what was replaced. esnext.js and class_esnext.js keep earning their place despite being carved out of gojacaps_test.go: TestDialectsScanReportsFullCoverage now asserts no js.unsupported over this directory, so they pin that modern syntax LOWERS cleanly, not merely that esbuild can parse it. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01Rao1GBomZ53fL2ydytD96r --- .../javascript/testdata/dialects/class_esnext.js | 13 +++++++------ converters/javascript/testdata/dialects/modern.js | 5 ----- 2 files changed, 7 insertions(+), 11 deletions(-) delete mode 100644 converters/javascript/testdata/dialects/modern.js diff --git a/converters/javascript/testdata/dialects/class_esnext.js b/converters/javascript/testdata/dialects/class_esnext.js index b95ff226..a2c2d961 100644 --- a/converters/javascript/testdata/dialects/class_esnext.js +++ b/converters/javascript/testdata/dialects/class_esnext.js @@ -1,8 +1,9 @@ -// Class-body syntax past ES2022: a static block, `#x in o`, and an auto -// accessor. All three are dropped by the lowering (non-method class members are -// unmodeled), so what this fixture pins is that they PARSE — an unparsed class -// costs the whole file, including its methods. -class Registry { +// Class-body syntax past ES2022: private and static fields, a static block, +// `#x in o`, an auto accessor, plus optional chaining and nullish coalescing in +// a method. Non-method class members are unmodeled by the lowering, so what this +// pins is that they PARSE and lower without a fallback — an unparsed class costs +// the whole file, methods included. +export class Registry { #entries = new Map(); accessor label = "registry"; static defaults = {}; @@ -10,5 +11,5 @@ class Registry { static owns(o) { return #entries in o; } add(k, v) { this.#entries.set(k, v); } + get(o) { return o?.a?.b ?? this.#entries; } } -module.exports = { Registry }; diff --git a/converters/javascript/testdata/dialects/modern.js b/converters/javascript/testdata/dialects/modern.js deleted file mode 100644 index c983f2cb..00000000 --- a/converters/javascript/testdata/dialects/modern.js +++ /dev/null @@ -1,5 +0,0 @@ -export class Store { - #secret = 1; - static config = {}; - get(o) { return o?.a?.b ?? this.#secret; } -}