This repository was archived by the owner on Jan 5, 2023. It is now read-only.
File tree Expand file tree Collapse file tree 3 files changed +73
-1
lines changed
src/semmle/go/dataflow/internal
test/library-tests/semmle/go/dataflow/CallGraph Expand file tree Collapse file tree 3 files changed +73
-1
lines changed Original file line number Diff line number Diff line change @@ -63,14 +63,36 @@ private FuncDecl getConcreteTarget(DataFlow::CallNode call) {
63
63
)
64
64
}
65
65
66
+ /**
67
+ * Holds if `call` is a method call whose receiver has an interface type.
68
+ */
69
+ private predicate isInterfaceMethodCall ( DataFlow:: CallNode call ) {
70
+ isInterfaceCallReceiver ( call , _, _, _)
71
+ }
72
+
73
+ /**
74
+ * Gets a method that might be called by `call`, where we restrict the result to
75
+ * implement the interface type of the receiver of `call`.
76
+ */
77
+ private MethodDecl getRestrictedInterfaceTarget ( DataFlow:: CallNode call ) {
78
+ exists ( InterfaceType tp , Type recvtp , string m |
79
+ isInterfaceCallReceiver ( call , _, tp , m ) and
80
+ result = recvtp .getMethod ( m ) .( DeclaredFunction ) .getFuncDecl ( ) and
81
+ recvtp .implements ( tp )
82
+ )
83
+ }
84
+
66
85
/**
67
86
* Gets a function that might be called by `call`.
68
87
*/
69
88
DataFlowCallable viableCallable ( CallExpr ma ) {
70
89
exists ( DataFlow:: CallNode call | call .asExpr ( ) = ma |
71
90
if isConcreteInterfaceCall ( call , _, _)
72
91
then result = getConcreteTarget ( call )
73
- else result = call .getACallee ( )
92
+ else
93
+ if isInterfaceMethodCall ( call )
94
+ then result = getRestrictedInterfaceTarget ( call )
95
+ else result = call .getACallee ( )
74
96
)
75
97
}
76
98
Original file line number Diff line number Diff line change @@ -3,3 +3,4 @@ spuriousCallee
3
3
| main.go:44:3:44:7 | call to m | main.go:17:1:17:17 | function declaration |
4
4
| main.go:44:3:44:7 | call to m | main.go:21:1:21:20 | function declaration |
5
5
| main.go:56:2:56:6 | call to m | main.go:21:1:21:20 | function declaration |
6
+ | test.go:42:2:42:13 | call to Write | test.go:36:1:39:1 | function declaration |
Original file line number Diff line number Diff line change
1
+ package main
2
+
3
+ import (
4
+ "fmt"
5
+ "hash"
6
+ "io"
7
+ )
8
+
9
+ type Resetter struct {}
10
+
11
+ func (_ Resetter ) Reset () {} // name: Resetter.Reset
12
+
13
+ type MockHash struct {
14
+ Resetter
15
+ }
16
+
17
+ func (_ MockHash ) Write (p []byte ) (n int , err error ) { // name: MockHash.Write
18
+ fmt .Println ("MockHash.Write" )
19
+ return 0 , nil
20
+ }
21
+
22
+ func (_ MockHash ) Sum (b []byte ) []byte {
23
+ return nil
24
+ }
25
+
26
+ func (_ MockHash ) Size () int {
27
+ return 0
28
+ }
29
+
30
+ func (_ MockHash ) BlockSize () int {
31
+ return 0
32
+ }
33
+
34
+ type MockWriter struct {}
35
+
36
+ func (_ MockWriter ) Write (p []byte ) (n int , err error ) { // name: MockWriter.Write
37
+ fmt .Println ("MockWriter.Write" )
38
+ return 0 , nil
39
+ }
40
+
41
+ func test5 (h hash.Hash , w io.Writer ) { // name: test5
42
+ h .Write (nil ) // callee: MockHash.Write
43
+ w .Write (nil ) // callee: MockWriter.Write callee: MockHash.Write
44
+ h .Reset () // callee: Resetter.Reset
45
+ }
46
+
47
+ func test6 (h MockHash , w MockWriter ) {
48
+ test5 (h , w ) // callee: test5
49
+ }
You can’t perform that action at this time.
0 commit comments