Open MikkelHJuul opened 3 years ago
I am not associated with the GCatch project. I just want to let the team know that I'm actually excited you've been engaging with us at all here in GitHub and I am excited to work with you to get this engineered up to where it can be used by "real people". I often am saddened when academia produces nifty, useful things that are then essentially abandoned because they can't be used. (I'm sure there's another paper to be written about "2 Years of GCatch Use in the Wild", if you get my drift. :) )
I'm sure the reason why they're using GOPATH is that this project has been in progress since before Go modules were officially the way to go.
GCatch team, I've been somewhat interested in digging in and turning this into a conventional and standard Go project, using current go modules, but one thing thing that I've been unsure about is the forks that @MikkelHJuul talks about here. Can you give us an idea about whether or not you've actually made significant changes to these included libraries, or whether or not these are essentially just "vendored" with no changes? If you can answer that, that will give us a lot more confidence to create PRs to bring these programs up to go module spec and resolve the issues @MikkelHJuul is pointing out here.
@thejerf The code under the directory tools IS modified. I think it is hard and unnecessary to update them.
Thx. @MikkelHJuul I've just created a to-do list so that we can handle them one by one.
- [ ] Scan go.mod instead of relying on GOPATH (Hard)
There must be other tools out there that does this? Or focus on the go.sum in stead
#!/bin/bash
while read -r line; do
GCatch -repo $line > report/$line
done < go.sum
There is a reason why other tools don't Scan dependencies like GCatch does
bash can do so much of the work for us
Then you can focus on making a great tool and not bugfixing your dependencies.
@thejerf It is not trivial to migrate GCatch from GOPATH to go.mod
When I typed the command "go mod init && go mod tidy" under "GCatch/GCatch", I found that "cmd/guru/serial" and "imports" do not exist under "GCatch/GCatch/tools".
GCatch/tools/internal/lsp/cmd/definition.go:15
guru "github.com/system-pclub/GCatch/GCatch/tools/cmd/guru/serial"
GCatch/tools/internal/lsp/source/format.go:16
"github.com/system-pclub/GCatch/GCatch/tools/imports"
@lzhfromustc They seem harmless when building with GOPATH but buggy for go.mod
Even after I added the missing source code from "golang/tools" and successfully built&installed GCatch using go.mod (https://github.com/BurtonQin/GCatch/tree/build-with-go-mod), GCatch still reported many building errors when scanning the demo buggy grpc without turning off GO111MODULE
I reckon the underlying analysis framework of GCatch is too old to support go module. Even if I can make GCatch BUILD with go module, it still requires a lot of work to make GCatch WORK on projects with go module on. So Task 4 is not just a job of shells. @MikkelHJuul For Task 5, we can use "-r" to toggle the CHECKING of dependencies. But dependencies are still compiled since the framework requires a whole program SSA. https://github.com/system-pclub/GCatch/blob/01c0e0281d7042d27d43e2bbdb5e63f8360b3cdc/GCatch/cmd/GCatch/main.go#L144
That is super sad! :( I find this project to be wonderful and the paper is insightful. I would like to see this tool incorporated as a linter into everything I touch.
Is there any way I could assist?
I wasn't expecting it to be trivial to migrate to go modules. I was expecting it to be the sort of thing software engineers can plow through without having to understand the underlying code per se. I expected both problems building it, and that the underlying code that gets the source code for processing will hae to be changed too. It's a perfect sort of engineering/academic partnership project.
Hi all.
Has there been any progress on this? I'm struggling to run even the provided example:
carlos@LAPTOP-K6R30EOS:~/go/src/github.com/system-pclub/GCatch/GCatch$ ./run.sh
Make sure you have run installZ3.sh and then install.sh
Step 1: setting GOPATH of the checked grpc
GOPATH is set to /home/carlos/go/src/github.com/system-pclub/GCatch/GCatch/testdata/grpc-buggy
Description of flags of GCatch:
Required Flag: -path=Full path of the application to be checked
Required Flag: -include=Relative path (what's after /src/) of the application to be checked
Required Flag: -checker=The checkers you want to run, divided by ":". Default value:BMOC
Optional Flag: -r Whether all children packages should also be checked recursively
Optional Flag: -compile-error Whether compilation errors should be printed, if there are any
Optional Flag: -vendor=Packages that will be ignored, divided by ":". Default value:vendor
Step 2: running GCatch on a buggy version of grpc in testdata
Note: all bugs reported below should be real BMOC bugs
GO111MODULE=off /home/carlos/go/bin/GCatch -path=/home/carlos/go/src/github.com/system-pclub/GCatch/GCatch/testdata/grpc-buggy/src/google.golang.org/grpc -include=google.golang.org/grpc -checker=BMOC -r
panic: no concrete method: func (*sync/atomic.Pointer[string]).CompareAndSwap(old *string, new *string) (swapped bool)
goroutine 3142 [running]:
github.com/system-pclub/GCatch/GCatch/tools/go/ssa.(*Program).declaredFunc(0xc00f42d680, 0xc0142d3a40)
/home/carlos/go/src/github.com/system-pclub/GCatch/GCatch/tools/go/ssa/methods.go:124 +0xf9
github.com/system-pclub/GCatch/GCatch/tools/go/ssa.(*Program).addMethod(0x7d4bf8?, 0xc0103173c0, 0xc0142d1950)
/home/carlos/go/src/github.com/system-pclub/GCatch/GCatch/tools/go/ssa/methods.go:86 +0x156
github.com/system-pclub/GCatch/GCatch/tools/go/ssa.(*Program).needMethods(0xc00f42d680, {0x7d4bf8?, 0xc001681930?}, 0x0)
/home/carlos/go/src/github.com/system-pclub/GCatch/GCatch/tools/go/ssa/methods.go:173 +0x645
github.com/system-pclub/GCatch/GCatch/tools/go/ssa.(*Program).needMethods(0xc00f42d680, {0x7d4c70?, 0xc0024aae10?}, 0x1)
/home/carlos/go/src/github.com/system-pclub/GCatch/GCatch/tools/go/ssa/methods.go:228 +0x55e
github.com/system-pclub/GCatch/GCatch/tools/go/ssa.(*Program).needMethods(0xc00f42d680, {0x7d4bd0?, 0xc0009a8c40?}, 0x0)
/home/carlos/go/src/github.com/system-pclub/GCatch/GCatch/tools/go/ssa/methods.go:221 +0x40c
github.com/system-pclub/GCatch/GCatch/tools/go/ssa.(*Program).needMethodsOf(0xc00f42d680, {0x7d4bd0?, 0xc0009a8c40?})
/home/carlos/go/src/github.com/system-pclub/GCatch/GCatch/tools/go/ssa/methods.go:145 +0x70
github.com/system-pclub/GCatch/GCatch/tools/go/ssa.(*Package).build(0xc00fcd1380)
/home/carlos/go/src/github.com/system-pclub/GCatch/GCatch/tools/go/ssa/builder.go:2281 +0x111
sync.(*Once).doSlow(0xc000297fb8?, 0x654b5e?)
/usr/local/go/src/sync/once.go:74 +0xc2
sync.(*Once).Do(...)
/usr/local/go/src/sync/once.go:65
github.com/system-pclub/GCatch/GCatch/tools/go/ssa.(*Package).Build(...)
/home/carlos/go/src/github.com/system-pclub/GCatch/GCatch/tools/go/ssa/builder.go:2269
github.com/system-pclub/GCatch/GCatch/tools/go/ssa.(*Program).Build.func1(0x0?)
/home/carlos/go/src/github.com/system-pclub/GCatch/GCatch/tools/go/ssa/builder.go:2253 +0x4c
created by github.com/system-pclub/GCatch/GCatch/tools/go/ssa.(*Program).Build
/home/carlos/go/src/github.com/system-pclub/GCatch/GCatch/tools/go/ssa/builder.go:2252 +0x19c
As well as the beta functionality:
carlos@LAPTOP-K6R30EOS:~$ GCatch -mod -mod-abs-path /playground/kubernetes -mod-module-path k8s.io/kube
rnetes/staging/src/k8s.io/apimachinery/pkg/util/wait -compile-error
-: cannot query module due to -mod=vendor
(Go version in go.mod is at least 1.14 and vendor directory exists.)
Failed to build the whole program. The entrance package or its dependencies have error. type_err
Exit. You are using the -mod flag, which only supports building and checking the specified program (and its dependencies)
Time of main(): seconds 0.535229652
Or building the provided Dockerfile
:
carlos@LAPTOP-K6R30EOS:~/go/src/github.com/system-pclub/GCatch/GCatch$ docker build - < Dockerfile
[+] Building 1.3s (11/12)
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 524B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/golang:1.16.4 0.9s
=> [1/8] FROM docker.io/library/golang:1.16.4@sha256:8a106c4b4005efb43c0ba4bb5763b84742c7e222b 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 2B 0.0s
=> CACHED [2/8] RUN git clone https://github.com/Z3Prover/z3 /repos/z3 0.0s
=> CACHED [3/8] WORKDIR /repos/z3 0.0s
=> CACHED [4/8] RUN python scripts/mk_make.py && cd build && make && make install 0.0s
=> CACHED [5/8] COPY . /go/src/github.com/system-pclub/GCatch/GCatch 0.0s
=> CACHED [6/8] RUN GO111MODULE=off go get golang.org/x/xerrors && GO111MODULE=off go get gola 0.0s
=> ERROR [7/8] RUN /go/src/github.com/system-pclub/GCatch/GCatch/install.sh 0.4s
------
> [7/8] RUN /go/src/github.com/system-pclub/GCatch/GCatch/install.sh:
#0 0.373 /bin/sh: 1: /go/src/github.com/system-pclub/GCatch/GCatch/install.sh: not found
------
Dockerfile:17
--------------------
15 | && GO111MODULE=off go get golang.org/x/sys/execabs
16 |
17 | >>> RUN /go/src/github.com/system-pclub/GCatch/GCatch/install.sh
18 |
19 | WORKDIR /playground
--------------------
ERROR: failed to solve: process "/bin/sh -c /go/src/github.com/system-pclub/GCatch/GCatch/install.sh" did not complete successfully: exit code: 127
All in all, I'm at a loss as to how to make it work. I would be happy to work on the code to get it to work, but I would need some pointers.
Appreciate any help!
After some tinkering, I have managed to make it work on go.mod
modules, by adding BuildFlags: []string{"-mod=mod"}
to the following line:
https://github.com/system-pclub/GCatch/blob/f0710b464a03c125aa57a1631882c3b331a3b881/GCatch/ssabuild/build.go#L61
Leading to the following output on a sample-like input:
carlos@LAPTOP-K6R30EOS:~$ GCatch -mod -mod-abs-path /playground/kubernetes/staging/src/k8s.io/metrics -mod-module-path k8s.io/metrics -compile-error
Successfully built whole program. Now running checkers
Exit. You are using the -mod flag, which only supports building and checking the specified program (and its dependencies)
Time of main(): seconds 0.289908609
Unfortunately, I have not managed to produce an example where GCatch detects a bug, partly because it seems to fail on any function involving generics, e.g:
carlos@LAPTOP-K6R30EOS:~/goat$ GCatch -mod -mod-abs-path /playground/kubernetes/staging/src/k8s.io/sample-apiserver -mod-module-path k8s.io/sample-apiserver -compile-error
panic: no concrete method: func (*sync/atomic.Pointer[string]).CompareAndSwap(old *string, new *string) (swapped bool)
Indeed, the problem arises here:
https://github.com/system-pclub/GCatch/blob/f0710b464a03c125aa57a1631882c3b331a3b881/GCatch/tools/go/ssa/source.go#L188-L193
The function receives another function obj
, whose Pkg()
is in prog.packages
, but which is not in pkg.values
.
In one example, obj
was func (*sync/atomic.Pointer[any]).CompareAndSwap(old *any, new *any) (swapped bool)
, and pkg.values
contained close relatives, most notably func (*sync/atomic.Pointer[T]).CompareAndSwap(old *T, new *T) (swapped bool)
.
I believe a potential cause for this is the version of the ssa
package used cannot deal with generics, which were introduced later. Will keep looking.
Indeed, migrating to golang.org/x/tools/go/ssa
(and necessarily golang.org/x/tools/go/packages
) solved it. I am now dealing with the following:
Error when building callgraph with nil Queries: internal error in pointer analysis: cannot flatten unsupported type *types.TypeParam (please report this bug)
which is thrown here: https://github.com/system-pclub/GCatch/blob/f0710b464a03c125aa57a1631882c3b331a3b881/GCatch/tools/go/mypointer/util.go#L173
The documentation for the official golang.org/x/tools/go/pointer
package reads:
Type parameters are not directly supported by the analysis. Calls to generic functions will be left as if they had empty bodies. Users of the package are expected to use the ssa.InstantiateGenerics builder mode when building code that uses or depends on code containing generics.
and gives the following example:
prog := ssautil.CreateProgram(iprog, ssa.InstantiateGenerics)
However, I have added ssa.InstantiateGenerics
to both places I have found it is needed, to no avail:
https://github.com/system-pclub/GCatch/blob/f0710b464a03c125aa57a1631882c3b331a3b881/GCatch/ssabuild/build.go#L86
https://github.com/system-pclub/GCatch/blob/f0710b464a03c125aa57a1631882c3b331a3b881/GCatch/tools/go/analysis/passes/buildssa/buildssa.go#L51-L53
I have also looked through all uses of ssa.BuilderMode
and all of its possible values, also to no avail.
Thank you for your interest in the project. The project was built a few years ago, and at that time Go didn't support generics. I appreciate your suggestion and will definitely explore the possibility of keeping the project up-to-date. However, I must admit that it won't be an easy task and may require a significant amount of effort.
Hi @BurtonQin. Thanks for your reply! This is a very interesting project indeed. I am optimistic about getting it to work, especially given that the underlying packages (golang.org/x/tools/go/pointer
specifically) seem to be able to deal with generics (with some help).
My current guess is that a different ssa.BuilderMode
is hardcoded somewhere else in the code, but I have been unable to find it.
On another note, it would be very useful to know if any changes were made to the ssa
or packages
packages, as I had to revert to the official implementations. Apologies if these are documented somewhere.
The original coder of the core code is lzhfromustc. As far as I know, his current email address is zil060@ucsd.edu. You can try to contact him for more details about the changes. The changes are briefed in tools/README.md
and ssabuild/build.go
I adapt the latest version of golang.org/x/tools/pointer
to GCatch, which is a drop-in replacement of the mypointer
package in current GCatch:
The code is in https://github.com/BurtonQin/mypointer
Thanks for that! I've replaced the package with that (and made a few other needed modifications) but I'm still getting the same error. Is there something else I need to do?
I added your version of mypointer
as a submodule to my repo. I have had to make a couple of changes:
mypointer
typeparams
and callgraph
Is there any chance I could get push permissions to https://github.com/BurtonQin/mypointer? Ditto for GCatch, but I understand that's a bigger commitment.
You can create a fork and make a PR to BurtonQin/mypointer. As for GCatch, can you push your changes to BurtonQin/GCatch?
I don't have permission to push to BurtonQin/GCatch. Should that be another PR?
I just sent you an invitation email.
@CarlosRosuero I have upgraded the dependencies of GCatch is in https://github.com/BurtonQin/GCatch/tree/generic/GCatch
, which should have support the detection of generic functions.
So many problems:
normal git clone will put the project in the folder 'gcatch' you restrict it to be cased 'GCatch' in installation, there is no real reason for this
suggestion: remove the install scripts, installation is really simple to install z3:
install GCatch requires z3 (WITH SOURCES) (
which z3
or/usr/[local/]bin/z3
is not enough; the packaged binaries don't save the headers etc. -- you would simply get an error compiling)please expose the project in some other way, fx
btw when this is all done the script still fails with the error message (even when it is blatantly false)
I would advise this project to change how it works, to at least scan the current directory without dependencies, so that you can scan your own project without relying on scanning the full dependency graph. also there must be another way to figure the dependent project's if you wan't to scan those as well.
GOPATH
is not even standard any longer (move to reading the go.mod file -- you could find other versions of the projects inGOPATH
-- there must be core or helper-libraries for this)You really designed yourself into a corner with your application relying on packages inside your GOPATH, and default working with dependencies as well as the specific filetree.
check the CLI of a project like scc (sloc, cloc and counter) essentially your tool should be able to be run like this:
and give some readable feedback including possible warnings and/or error codes based on findings. then maybe add a
-recurse-dependencies
if you want to do a dependency scan. and you could scan a project using something likeGCatch -remote github.com/some/project@tag
(or make the-include
tag scan another project as well as the current directory filetree)I'm just sad that running this code is virtually impossible.