This repository was archived by the owner on Jan 5, 2023. It is now read-only.
File tree Expand file tree Collapse file tree
src/semmle/go/dataflow/internal
test/library-tests/semmle/go/dataflow/CallGraph Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -63,14 +63,36 @@ private FuncDecl getConcreteTarget(DataFlow::CallNode call) {
6363 )
6464}
6565
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+
6685/**
6786 * Gets a function that might be called by `call`.
6887 */
6988DataFlowCallable viableCallable ( CallExpr ma ) {
7089 exists ( DataFlow:: CallNode call | call .asExpr ( ) = ma |
7190 if isConcreteInterfaceCall ( call , _, _)
7291 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 ( )
7496 )
7597}
7698
Original file line number Diff line number Diff line change @@ -3,3 +3,4 @@ spuriousCallee
33| main.go:44:3:44:7 | call to m | main.go:17:1:17:17 | function declaration |
44| main.go:44:3:44:7 | call to m | main.go:21:1:21:20 | function declaration |
55| 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