Skip to content

Commit 00d5cb7

Browse files
committed
Different approach to avoiding getTarget()
1 parent d2b8d83 commit 00d5cb7

File tree

2 files changed

+32
-7
lines changed

2 files changed

+32
-7
lines changed

go/ql/lib/semmle/go/dataflow/internal/DataFlowDispatch.qll

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,10 @@ class ArgumentPosition extends int {
134134
pragma[inline]
135135
predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) { ppos = apos }
136136

137+
private predicate isInterfaceMethod(Method c) {
138+
c.getReceiverBaseType().getUnderlyingType() instanceof InterfaceType
139+
}
140+
137141
/**
138142
* Holds if `call` is passing `arg` to param `p` in any circumstance except passing
139143
* a receiver parameter to a concrete method.
@@ -147,6 +151,17 @@ predicate golangSpecificParamArgFilter(
147151
or
148152
p instanceof DataFlow::SummarizedParameterNode
149153
or
150-
not call.getNode().(DataFlow::CallNode).getReceiver().getType().getUnderlyingType() instanceof
151-
InterfaceType
154+
not isInterfaceMethod(call.getNode()
155+
.(DataFlow::CallNode)
156+
.getACalleeWithoutVirtualDispatch()
157+
.asFunction())
158+
}
159+
160+
predicate foo(DataFlowCall call, DataFlow::Node rec0) {
161+
exists(DataFlow::Node rec | rec = call.getNode().(DataFlow::CallNode).getReceiver() |
162+
rec = rec0 and rec.getType().getUnderlyingType() instanceof InterfaceType
163+
) and
164+
not exists(Function callTarget | callTarget = call.getNode().(DataFlow::CallNode).getTarget() |
165+
not isInterfaceMethod(callTarget)
166+
)
152167
}

go/ql/lib/semmle/go/dataflow/internal/DataFlowNodes.qll

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -489,13 +489,9 @@ module Public {
489489
* interface type.
490490
*/
491491
Callable getACalleeIncludingExternals() {
492-
result.asFunction() = this.getTarget()
492+
result = this.getACalleeWithoutVirtualDispatch()
493493
or
494494
exists(DataFlow::Node calleeSource | calleeSource = this.getACalleeSource() |
495-
result.asFuncLit() = calleeSource.asExpr()
496-
or
497-
calleeSource = result.asFunction().getARead()
498-
or
499495
exists(Method declared, Method actual |
500496
calleeSource = declared.getARead() and
501497
actual.implements(declared) and
@@ -510,6 +506,20 @@ module Public {
510506
*/
511507
FuncDef getACallee() { result = this.getACalleeIncludingExternals().getFuncDef() }
512508

509+
/**
510+
* As `getACalleeIncludingExternals`, except excluding external functions (those for which
511+
* we lack a definition, such as standard library functions).
512+
*/
513+
Callable getACalleeWithoutVirtualDispatch() {
514+
result.asFunction() = this.getTarget()
515+
or
516+
exists(DataFlow::Node calleeSource | calleeSource = this.getACalleeSource() |
517+
result.asFuncLit() = calleeSource.asExpr()
518+
or
519+
calleeSource = result.asFunction().getARead()
520+
)
521+
}
522+
513523
/**
514524
* Gets the name of the function, method or variable that is being called.
515525
*

0 commit comments

Comments
 (0)