blob: ae8bfb8e79bdb8fc7dd8a8908a405d0d867df62b [file] [log] [blame]
Zvonimir Pavlinovic5380ba12021-11-12 16:31:44 -08001// Copyright 2021 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package vulncheck
6
7import (
8 "path"
9 "reflect"
10 "testing"
11
12 "golang.org/x/tools/go/callgraph/cha"
13 "golang.org/x/tools/go/packages/packagestest"
14 "golang.org/x/tools/go/ssa"
15 "golang.org/x/tools/go/ssa/ssautil"
16)
17
18// funcNames returns a set of function names for `funcs`.
19func funcNames(funcs map[*ssa.Function]bool) map[string]bool {
20 fs := make(map[string]bool)
21 for f := range funcs {
22 fs[dbFuncName(f)] = true
23 }
24 return fs
25}
26
27func TestSlicing(t *testing.T) {
28 // test program
29 p := `
30package slice
31
32func X() {}
33func Y() {}
34
35// not reachable
36func id(i int) int {
37 return i
38}
39
40// not reachable
41func inc(i int) int {
42 return i + 1
43}
44
45func Apply(b bool, h func()) {
46 if b {
47 func() {
48 print("applied")
49 }()
50 return
51 }
52 h()
53}
54
55type I interface {
56 Foo()
57}
58
59type A struct{}
60
61func (a A) Foo() {}
62
63// not reachable
64func (a A) Bar() {}
65
66type B struct{}
67
68func (b B) Foo() {}
69
70func debug(s string) {
71 print(s)
72}
73
74func Do(i I, input string) {
75 debug(input)
76
77 i.Foo()
78
79 func(x string) {
80 func(l int) {
81 print(l)
82 }(len(x))
83 }(input)
84}`
85
86 e := packagestest.Export(t, packagestest.Modules, []packagestest.Module{
87 {
88 Name: "some/module",
89 Files: map[string]interface{}{"slice/slice.go": p},
90 },
91 })
92
93 pkgs, err := loadPackages(e, path.Join(e.Temp(), "/module/slice"))
94 if err != nil {
95 t.Fatal(err)
96 }
97 prog, ssaPkgs := ssautil.AllPackages(pkgs, 0)
98 prog.Build()
99
100 pkg := ssaPkgs[0]
101 sources := map[*ssa.Function]bool{pkg.Func("Apply"): true, pkg.Func("Do"): true}
102 fs := funcNames(forwardReachableFrom(sources, cha.CallGraph(prog)))
103 want := map[string]bool{
104 "Apply": true,
105 "Apply$1": true,
106 "X": true,
107 "Y": true,
108 "Do": true,
109 "Do$1": true,
110 "Do$1$1": true,
111 "debug": true,
112 "A.Foo": true,
113 "B.Foo": true,
114 }
115 if !reflect.DeepEqual(want, fs) {
116 t.Errorf("want %v; got %v", want, fs)
117 }
118}