internal/govulncheck: choose unique call stacks

A call stack is unique if it does not go through other detected
vulnerable symbols.

Fixes golang/go#56176

Change-Id: Iea214f9a879610131910dbede7fa87012bb91fa3
Reviewed-on: https://go-review.googlesource.com/c/vuln/+/445078
Run-TryBot: Zvonimir Pavlinovic <zpavlinovic@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
diff --git a/cmd/govulncheck/testdata/manystacks-verbose.ct b/cmd/govulncheck/testdata/manystacks-verbose.ct
index 6de910c..ce0215a 100644
--- a/cmd/govulncheck/testdata/manystacks-verbose.ct
+++ b/cmd/govulncheck/testdata/manystacks-verbose.ct
@@ -18,1138 +18,14 @@
         example.com/manystacks/otherpkg.GetPeers
             .../otherpkg.go:6:19
         github.com/shiyanhui/dht.DHT.GetPeers
-      #2: for function DHT.IsCrawlMode
+      #2: for function DHT.Run
         example.com/manystacks.main
             .../main.go:44:7
         github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:285:5
-        github.com/shiyanhui/dht.routingTable.Fresh
-            .../routingtable.go:524:23
-        github.com/shiyanhui/dht.DHT.IsCrawlMode
-      #3: for function DHT.IsStandardMode
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:270:10
-        github.com/shiyanhui/dht.DHT.join
-            .../dht.go:207:34
-        github.com/shiyanhui/dht.transactionManager.findNode
-            .../krpc.go:343:22
-        github.com/shiyanhui/dht.DHT.id
-            .../dht.go:232:23
-        github.com/shiyanhui/dht.DHT.IsStandardMode
-      #4: for function DHT.Run
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-      #5: for function DHT.id
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:270:10
-        github.com/shiyanhui/dht.DHT.join
-            .../dht.go:207:34
-        github.com/shiyanhui/dht.transactionManager.findNode
-            .../krpc.go:343:22
-        github.com/shiyanhui/dht.DHT.id
-      #6: for function DHT.init
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:268:10
-        github.com/shiyanhui/dht.DHT.init
-      #7: for function DHT.join
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:270:10
-        github.com/shiyanhui/dht.DHT.join
-      #8: for function DHT.listen
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:269:12
-        github.com/shiyanhui/dht.DHT.listen
-      #9: for function Decode
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:280:10
-        github.com/shiyanhui/dht.handle
-            .../krpc.go:762:2
-        github.com/shiyanhui/dht.handle$1
-            .../krpc.go:771:22
-        github.com/shiyanhui/dht.Decode
-      #10: for function DecodeDict
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:280:10
-        github.com/shiyanhui/dht.handle
-            .../krpc.go:762:2
-        github.com/shiyanhui/dht.handle$1
-            .../krpc.go:771:22
-        github.com/shiyanhui/dht.Decode
-            .../bencode.go:193:29
-        github.com/shiyanhui/dht.decodeItem
-            .../bencode.go:93:25
-        github.com/shiyanhui/dht.DecodeDict
-      #11: for function DecodeInt
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:280:10
-        github.com/shiyanhui/dht.handle
-            .../krpc.go:762:2
-        github.com/shiyanhui/dht.handle$1
-            .../krpc.go:771:22
-        github.com/shiyanhui/dht.Decode
-            .../bencode.go:193:29
-        github.com/shiyanhui/dht.decodeItem
-            .../bencode.go:93:25
-        github.com/shiyanhui/dht.DecodeInt
-      #12: for function DecodeList
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:280:10
-        github.com/shiyanhui/dht.handle
-            .../krpc.go:762:2
-        github.com/shiyanhui/dht.handle$1
-            .../krpc.go:771:22
-        github.com/shiyanhui/dht.Decode
-            .../bencode.go:193:29
-        github.com/shiyanhui/dht.decodeItem
-            .../bencode.go:93:25
-        github.com/shiyanhui/dht.DecodeList
-      #13: for function DecodeString
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:280:10
-        github.com/shiyanhui/dht.handle
-            .../krpc.go:762:2
-        github.com/shiyanhui/dht.handle$1
-            .../krpc.go:771:22
-        github.com/shiyanhui/dht.Decode
-            .../bencode.go:193:29
-        github.com/shiyanhui/dht.decodeItem
-            .../bencode.go:93:25
-        github.com/shiyanhui/dht.DecodeString
-      #14: for function Encode
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:268:10
-        github.com/shiyanhui/dht.DHT.init
-            .../dht.go:193:2
-        github.com/shiyanhui/dht.transactionManager.run
-            .../krpc.go:310:4
-        github.com/shiyanhui/dht.transactionManager.query
-            .../krpc.go:285:17
-        github.com/shiyanhui/dht.send
-            .../krpc.go:131:45
-        github.com/shiyanhui/dht.Encode
-      #15: for function EncodeDict
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:268:10
-        github.com/shiyanhui/dht.DHT.init
-            .../dht.go:193:2
-        github.com/shiyanhui/dht.transactionManager.run
-            .../krpc.go:310:4
-        github.com/shiyanhui/dht.transactionManager.query
-            .../krpc.go:285:17
-        github.com/shiyanhui/dht.send
-            .../krpc.go:131:45
-        github.com/shiyanhui/dht.Encode
-            .../bencode.go:259:20
-        github.com/shiyanhui/dht.EncodeDict
-      #16: for function EncodeInt
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:268:10
-        github.com/shiyanhui/dht.DHT.init
-            .../dht.go:193:2
-        github.com/shiyanhui/dht.transactionManager.run
-            .../krpc.go:310:4
-        github.com/shiyanhui/dht.transactionManager.query
-            .../krpc.go:285:17
-        github.com/shiyanhui/dht.send
-            .../krpc.go:131:45
-        github.com/shiyanhui/dht.Encode
-            .../bencode.go:255:19
-        github.com/shiyanhui/dht.EncodeInt
-      #17: for function EncodeList
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:268:10
-        github.com/shiyanhui/dht.DHT.init
-            .../dht.go:193:2
-        github.com/shiyanhui/dht.transactionManager.run
-            .../krpc.go:310:4
-        github.com/shiyanhui/dht.transactionManager.query
-            .../krpc.go:285:17
-        github.com/shiyanhui/dht.send
-            .../krpc.go:131:45
-        github.com/shiyanhui/dht.Encode
-            .../bencode.go:257:20
-        github.com/shiyanhui/dht.EncodeList
-      #18: for function EncodeString
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:268:10
-        github.com/shiyanhui/dht.DHT.init
-            .../dht.go:193:2
-        github.com/shiyanhui/dht.transactionManager.run
-            .../krpc.go:310:4
-        github.com/shiyanhui/dht.transactionManager.query
-            .../krpc.go:285:17
-        github.com/shiyanhui/dht.send
-            .../krpc.go:131:45
-        github.com/shiyanhui/dht.Encode
-            .../bencode.go:253:22
-        github.com/shiyanhui/dht.EncodeString
-      #19: for function New
+      #3: for function New
         example.com/manystacks.main
             .../main.go:16:14
         github.com/shiyanhui/dht.New
-      #20: for function NewStandardConfig
-        example.com/manystacks.main
-            .../main.go:16:14
-        github.com/shiyanhui/dht.New
-            .../dht.go:135:29
-        github.com/shiyanhui/dht.NewStandardConfig
-      #21: for function ParseKey
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:280:10
-        github.com/shiyanhui/dht.handle
-            .../krpc.go:762:2
-        github.com/shiyanhui/dht.handle$1
-            .../krpc.go:776:32
-        github.com/shiyanhui/dht.parseMessage
-            .../krpc.go:416:21
-        github.com/shiyanhui/dht.ParseKeys
-            .../krpc.go:401:21
-        github.com/shiyanhui/dht.ParseKey
-      #22: for function ParseKeys
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:280:10
-        github.com/shiyanhui/dht.handle
-            .../krpc.go:762:2
-        github.com/shiyanhui/dht.handle$1
-            .../krpc.go:776:32
-        github.com/shiyanhui/dht.parseMessage
-            .../krpc.go:416:21
-        github.com/shiyanhui/dht.ParseKeys
-      #23: for function bitmap.Bit
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:268:10
-        github.com/shiyanhui/dht.DHT.init
-            .../dht.go:187:36
-        github.com/shiyanhui/dht.newRoutingTable
-            .../routingtable.go:351:50
-        github.com/shiyanhui/dht.bitmap.String
-            .../bitmap.go:144:42
-        github.com/shiyanhui/dht.bitmap.Bit
-      #24: for function bitmap.Compare
-        example.com/manystacks.main
-            .../main.go:27:2
-        example.com/manystacks.main$2
-            .../main.go:30:28
-        example.com/manystacks/otherpkg.GetPeers
-            .../otherpkg.go:6:19
-        github.com/shiyanhui/dht.DHT.GetPeers
-            .../dht.go:256:44
-        github.com/shiyanhui/dht.routingTable.GetNeighbors
-            .../routingtable.go:426:22
-        github.com/shiyanhui/dht.getTopK
-            .../routingtable.go:583:28
-        github.com/shiyanhui/dht.bitmap.Compare
-      #25: for function bitmap.RawString
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:270:10
-        github.com/shiyanhui/dht.DHT.join
-            .../dht.go:209:25
-        github.com/shiyanhui/dht.bitmap.RawString
-      #26: for function bitmap.String
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:268:10
-        github.com/shiyanhui/dht.DHT.init
-            .../dht.go:187:36
-        github.com/shiyanhui/dht.newRoutingTable
-            .../routingtable.go:351:50
-        github.com/shiyanhui/dht.bitmap.String
-      #27: for function bitmap.Xor
-        example.com/manystacks.main
-            .../main.go:27:2
-        example.com/manystacks.main$2
-            .../main.go:30:28
-        example.com/manystacks/otherpkg.GetPeers
-            .../otherpkg.go:6:19
-        github.com/shiyanhui/dht.DHT.GetPeers
-            .../dht.go:256:44
-        github.com/shiyanhui/dht.routingTable.GetNeighbors
-            .../routingtable.go:426:22
-        github.com/shiyanhui/dht.getTopK
-            .../routingtable.go:580:21
-        github.com/shiyanhui/dht.bitmap.Xor
-      #28: for function blackList.clear
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:268:10
-        github.com/shiyanhui/dht.DHT.init
-            .../dht.go:195:2
-        github.com/shiyanhui/dht.blackList.clear
-      #29: for function blackList.genKey
-        example.com/manystacks.main
-            .../main.go:16:14
-        github.com/shiyanhui/dht.New
-            .../dht.go:152:21
-        github.com/shiyanhui/dht.blackList.insert
-            .../blacklist.go:47:23
-        github.com/shiyanhui/dht.blackList.genKey
-      #30: for function blackList.in
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:280:10
-        github.com/shiyanhui/dht.handle
-            .../krpc.go:762:2
-        github.com/shiyanhui/dht.handle$1
-            .../krpc.go:767:22
-        github.com/shiyanhui/dht.blackList.in
-      #31: for function blackList.insert
-        example.com/manystacks.main
-            .../main.go:16:14
-        github.com/shiyanhui/dht.New
-            .../dht.go:152:21
-        github.com/shiyanhui/dht.blackList.insert
-      #32: for function decodeItem
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:280:10
-        github.com/shiyanhui/dht.handle
-            .../krpc.go:762:2
-        github.com/shiyanhui/dht.handle$1
-            .../krpc.go:771:22
-        github.com/shiyanhui/dht.Decode
-            .../bencode.go:193:29
-        github.com/shiyanhui/dht.decodeItem
-      #33: for function encodeItem
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:268:10
-        github.com/shiyanhui/dht.DHT.init
-            .../dht.go:193:2
-        github.com/shiyanhui/dht.transactionManager.run
-            .../krpc.go:310:4
-        github.com/shiyanhui/dht.transactionManager.query
-            .../krpc.go:285:17
-        github.com/shiyanhui/dht.send
-            .../krpc.go:131:45
-        github.com/shiyanhui/dht.Encode
-            .../bencode.go:257:20
-        github.com/shiyanhui/dht.EncodeList
-            .../bencode.go:229:25
-        github.com/shiyanhui/dht.encodeItem
-      #34: for function find
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:280:10
-        github.com/shiyanhui/dht.handle
-            .../krpc.go:762:2
-        github.com/shiyanhui/dht.handle$1
-            .../krpc.go:771:22
-        github.com/shiyanhui/dht.Decode
-            .../bencode.go:193:29
-        github.com/shiyanhui/dht.decodeItem
-            .../bencode.go:93:25
-        github.com/shiyanhui/dht.DecodeString
-            .../bencode.go:32:11
-        github.com/shiyanhui/dht.find
-      #35: for function genAddress
-        example.com/manystacks.main
-            .../main.go:16:14
-        github.com/shiyanhui/dht.New
-            .../dht.go:152:21
-        github.com/shiyanhui/dht.blackList.insert
-            .../blacklist.go:47:23
-        github.com/shiyanhui/dht.blackList.genKey
-            .../blacklist.go:36:19
-        github.com/shiyanhui/dht.genAddress
-      #36: for function getLocalIPs
-        example.com/manystacks.main
-            .../main.go:16:14
-        github.com/shiyanhui/dht.New
-            .../dht.go:155:2
-        github.com/shiyanhui/dht.New$1
-            .../dht.go:156:33
-        github.com/shiyanhui/dht.getLocalIPs
-      #37: for function getRemoteIP
-        example.com/manystacks.main
-            .../main.go:16:14
-        github.com/shiyanhui/dht.New
-            .../dht.go:155:2
-        github.com/shiyanhui/dht.New$1
-            .../dht.go:160:25
-        github.com/shiyanhui/dht.getRemoteIP
-      #38: for function getTopK
-        example.com/manystacks.main
-            .../main.go:27:2
-        example.com/manystacks.main$2
-            .../main.go:30:28
-        example.com/manystacks/otherpkg.GetPeers
-            .../otherpkg.go:6:19
-        github.com/shiyanhui/dht.DHT.GetPeers
-            .../dht.go:256:44
-        github.com/shiyanhui/dht.routingTable.GetNeighbors
-            .../routingtable.go:426:22
-        github.com/shiyanhui/dht.getTopK
-      #39: for function handle
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:280:10
-        github.com/shiyanhui/dht.handle
-      #40: for function int2bytes
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:270:10
-        github.com/shiyanhui/dht.DHT.join
-            .../dht.go:207:34
-        github.com/shiyanhui/dht.transactionManager.findNode
-            .../krpc.go:342:14
-        github.com/shiyanhui/dht.transactionManager.sendQuery
-            .../krpc.go:326:33
-        github.com/shiyanhui/dht.transactionManager.genTransID
-            .../krpc.go:180:25
-        github.com/shiyanhui/dht.int2bytes
-      #41: for function kbucket.LastChanged
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:285:5
-        github.com/shiyanhui/dht.routingTable.Fresh
-            .../routingtable.go:508:32
-        github.com/shiyanhui/dht.kbucket.LastChanged
-      #42: for function kbucket.RandomChildID
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:285:5
-        github.com/shiyanhui/dht.routingTable.Fresh
-            .../routingtable.go:517:64
-        github.com/shiyanhui/dht.kbucket.RandomChildID
-      #43: for function kbucket.Replace
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:285:5
-        github.com/shiyanhui/dht.routingTable.Fresh
-            .../routingtable.go:526:13
-        github.com/shiyanhui/dht.routingTable.Remove
-            .../routingtable.go:488:17
-        github.com/shiyanhui/dht.kbucket.Replace
-      #44: for function kbucket.UpdateTimestamp
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:285:5
-        github.com/shiyanhui/dht.routingTable.Fresh
-            .../routingtable.go:526:13
-        github.com/shiyanhui/dht.routingTable.Remove
-            .../routingtable.go:488:17
-        github.com/shiyanhui/dht.kbucket.Replace
-            .../routingtable.go:209:24
-        github.com/shiyanhui/dht.kbucket.UpdateTimestamp
-      #45: for function syncedList.Back
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:285:5
-        github.com/shiyanhui/dht.routingTable.Fresh
-            .../routingtable.go:526:13
-        github.com/shiyanhui/dht.routingTable.Remove
-            .../routingtable.go:488:17
-        github.com/shiyanhui/dht.kbucket.Replace
-            .../routingtable.go:215:54
-        github.com/shiyanhui/dht.syncedList.Back
-      #46: for function keyedDeque.Delete
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:285:5
-        github.com/shiyanhui/dht.routingTable.Fresh
-            .../routingtable.go:526:13
-        github.com/shiyanhui/dht.routingTable.Remove
-            .../routingtable.go:488:17
-        github.com/shiyanhui/dht.kbucket.Replace
-            .../routingtable.go:208:21
-        github.com/shiyanhui/dht.keyedDeque.Delete
-      #47: for function keyedDeque.Get
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:285:5
-        github.com/shiyanhui/dht.routingTable.Fresh
-            .../routingtable.go:526:13
-        github.com/shiyanhui/dht.routingTable.Remove
-            .../routingtable.go:487:39
-        github.com/shiyanhui/dht.routingTable.GetNodeKBucktByID
-            .../routingtable.go:461:37
-        github.com/shiyanhui/dht.keyedDeque.Get
-      #48: for function syncedList.InsertBefore
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:285:5
-        github.com/shiyanhui/dht.routingTable.Fresh
-            .../routingtable.go:526:13
-        github.com/shiyanhui/dht.routingTable.Remove
-            .../routingtable.go:488:17
-        github.com/shiyanhui/dht.kbucket.Replace
-            .../routingtable.go:222:29
-        github.com/shiyanhui/dht.syncedList.InsertBefore
-      #49: for function syncedList.Iter
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:285:5
-        github.com/shiyanhui/dht.routingTable.Fresh
-            .../routingtable.go:506:39
-        github.com/shiyanhui/dht.syncedList.Iter
-      #50: for function syncedList.Len
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:285:5
-        github.com/shiyanhui/dht.routingTable.Fresh
-            .../routingtable.go:509:20
-        github.com/shiyanhui/dht.syncedList.Len
-      #51: for function keyedDeque.Push
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:268:10
-        github.com/shiyanhui/dht.DHT.init
-            .../dht.go:187:36
-        github.com/shiyanhui/dht.newRoutingTable
-            .../routingtable.go:351:24
-        github.com/shiyanhui/dht.keyedDeque.Push
-      #52: for function syncedList.PushBack
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:285:5
-        github.com/shiyanhui/dht.routingTable.Fresh
-            .../routingtable.go:518:27
-        github.com/shiyanhui/dht.syncedList.PushBack
-      #53: for function keyedDeque.Remove
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:285:5
-        github.com/shiyanhui/dht.routingTable.Fresh
-            .../routingtable.go:526:13
-        github.com/shiyanhui/dht.routingTable.Remove
-            .../routingtable.go:488:17
-        github.com/shiyanhui/dht.kbucket.Replace
-            .../routingtable.go:215:31
-        github.com/shiyanhui/dht.keyedDeque.Remove
-      #54: for function makeQuery
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:270:10
-        github.com/shiyanhui/dht.DHT.join
-            .../dht.go:207:34
-        github.com/shiyanhui/dht.transactionManager.findNode
-            .../krpc.go:342:14
-        github.com/shiyanhui/dht.transactionManager.sendQuery
-            .../krpc.go:326:19
-        github.com/shiyanhui/dht.makeQuery
-      #55: for function newBitmap
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:268:10
-        github.com/shiyanhui/dht.DHT.init
-            .../dht.go:187:36
-        github.com/shiyanhui/dht.newRoutingTable
-            .../routingtable.go:339:39
-        github.com/shiyanhui/dht.newBitmap
-      #56: for function newBitmapFromBytes
-        example.com/manystacks.main
-            .../main.go:16:14
-        github.com/shiyanhui/dht.New
-            .../dht.go:138:22
-        github.com/shiyanhui/dht.newNode
-            .../routingtable.go:33:34
-        github.com/shiyanhui/dht.newBitmapFromString
-            .../bitmap.go:57:27
-        github.com/shiyanhui/dht.newBitmapFromBytes
-      #57: for function newBitmapFromString
-        example.com/manystacks.main
-            .../main.go:16:14
-        github.com/shiyanhui/dht.New
-            .../dht.go:138:22
-        github.com/shiyanhui/dht.newNode
-            .../routingtable.go:33:34
-        github.com/shiyanhui/dht.newBitmapFromString
-      #58: for function newBlackList
-        example.com/manystacks.main
-            .../main.go:16:14
-        github.com/shiyanhui/dht.New
-            .../dht.go:146:29
-        github.com/shiyanhui/dht.newBlackList
-      #59: for function newKBucket
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:268:10
-        github.com/shiyanhui/dht.DHT.init
-            .../dht.go:187:36
-        github.com/shiyanhui/dht.newRoutingTable
-            .../routingtable.go:339:29
-        github.com/shiyanhui/dht.newRoutingTableNode
-            .../routingtable.go:253:23
-        github.com/shiyanhui/dht.newKBucket
-      #60: for function newKeyedDeque
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:268:10
-        github.com/shiyanhui/dht.DHT.init
-            .../dht.go:187:36
-        github.com/shiyanhui/dht.newRoutingTable
-            .../routingtable.go:346:32
-        github.com/shiyanhui/dht.newKeyedDeque
-      #61: for function newNode
-        example.com/manystacks.main
-            .../main.go:16:14
-        github.com/shiyanhui/dht.New
-            .../dht.go:138:22
-        github.com/shiyanhui/dht.newNode
-      #62: for function newPeersManager
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:268:10
-        github.com/shiyanhui/dht.DHT.init
-            .../dht.go:188:36
-        github.com/shiyanhui/dht.newPeersManager
-      #63: for function newRoutingTable
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:268:10
-        github.com/shiyanhui/dht.DHT.init
-            .../dht.go:187:36
-        github.com/shiyanhui/dht.newRoutingTable
-      #64: for function newRoutingTableNode
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:268:10
-        github.com/shiyanhui/dht.DHT.init
-            .../dht.go:187:36
-        github.com/shiyanhui/dht.newRoutingTable
-            .../routingtable.go:339:29
-        github.com/shiyanhui/dht.newRoutingTableNode
-      #65: for function newSyncedList
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:268:10
-        github.com/shiyanhui/dht.DHT.init
-            .../dht.go:187:36
-        github.com/shiyanhui/dht.newRoutingTable
-            .../routingtable.go:348:32
-        github.com/shiyanhui/dht.newSyncedList
-      #66: for function newSyncedMap
-        example.com/manystacks.main
-            .../main.go:16:14
-        github.com/shiyanhui/dht.New
-            .../dht.go:146:29
-        github.com/shiyanhui/dht.newBlackList
-            .../blacklist.go:25:29
-        github.com/shiyanhui/dht.newSyncedMap
-      #67: for function newTokenManager
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:268:10
-        github.com/shiyanhui/dht.DHT.init
-            .../dht.go:189:36
-        github.com/shiyanhui/dht.newTokenManager
-      #68: for function newTransactionManager
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:268:10
-        github.com/shiyanhui/dht.DHT.init
-            .../dht.go:190:48
-        github.com/shiyanhui/dht.newTransactionManager
-      #69: for function parseMessage
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:280:10
-        github.com/shiyanhui/dht.handle
-            .../krpc.go:762:2
-        github.com/shiyanhui/dht.handle$1
-            .../krpc.go:776:32
-        github.com/shiyanhui/dht.parseMessage
-      #70: for function randomString
-        example.com/manystacks.main
-            .../main.go:16:14
-        github.com/shiyanhui/dht.New
-            .../dht.go:138:35
-        github.com/shiyanhui/dht.randomString
-      #71: for function routingTable.Fresh
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:285:5
-        github.com/shiyanhui/dht.routingTable.Fresh
-      #72: for function routingTable.GetNeighbors
-        example.com/manystacks.main
-            .../main.go:27:2
-        example.com/manystacks.main$2
-            .../main.go:30:28
-        example.com/manystacks/otherpkg.GetPeers
-            .../otherpkg.go:6:19
-        github.com/shiyanhui/dht.DHT.GetPeers
-            .../dht.go:256:44
-        github.com/shiyanhui/dht.routingTable.GetNeighbors
-      #73: for function routingTable.GetNodeKBucktByID
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:285:5
-        github.com/shiyanhui/dht.routingTable.Fresh
-            .../routingtable.go:526:13
-        github.com/shiyanhui/dht.routingTable.Remove
-            .../routingtable.go:487:39
-        github.com/shiyanhui/dht.routingTable.GetNodeKBucktByID
-      #74: for function routingTable.Len
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:282:27
-        github.com/shiyanhui/dht.routingTable.Len
-      #75: for function routingTable.Remove
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:285:5
-        github.com/shiyanhui/dht.routingTable.Fresh
-            .../routingtable.go:526:13
-        github.com/shiyanhui/dht.routingTable.Remove
-      #76: for function routingTable.RemoveByAddr
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:268:10
-        github.com/shiyanhui/dht.DHT.init
-            .../dht.go:193:2
-        github.com/shiyanhui/dht.transactionManager.run
-            .../krpc.go:310:4
-        github.com/shiyanhui/dht.transactionManager.query
-            .../krpc.go:299:35
-        github.com/shiyanhui/dht.routingTable.RemoveByAddr
-      #77: for function routingTableNode.Child
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:285:5
-        github.com/shiyanhui/dht.routingTable.Fresh
-            .../routingtable.go:526:13
-        github.com/shiyanhui/dht.routingTable.Remove
-            .../routingtable.go:487:39
-        github.com/shiyanhui/dht.routingTable.GetNodeKBucktByID
-            .../routingtable.go:459:20
-        github.com/shiyanhui/dht.routingTableNode.Child
-      #78: for function routingTableNode.KBucket
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:285:5
-        github.com/shiyanhui/dht.routingTable.Fresh
-            .../routingtable.go:526:13
-        github.com/shiyanhui/dht.routingTable.Remove
-            .../routingtable.go:487:39
-        github.com/shiyanhui/dht.routingTable.GetNodeKBucktByID
-            .../routingtable.go:461:25
-        github.com/shiyanhui/dht.routingTableNode.KBucket
-      #79: for function send
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:268:10
-        github.com/shiyanhui/dht.DHT.init
-            .../dht.go:193:2
-        github.com/shiyanhui/dht.transactionManager.run
-            .../krpc.go:310:4
-        github.com/shiyanhui/dht.transactionManager.query
-            .../krpc.go:285:17
-        github.com/shiyanhui/dht.send
-      #80: for function syncedList.Clear
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:285:5
-        github.com/shiyanhui/dht.routingTable.Fresh
-            .../routingtable.go:530:21
-        github.com/shiyanhui/dht.syncedList.Clear
-      #81: for function syncedList.Remove
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:268:10
-        github.com/shiyanhui/dht.DHT.init
-            .../dht.go:187:36
-        github.com/shiyanhui/dht.newRoutingTable
-            .../routingtable.go:351:24
-        github.com/shiyanhui/dht.keyedDeque.Push
-            .../container.go:229:26
-        github.com/shiyanhui/dht.syncedList.Remove
-      #82: for function syncedMap.Delete
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:285:5
-        github.com/shiyanhui/dht.routingTable.Fresh
-            .../routingtable.go:526:13
-        github.com/shiyanhui/dht.routingTable.Remove
-            .../routingtable.go:489:24
-        github.com/shiyanhui/dht.syncedMap.Delete
-      #83: for function syncedMap.DeleteMulti
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:268:10
-        github.com/shiyanhui/dht.DHT.init
-            .../dht.go:194:2
-        github.com/shiyanhui/dht.tokenManager.clear
-            .../krpc.go:82:17
-        github.com/shiyanhui/dht.syncedMap.DeleteMulti
-      #84: for function syncedMap.Get
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:280:10
-        github.com/shiyanhui/dht.handle
-            .../krpc.go:762:2
-        github.com/shiyanhui/dht.handle$1
-            .../krpc.go:767:22
-        github.com/shiyanhui/dht.blackList.in
-            .../blacklist.go:61:25
-        github.com/shiyanhui/dht.syncedMap.Get
-      #85: for function syncedMap.Iter
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:268:10
-        github.com/shiyanhui/dht.DHT.init
-            .../dht.go:194:2
-        github.com/shiyanhui/dht.tokenManager.clear
-            .../krpc.go:76:28
-        github.com/shiyanhui/dht.syncedMap.Iter
-      #86: for function syncedMap.Len
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:284:40
-        github.com/shiyanhui/dht.transactionManager.len
-            .../krpc.go:229:28
-        github.com/shiyanhui/dht.syncedMap.Len
-      #87: for function syncedMap.Set
-        example.com/manystacks.main
-            .../main.go:16:14
-        github.com/shiyanhui/dht.New
-            .../dht.go:152:21
-        github.com/shiyanhui/dht.blackList.insert
-            .../blacklist.go:47:13
-        github.com/shiyanhui/dht.syncedMap.Set
-      #88: for function tokenManager.clear
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:268:10
-        github.com/shiyanhui/dht.DHT.init
-            .../dht.go:194:2
-        github.com/shiyanhui/dht.tokenManager.clear
-      #89: for function topKHeap.Len
-        example.com/manystacks.main
-            .../main.go:27:2
-        example.com/manystacks.main$2
-            .../main.go:30:28
-        example.com/manystacks/otherpkg.GetPeers
-            .../otherpkg.go:6:19
-        github.com/shiyanhui/dht.DHT.GetPeers
-            .../dht.go:256:44
-        github.com/shiyanhui/dht.routingTable.GetNeighbors
-            .../routingtable.go:426:22
-        github.com/shiyanhui/dht.getTopK
-            .../routingtable.go:581:18
-        github.com/shiyanhui/dht.topKHeap.Len
-      #90: for function topKHeap.Less
-        example.com/manystacks.main
-            .../main.go:27:2
-        example.com/manystacks.main$2
-            .../main.go:30:28
-        example.com/manystacks/otherpkg.GetPeers
-            .../otherpkg.go:6:19
-        github.com/shiyanhui/dht.DHT.GetPeers
-            .../dht.go:256:44
-        github.com/shiyanhui/dht.routingTable.GetNeighbors
-            .../routingtable.go:426:22
-        github.com/shiyanhui/dht.getTopK
-            .../routingtable.go:588:14
-        container/heap.Push
-            .../N:4
-        container/heap.up
-            .../N:23
-        github.com/shiyanhui/dht.topKHeap.Less
-      #91: for function topKHeap.Pop
-        example.com/manystacks.main
-            .../main.go:27:2
-        example.com/manystacks.main$2
-            .../main.go:30:28
-        example.com/manystacks/otherpkg.GetPeers
-            .../otherpkg.go:6:19
-        github.com/shiyanhui/dht.DHT.GetPeers
-            .../dht.go:256:44
-        github.com/shiyanhui/dht.routingTable.GetNeighbors
-            .../routingtable.go:426:22
-        github.com/shiyanhui/dht.getTopK
-            .../routingtable.go:589:13
-        container/heap.Pop
-            .../N:14
-        github.com/shiyanhui/dht.topKHeap.Pop
-      #92: for function topKHeap.Push
-        example.com/manystacks.main
-            .../main.go:27:2
-        example.com/manystacks.main$2
-            .../main.go:30:28
-        example.com/manystacks/otherpkg.GetPeers
-            .../otherpkg.go:6:19
-        github.com/shiyanhui/dht.DHT.GetPeers
-            .../dht.go:256:44
-        github.com/shiyanhui/dht.routingTable.GetNeighbors
-            .../routingtable.go:426:22
-        github.com/shiyanhui/dht.getTopK
-            .../routingtable.go:588:14
-        container/heap.Push
-            .../N:8
-        github.com/shiyanhui/dht.topKHeap.Push
-      #93: for function topKHeap.Swap
-        example.com/manystacks.main
-            .../main.go:27:2
-        example.com/manystacks.main$2
-            .../main.go:30:28
-        example.com/manystacks/otherpkg.GetPeers
-            .../otherpkg.go:6:19
-        github.com/shiyanhui/dht.DHT.GetPeers
-            .../dht.go:256:44
-        github.com/shiyanhui/dht.routingTable.GetNeighbors
-            .../routingtable.go:426:22
-        github.com/shiyanhui/dht.getTopK
-            .../routingtable.go:589:13
-        container/heap.Pop
-            .../N:8
-        github.com/shiyanhui/dht.topKHeap.Swap
-      #94: for function transactionManager.delete
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:268:10
-        github.com/shiyanhui/dht.DHT.init
-            .../dht.go:193:2
-        github.com/shiyanhui/dht.transactionManager.run
-            .../krpc.go:310:4
-        github.com/shiyanhui/dht.transactionManager.query
-            .../krpc.go:281:2
-        github.com/shiyanhui/dht.transactionManager.delete
-      #95: for function transactionManager.findNode
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:270:10
-        github.com/shiyanhui/dht.DHT.join
-            .../dht.go:207:34
-        github.com/shiyanhui/dht.transactionManager.findNode
-      #96: for function transactionManager.genIndexKey
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:270:10
-        github.com/shiyanhui/dht.DHT.join
-            .../dht.go:207:34
-        github.com/shiyanhui/dht.transactionManager.findNode
-            .../krpc.go:342:14
-        github.com/shiyanhui/dht.transactionManager.sendQuery
-            .../krpc.go:321:31
-        github.com/shiyanhui/dht.transactionManager.genIndexKey
-      #97: for function transactionManager.genIndexKeyByTrans
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:268:10
-        github.com/shiyanhui/dht.DHT.init
-            .../dht.go:193:2
-        github.com/shiyanhui/dht.transactionManager.run
-            .../krpc.go:310:4
-        github.com/shiyanhui/dht.transactionManager.query
-            .../krpc.go:280:11
-        github.com/shiyanhui/dht.transactionManager.insert
-            .../krpc.go:209:36
-        github.com/shiyanhui/dht.transactionManager.genIndexKeyByTrans
-      #98: for function transactionManager.genTransID
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:270:10
-        github.com/shiyanhui/dht.DHT.join
-            .../dht.go:207:34
-        github.com/shiyanhui/dht.transactionManager.findNode
-            .../krpc.go:342:14
-        github.com/shiyanhui/dht.transactionManager.sendQuery
-            .../krpc.go:326:33
-        github.com/shiyanhui/dht.transactionManager.genTransID
-      #99: for function transactionManager.getByIndex
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:270:10
-        github.com/shiyanhui/dht.DHT.join
-            .../dht.go:207:34
-        github.com/shiyanhui/dht.transactionManager.findNode
-            .../krpc.go:342:14
-        github.com/shiyanhui/dht.transactionManager.sendQuery
-            .../krpc.go:321:16
-        github.com/shiyanhui/dht.transactionManager.getByIndex
-      #100: for function transactionManager.getPeers
-        example.com/manystacks.main
-            .../main.go:27:2
-        example.com/manystacks.main$2
-            .../main.go:30:28
-        example.com/manystacks/otherpkg.GetPeers
-            .../otherpkg.go:6:19
-        github.com/shiyanhui/dht.DHT.GetPeers
-            .../dht.go:260:34
-        github.com/shiyanhui/dht.transactionManager.getPeers
-      #101: for function transactionManager.insert
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:268:10
-        github.com/shiyanhui/dht.DHT.init
-            .../dht.go:193:2
-        github.com/shiyanhui/dht.transactionManager.run
-            .../krpc.go:310:4
-        github.com/shiyanhui/dht.transactionManager.query
-            .../krpc.go:280:11
-        github.com/shiyanhui/dht.transactionManager.insert
-      #102: for function transactionManager.len
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:284:40
-        github.com/shiyanhui/dht.transactionManager.len
-      #103: for function transactionManager.newTransaction
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:268:10
-        github.com/shiyanhui/dht.DHT.init
-            .../dht.go:193:2
-        github.com/shiyanhui/dht.transactionManager.run
-            .../krpc.go:310:4
-        github.com/shiyanhui/dht.transactionManager.query
-            .../krpc.go:278:28
-        github.com/shiyanhui/dht.transactionManager.newTransaction
-      #104: for function transactionManager.query
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:268:10
-        github.com/shiyanhui/dht.DHT.init
-            .../dht.go:193:2
-        github.com/shiyanhui/dht.transactionManager.run
-            .../krpc.go:310:4
-        github.com/shiyanhui/dht.transactionManager.query
-      #105: for function transactionManager.run
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:268:10
-        github.com/shiyanhui/dht.DHT.init
-            .../dht.go:193:2
-        github.com/shiyanhui/dht.transactionManager.run
-      #106: for function transactionManager.sendQuery
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:270:10
-        github.com/shiyanhui/dht.DHT.join
-            .../dht.go:207:34
-        github.com/shiyanhui/dht.transactionManager.findNode
-            .../krpc.go:342:14
-        github.com/shiyanhui/dht.transactionManager.sendQuery
-      #107: for function transactionManager.transaction
-        example.com/manystacks.main
-            .../main.go:44:7
-        github.com/shiyanhui/dht.DHT.Run
-            .../dht.go:270:10
-        github.com/shiyanhui/dht.DHT.join
-            .../dht.go:207:34
-        github.com/shiyanhui/dht.transactionManager.findNode
-            .../krpc.go:342:14
-        github.com/shiyanhui/dht.transactionManager.sendQuery
-            .../krpc.go:321:16
-        github.com/shiyanhui/dht.transactionManager.getByIndex
-            .../krpc.go:257:23
-        github.com/shiyanhui/dht.transactionManager.transaction
-      #108: for function xor
-        example.com/manystacks.main
-            .../main.go:27:2
-        example.com/manystacks.main$2
-            .../main.go:30:28
-        example.com/manystacks/otherpkg.GetPeers
-            .../otherpkg.go:6:19
-        github.com/shiyanhui/dht.DHT.GetPeers
-            .../dht.go:256:44
-        github.com/shiyanhui/dht.routingTable.GetNeighbors
-            .../routingtable.go:426:22
-        github.com/shiyanhui/dht.getTopK
-            .../routingtable.go:580:21
-        github.com/shiyanhui/dht.bitmap.Xor
-            .../bitmap.go:129:5
-        github.com/shiyanhui/dht.xor
-          There are 2 more call stacks available.
-      To see all of them, pass the -json flags.
 
   Found in: github.com/shiyanhui/dht@v0.0.0-20201219151056-5a20f3199263
   Fixed in: N/A
diff --git a/internal/govulncheck/legacy_run.go b/internal/govulncheck/legacy_run.go
index 97e080d..d291140 100644
--- a/internal/govulncheck/legacy_run.go
+++ b/internal/govulncheck/legacy_run.go
@@ -159,7 +159,8 @@
 	for idx, vg := range ci.vulnGroups {
 		fmt.Println()
 		// All the vulns in vg have the same PkgPath, ModPath and OSV.
-		// All have a non-zero CallSink.
+		// All have a non-zero CallSink when not in binary mode, otherwise
+		// they all have a zero CallSink.
 
 		// TODO(https://go.dev/issue/56042): add ID, details, found and fixed
 		// below to govulncheck.Result.
@@ -169,21 +170,23 @@
 		found := packageVersionString(v0.PkgPath, foundVersion(v0.ModPath, ci))
 		fixed := packageVersionString(v0.PkgPath, fixedVersion(v0.ModPath, v0.OSV.Affected))
 
-		// TODO(https://go.dev/issue/56042): add stacks to govulncheck.Result.
-		var stacks string
-		if !verbose {
-			stacks = defaultCallStacks(vg, ci)
-		} else {
-			stacks = verboseCallStacks(vg, ci)
-		}
-		var b strings.Builder
-		if len(stacks) > 0 {
-			b.WriteString(indent("\n\nCall stacks in your code:\n", 2))
-			b.WriteString(indent(stacks, 6))
+		var stacksBuilder strings.Builder
+		if r.Calls != nil { // there are no call stacks in binary mode
+			// TODO(https://go.dev/issue/56042): add stacks to govulncheck.Result.
+			var stacks string
+			if !verbose {
+				stacks = defaultCallStacks(vg, ci, r)
+			} else {
+				stacks = verboseCallStacks(vg, ci, r)
+			}
+			if len(stacks) > 0 {
+				stacksBuilder.WriteString(indent("\n\nCall stacks in your code:\n", 2))
+				stacksBuilder.WriteString(indent(stacks, 6))
+			}
 		}
 		// TODO(https://go.dev/issue/56042): add platform and callstack summary
 		// to govulncheck.Result
-		writeVulnerability(idx+1, id, details, b.String(), found, fixed, platforms(v0.OSV))
+		writeVulnerability(idx+1, id, details, stacksBuilder.String(), found, fixed, platforms(v0.OSV))
 	}
 	if len(unaffected) > 0 {
 		fmt.Println()
@@ -228,15 +231,16 @@
 	return fixed
 }
 
-func defaultCallStacks(vg []*vulncheck.Vuln, ci *callInfo) string {
+func defaultCallStacks(vg []*vulncheck.Vuln, ci *callInfo, r *vulncheck.Result) string {
 	var summaries []string
-	for _, v := range vg {
-		if css := ci.callStacks[v]; len(css) > 0 {
-			if sum := SummarizeCallStack(css[0], ci.topPackages, v.PkgPath); sum != "" {
-				summaries = append(summaries, strings.TrimSpace(sum))
-			}
+	forUniqueCallStacks(vg, ci, r, func(v *vulncheck.Vuln, cs vulncheck.CallStack, ci *callInfo) {
+		if sum := SummarizeCallStack(cs, ci.topPackages, v.PkgPath); sum != "" {
+			summaries = append(summaries, strings.TrimSpace(sum))
 		}
-	}
+	})
+
+	// Sort call stack summaries and get rid of duplicates.
+	// Note that different call stacks can yield same summaries.
 	if len(summaries) > 0 {
 		sort.Strings(summaries)
 		summaries = compact(summaries)
@@ -249,26 +253,22 @@
 	return b.String()
 }
 
-func verboseCallStacks(vg []*vulncheck.Vuln, ci *callInfo) string {
+func verboseCallStacks(vg []*vulncheck.Vuln, ci *callInfo, r *vulncheck.Result) string {
 	// Display one full call stack for each vuln.
 	i := 1
 	nMore := 0
 	var b strings.Builder
-	for _, v := range vg {
-		css := ci.callStacks[v]
-		if len(css) == 0 {
-			continue
-		}
+	forUniqueCallStacks(vg, ci, r, func(v *vulncheck.Vuln, cs vulncheck.CallStack, ci *callInfo) {
 		b.WriteString(fmt.Sprintf("#%d: for function %s\n", i, v.Symbol))
-		for _, e := range css[0] {
+		for _, e := range cs {
 			b.WriteString(fmt.Sprintf("  %s\n", FuncName(e.Function)))
 			if pos := AbsRelShorter(FuncPos(e.Call)); pos != "" {
 				b.WriteString(fmt.Sprintf("      %s\n", pos))
 			}
 		}
 		i++
-		nMore += len(css) - 1
-	}
+		nMore += len(ci.callStacks[v]) - 1
+	})
 	if nMore > 0 {
 		b.WriteString(fmt.Sprintf("    There are %d more call stacks available.\n", nMore))
 		b.WriteString(fmt.Sprintf("To see all of them, pass the -json flags.\n"))
@@ -276,6 +276,35 @@
 	return b.String()
 }
 
+// forUniqueCallStacks applies f to each unique call stack of vg.
+func forUniqueCallStacks(vg []*vulncheck.Vuln, ci *callInfo, r *vulncheck.Result, f func(v *vulncheck.Vuln, cs vulncheck.CallStack, ci *callInfo)) {
+	vulnFuncs := make(map[*vulncheck.FuncNode]bool)
+	for _, v := range vg {
+		vulnFuncs[r.Calls.Functions[v.CallSink]] = true
+	}
+	for _, v := range vg {
+		vFunc := r.Calls.Functions[v.CallSink]
+		if cs := uniqueCallStack(vFunc, ci.callStacks[v], vulnFuncs); cs != nil {
+			f(v, cs, ci)
+		}
+	}
+}
+
+// uniqueCallStack returns the first member of stacks for vulnFunc that does not
+// go through skip list (except vulnFunc). Returns nil if no such stack can be found.
+func uniqueCallStack(vulnFunc *vulncheck.FuncNode, stacks []vulncheck.CallStack, skip map[*vulncheck.FuncNode]bool) vulncheck.CallStack {
+callstack:
+	for _, cs := range stacks {
+		for _, e := range cs {
+			if e.Function != vulnFunc && skip[e.Function] {
+				continue callstack
+			}
+		}
+		return cs
+	}
+	return nil
+}
+
 // platforms returns a string describing the GOOS/GOARCH pairs that the vuln affects.
 // If it affects all of them, it returns the empty string.
 func platforms(e *osv.Entry) string {
diff --git a/internal/govulncheck/run_test.go b/internal/govulncheck/run_test.go
index c325712..71fc2d4 100644
--- a/internal/govulncheck/run_test.go
+++ b/internal/govulncheck/run_test.go
@@ -9,6 +9,7 @@
 
 	"github.com/google/go-cmp/cmp"
 	"golang.org/x/vuln/osv"
+	"golang.org/x/vuln/vulncheck"
 )
 
 func TestLatestFixed(t *testing.T) {
@@ -182,3 +183,41 @@
 		})
 	}
 }
+
+func TestUniqueCallStack(t *testing.T) {
+	a := &vulncheck.FuncNode{Name: "A"}
+	b := &vulncheck.FuncNode{Name: "B"}
+	v1 := &vulncheck.FuncNode{Name: "V1"}
+	v2 := &vulncheck.FuncNode{Name: "V2"}
+	v3 := &vulncheck.FuncNode{Name: "V3"}
+
+	callStack := func(fs ...*vulncheck.FuncNode) vulncheck.CallStack {
+		var cs vulncheck.CallStack
+		for _, f := range fs {
+			cs = append(cs, vulncheck.StackEntry{Function: f})
+		}
+		return cs
+	}
+
+	// V1, V2, and V3 are vulnerable symbols
+	skip := map[*vulncheck.FuncNode]bool{v1: true, v2: true, v3: true}
+	for _, test := range []struct {
+		v    *vulncheck.FuncNode
+		css  []vulncheck.CallStack
+		want vulncheck.CallStack
+	}{
+		// [A -> B -> V3 -> V1, A -> V1] ==> A -> V1 since the first stack goes through V3
+		{v1, []vulncheck.CallStack{callStack(a, b, v3, v1), callStack(a, v1)}, callStack(a, v1)},
+		// [A -> V1 -> V2] ==> nil since the only candidate call stack goes through V1
+		{v2, []vulncheck.CallStack{callStack(a, v1, v2)}, nil},
+		// [A -> V1 -> V3, A -> B -> v3] ==> A -> B -> V3 since the first stack goes through V1
+		{v3, []vulncheck.CallStack{callStack(a, v1, v3), callStack(a, b, v3)}, callStack(a, b, v3)},
+	} {
+		t.Run(test.v.Name, func(t *testing.T) {
+			got := uniqueCallStack(test.v, test.css, skip)
+			if diff := cmp.Diff(test.want, got); diff != "" {
+				t.Fatalf("mismatch (-want, +got):\n%s", diff)
+			}
+		})
+	}
+}