File: slicing_test.go

package info (click to toggle)
golang-golang-x-vuln 0.0~git20230201.4c848ed-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 992 kB
  • sloc: sh: 288; asm: 40; makefile: 7
file content (119 lines) | stat: -rw-r--r-- 2,221 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package vulncheck

import (
	"path"
	"reflect"
	"testing"

	"golang.org/x/tools/go/callgraph/cha"
	"golang.org/x/tools/go/packages/packagestest"
	"golang.org/x/tools/go/ssa"
	"golang.org/x/tools/go/ssa/ssautil"
	"golang.org/x/vuln/internal/test"
)

// funcNames returns a set of function names for `funcs`.
func funcNames(funcs map[*ssa.Function]bool) map[string]bool {
	fs := make(map[string]bool)
	for f := range funcs {
		fs[dbFuncName(f)] = true
	}
	return fs
}

func TestSlicing(t *testing.T) {
	// test program
	p := `
package slice

func X() {}
func Y() {}

// not reachable
func id(i int) int {
        return i
}

// not reachable
func inc(i int) int {
        return i + 1
}

func Apply(b bool, h func()) {
        if b {
                func() {
                        print("applied")
                }()
                return
        }
        h()
}

type I interface {
        Foo()
}

type A struct{}

func (a A) Foo() {}

// not reachable
func (a A) Bar() {}

type B struct{}

func (b B) Foo() {}

func debug(s string) {
        print(s)
}

func Do(i I, input string) {
        debug(input)

        i.Foo()

        func(x string) {
                func(l int) {
                        print(l)
                }(len(x))
        }(input)
}`

	e := packagestest.Export(t, packagestest.Modules, []packagestest.Module{
		{
			Name:  "some/module",
			Files: map[string]interface{}{"slice/slice.go": p},
		},
	})

	pkgs, err := test.LoadPackages(e, path.Join(e.Temp(), "/module/slice"))
	if err != nil {
		t.Fatal(err)
	}
	prog, ssaPkgs := ssautil.AllPackages(pkgs, 0)
	prog.Build()

	pkg := ssaPkgs[0]
	sources := map[*ssa.Function]bool{pkg.Func("Apply"): true, pkg.Func("Do"): true}
	fs := funcNames(forwardSlice(sources, cha.CallGraph(prog)))
	want := map[string]bool{
		"Apply":   true,
		"Apply$1": true,
		"X":       true,
		"Y":       true,
		"Do":      true,
		"Do$1":    true,
		"Do$1$1":  true,
		"debug":   true,
		"A.Foo":   true,
		"B.Foo":   true,
	}
	if !reflect.DeepEqual(want, fs) {
		t.Errorf("want %v; got %v", want, fs)
	}
}