summaryrefslogtreecommitdiffhomepage
path: root/tools/nogo
diff options
context:
space:
mode:
Diffstat (limited to 'tools/nogo')
-rw-r--r--tools/nogo/BUILD14
-rw-r--r--tools/nogo/build.go6
-rw-r--r--tools/nogo/config.go428
-rw-r--r--tools/nogo/defs.bzl77
-rwxr-xr-xtools/nogo/gentest.sh47
-rw-r--r--tools/nogo/matchers.go47
-rw-r--r--tools/nogo/util/BUILD9
-rw-r--r--tools/nogo/util/util.go85
8 files changed, 656 insertions, 57 deletions
diff --git a/tools/nogo/BUILD b/tools/nogo/BUILD
index 9f1fcd9c7..dd4b46f58 100644
--- a/tools/nogo/BUILD
+++ b/tools/nogo/BUILD
@@ -1,10 +1,10 @@
load("//tools:defs.bzl", "bzl_library", "go_library")
-load("//tools/nogo:defs.bzl", "nogo_dump_tool", "nogo_stdlib")
+load("//tools/nogo:defs.bzl", "nogo_objdump_tool", "nogo_stdlib")
package(licenses = ["notice"])
-nogo_dump_tool(
- name = "dump_tool",
+nogo_objdump_tool(
+ name = "objdump_tool",
visibility = ["//visibility:public"],
)
@@ -13,6 +13,12 @@ nogo_stdlib(
visibility = ["//visibility:public"],
)
+sh_binary(
+ name = "gentest",
+ srcs = ["gentest.sh"],
+ visibility = ["//visibility:public"],
+)
+
go_library(
name = "nogo",
srcs = [
@@ -27,6 +33,8 @@ go_library(
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",
diff --git a/tools/nogo/build.go b/tools/nogo/build.go
index 37947b5c3..55d34760f 100644
--- a/tools/nogo/build.go
+++ b/tools/nogo/build.go
@@ -26,6 +26,12 @@ var (
// 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/"
)
diff --git a/tools/nogo/config.go b/tools/nogo/config.go
index cfe7b4aa4..8079618ab 100644
--- a/tools/nogo/config.go
+++ b/tools/nogo/config.go
@@ -41,6 +41,8 @@ import (
"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"
@@ -123,6 +125,432 @@ var analyzerConfig = map[*analysis.Analyzer]matcher{
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/refs_vfs2/refs.go:16",
+ "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_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/tcpip/adapters/gonet/gonet_test.go:144",
+ "pkg/tcpip/adapters/gonet/gonet_test.go:415",
+ "pkg/tcpip/adapters/gonet/gonet_test.go:99",
+ "pkg/tcpip/buffer/view.go:238",
+ "pkg/tcpip/buffer/view.go:238",
+ "pkg/tcpip/buffer/view.go:246",
+ "pkg/tcpip/header/tcp.go:151",
+ "pkg/tcpip/link/sharedmem/pipe/pipe_test.go:493",
+ "pkg/tcpip/stack/iptables.go:293",
+ "pkg/tcpip/stack/iptables_types.go:277",
+ "pkg/tcpip/stack/stack.go:553",
+ "pkg/tcpip/stack/transport_test.go:30",
+ "pkg/tcpip/transport/packet/endpoint.go:126",
+ "pkg/tcpip/transport/raw/endpoint.go:145",
+ "pkg/tcpip/transport/tcp/sack_scoreboard.go:167",
+ "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
index 480438047..c6fcfd402 100644
--- a/tools/nogo/defs.bzl
+++ b/tools/nogo/defs.bzl
@@ -2,8 +2,7 @@
load("//tools/bazeldefs:defs.bzl", "go_context", "go_importpath", "go_rule", "go_test_library")
-def _nogo_dump_tool_impl(ctx):
- # Extract the Go context.
+def _nogo_objdump_tool_impl(ctx):
go_ctx = go_context(ctx)
# Construct the magic dump command.
@@ -40,9 +39,9 @@ def _nogo_dump_tool_impl(ctx):
executable = dumper,
)]
-nogo_dump_tool = go_rule(
+nogo_objdump_tool = go_rule(
rule,
- implementation = _nogo_dump_tool_impl,
+ implementation = _nogo_objdump_tool_impl,
)
# NogoStdlibInfo is the set of standard library facts.
@@ -55,7 +54,6 @@ NogoStdlibInfo = provider(
)
def _nogo_stdlib_impl(ctx):
- # Extract the Go context.
go_ctx = go_context(ctx)
# Build the standard library facts.
@@ -72,12 +70,12 @@ def _nogo_stdlib_impl(ctx):
ctx.actions.run(
inputs = [config_file] + go_ctx.stdlib_srcs,
outputs = [facts, findings],
- tools = depset(go_ctx.runfiles.to_list() + ctx.files._dump_tool),
+ tools = depset(go_ctx.runfiles.to_list() + ctx.files._objdump_tool),
executable = ctx.files._nogo[0],
mnemonic = "GoStandardLibraryAnalysis",
progress_message = "Analyzing Go Standard Library",
arguments = go_ctx.nogo_args + [
- "-dump_tool=%s" % ctx.files._dump_tool[0].path,
+ "-objdump_tool=%s" % ctx.files._objdump_tool[0].path,
"-stdlib=%s" % config_file.path,
"-findings=%s" % findings.path,
"-facts=%s" % facts.path,
@@ -97,8 +95,8 @@ nogo_stdlib = go_rule(
"_nogo": attr.label(
default = "//tools/nogo/check:check",
),
- "_dump_tool": attr.label(
- default = "//tools/nogo:dump_tool",
+ "_objdump_tool": attr.label(
+ default = "//tools/nogo:objdump_tool",
),
},
)
@@ -121,6 +119,8 @@ NogoInfo = provider(
)
def _nogo_aspect_impl(target, ctx):
+ go_ctx = go_context(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
@@ -135,9 +135,6 @@ def _nogo_aspect_impl(target, ctx):
else:
return [NogoInfo()]
- # Extract the Go context.
- go_ctx = go_context(ctx)
-
# 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.
@@ -227,13 +224,13 @@ def _nogo_aspect_impl(target, ctx):
ctx.actions.run(
inputs = inputs,
outputs = [facts, findings, escapes],
- tools = depset(go_ctx.runfiles.to_list() + ctx.files._dump_tool),
+ tools = depset(go_ctx.runfiles.to_list() + ctx.files._objdump_tool),
executable = ctx.files._nogo[0],
mnemonic = "GoStaticAnalysis",
progress_message = "Analyzing %s" % target.label,
arguments = go_ctx.nogo_args + [
"-binary=%s" % target_objfile.path,
- "-dump_tool=%s" % ctx.files._dump_tool[0].path,
+ "-objdump_tool=%s" % ctx.files._objdump_tool[0].path,
"-package=%s" % config_file.path,
"-findings=%s" % findings.path,
"-facts=%s" % facts.path,
@@ -271,58 +268,48 @@ nogo_aspect = go_rule(
attrs = {
"_nogo": attr.label(default = "//tools/nogo/check:check"),
"_nogo_stdlib": attr.label(default = "//tools/nogo:stdlib"),
- "_dump_tool": attr.label(default = "//tools/nogo:dump_tool"),
+ "_objdump_tool": attr.label(default = "//tools/nogo:objdump_tool"),
},
)
def _nogo_test_impl(ctx):
"""Check nogo findings."""
- # Build a runner that checks for the existence of the facts file. Note that
- # the actual build will fail in the case of a broken analysis. We things
- # this way so that any test applied is effectively pushed down to all
- # upstream dependencies through the aspect.
- inputs = []
- findings = []
- runner = ctx.actions.declare_file("%s-executer" % ctx.label.name)
- runner_content = ["#!/bin/bash"]
- for dep in ctx.attr.deps:
- # Extract the findings.
- info = dep[NogoInfo]
- inputs.append(info.findings)
- findings.append(info.findings)
-
- # Include all source files, transitively. This will make this target
- # "directly affected" for the purpose of build analysis.
- inputs += info.srcs
-
- # If there are findings, dump them and fail.
- runner_content.append("if [[ -s \"%s\" ]]; then cat \"%s\" && exit 1; fi" % (
- info.findings.short_path,
- info.findings.short_path,
- ))
-
- # Otherwise, draw a sweet unicode checkmark with the package name (in green).
- runner_content.append("echo -e \"\\033[0;32m\\xE2\\x9C\\x94\\033[0;31m\\033[0m %s\"" % info.importpath)
- runner_content.append("exit 0\n")
- ctx.actions.write(runner, "\n".join(runner_content), is_executable = True)
+ # 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(
- runfiles = ctx.runfiles(files = inputs),
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, **kwargs):
+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
new file mode 100755
index 000000000..033da11ad
--- /dev/null
+++ b/tools/nogo/gentest.sh
@@ -0,0 +1,47 @@
+#!/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
+ 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
index 57a250501..b7b73fa27 100644
--- a/tools/nogo/matchers.go
+++ b/tools/nogo/matchers.go
@@ -16,7 +16,6 @@ package nogo
import (
"go/token"
- "path/filepath"
"regexp"
"strings"
@@ -44,11 +43,30 @@ type pathRegexps struct {
func buildRegexps(prefix string, args ...string) []*regexp.Regexp {
result := make([]*regexp.Regexp, 0, len(args))
for _, arg := range args {
- result = append(result, regexp.MustCompile(filepath.Join(prefix, arg)))
+ 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()
@@ -79,11 +97,19 @@ func externalExcluded(paths ...string) *pathRegexps {
// internalMatches returns a path matcher for internal packages.
func internalMatches() *pathRegexps {
return &pathRegexps{
- expr: buildRegexps(internalPrefix, ".*"),
+ 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
@@ -99,20 +125,23 @@ func (r resultExcluded) ShouldReport(d analysis.Diagnostic, _ *token.FileSet) bo
// andMatcher is a composite matcher.
type andMatcher struct {
- first matcher
- second matcher
+ all []matcher
}
// ShouldReport implements matcher.ShouldReport.
func (a *andMatcher) ShouldReport(d analysis.Diagnostic, fs *token.FileSet) bool {
- return a.first.ShouldReport(d, fs) && a.second.ShouldReport(d, fs)
+ for _, m := range a.all {
+ if !m.ShouldReport(d, fs) {
+ return false
+ }
+ }
+ return true
}
// and is a syntactic convension for andMatcher.
-func and(first matcher, second matcher) *andMatcher {
+func and(ms ...matcher) *andMatcher {
return &andMatcher{
- first: first,
- second: second,
+ all: ms,
}
}
diff --git a/tools/nogo/util/BUILD b/tools/nogo/util/BUILD
new file mode 100644
index 000000000..7ab340b51
--- /dev/null
+++ b/tools/nogo/util/BUILD
@@ -0,0 +1,9 @@
+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
new file mode 100644
index 000000000..919fec799
--- /dev/null
+++ b/tools/nogo/util/util.go
@@ -0,0 +1,85 @@
+// 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
+}