diff options
Diffstat (limited to 'tools/nogo')
-rw-r--r-- | tools/nogo/BUILD | 80 | ||||
-rw-r--r-- | tools/nogo/README.md | 31 | ||||
-rw-r--r-- | tools/nogo/build.go | 46 | ||||
-rw-r--r-- | tools/nogo/check/BUILD | 13 | ||||
-rw-r--r-- | tools/nogo/check/main.go | 24 | ||||
-rw-r--r-- | tools/nogo/config.go | 543 | ||||
-rw-r--r-- | tools/nogo/defs.bzl | 367 | ||||
-rwxr-xr-x | tools/nogo/gentest.sh | 48 | ||||
-rw-r--r-- | tools/nogo/matchers.go | 172 | ||||
-rw-r--r-- | tools/nogo/nogo.go | 586 | ||||
-rw-r--r-- | tools/nogo/register.go | 67 | ||||
-rw-r--r-- | tools/nogo/util/BUILD | 9 | ||||
-rw-r--r-- | tools/nogo/util/util.go | 85 |
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 -} |