summaryrefslogtreecommitdiffhomepage
path: root/tools/nogo
diff options
context:
space:
mode:
Diffstat (limited to 'tools/nogo')
-rw-r--r--tools/nogo/BUILD80
-rw-r--r--tools/nogo/README.md31
-rw-r--r--tools/nogo/build.go46
-rw-r--r--tools/nogo/check/BUILD13
-rw-r--r--tools/nogo/check/main.go24
-rw-r--r--tools/nogo/config.go543
-rw-r--r--tools/nogo/defs.bzl367
-rwxr-xr-xtools/nogo/gentest.sh48
-rw-r--r--tools/nogo/matchers.go172
-rw-r--r--tools/nogo/nogo.go586
-rw-r--r--tools/nogo/register.go67
-rw-r--r--tools/nogo/util/BUILD9
-rw-r--r--tools/nogo/util/util.go85
13 files changed, 0 insertions, 2071 deletions
diff --git a/tools/nogo/BUILD b/tools/nogo/BUILD
deleted file mode 100644
index 3c6be3339..000000000
--- a/tools/nogo/BUILD
+++ /dev/null
@@ -1,80 +0,0 @@
-load("//tools:defs.bzl", "bzl_library", "go_library", "select_goarch", "select_goos")
-load("//tools/nogo:defs.bzl", "nogo_objdump_tool", "nogo_stdlib", "nogo_target")
-
-package(licenses = ["notice"])
-
-nogo_target(
- name = "target",
- goarch = select_goarch(),
- goos = select_goos(),
- visibility = ["//visibility:public"],
-)
-
-nogo_objdump_tool(
- name = "objdump_tool",
- visibility = ["//visibility:public"],
-)
-
-nogo_stdlib(
- name = "stdlib",
- visibility = ["//visibility:public"],
-)
-
-sh_binary(
- name = "gentest",
- srcs = ["gentest.sh"],
- visibility = ["//visibility:public"],
-)
-
-go_library(
- name = "nogo",
- srcs = [
- "build.go",
- "config.go",
- "matchers.go",
- "nogo.go",
- "register.go",
- ],
- nogo = False,
- visibility = ["//:sandbox"],
- deps = [
- "//tools/checkescape",
- "//tools/checkunsafe",
- "@co_honnef_go_tools//staticcheck:go_default_library",
- "@co_honnef_go_tools//stylecheck:go_default_library",
- "@org_golang_x_tools//go/analysis:go_tool_library",
- "@org_golang_x_tools//go/analysis/internal/facts:go_tool_library",
- "@org_golang_x_tools//go/analysis/passes/asmdecl:go_tool_library",
- "@org_golang_x_tools//go/analysis/passes/assign:go_tool_library",
- "@org_golang_x_tools//go/analysis/passes/atomic:go_tool_library",
- "@org_golang_x_tools//go/analysis/passes/bools:go_tool_library",
- "@org_golang_x_tools//go/analysis/passes/buildtag:go_tool_library",
- "@org_golang_x_tools//go/analysis/passes/cgocall:go_tool_library",
- "@org_golang_x_tools//go/analysis/passes/composite:go_tool_library",
- "@org_golang_x_tools//go/analysis/passes/copylock:go_tool_library",
- "@org_golang_x_tools//go/analysis/passes/errorsas:go_tool_library",
- "@org_golang_x_tools//go/analysis/passes/httpresponse:go_tool_library",
- "@org_golang_x_tools//go/analysis/passes/loopclosure:go_tool_library",
- "@org_golang_x_tools//go/analysis/passes/lostcancel:go_tool_library",
- "@org_golang_x_tools//go/analysis/passes/nilfunc:go_tool_library",
- "@org_golang_x_tools//go/analysis/passes/nilness:go_tool_library",
- "@org_golang_x_tools//go/analysis/passes/printf:go_tool_library",
- "@org_golang_x_tools//go/analysis/passes/shadow:go_tool_library",
- "@org_golang_x_tools//go/analysis/passes/shift:go_tool_library",
- "@org_golang_x_tools//go/analysis/passes/stdmethods:go_tool_library",
- "@org_golang_x_tools//go/analysis/passes/stringintconv:go_tool_library",
- "@org_golang_x_tools//go/analysis/passes/structtag:go_tool_library",
- "@org_golang_x_tools//go/analysis/passes/tests:go_tool_library",
- "@org_golang_x_tools//go/analysis/passes/unmarshal:go_tool_library",
- "@org_golang_x_tools//go/analysis/passes/unreachable:go_tool_library",
- "@org_golang_x_tools//go/analysis/passes/unsafeptr:go_tool_library",
- "@org_golang_x_tools//go/analysis/passes/unusedresult:go_tool_library",
- "@org_golang_x_tools//go/gcexportdata:go_tool_library",
- ],
-)
-
-bzl_library(
- name = "defs_bzl",
- srcs = ["defs.bzl"],
- visibility = ["//visibility:private"],
-)
diff --git a/tools/nogo/README.md b/tools/nogo/README.md
deleted file mode 100644
index 6e4db18de..000000000
--- a/tools/nogo/README.md
+++ /dev/null
@@ -1,31 +0,0 @@
-# Extended "nogo" analysis
-
-This package provides a build aspect that perform nogo analysis. This will be
-automatically injected to all relevant libraries when using the default
-`go_binary` and `go_library` rules.
-
-It exists for several reasons.
-
-* The default `nogo` provided by bazel is insufficient with respect to the
- possibility of binary analysis. This package allows us to analyze the
- generated binary in addition to using the standard analyzers.
-
-* The configuration provided in this package is much richer than the standard
- `nogo` JSON blob. Specifically, it allows us to exclude specific structures
- from the composite rules (such as the Ranges that are common with the set
- types).
-
-* The bazel version of `nogo` is run directly against the `go_library` and
- `go_binary` targets, meaning that any change to the configuration requires a
- rebuild from scratch (for some reason included all C++ source files in the
- process). Using an aspect is more efficient in this regard.
-
-* The checks supported by this package are exported as tests, which makes it
- easier to reason about and plumb into the build system.
-
-* For uninteresting reasons, it is impossible to integrate the default `nogo`
- analyzer provided by bazel with internal Google tooling. To provide a
- consistent experience, this package allows those systems to be unified.
-
-To use this package, import `nogo_test` from `defs.bzl` and add a single
-dependency which is a `go_binary` or `go_library` rule.
diff --git a/tools/nogo/build.go b/tools/nogo/build.go
deleted file mode 100644
index 55d34760f..000000000
--- a/tools/nogo/build.go
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2019 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package nogo
-
-import (
- "fmt"
- "io"
- "os"
-)
-
-var (
- // internalPrefix is the internal path prefix. Note that this is not
- // special, as paths should be passed relative to the repository root
- // and should not have any special prefix applied.
- internalPrefix = fmt.Sprintf("^")
-
- // internalDefault is applied when no paths are provided.
- internalDefault = fmt.Sprintf("%s/.*", notPath("external"))
-
- // generatedPrefix is a regex for generated files.
- generatedPrefix = "^(.*/)?(bazel-genfiles|bazel-out|bazel-bin)/"
-
- // externalPrefix is external workspace packages.
- externalPrefix = "^external/"
-)
-
-// findStdPkg needs to find the bundled standard library packages.
-func findStdPkg(GOOS, GOARCH, path string) (io.ReadCloser, error) {
- if path == "C" {
- // Cgo builds cannot be analyzed. Skip.
- return nil, ErrSkip
- }
- return os.Open(fmt.Sprintf("external/go_sdk/pkg/%s_%s/%s.a", GOOS, GOARCH, path))
-}
diff --git a/tools/nogo/check/BUILD b/tools/nogo/check/BUILD
deleted file mode 100644
index 21ba2c306..000000000
--- a/tools/nogo/check/BUILD
+++ /dev/null
@@ -1,13 +0,0 @@
-load("//tools:defs.bzl", "go_binary")
-
-package(licenses = ["notice"])
-
-# Note that the check binary must be public, since an aspect may be applied
-# across lots of different rules in different repositories.
-go_binary(
- name = "check",
- srcs = ["main.go"],
- nogo = False,
- visibility = ["//visibility:public"],
- deps = ["//tools/nogo"],
-)
diff --git a/tools/nogo/check/main.go b/tools/nogo/check/main.go
deleted file mode 100644
index 3828edf3a..000000000
--- a/tools/nogo/check/main.go
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2019 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Binary check is the nogo entrypoint.
-package main
-
-import (
- "gvisor.dev/gvisor/tools/nogo"
-)
-
-func main() {
- nogo.Main()
-}
diff --git a/tools/nogo/config.go b/tools/nogo/config.go
deleted file mode 100644
index 91b36576f..000000000
--- a/tools/nogo/config.go
+++ /dev/null
@@ -1,543 +0,0 @@
-// Copyright 2019 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package nogo
-
-import (
- "golang.org/x/tools/go/analysis"
- "golang.org/x/tools/go/analysis/passes/asmdecl"
- "golang.org/x/tools/go/analysis/passes/assign"
- "golang.org/x/tools/go/analysis/passes/atomic"
- "golang.org/x/tools/go/analysis/passes/bools"
- "golang.org/x/tools/go/analysis/passes/buildtag"
- "golang.org/x/tools/go/analysis/passes/cgocall"
- "golang.org/x/tools/go/analysis/passes/composite"
- "golang.org/x/tools/go/analysis/passes/copylock"
- "golang.org/x/tools/go/analysis/passes/errorsas"
- "golang.org/x/tools/go/analysis/passes/httpresponse"
- "golang.org/x/tools/go/analysis/passes/loopclosure"
- "golang.org/x/tools/go/analysis/passes/lostcancel"
- "golang.org/x/tools/go/analysis/passes/nilfunc"
- "golang.org/x/tools/go/analysis/passes/nilness"
- "golang.org/x/tools/go/analysis/passes/printf"
- "golang.org/x/tools/go/analysis/passes/shadow"
- "golang.org/x/tools/go/analysis/passes/shift"
- "golang.org/x/tools/go/analysis/passes/stdmethods"
- "golang.org/x/tools/go/analysis/passes/stringintconv"
- "golang.org/x/tools/go/analysis/passes/structtag"
- "golang.org/x/tools/go/analysis/passes/tests"
- "golang.org/x/tools/go/analysis/passes/unmarshal"
- "golang.org/x/tools/go/analysis/passes/unreachable"
- "golang.org/x/tools/go/analysis/passes/unsafeptr"
- "golang.org/x/tools/go/analysis/passes/unusedresult"
- "honnef.co/go/tools/staticcheck"
- "honnef.co/go/tools/stylecheck"
-
- "gvisor.dev/gvisor/tools/checkescape"
- "gvisor.dev/gvisor/tools/checkunsafe"
-)
-
-var analyzerConfig = map[*analysis.Analyzer]matcher{
- // Standard analyzers.
- asmdecl.Analyzer: alwaysMatches(),
- assign.Analyzer: externalExcluded(
- ".*gazelle/walk/walk.go", // False positive.
- ),
- atomic.Analyzer: alwaysMatches(),
- bools.Analyzer: alwaysMatches(),
- buildtag.Analyzer: alwaysMatches(),
- cgocall.Analyzer: alwaysMatches(),
- composite.Analyzer: and(
- disableMatches(), // Disabled for now.
- resultExcluded{
- "Object_",
- "Range{",
- },
- ),
- copylock.Analyzer: internalMatches(), // Common external issues (e.g. protos).
- errorsas.Analyzer: alwaysMatches(),
- httpresponse.Analyzer: alwaysMatches(),
- loopclosure.Analyzer: alwaysMatches(),
- lostcancel.Analyzer: internalMatches(), // Common external issues.
- nilfunc.Analyzer: alwaysMatches(),
- nilness.Analyzer: and(
- internalMatches(), // Common "tautological checks".
- internalExcluded(
- "pkg/sentry/platform/kvm/kvm_test.go", // Intentional.
- "tools/bigquery/bigquery.go", // False positive.
- ),
- ),
- printf.Analyzer: alwaysMatches(),
- shift.Analyzer: alwaysMatches(),
- stdmethods.Analyzer: internalMatches(), // Common external issues (e.g. methods named "Write").
- stringintconv.Analyzer: and(
- internalExcluded(),
- externalExcluded(
- ".*protobuf/.*.go", // Bad conversions.
- ".*flate/huffman_bit_writer.go", // Bad conversion.
-
- // Runtime internal violations.
- ".*reflect/value.go",
- ".*encoding/xml/xml.go",
- ".*runtime/pprof/internal/profile/proto.go",
- ".*fmt/scan.go",
- ".*go/types/conversions.go",
- ".*golang.org/x/net/dns/dnsmessage/message.go",
- ),
- ),
- shadow.Analyzer: disableMatches(), // Disabled for now.
- structtag.Analyzer: internalMatches(), // External not subject to rules.
- tests.Analyzer: alwaysMatches(),
- unmarshal.Analyzer: alwaysMatches(),
- unreachable.Analyzer: internalMatches(),
- unsafeptr.Analyzer: and(
- internalMatches(),
- internalExcluded(
- ".*_test.go", // Exclude tests.
- "pkg/flipcall/.*_unsafe.go", // Special case.
- "pkg/gohacks/gohacks_unsafe.go", // Special case.
- "pkg/sentry/fs/fsutil/host_file_mapper_unsafe.go", // Special case.
- "pkg/sentry/platform/kvm/bluepill_unsafe.go", // Special case.
- "pkg/sentry/platform/kvm/machine_unsafe.go", // Special case.
- "pkg/sentry/platform/ring0/pagetables/allocator_unsafe.go", // Special case.
- "pkg/sentry/platform/safecopy/safecopy_unsafe.go", // Special case.
- "pkg/sentry/vfs/mount_unsafe.go", // Special case.
- "pkg/sentry/platform/systrap/stub_unsafe.go", // Special case.
- "pkg/sentry/platform/systrap/switchto_google_unsafe.go", // Special case.
- "pkg/sentry/platform/systrap/sysmsg_thread_unsafe.go", // Special case.
- "pkg/state/decode_unsafe.go", // Special case.
- ),
- ),
- unusedresult.Analyzer: alwaysMatches(),
-
- // Internal analyzers: external packages not subject.
- checkescape.Analyzer: internalMatches(),
- checkunsafe.Analyzer: internalMatches(),
-}
-
-func init() {
- staticMatcher := and(
- // Only match internal, non-generated files.
- internalMatches(),
- generatedExcluded(),
-
- // We use ALL_CAPS for system definitions,
- // which are common enough in the code base
- // that we shouldn't annotate exceptions.
- //
- // Same story for underscores.
- resultExcluded([]string{
- "should not use ALL_CAPS in Go names",
- "should not use underscores in Go names",
- }),
-
- // Exclude existing matches.
- internalExcluded(
- "pkg/abi/linux/fuse.go:22",
- "pkg/abi/linux/fuse.go:25",
- "pkg/abi/linux/socket.go:113",
- "pkg/abi/linux/tty.go:73",
- "pkg/bpf/decoder.go:112",
- "pkg/cpuid/cpuid_x86.go:675",
- "pkg/eventchannel/event.go:193",
- "pkg/eventchannel/event.go:27",
- "pkg/eventchannel/event_test.go:22",
- "pkg/eventchannel/rate.go:19",
- "pkg/gohacks/gohacks_unsafe.go:33",
- "pkg/log/json.go:30",
- "pkg/log/log.go:359",
- "pkg/merkletree/merkletree.go:230",
- "pkg/merkletree/merkletree.go:243",
- "pkg/merkletree/merkletree.go:249",
- "pkg/merkletree/merkletree.go:266",
- "pkg/merkletree/merkletree.go:355",
- "pkg/merkletree/merkletree.go:369",
- "pkg/metric/metric_test.go:20",
- "pkg/p9/p9test/client_test.go:687",
- "pkg/p9/transport_test.go:196",
- "pkg/pool/pool.go:15",
- "pkg/refs/refcounter.go:510",
- "pkg/refs/refcounter_test.go:169",
- "pkg/safemem/block_unsafe.go:89",
- "pkg/seccomp/seccomp.go:82",
- "pkg/segment/test/set_functions.go:15",
- "pkg/sentry/arch/signal.go:166",
- "pkg/sentry/arch/signal.go:171",
- "pkg/sentry/control/pprof.go:196",
- "pkg/sentry/devices/memdev/full.go:58",
- "pkg/sentry/devices/memdev/null.go:59",
- "pkg/sentry/devices/memdev/random.go:68",
- "pkg/sentry/devices/memdev/zero.go:86",
- "pkg/sentry/fdimport/fdimport.go:15",
- "pkg/sentry/fs/attr.go:257",
- "pkg/sentry/fsbridge/fs.go:116",
- "pkg/sentry/fsbridge/vfs.go:124",
- "pkg/sentry/fsbridge/vfs.go:70",
- "pkg/sentry/fs/copy_up.go:365",
- "pkg/sentry/fs/copy_up_test.go:65",
- "pkg/sentry/fs/dev/net_tun.go:161",
- "pkg/sentry/fs/dev/net_tun.go:63",
- "pkg/sentry/fs/dev/null.go:97",
- "pkg/sentry/fs/dirent_cache.go:64",
- "pkg/sentry/fs/file_overlay.go:327",
- "pkg/sentry/fs/file_overlay.go:524",
- "pkg/sentry/fs/filetest/filetest.go:55",
- "pkg/sentry/fs/filetest/filetest.go:60",
- "pkg/sentry/fs/fs.go:77",
- "pkg/sentry/fs/fsutil/file.go:290",
- "pkg/sentry/fs/fsutil/file.go:346",
- "pkg/sentry/fs/fsutil/host_file_mapper.go:105",
- "pkg/sentry/fs/fsutil/inode_cached.go:676",
- "pkg/sentry/fs/fsutil/inode_cached.go:772",
- "pkg/sentry/fs/gofer/attr.go:120",
- "pkg/sentry/fs/gofer/fifo.go:33",
- "pkg/sentry/fs/gofer/inode.go:410",
- "pkg/sentry/fsimpl/devpts/devpts.go:110",
- "pkg/sentry/fsimpl/devpts/devpts.go:246",
- "pkg/sentry/fsimpl/devpts/devpts.go:50",
- "pkg/sentry/fsimpl/devpts/master.go:110",
- "pkg/sentry/fsimpl/devpts/master.go:55",
- "pkg/sentry/fsimpl/devpts/replica.go:113",
- "pkg/sentry/fsimpl/devpts/replica.go:57",
- "pkg/sentry/fsimpl/devtmpfs/devtmpfs.go:54",
- "pkg/sentry/fsimpl/ext/disklayout/superblock_64.go:97",
- "pkg/sentry/fsimpl/ext/disklayout/superblock_old.go:92",
- "pkg/sentry/fsimpl/ext/disklayout/block_group_32.go:44",
- "pkg/sentry/fsimpl/ext/disklayout/inode_new.go:91",
- "pkg/sentry/fsimpl/ext/disklayout/inode_old.go:93",
- "pkg/sentry/fsimpl/ext/disklayout/superblock_32.go:66",
- "pkg/sentry/fsimpl/ext/disklayout/block_group_64.go:53",
- "pkg/sentry/fsimpl/eventfd/eventfd.go:268",
- "pkg/sentry/fsimpl/ext/directory.go:163",
- "pkg/sentry/fsimpl/ext/directory.go:164",
- "pkg/sentry/fsimpl/ext/extent_file.go:142",
- "pkg/sentry/fsimpl/ext/extent_file.go:143",
- "pkg/sentry/fsimpl/ext/ext.go:105",
- "pkg/sentry/fsimpl/ext/filesystem.go:287",
- "pkg/sentry/fsimpl/ext/regular_file.go:153",
- "pkg/sentry/fsimpl/ext/symlink.go:113",
- "pkg/sentry/fsimpl/fuse/connection_control.go:194",
- "pkg/sentry/fsimpl/fuse/dev.go:387",
- "pkg/sentry/fsimpl/fuse/dev_test.go:318",
- "pkg/sentry/fsimpl/fuse/fusefs.go:102",
- "pkg/sentry/fsimpl/fuse/read_write.go:129",
- "pkg/sentry/fsimpl/fuse/request_response.go:71",
- "pkg/sentry/fsimpl/gofer/directory.go:135",
- "pkg/sentry/fsimpl/gofer/filesystem.go:679",
- "pkg/sentry/fsimpl/gofer/gofer.go:1694",
- "pkg/sentry/fsimpl/gofer/gofer.go:276",
- "pkg/sentry/fsimpl/gofer/regular_file.go:81",
- "pkg/sentry/fsimpl/gofer/special_file.go:141",
- "pkg/sentry/fsimpl/host/host.go:184",
- "pkg/sentry/fsimpl/kernfs/dynamic_bytes_file.go:50",
- "pkg/sentry/fsimpl/kernfs/dynamic_bytes_file.go:90",
- "pkg/sentry/fsimpl/kernfs/fd_impl_util.go:273",
- "pkg/sentry/fsimpl/kernfs/filesystem.go:247",
- "pkg/sentry/fsimpl/kernfs/inode_impl_util.go:320",
- "pkg/sentry/fsimpl/kernfs/inode_impl_util.go:497",
- "pkg/sentry/fsimpl/kernfs/synthetic_directory.go:52",
- "pkg/sentry/fsimpl/overlay/directory.go:119",
- "pkg/sentry/fsimpl/overlay/filesystem.go:527",
- "pkg/sentry/fsimpl/overlay/non_directory.go:152",
- "pkg/sentry/fsimpl/overlay/overlay.go:115",
- "pkg/sentry/fsimpl/overlay/overlay.go:719",
- "pkg/sentry/fsimpl/pipefs/pipefs.go:74",
- "pkg/sentry/fsimpl/proc/filesystem.go:52",
- "pkg/sentry/fsimpl/proc/filesystem.go:81",
- "pkg/sentry/fsimpl/proc/subtasks.go:126",
- "pkg/sentry/fsimpl/proc/subtasks.go:189",
- "pkg/sentry/fsimpl/proc/task_fds.go:168",
- "pkg/sentry/fsimpl/proc/task_fds.go:228",
- "pkg/sentry/fsimpl/proc/task_fds.go:301",
- "pkg/sentry/fsimpl/proc/task_fds.go:318",
- "pkg/sentry/fsimpl/proc/task_fds.go:67",
- "pkg/sentry/fsimpl/proc/task_files.go:112",
- "pkg/sentry/fsimpl/proc/task_files.go:158",
- "pkg/sentry/fsimpl/proc/task_files.go:259",
- "pkg/sentry/fsimpl/proc/task_files.go:285",
- "pkg/sentry/fsimpl/proc/task_files.go:305",
- "pkg/sentry/fsimpl/proc/task_files.go:384",
- "pkg/sentry/fsimpl/proc/task_files.go:403",
- "pkg/sentry/fsimpl/proc/task_files.go:428",
- "pkg/sentry/fsimpl/proc/task_files.go:691",
- "pkg/sentry/fsimpl/proc/task_files.go:770",
- "pkg/sentry/fsimpl/proc/task_files.go:797",
- "pkg/sentry/fsimpl/proc/task_files.go:828",
- "pkg/sentry/fsimpl/proc/task_files.go:879",
- "pkg/sentry/fsimpl/proc/task_files.go:910",
- "pkg/sentry/fsimpl/proc/task_files.go:961",
- "pkg/sentry/fsimpl/proc/task.go:127",
- "pkg/sentry/fsimpl/proc/task.go:193",
- "pkg/sentry/fsimpl/proc/task_net.go:134",
- "pkg/sentry/fsimpl/proc/task_net.go:475",
- "pkg/sentry/fsimpl/proc/task_net.go:491",
- "pkg/sentry/fsimpl/proc/task_net.go:508",
- "pkg/sentry/fsimpl/proc/task_net.go:665",
- "pkg/sentry/fsimpl/proc/task_net.go:715",
- "pkg/sentry/fsimpl/proc/task_net.go:779",
- "pkg/sentry/fsimpl/proc/tasks_files.go:113",
- "pkg/sentry/fsimpl/proc/tasks_files.go:388",
- "pkg/sentry/fsimpl/proc/tasks.go:232",
- "pkg/sentry/fsimpl/proc/tasks_sys.go:145",
- "pkg/sentry/fsimpl/proc/tasks_sys.go:181",
- "pkg/sentry/fsimpl/proc/tasks_sys.go:239",
- "pkg/sentry/fsimpl/proc/tasks_sys.go:291",
- "pkg/sentry/fsimpl/proc/tasks_sys.go:375",
- "pkg/sentry/fsimpl/signalfd/signalfd.go:124",
- "pkg/sentry/fsimpl/signalfd/signalfd.go:15",
- "pkg/sentry/fsimpl/signalfd/signalfd.go:126",
- "pkg/sentry/fsimpl/sockfs/sockfs.go:36",
- "pkg/sentry/fsimpl/sockfs/sockfs.go:79",
- "pkg/sentry/fsimpl/sys/kcov.go:49",
- "pkg/sentry/fsimpl/sys/kcov.go:99",
- "pkg/sentry/fsimpl/sys/sys.go:118",
- "pkg/sentry/fsimpl/sys/sys.go:56",
- "pkg/sentry/fsimpl/testutil/testutil.go:257",
- "pkg/sentry/fsimpl/testutil/testutil.go:260",
- "pkg/sentry/fsimpl/timerfd/timerfd.go:87",
- "pkg/sentry/fsimpl/tmpfs/directory.go:112",
- "pkg/sentry/fsimpl/tmpfs/filesystem.go:195",
- "pkg/sentry/fsimpl/tmpfs/regular_file.go:226",
- "pkg/sentry/fsimpl/tmpfs/regular_file.go:346",
- "pkg/sentry/fsimpl/tmpfs/tmpfs.go:103",
- "pkg/sentry/fsimpl/tmpfs/tmpfs.go:733",
- "pkg/sentry/fsimpl/verity/filesystem.go:490",
- "pkg/sentry/fsimpl/verity/verity.go:156",
- "pkg/sentry/fsimpl/verity/verity.go:629",
- "pkg/sentry/fsimpl/verity/verity.go:672",
- "pkg/sentry/fs/mount.go:162",
- "pkg/sentry/fs/mount.go:256",
- "pkg/sentry/fs/mount_overlay.go:144",
- "pkg/sentry/fs/mounts.go:432",
- "pkg/sentry/fs/proc/exec_args.go:104",
- "pkg/sentry/fs/proc/exec_args.go:73",
- "pkg/sentry/fs/proc/fds.go:269",
- "pkg/sentry/fs/proc/loadavg.go:33",
- "pkg/sentry/fs/proc/meminfo.go:39",
- "pkg/sentry/fs/proc/mounts.go:193",
- "pkg/sentry/fs/proc/mounts.go:84",
- "pkg/sentry/fs/proc/net.go:125",
- "pkg/sentry/fs/proc/proc.go:146",
- "pkg/sentry/fs/proc/proc.go:204",
- "pkg/sentry/fs/proc/seqfile/seqfile.go:210",
- "pkg/sentry/fs/proc/sys.go:146",
- "pkg/sentry/fs/proc/sys.go:43",
- "pkg/sentry/fs/proc/sys_net.go:113",
- "pkg/sentry/fs/proc/sys_net.go:205",
- "pkg/sentry/fs/proc/sys_net.go:233",
- "pkg/sentry/fs/proc/sys_net.go:307",
- "pkg/sentry/fs/proc/sys_net.go:335",
- "pkg/sentry/fs/proc/sys_net.go:446",
- "pkg/sentry/fs/proc/sys_net.go:456",
- "pkg/sentry/fs/proc/sys_net.go:89",
- "pkg/sentry/fs/proc/task.go:170",
- "pkg/sentry/fs/proc/task.go:322",
- "pkg/sentry/fs/proc/task.go:427",
- "pkg/sentry/fs/proc/task.go:467",
- "pkg/sentry/fs/proc/task.go:500",
- "pkg/sentry/fs/proc/task.go:784",
- "pkg/sentry/fs/proc/task.go:839",
- "pkg/sentry/fs/proc/task.go:920",
- "pkg/sentry/fs/proc/uid_gid_map.go:108",
- "pkg/sentry/fs/proc/uid_gid_map.go:79",
- "pkg/sentry/fs/proc/uptime.go:75",
- "pkg/sentry/fs/ramfs/dir.go:447",
- "pkg/sentry/fs/tmpfs/inode_file.go:436",
- "pkg/sentry/fs/tmpfs/inode_file.go:537",
- "pkg/sentry/fs/tty/dir.go:313",
- "pkg/sentry/fs/tty/master.go:131",
- "pkg/sentry/fs/tty/master.go:91",
- "pkg/sentry/fs/tty/replica.go:116",
- "pkg/sentry/fs/tty/replica.go:88",
- "pkg/sentry/kernel/auth/id_map.go:269",
- "pkg/sentry/kernel/fasync/fasync.go:67",
- "pkg/sentry/kernel/kcov.go:209",
- "pkg/sentry/kernel/kcov.go:223",
- "pkg/sentry/kernel/kernel.go:343",
- "pkg/sentry/kernel/kernel.go:368",
- "pkg/sentry/kernel/pipe/node_test.go:112",
- "pkg/sentry/kernel/pipe/node_test.go:119",
- "pkg/sentry/kernel/pipe/node_test.go:130",
- "pkg/sentry/kernel/pipe/node_test.go:137",
- "pkg/sentry/kernel/pipe/node_test.go:149",
- "pkg/sentry/kernel/pipe/node_test.go:150",
- "pkg/sentry/kernel/pipe/node_test.go:158",
- "pkg/sentry/kernel/pipe/node_test.go:174",
- "pkg/sentry/kernel/pipe/node_test.go:180",
- "pkg/sentry/kernel/pipe/node_test.go:193",
- "pkg/sentry/kernel/pipe/node_test.go:202",
- "pkg/sentry/kernel/pipe/node_test.go:205",
- "pkg/sentry/kernel/pipe/node_test.go:216",
- "pkg/sentry/kernel/pipe/node_test.go:219",
- "pkg/sentry/kernel/pipe/node_test.go:271",
- "pkg/sentry/kernel/pipe/node_test.go:290",
- "pkg/sentry/kernel/pipe/pipe_test.go:93",
- "pkg/sentry/kernel/pipe/reader_writer.go:65",
- "pkg/sentry/kernel/posixtimer.go:157",
- "pkg/sentry/kernel/ptrace.go:218",
- "pkg/sentry/kernel/semaphore/semaphore.go:323",
- "pkg/sentry/kernel/sessions.go:123",
- "pkg/sentry/kernel/sessions.go:508",
- "pkg/sentry/kernel/signal_handlers.go:57",
- "pkg/sentry/kernel/task_context.go:72",
- "pkg/sentry/kernel/task_exit.go:67",
- "pkg/sentry/kernel/task_sched.go:255",
- "pkg/sentry/kernel/task_sched.go:280",
- "pkg/sentry/kernel/task_sched.go:323",
- "pkg/sentry/kernel/task_stop.go:192",
- "pkg/sentry/kernel/thread_group.go:530",
- "pkg/sentry/kernel/timekeeper.go:316",
- "pkg/sentry/kernel/vdso.go:106",
- "pkg/sentry/kernel/vdso.go:118",
- "pkg/sentry/memmap/memmap.go:103",
- "pkg/sentry/memmap/memmap.go:163",
- "pkg/sentry/mm/address_space.go:42",
- "pkg/sentry/mm/address_space.go:42",
- "pkg/sentry/mm/aio_context.go:208",
- "pkg/sentry/mm/aio_context.go:288",
- "pkg/sentry/mm/pma.go:683",
- "pkg/sentry/mm/special_mappable.go:80",
- "pkg/sentry/platform/systrap/subprocess.go:370",
- "pkg/sentry/platform/systrap/usertrap/usertrap_amd64.go:124",
- "pkg/sentry/socket/control/control.go:260",
- "pkg/sentry/socket/control/control.go:94",
- "pkg/sentry/socket/control/control_vfs2.go:37",
- "pkg/sentry/socket/hostinet/stack.go:433",
- "pkg/sentry/socket/hostinet/stack.go:438",
- "pkg/sentry/socket/hostinet/stack.go:444",
- "pkg/sentry/socket/hostinet/stack.go:460",
- "pkg/sentry/socket/netfilter/tcp_matcher.go:74",
- "pkg/sentry/socket/netfilter/udp_matcher.go:71",
- "pkg/sentry/socket/netlink/route/protocol.go:38",
- "pkg/sentry/socket/socket.go:332",
- "pkg/sentry/socket/unix/transport/connectioned.go:394",
- "pkg/sentry/socket/unix/transport/connectionless.go:152",
- "pkg/sentry/socket/unix/transport/unix.go:436",
- "pkg/sentry/socket/unix/transport/unix.go:490",
- "pkg/sentry/socket/unix/transport/unix.go:685",
- "pkg/sentry/socket/unix/transport/unix.go:795",
- "pkg/sentry/syscalls/linux/sys_sem.go:62",
- "pkg/sentry/syscalls/linux/sys_time.go:189",
- "pkg/sentry/usage/cpu.go:42",
- "pkg/sentry/vfs/anonfs.go:302",
- "pkg/sentry/vfs/anonfs.go:99",
- "pkg/sentry/vfs/dentry.go:214",
- "pkg/sentry/vfs/epoll.go:168",
- "pkg/sentry/vfs/epoll.go:314",
- "pkg/sentry/vfs/file_description.go:549",
- "pkg/sentry/vfs/file_description_impl_util.go:304",
- "pkg/sentry/vfs/file_description_impl_util.go:412",
- "pkg/sentry/vfs/filesystem.go:76",
- "pkg/sentry/vfs/lock.go:15",
- "pkg/sentry/vfs/lock.go:47",
- "pkg/sentry/vfs/memxattr/xattr.go:37",
- "pkg/sentry/vfs/mount.go:510",
- "pkg/sentry/vfs/mount.go:667",
- "pkg/sentry/vfs/mount_test.go:106",
- "pkg/sentry/vfs/mount_test.go:160",
- "pkg/sentry/vfs/mount_test.go:215",
- "pkg/sentry/vfs/mount_unsafe.go:153",
- "pkg/sentry/vfs/resolving_path.go:228",
- "pkg/sentry/vfs/vfs.go:897",
- "pkg/shim/runsc/runsc.go:16",
- "pkg/shim/runsc/utils.go:16",
- "pkg/shim/v1/proc/deleted_state.go:16",
- "pkg/shim/v1/proc/exec.go:16",
- "pkg/shim/v1/proc/exec_state.go:16",
- "pkg/shim/v1/proc/init.go:16",
- "pkg/shim/v1/proc/init_state.go:16",
- "pkg/shim/v1/proc/io.go:16",
- "pkg/shim/v1/proc/process.go:16",
- "pkg/shim/v1/proc/types.go:16",
- "pkg/shim/v1/proc/utils.go:16",
- "pkg/shim/v1/shim/api.go:16",
- "pkg/shim/v1/shim/platform.go:16",
- "pkg/shim/v1/shim/service.go:16",
- "pkg/shim/v1/utils/annotations.go:15",
- "pkg/shim/v1/utils/utils.go:15",
- "pkg/shim/v1/utils/volumes.go:15",
- "pkg/shim/v2/api.go:16",
- "pkg/shim/v2/epoll.go:18",
- "pkg/shim/v2/options/options.go:15",
- "pkg/shim/v2/options/options.go:24",
- "pkg/shim/v2/options/options.go:26",
- "pkg/shim/v2/runtimeoptions/runtimeoptions.go:16",
- "pkg/shim/v2/runtimeoptions/runtimeoptions_cri.go", // Generated: exempt all.
- "pkg/shim/v2/runtimeoptions/runtimeoptions_test.go:22",
- "pkg/shim/v2/service.go:15",
- "pkg/shim/v2/service_linux.go:18",
- "pkg/state/tests/integer_test.go:23",
- "pkg/state/tests/integer_test.go:28",
- "pkg/sync/rwmutex_test.go:105",
- "pkg/syserr/host_linux.go:35",
- "pkg/unet/unet_test.go:634",
- "pkg/unet/unet_test.go:662",
- "pkg/unet/unet_test.go:703",
- "pkg/unet/unet_test.go:98",
- "pkg/usermem/addr.go:34",
- "pkg/usermem/usermem.go:171",
- "pkg/usermem/usermem.go:170",
- "runsc/boot/compat.go:22",
- "runsc/boot/compat.go:56",
- "runsc/boot/loader.go:1115",
- "runsc/boot/loader.go:1120",
- "runsc/cmd/checkpoint.go:151",
- "runsc/config/flags.go:32",
- "runsc/container/container.go:641",
- "runsc/container/container.go:988",
- "runsc/specutils/specutils.go:172",
- "runsc/specutils/specutils.go:428",
- "runsc/specutils/specutils.go:436",
- "runsc/specutils/specutils.go:442",
- "runsc/specutils/specutils.go:447",
- "runsc/specutils/specutils.go:454",
- "test/cmd/test_app/fds.go:171",
- "test/iptables/filter_output.go:251",
- "test/packetimpact/testbench/connections.go:77",
- "tools/bigquery/bigquery.go:106",
- "tools/checkescape/test1/test1.go:108",
- "tools/checkescape/test1/test1.go:122",
- "tools/checkescape/test1/test1.go:137",
- "tools/checkescape/test1/test1.go:151",
- "tools/checkescape/test1/test1.go:170",
- "tools/checkescape/test1/test1.go:39",
- "tools/checkescape/test1/test1.go:45",
- "tools/checkescape/test1/test1.go:50",
- "tools/checkescape/test1/test1.go:64",
- "tools/checkescape/test1/test1.go:80",
- "tools/checkescape/test1/test1.go:94",
- "tools/go_generics/imports.go:51",
- "tools/go_generics/imports.go:75",
- "tools/go_marshal/gomarshal/generator.go:177",
- "tools/go_marshal/gomarshal/generator.go:81",
- "tools/go_marshal/gomarshal/generator.go:85",
- "tools/go_marshal/test/escape/escape.go:15",
- "tools/go_marshal/test/test.go:164",
- ),
- )
-
- // Add all staticcheck analyzers; internal only.
- for _, a := range staticcheck.Analyzers {
- analyzerConfig[a] = staticMatcher
- }
- // Add all stylecheck analyzers; internal only.
- for _, a := range stylecheck.Analyzers {
- analyzerConfig[a] = staticMatcher
- }
-}
-
-var escapesConfig = map[*analysis.Analyzer]matcher{
- // Informational only: include all packages.
- checkescape.EscapeAnalyzer: alwaysMatches(),
-}
diff --git a/tools/nogo/defs.bzl b/tools/nogo/defs.bzl
deleted file mode 100644
index 543598b52..000000000
--- a/tools/nogo/defs.bzl
+++ /dev/null
@@ -1,367 +0,0 @@
-"""Nogo rules."""
-
-load("//tools/bazeldefs:go.bzl", "go_context", "go_importpath", "go_rule", "go_test_library")
-
-NogoTargetInfo = provider(
- "information about the Go target",
- fields = {
- "goarch": "the build architecture (GOARCH)",
- "goos": "the build OS target (GOOS)",
- },
-)
-
-def _nogo_target_impl(ctx):
- return [NogoTargetInfo(
- goarch = ctx.attr.goarch,
- goos = ctx.attr.goos,
- )]
-
-nogo_target = go_rule(
- rule,
- implementation = _nogo_target_impl,
- attrs = {
- # goarch is the build architecture. This will normally be provided by a
- # select statement, but this information is propagated to other rules.
- "goarch": attr.string(mandatory = True),
- # goos is similarly the build operating system target.
- "goos": attr.string(mandatory = True),
- },
-)
-
-def _nogo_objdump_tool_impl(ctx):
- # Construct the magic dump command.
- #
- # Note that in some cases, the input is being fed into the tool via stdin.
- # Unfortunately, the Go objdump tool expects to see a seekable file [1], so
- # we need the tool to handle this case by creating a temporary file.
- #
- # [1] https://github.com/golang/go/issues/41051
- nogo_target_info = ctx.attr._nogo_target[NogoTargetInfo]
- go_ctx = go_context(ctx, goos = nogo_target_info.goos, goarch = nogo_target_info.goarch)
- env_prefix = " ".join(["%s=%s" % (key, value) for (key, value) in go_ctx.env.items()])
- dumper = ctx.actions.declare_file(ctx.label.name)
- ctx.actions.write(dumper, "\n".join([
- "#!/bin/bash",
- "set -euo pipefail",
- "if [[ $# -eq 0 ]]; then",
- " T=$(mktemp -u -t libXXXXXX.a)",
- " cat /dev/stdin > ${T}",
- "else",
- " T=$1;",
- "fi",
- "%s %s tool objdump ${T}" % (
- env_prefix,
- go_ctx.go.path,
- ),
- "if [[ $# -eq 0 ]]; then",
- " rm -rf ${T}",
- "fi",
- "",
- ]), is_executable = True)
-
- # Include the full runfiles.
- return [DefaultInfo(
- runfiles = ctx.runfiles(files = go_ctx.runfiles.to_list()),
- executable = dumper,
- )]
-
-nogo_objdump_tool = go_rule(
- rule,
- implementation = _nogo_objdump_tool_impl,
- attrs = {
- "_nogo_target": attr.label(
- default = "//tools/nogo:target",
- cfg = "target",
- ),
- },
-)
-
-# NogoStdlibInfo is the set of standard library facts.
-NogoStdlibInfo = provider(
- "information for nogo analysis (standard library facts)",
- fields = {
- "facts": "serialized standard library facts",
- "findings": "package findings (if relevant)",
- },
-)
-
-def _nogo_stdlib_impl(ctx):
- # Build the standard library facts.
- nogo_target_info = ctx.attr._nogo_target[NogoTargetInfo]
- go_ctx = go_context(ctx, goos = nogo_target_info.goos, goarch = nogo_target_info.goarch)
- facts = ctx.actions.declare_file(ctx.label.name + ".facts")
- findings = ctx.actions.declare_file(ctx.label.name + ".findings")
- config = struct(
- Srcs = [f.path for f in go_ctx.stdlib_srcs],
- GOOS = go_ctx.goos,
- GOARCH = go_ctx.goarch,
- Tags = go_ctx.tags,
- )
- config_file = ctx.actions.declare_file(ctx.label.name + ".cfg")
- ctx.actions.write(config_file, config.to_json())
- ctx.actions.run(
- inputs = [config_file] + go_ctx.stdlib_srcs,
- outputs = [facts, findings],
- tools = depset(go_ctx.runfiles.to_list() + ctx.files._nogo_objdump_tool),
- executable = ctx.files._nogo_check[0],
- mnemonic = "GoStandardLibraryAnalysis",
- progress_message = "Analyzing Go Standard Library",
- arguments = go_ctx.nogo_args + [
- "-objdump_tool=%s" % ctx.files._nogo_objdump_tool[0].path,
- "-stdlib=%s" % config_file.path,
- "-findings=%s" % findings.path,
- "-facts=%s" % facts.path,
- ],
- )
-
- # Return the stdlib facts as output.
- return [NogoStdlibInfo(
- facts = facts,
- findings = findings,
- )]
-
-nogo_stdlib = go_rule(
- rule,
- implementation = _nogo_stdlib_impl,
- attrs = {
- "_nogo_check": attr.label(
- default = "//tools/nogo/check:check",
- cfg = "host",
- ),
- "_nogo_objdump_tool": attr.label(
- default = "//tools/nogo:objdump_tool",
- cfg = "host",
- ),
- "_nogo_target": attr.label(
- default = "//tools/nogo:target",
- cfg = "target",
- ),
- },
-)
-
-# NogoInfo is the serialized set of package facts for a nogo analysis.
-#
-# Each go_library rule will generate a corresponding nogo rule, which will run
-# with the source files as input. Note however, that the individual nogo rules
-# are simply stubs that enter into the shadow dependency tree (the "aspect").
-NogoInfo = provider(
- "information for nogo analysis",
- fields = {
- "facts": "serialized package facts",
- "findings": "package findings (if relevant)",
- "importpath": "package import path",
- "binaries": "package binary files",
- "srcs": "srcs (for go_test support)",
- "deps": "deps (for go_test support)",
- },
-)
-
-def _nogo_aspect_impl(target, ctx):
- # If this is a nogo rule itself (and not the shadow of a go_library or
- # go_binary rule created by such a rule), then we simply return nothing.
- # All work is done in the shadow properties for go rules. For a proto
- # library, we simply skip the analysis portion but still need to return a
- # valid NogoInfo to reference the generated binary.
- if ctx.rule.kind in ("go_library", "go_tool_library", "go_binary", "go_test"):
- srcs = ctx.rule.files.srcs
- deps = ctx.rule.attr.deps
- elif ctx.rule.kind in ("go_proto_library", "go_wrap_cc"):
- srcs = []
- deps = ctx.rule.attr.deps
- else:
- return [NogoInfo()]
-
- # If we're using the "library" attribute, then we need to aggregate the
- # original library sources and dependencies into this target to perform
- # proper type analysis.
- if ctx.rule.kind == "go_test":
- library = go_test_library(ctx.rule)
- if library != None:
- info = library[NogoInfo]
- if hasattr(info, "srcs"):
- srcs = srcs + info.srcs
- if hasattr(info, "deps"):
- deps = deps + info.deps
-
- # Start with all target files and srcs as input.
- inputs = target.files.to_list() + srcs
-
- # Generate a shell script that dumps the binary. Annoyingly, this seems
- # necessary as the context in which a run_shell command runs does not seem
- # to cleanly allow us redirect stdout to the actual output file. Perhaps
- # I'm missing something here, but the intermediate script does work.
- binaries = target.files.to_list()
- objfiles = [f for f in binaries if f.path.endswith(".a")]
- if len(objfiles) > 0:
- # Prefer the .a files for go_library targets.
- target_objfile = objfiles[0]
- else:
- # Use the raw binary for go_binary and go_test targets.
- target_objfile = binaries[0]
- inputs.append(target_objfile)
-
- # Extract the importpath for this package.
- if ctx.rule.kind == "go_test":
- # If this is a test, then it will not be imported by anything else.
- # We can safely set the importapth to just "test". Note that this
- # is necessary if the library also imports the core library (in
- # addition to including the sources directly), which happens in
- # some complex cases (seccomp_victim).
- importpath = "test"
- else:
- importpath = go_importpath(target)
-
- # Collect all info from shadow dependencies.
- fact_map = dict()
- import_map = dict()
- for dep in deps:
- # There will be no file attribute set for all transitive dependencies
- # that are not go_library or go_binary rules, such as a proto rules.
- # This is handled by the ctx.rule.kind check above.
- info = dep[NogoInfo]
- if not hasattr(info, "facts"):
- continue
-
- # Configure where to find the binary & fact files. Note that this will
- # use .x and .a regardless of whether this is a go_binary rule, since
- # these dependencies must be go_library rules.
- x_files = [f.path for f in info.binaries if f.path.endswith(".x")]
- if not len(x_files):
- x_files = [f.path for f in info.binaries if f.path.endswith(".a")]
- import_map[info.importpath] = x_files[0]
- fact_map[info.importpath] = info.facts.path
-
- # Ensure the above are available as inputs.
- inputs.append(info.facts)
- inputs += info.binaries
-
- # Add the standard library facts.
- stdlib_info = ctx.attr._nogo_stdlib[NogoStdlibInfo]
- stdlib_facts = stdlib_info.facts
- inputs.append(stdlib_facts)
-
- # The nogo tool operates on a configuration serialized in JSON format.
- nogo_target_info = ctx.attr._nogo_target[NogoTargetInfo]
- go_ctx = go_context(ctx, goos = nogo_target_info.goos, goarch = nogo_target_info.goarch)
- facts = ctx.actions.declare_file(target.label.name + ".facts")
- findings = ctx.actions.declare_file(target.label.name + ".findings")
- escapes = ctx.actions.declare_file(target.label.name + ".escapes")
- config = struct(
- ImportPath = importpath,
- GoFiles = [src.path for src in srcs if src.path.endswith(".go")],
- NonGoFiles = [src.path for src in srcs if not src.path.endswith(".go")],
- GOOS = go_ctx.goos,
- GOARCH = go_ctx.goarch,
- Tags = go_ctx.tags,
- FactMap = fact_map,
- ImportMap = import_map,
- StdlibFacts = stdlib_facts.path,
- )
- config_file = ctx.actions.declare_file(target.label.name + ".cfg")
- ctx.actions.write(config_file, config.to_json())
- inputs.append(config_file)
- ctx.actions.run(
- inputs = inputs,
- outputs = [facts, findings, escapes],
- tools = depset(go_ctx.runfiles.to_list() + ctx.files._nogo_objdump_tool),
- executable = ctx.files._nogo_check[0],
- mnemonic = "GoStaticAnalysis",
- progress_message = "Analyzing %s" % target.label,
- arguments = go_ctx.nogo_args + [
- "-binary=%s" % target_objfile.path,
- "-objdump_tool=%s" % ctx.files._nogo_objdump_tool[0].path,
- "-package=%s" % config_file.path,
- "-findings=%s" % findings.path,
- "-facts=%s" % facts.path,
- "-escapes=%s" % escapes.path,
- ],
- )
-
- # Return the package facts as output.
- return [
- NogoInfo(
- facts = facts,
- findings = findings,
- importpath = importpath,
- binaries = binaries,
- srcs = srcs,
- deps = deps,
- ),
- OutputGroupInfo(
- # Expose all findings (should just be a single file). This can be
- # used for build analysis of the nogo findings.
- nogo_findings = depset([findings]),
- # Expose all escape analysis findings (see above).
- nogo_escapes = depset([escapes]),
- ),
- ]
-
-nogo_aspect = go_rule(
- aspect,
- implementation = _nogo_aspect_impl,
- attr_aspects = [
- "deps",
- "library",
- "embed",
- ],
- attrs = {
- "_nogo_check": attr.label(
- default = "//tools/nogo/check:check",
- cfg = "host",
- ),
- "_nogo_stdlib": attr.label(
- default = "//tools/nogo:stdlib",
- cfg = "host",
- ),
- "_nogo_objdump_tool": attr.label(
- default = "//tools/nogo:objdump_tool",
- cfg = "host",
- ),
- "_nogo_target": attr.label(
- default = "//tools/nogo:target",
- cfg = "target",
- ),
- },
-)
-
-def _nogo_test_impl(ctx):
- """Check nogo findings."""
-
- # Build a runner that checks the facts files.
- findings = [dep[NogoInfo].findings for dep in ctx.attr.deps]
- runner = ctx.actions.declare_file(ctx.label.name)
- ctx.actions.run(
- inputs = findings + ctx.files.srcs,
- outputs = [runner],
- tools = depset(ctx.files._gentest),
- executable = ctx.files._gentest[0],
- mnemonic = "Gentest",
- progress_message = "Generating %s" % ctx.label,
- arguments = [runner.path] + [f.path for f in findings],
- )
- return [DefaultInfo(
- executable = runner,
- )]
-
-_nogo_test = rule(
- implementation = _nogo_test_impl,
- attrs = {
- # deps should have only a single element.
- "deps": attr.label_list(aspects = [nogo_aspect]),
- # srcs exist here only to ensure that this target is
- # directly affected by changes to the source files.
- "srcs": attr.label_list(allow_files = True),
- "_gentest": attr.label(default = "//tools/nogo:gentest"),
- },
- test = True,
-)
-
-def nogo_test(name, srcs, library, **kwargs):
- tags = kwargs.pop("tags", []) + ["nogo"]
- _nogo_test(
- name = name,
- srcs = srcs,
- deps = [library],
- tags = tags,
- **kwargs
- )
diff --git a/tools/nogo/gentest.sh b/tools/nogo/gentest.sh
deleted file mode 100755
index 0a762f9f6..000000000
--- a/tools/nogo/gentest.sh
+++ /dev/null
@@ -1,48 +0,0 @@
-#!/bin/bash
-# Copyright 2019 The gVisor Authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-set -euo pipefail
-
-if [[ "$#" -lt 2 ]]; then
- echo "usage: $0 <output> <findings...>"
- exit 2
-fi
-declare violations=0
-declare output=$1
-shift
-
-# Start the script.
-echo "#!/bin/sh" > "${output}"
-
-# Read a list of findings files.
-declare filename
-declare line
-for filename in "$@"; do
- if [[ -z "${filename}" ]]; then
- continue
- fi
- while read -r line; do
- line="${line@Q}"
- violations=$((${violations}+1));
- echo "echo -e '\\033[0;31m${line}\\033[0;31m\\033[0m'" >> "${output}"
- done < "${filename}"
-done
-
-# Show violations.
-if [[ "${violations}" -eq 0 ]]; then
- echo "echo -e '\\033[0;32mPASS\\033[0;31m\\033[0m'" >> "${output}"
-else
- echo "exit 1" >> "${output}"
-fi
diff --git a/tools/nogo/matchers.go b/tools/nogo/matchers.go
deleted file mode 100644
index b7b73fa27..000000000
--- a/tools/nogo/matchers.go
+++ /dev/null
@@ -1,172 +0,0 @@
-// Copyright 2019 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package nogo
-
-import (
- "go/token"
- "regexp"
- "strings"
-
- "golang.org/x/tools/go/analysis"
-)
-
-type matcher interface {
- ShouldReport(d analysis.Diagnostic, fs *token.FileSet) bool
-}
-
-// pathRegexps filters explicit paths.
-type pathRegexps struct {
- expr []*regexp.Regexp
-
- // include, if true, indicates that paths matching any regexp in expr
- // match.
- //
- // If false, paths matching no regexps in expr match.
- include bool
-}
-
-// buildRegexps builds a list of regular expressions.
-//
-// This will panic on error.
-func buildRegexps(prefix string, args ...string) []*regexp.Regexp {
- result := make([]*regexp.Regexp, 0, len(args))
- for _, arg := range args {
- result = append(result, regexp.MustCompile(prefix+arg))
- }
- return result
-}
-
-// notPath works around the lack of backtracking.
-//
-// It is used to construct a regular expression for non-matching components.
-func notPath(name string) string {
- sb := strings.Builder{}
- sb.WriteString("(")
- for i := range name {
- if i > 0 {
- sb.WriteString("|")
- }
- sb.WriteString(name[:i])
- sb.WriteString("[^")
- sb.WriteByte(name[i])
- sb.WriteString("/][^/]*")
- }
- sb.WriteString(")")
- return sb.String()
-}
-
-// ShouldReport implements matcher.ShouldReport.
-func (p *pathRegexps) ShouldReport(d analysis.Diagnostic, fs *token.FileSet) bool {
- fullPos := fs.Position(d.Pos).String()
- for _, path := range p.expr {
- if path.MatchString(fullPos) {
- return p.include
- }
- }
- return !p.include
-}
-
-// internalExcluded excludes specific internal paths.
-func internalExcluded(paths ...string) *pathRegexps {
- return &pathRegexps{
- expr: buildRegexps(internalPrefix, paths...),
- include: false,
- }
-}
-
-// excludedExcluded excludes specific external paths.
-func externalExcluded(paths ...string) *pathRegexps {
- return &pathRegexps{
- expr: buildRegexps(externalPrefix, paths...),
- include: false,
- }
-}
-
-// internalMatches returns a path matcher for internal packages.
-func internalMatches() *pathRegexps {
- return &pathRegexps{
- expr: buildRegexps(internalPrefix, internalDefault),
- include: true,
- }
-}
-
-// generatedExcluded excludes all generated code.
-func generatedExcluded() *pathRegexps {
- return &pathRegexps{
- expr: buildRegexps(generatedPrefix, ".*"),
- include: false,
- }
-}
-
-// resultExcluded excludes explicit message contents.
-type resultExcluded []string
-
-// ShouldReport implements matcher.ShouldReport.
-func (r resultExcluded) ShouldReport(d analysis.Diagnostic, _ *token.FileSet) bool {
- for _, str := range r {
- if strings.Contains(d.Message, str) {
- return false
- }
- }
- return true // Not excluded.
-}
-
-// andMatcher is a composite matcher.
-type andMatcher struct {
- all []matcher
-}
-
-// ShouldReport implements matcher.ShouldReport.
-func (a *andMatcher) ShouldReport(d analysis.Diagnostic, fs *token.FileSet) bool {
- for _, m := range a.all {
- if !m.ShouldReport(d, fs) {
- return false
- }
- }
- return true
-}
-
-// and is a syntactic convension for andMatcher.
-func and(ms ...matcher) *andMatcher {
- return &andMatcher{
- all: ms,
- }
-}
-
-// anyMatcher matches everything.
-type anyMatcher struct{}
-
-// ShouldReport implements matcher.ShouldReport.
-func (anyMatcher) ShouldReport(analysis.Diagnostic, *token.FileSet) bool {
- return true
-}
-
-// alwaysMatches returns an anyMatcher instance.
-func alwaysMatches() anyMatcher {
- return anyMatcher{}
-}
-
-// neverMatcher will never match.
-type neverMatcher struct{}
-
-// ShouldReport implements matcher.ShouldReport.
-func (neverMatcher) ShouldReport(analysis.Diagnostic, *token.FileSet) bool {
- return false
-}
-
-// disableMatches returns a neverMatcher instance.
-func disableMatches() neverMatcher {
- return neverMatcher{}
-}
diff --git a/tools/nogo/nogo.go b/tools/nogo/nogo.go
deleted file mode 100644
index e19e3c237..000000000
--- a/tools/nogo/nogo.go
+++ /dev/null
@@ -1,586 +0,0 @@
-// Copyright 2019 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Package nogo implements binary analysis similar to bazel's nogo,
-// or the unitchecker package. It exists in order to provide additional
-// facilities for analysis, namely plumbing through the output from
-// dumping the generated binary (to analyze actual produced code).
-package nogo
-
-import (
- "encoding/json"
- "errors"
- "flag"
- "fmt"
- "go/ast"
- "go/build"
- "go/parser"
- "go/token"
- "go/types"
- "io"
- "io/ioutil"
- "log"
- "os"
- "path"
- "path/filepath"
- "reflect"
- "strings"
-
- "golang.org/x/tools/go/analysis"
- "golang.org/x/tools/go/analysis/internal/facts"
- "golang.org/x/tools/go/gcexportdata"
-
- // Special case: flags live here and change overall behavior.
- "gvisor.dev/gvisor/tools/checkescape"
-)
-
-// stdlibConfig is serialized as the configuration.
-//
-// This contains everything required for stdlib analysis.
-type stdlibConfig struct {
- Srcs []string
- GOOS string
- GOARCH string
- Tags []string
-}
-
-// packageConfig is serialized as the configuration.
-//
-// This contains everything required for single package analysis.
-type packageConfig struct {
- ImportPath string
- GoFiles []string
- NonGoFiles []string
- Tags []string
- GOOS string
- GOARCH string
- ImportMap map[string]string
- FactMap map[string]string
- StdlibFacts string
-}
-
-// loader is a fact-loader function.
-type loader func(string) ([]byte, error)
-
-// saver is a fact-saver function.
-type saver func([]byte) error
-
-// factLoader returns a function that loads facts.
-//
-// This resolves all standard library facts and imported package facts up
-// front. The returned loader function will never return an error, only
-// empty facts.
-//
-// This is done because all stdlib data is stored together, and we don't want
-// to load this data many times over.
-func (c *packageConfig) factLoader() (loader, error) {
- allFacts := make(map[string][]byte)
- if c.StdlibFacts != "" {
- data, err := ioutil.ReadFile(c.StdlibFacts)
- if err != nil {
- return nil, fmt.Errorf("error loading stdlib facts from %q: %w", c.StdlibFacts, err)
- }
- var stdlibFacts map[string][]byte
- if err := json.Unmarshal(data, &stdlibFacts); err != nil {
- return nil, fmt.Errorf("error loading stdlib facts: %w", err)
- }
- for pkg, data := range stdlibFacts {
- allFacts[pkg] = data
- }
- }
- for pkg, file := range c.FactMap {
- data, err := ioutil.ReadFile(file)
- if err != nil {
- return nil, fmt.Errorf("error loading %q: %w", file, err)
- }
- allFacts[pkg] = data
- }
- return func(path string) ([]byte, error) {
- return allFacts[path], nil
- }, nil
-}
-
-// shouldInclude indicates whether the file should be included.
-//
-// NOTE: This does only basic parsing of tags.
-func (c *packageConfig) shouldInclude(path string) (bool, error) {
- ctx := build.Default
- ctx.GOOS = c.GOOS
- ctx.GOARCH = c.GOARCH
- ctx.BuildTags = c.Tags
- return ctx.MatchFile(filepath.Dir(path), filepath.Base(path))
-}
-
-// importer is an implementation of go/types.Importer.
-//
-// This wraps a configuration, which provides the map of package names to
-// files, and the facts. Note that this importer implementation will always
-// pass when a given package is not available.
-type importer struct {
- *packageConfig
- fset *token.FileSet
- cache map[string]*types.Package
- lastErr error
- callback func(string) error
-}
-
-// Import implements types.Importer.Import.
-func (i *importer) Import(path string) (*types.Package, error) {
- if path == "unsafe" {
- // Special case: go/types has pre-defined type information for
- // unsafe. We ensure that this package is correct, in case any
- // analyzers are specifically looking for this.
- return types.Unsafe, nil
- }
-
- // Call the internal callback. This is used to resolve loading order
- // for the standard library. See checkStdlib.
- if i.callback != nil {
- if err := i.callback(path); err != nil {
- i.lastErr = err
- return nil, err
- }
- }
-
- // Actually load the data.
- realPath, ok := i.ImportMap[path]
- var (
- rc io.ReadCloser
- err error
- )
- if !ok {
- // Not found in the import path. Attempt to find the package
- // via the standard library.
- rc, err = findStdPkg(i.GOOS, i.GOARCH, path)
- } else {
- // Open the file.
- rc, err = os.Open(realPath)
- }
- if err != nil {
- i.lastErr = err
- return nil, err
- }
- defer rc.Close()
-
- // Load all exported data.
- r, err := gcexportdata.NewReader(rc)
- if err != nil {
- return nil, err
- }
-
- return gcexportdata.Read(r, i.fset, i.cache, path)
-}
-
-// ErrSkip indicates the package should be skipped.
-var ErrSkip = errors.New("skipped")
-
-// checkStdlib checks the standard library.
-//
-// This constructs a synthetic package configuration for each library in the
-// standard library sources, and call checkPackage repeatedly.
-//
-// Note that not all parts of the source are expected to build. We skip obvious
-// test files, and cmd files, which should not be dependencies.
-func checkStdlib(config *stdlibConfig, ac map[*analysis.Analyzer]matcher) ([]string, []byte, error) {
- if len(config.Srcs) == 0 {
- return nil, nil, nil
- }
-
- // Ensure all paths are normalized.
- for i := 0; i < len(config.Srcs); i++ {
- config.Srcs[i] = path.Clean(config.Srcs[i])
- }
-
- // Calculate the root source directory. This is always a directory
- // named 'src', of which we simply take the first we find. This is a
- // bit fragile, but works for all currently known Go source
- // configurations.
- //
- // Note that there may be extra files outside of the root source
- // directory; we simply ignore those.
- rootSrcPrefix := ""
- for _, file := range config.Srcs {
- const src = "/src/"
- i := strings.Index(file, src)
- if i == -1 {
- // Superfluous file.
- continue
- }
-
- // Index of first character after /src/.
- i += len(src)
- rootSrcPrefix = file[:i]
- break
- }
-
- // Aggregate all files by directory.
- packages := make(map[string]*packageConfig)
- for _, file := range config.Srcs {
- if !strings.HasPrefix(file, rootSrcPrefix) {
- // Superflouous file.
- continue
- }
-
- d := path.Dir(file)
- if len(rootSrcPrefix) >= len(d) {
- continue // Not a file.
- }
- pkg := d[len(rootSrcPrefix):]
- // Skip cmd packages and obvious test files: see above.
- if strings.HasPrefix(pkg, "cmd/") || strings.HasSuffix(file, "_test.go") {
- continue
- }
- c, ok := packages[pkg]
- if !ok {
- c = &packageConfig{
- ImportPath: pkg,
- GOOS: config.GOOS,
- GOARCH: config.GOARCH,
- Tags: config.Tags,
- }
- packages[pkg] = c
- }
- // Add the files appropriately. Note that they will be further
- // filtered by architecture and build tags below, so this need
- // not be done immediately.
- if strings.HasSuffix(file, ".go") {
- c.GoFiles = append(c.GoFiles, file)
- } else {
- c.NonGoFiles = append(c.NonGoFiles, file)
- }
- }
-
- // Closure to check a single package.
- allFindings := make([]string, 0)
- stdlibFacts := make(map[string][]byte)
- stdlibErrs := make(map[string]error)
- var checkOne func(pkg string) error // Recursive.
- checkOne = func(pkg string) error {
- // Is this already done?
- if _, ok := stdlibFacts[pkg]; ok {
- return nil
- }
- // Did this fail previously?
- if _, ok := stdlibErrs[pkg]; ok {
- return nil
- }
-
- // Lookup the configuration.
- config, ok := packages[pkg]
- if !ok {
- return nil // Not known.
- }
-
- // Find the binary package, and provide to objdump.
- rc, err := findStdPkg(config.GOOS, config.GOARCH, pkg)
- if err != nil {
- // If there's no binary for this package, it is likely
- // not built with the distribution. That's fine, we can
- // just skip analysis.
- stdlibErrs[pkg] = err
- return nil
- }
-
- // Provide the input.
- oldReader := checkescape.Reader
- checkescape.Reader = rc // For analysis.
- defer func() {
- rc.Close()
- checkescape.Reader = oldReader // Restore.
- }()
-
- // Run the analysis.
- findings, factData, err := checkPackage(config, ac, checkOne)
- if err != nil {
- // If we can't analyze a package from the standard library,
- // then we skip it. It will simply not have any findings.
- stdlibErrs[pkg] = err
- return nil
- }
- stdlibFacts[pkg] = factData
- allFindings = append(allFindings, findings...)
- return nil
- }
-
- // Check all packages.
- //
- // Note that this may call checkOne recursively, so it's not guaranteed
- // to evaluate in the order provided here. We do ensure however, that
- // all packages are evaluated.
- for pkg := range packages {
- if err := checkOne(pkg); err != nil {
- return nil, nil, err
- }
- }
-
- // Sanity check.
- if len(stdlibFacts) == 0 {
- return nil, nil, fmt.Errorf("no stdlib facts found: misconfiguration?")
- }
-
- // Write out all findings.
- factData, err := json.Marshal(stdlibFacts)
- if err != nil {
- return nil, nil, fmt.Errorf("error saving stdlib facts: %w", err)
- }
-
- // Write out all errors.
- for pkg, err := range stdlibErrs {
- log.Printf("WARNING: error while processing %v: %v", pkg, err)
- }
-
- // Return all findings.
- return allFindings, factData, nil
-}
-
-// checkPackage runs all analyzers.
-//
-// The implementation was adapted from [1], which was in turn adpated from [2].
-// This returns a list of matching analysis issues, or an error if the analysis
-// could not be completed.
-//
-// [1] bazelbuid/rules_go/tools/builders/nogo_main.go
-// [2] golang.org/x/tools/go/checker/internal/checker
-func checkPackage(config *packageConfig, ac map[*analysis.Analyzer]matcher, importCallback func(string) error) ([]string, []byte, error) {
- imp := &importer{
- packageConfig: config,
- fset: token.NewFileSet(),
- cache: make(map[string]*types.Package),
- callback: importCallback,
- }
-
- // Load all source files.
- var syntax []*ast.File
- for _, file := range config.GoFiles {
- include, err := config.shouldInclude(file)
- if err != nil {
- return nil, nil, fmt.Errorf("error evaluating file %q: %v", file, err)
- }
- if !include {
- continue
- }
- s, err := parser.ParseFile(imp.fset, file, nil, parser.ParseComments)
- if err != nil {
- return nil, nil, fmt.Errorf("error parsing file %q: %v", file, err)
- }
- syntax = append(syntax, s)
- }
-
- // Check type information.
- typesSizes := types.SizesFor("gc", config.GOARCH)
- typeConfig := types.Config{Importer: imp}
- typesInfo := &types.Info{
- Types: make(map[ast.Expr]types.TypeAndValue),
- Uses: make(map[*ast.Ident]types.Object),
- Defs: make(map[*ast.Ident]types.Object),
- Implicits: make(map[ast.Node]types.Object),
- Scopes: make(map[ast.Node]*types.Scope),
- Selections: make(map[*ast.SelectorExpr]*types.Selection),
- }
- types, err := typeConfig.Check(config.ImportPath, imp.fset, syntax, typesInfo)
- if err != nil && imp.lastErr != ErrSkip {
- return nil, nil, fmt.Errorf("error checking types: %w", err)
- }
-
- // Load all package facts.
- loader, err := config.factLoader()
- if err != nil {
- return nil, nil, fmt.Errorf("error loading facts: %w", err)
- }
- facts, err := facts.Decode(types, loader)
- if err != nil {
- return nil, nil, fmt.Errorf("error decoding facts: %w", err)
- }
-
- // Register fact types and establish dependencies between analyzers.
- // The visit closure will execute recursively, and populate results
- // will all required analysis results.
- diagnostics := make(map[*analysis.Analyzer][]analysis.Diagnostic)
- results := make(map[*analysis.Analyzer]interface{})
- var visit func(*analysis.Analyzer) error // For recursion.
- visit = func(a *analysis.Analyzer) error {
- if _, ok := results[a]; ok {
- return nil
- }
-
- // Run recursively for all dependencies.
- for _, req := range a.Requires {
- if err := visit(req); err != nil {
- return err
- }
- }
-
- // Prepare the matcher.
- m := ac[a]
- report := func(d analysis.Diagnostic) {
- if m.ShouldReport(d, imp.fset) {
- diagnostics[a] = append(diagnostics[a], d)
- }
- }
-
- // Run the analysis.
- factFilter := make(map[reflect.Type]bool)
- for _, f := range a.FactTypes {
- factFilter[reflect.TypeOf(f)] = true
- }
- p := &analysis.Pass{
- Analyzer: a,
- Fset: imp.fset,
- Files: syntax,
- Pkg: types,
- TypesInfo: typesInfo,
- ResultOf: results, // All results.
- Report: report,
- ImportPackageFact: facts.ImportPackageFact,
- ExportPackageFact: facts.ExportPackageFact,
- ImportObjectFact: facts.ImportObjectFact,
- ExportObjectFact: facts.ExportObjectFact,
- AllPackageFacts: func() []analysis.PackageFact { return facts.AllPackageFacts(factFilter) },
- AllObjectFacts: func() []analysis.ObjectFact { return facts.AllObjectFacts(factFilter) },
- TypesSizes: typesSizes,
- }
- result, err := a.Run(p)
- if err != nil {
- return fmt.Errorf("error running analysis %s: %v", a, err)
- }
-
- // Sanity check & save the result.
- if got, want := reflect.TypeOf(result), a.ResultType; got != want {
- return fmt.Errorf("error: analyzer %s returned a result of type %v, but declared ResultType %v", a, got, want)
- }
- results[a] = result
- return nil // Success.
- }
-
- // Visit all analyzers recursively.
- for a, _ := range ac {
- if imp.lastErr == ErrSkip {
- continue // No local analysis.
- }
- if err := visit(a); err != nil {
- return nil, nil, err // Already has context.
- }
- }
-
- // Convert all diagnostics to strings.
- findings := make([]string, 0, len(diagnostics))
- for a, ds := range diagnostics {
- for _, d := range ds {
- // Include the anlyzer name for debugability and configuration.
- findings = append(findings, fmt.Sprintf("%s: %s: %s", a.Name, imp.fset.Position(d.Pos), d.Message))
- }
- }
-
- // Return all findings.
- factData := facts.Encode()
- return findings, factData, nil
-}
-
-var (
- packageFile = flag.String("package", "", "package configuration file (in JSON format)")
- stdlibFile = flag.String("stdlib", "", "stdlib configuration file (in JSON format)")
- findingsOutput = flag.String("findings", "", "output file (or stdout, if not specified)")
- factsOutput = flag.String("facts", "", "output file for facts (optional)")
- escapesOutput = flag.String("escapes", "", "output file for escapes (optional)")
-)
-
-func loadConfig(file string, config interface{}) interface{} {
- // Load the configuration.
- f, err := os.Open(file)
- if err != nil {
- log.Fatalf("unable to open configuration %q: %v", file, err)
- }
- defer f.Close()
- dec := json.NewDecoder(f)
- dec.DisallowUnknownFields()
- if err := dec.Decode(config); err != nil {
- log.Fatalf("unable to decode configuration: %v", err)
- }
- return config
-}
-
-// Main is the entrypoint; it should be called directly from main.
-//
-// N.B. This package registers it's own flags.
-func Main() {
- // Parse all flags.
- flag.Parse()
-
- var (
- findings []string
- factData []byte
- err error
- )
-
- // Check the configuration.
- if *packageFile != "" && *stdlibFile != "" {
- log.Fatalf("unable to perform stdlib and package analysis; provide only one!")
- } else if *stdlibFile != "" {
- // Perform basic analysis.
- c := loadConfig(*stdlibFile, new(stdlibConfig)).(*stdlibConfig)
- findings, factData, err = checkStdlib(c, analyzerConfig)
- } else if *packageFile != "" {
- // Perform basic analysis.
- c := loadConfig(*packageFile, new(packageConfig)).(*packageConfig)
- findings, factData, err = checkPackage(c, analyzerConfig, nil)
- // Do we need to do escape analysis?
- if *escapesOutput != "" {
- f, err := os.OpenFile(*escapesOutput, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
- if err != nil {
- log.Fatalf("unable to open output %q: %v", *escapesOutput, err)
- }
- defer f.Close()
- escapes, _, err := checkPackage(c, escapesConfig, nil)
- if err != nil {
- log.Fatalf("error performing escape analysis: %v", err)
- }
- for _, escape := range escapes {
- fmt.Fprintf(f, "%s\n", escape)
- }
- }
- } else {
- log.Fatalf("please provide at least one of package or stdlib!")
- }
-
- // Save facts.
- if *factsOutput != "" {
- if err := ioutil.WriteFile(*factsOutput, factData, 0644); err != nil {
- log.Fatalf("error saving findings to %q: %v", *factsOutput, err)
- }
- }
-
- // Open the output file.
- var w io.Writer = os.Stdout
- if *findingsOutput != "" {
- f, err := os.OpenFile(*findingsOutput, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
- if err != nil {
- log.Fatalf("unable to open output %q: %v", *findingsOutput, err)
- }
- defer f.Close()
- w = f
- }
-
- // Handle findings & errors.
- if err != nil {
- log.Fatalf("error checking package: %v", err)
- }
- if len(findings) == 0 {
- return
- }
-
- // Print findings.
- for _, finding := range findings {
- fmt.Fprintf(w, "%s\n", finding)
- }
-}
diff --git a/tools/nogo/register.go b/tools/nogo/register.go
deleted file mode 100644
index 34b173937..000000000
--- a/tools/nogo/register.go
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2019 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package nogo
-
-import (
- "encoding/gob"
- "log"
-
- "golang.org/x/tools/go/analysis"
-)
-
-// analyzers returns all configured analyzers.
-func analyzers() (all []*analysis.Analyzer) {
- for a, _ := range analyzerConfig {
- all = append(all, a)
- }
- for a, _ := range escapesConfig {
- all = append(all, a)
- }
- return all
-}
-
-func init() {
- // Validate basic configuration.
- if err := analysis.Validate(analyzers()); err != nil {
- log.Fatalf("unable to validate analyzer: %v", err)
- }
-
- // Register all fact types.
- //
- // N.B. This needs to be done recursively, because there may be
- // analyzers in the Requires list that do not appear explicitly above.
- registered := make(map[*analysis.Analyzer]struct{})
- var register func(*analysis.Analyzer)
- register = func(a *analysis.Analyzer) {
- if _, ok := registered[a]; ok {
- return
- }
-
- // Regsiter dependencies.
- for _, da := range a.Requires {
- register(da)
- }
-
- // Register local facts.
- for _, f := range a.FactTypes {
- gob.Register(f)
- }
-
- registered[a] = struct{}{} // Done.
- }
- for _, a := range analyzers() {
- register(a)
- }
-}
diff --git a/tools/nogo/util/BUILD b/tools/nogo/util/BUILD
deleted file mode 100644
index 7ab340b51..000000000
--- a/tools/nogo/util/BUILD
+++ /dev/null
@@ -1,9 +0,0 @@
-load("//tools:defs.bzl", "go_library")
-
-package(licenses = ["notice"])
-
-go_library(
- name = "util",
- srcs = ["util.go"],
- visibility = ["//visibility:public"],
-)
diff --git a/tools/nogo/util/util.go b/tools/nogo/util/util.go
deleted file mode 100644
index 919fec799..000000000
--- a/tools/nogo/util/util.go
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright 2019 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Package util contains nogo-related utilities.
-package util
-
-import (
- "fmt"
- "io/ioutil"
- "regexp"
- "strconv"
- "strings"
-)
-
-// findingRegexp is used to parse findings.
-var findingRegexp = regexp.MustCompile(`([a-zA-Z0-9_\/\.-]+): (-|([a-zA-Z0-9_\/\.-]+):([0-9]+)(:([0-9]+))?): (.*)`)
-
-const (
- categoryIndex = 1
- fullPathAndLineIndex = 2
- fullPathIndex = 3
- lineIndex = 4
- messageIndex = 7
-)
-
-// Finding is a single finding.
-type Finding struct {
- Category string
- Path string
- Line int
- Message string
-}
-
-// ExtractFindingsFromFile loads findings from a file.
-func ExtractFindingsFromFile(filename string) ([]Finding, error) {
- content, err := ioutil.ReadFile(filename)
- if err != nil {
- return nil, err
- }
- return ExtractFindingsFromBytes(content)
-}
-
-// ExtractFindingsFromBytes loads findings from bytes.
-func ExtractFindingsFromBytes(content []byte) (findings []Finding, err error) {
- lines := strings.Split(string(content), "\n")
- for _, singleLine := range lines {
- // Skip blank lines.
- singleLine = strings.TrimSpace(singleLine)
- if singleLine == "" {
- continue
- }
- m := findingRegexp.FindStringSubmatch(singleLine)
- if m == nil {
- // We shouldn't see findings like this.
- return findings, fmt.Errorf("poorly formated line: %v", singleLine)
- }
- if m[fullPathAndLineIndex] == "-" {
- continue // No source file available.
- }
- // Cleanup the message.
- message := m[messageIndex]
- message = strings.Replace(message, " → ", "\n → ", -1)
- message = strings.Replace(message, " or ", "\n or ", -1)
- // Construct a new annotation.
- lineNumber, _ := strconv.ParseUint(m[lineIndex], 10, 32)
- findings = append(findings, Finding{
- Category: m[categoryIndex],
- Path: m[fullPathIndex],
- Line: int(lineNumber),
- Message: message,
- })
- }
- return findings, nil
-}