Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4d8ca3d

Browse files
committed
Add dataflow callback to filter out receiver argument flow to Golang interface dispatch candidates.
Other langauges stub the callback.
1 parent 7ffe863 commit 4d8ca3d

17 files changed

Lines changed: 108 additions & 16 deletions

File tree

cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowDispatch.qll

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,11 @@ class ArgumentPosition extends int {
7979
/** Holds if arguments at position `apos` match parameters at position `ppos`. */
8080
pragma[inline]
8181
predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) { ppos = apos }
82+
83+
/**
84+
* Holds if flow from `call`'s argument `arg` to parameter `p` is permissible.
85+
*
86+
* This is a filter on top of the language-neutral argument/parameter matching implemented by `viableParamArg`.
87+
*/
88+
pragma[inline]
89+
predicate viableParamArgSpecific(DataFlowCall call, ParameterNode p, ArgumentNode arg) { any() }

cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,8 @@ private module Cached {
425425
exists(ParameterPosition ppos |
426426
viableParam(call, ppos, p) and
427427
argumentPositionMatch(call, arg, ppos) and
428-
compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(p))
428+
compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(p)) and
429+
viableParamArgSpecific(call, p, arg)
429430
)
430431
}
431432

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,3 +271,11 @@ Function viableImplInCallContext(CallInstruction call, CallInstruction ctx) {
271271
/** Holds if arguments at position `apos` match parameters at position `ppos`. */
272272
pragma[inline]
273273
predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) { ppos = apos }
274+
275+
/**
276+
* Holds if flow from `call`'s argument `arg` to parameter `p` is permissible.
277+
*
278+
* This is a filter on top of the language-neutral argument/parameter matching implemented by `viableParamArg`.
279+
*/
280+
pragma[inline]
281+
predicate viableParamArgSpecific(DataFlowCall call, ParameterNode p, ArgumentNode arg) { any() }

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,8 @@ private module Cached {
425425
exists(ParameterPosition ppos |
426426
viableParam(call, ppos, p) and
427427
argumentPositionMatch(call, arg, ppos) and
428-
compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(p))
428+
compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(p)) and
429+
viableParamArgSpecific(call, p, arg)
429430
)
430431
}
431432

csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowDispatch.qll

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,3 +555,11 @@ predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) {
555555
apos.isImplicitCapturedArgumentPosition(v)
556556
)
557557
}
558+
559+
/**
560+
* Holds if flow from `call`'s argument `arg` to parameter `p` is permissible.
561+
*
562+
* This is a filter on top of the language-neutral argument/parameter matching implemented by `viableParamArg`.
563+
*/
564+
pragma[inline]
565+
predicate viableParamArgSpecific(DataFlowCall call, ParameterNode p, ArgumentNode arg) { any() }

csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,8 @@ private module Cached {
425425
exists(ParameterPosition ppos |
426426
viableParam(call, ppos, p) and
427427
argumentPositionMatch(call, arg, ppos) and
428-
compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(p))
428+
compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(p)) and
429+
viableParamArgSpecific(call, p, arg)
429430
)
430431
}
431432

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,25 @@ class ArgumentPosition extends int {
133133
/** Holds if arguments at position `apos` match parameters at position `ppos`. */
134134
pragma[inline]
135135
predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) { ppos = apos }
136+
137+
private predicate isInterfaceMethod(Method c) {
138+
c.getReceiverBaseType().getUnderlyingType() instanceof InterfaceType
139+
}
140+
141+
/**
142+
* Holds if `call` is passing `arg` to param `p` in any circumstance except passing
143+
* a receiver parameter to a concrete method.
144+
*/
145+
pragma[inline]
146+
predicate viableParamArgSpecific(
147+
DataFlowCall call, DataFlow::ParameterNode p, DataFlow::ArgumentNode arg
148+
) {
149+
// Interface methods calls may be passed strictly to that exact method's model receiver:
150+
arg.getPosition() != -1
151+
or
152+
exists(Function callTarget | callTarget = call.getNode().(DataFlow::CallNode).getTarget() |
153+
not isInterfaceMethod(callTarget)
154+
or
155+
callTarget = p.getCallable().asSummarizedCallable().asFunction()
156+
)
157+
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,8 @@ private module Cached {
425425
exists(ParameterPosition ppos |
426426
viableParam(call, ppos, p) and
427427
argumentPositionMatch(call, arg, ppos) and
428-
compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(p))
428+
compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(p)) and
429+
viableParamArgSpecific(call, p, arg)
429430
)
430431
}
431432

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

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,12 @@ module Public {
570570
abstract class ParameterNode extends DataFlow::Node {
571571
/** Holds if this node initializes the `i`th parameter of `c`. */
572572
abstract predicate isParameterOf(DataFlowCallable c, int i);
573+
574+
/** Gets the callable that this parameter belongs to. */
575+
DataFlowCallable getCallable() { this.isParameterOf(result, _) }
576+
577+
/** Gets this parameter's position. */
578+
int getPosition() { this.isParameterOf(_, result) }
573579
}
574580

575581
/**
@@ -722,20 +728,18 @@ module Public {
722728
*/
723729
predicate argumentOf(CallExpr call, int pos) {
724730
call = c.asExpr() and
725-
pos = i and
726-
(
727-
i != -1
728-
or
729-
exists(c.(MethodCallNode).getTarget().getBody())
730-
or
731-
hasExternalSpecification(c.(DataFlow::MethodCallNode).getTarget())
732-
)
731+
pos = i
733732
}
734733

735734
/**
736735
* Gets the `CallNode` this is an argument to.
737736
*/
738737
CallNode getCall() { result = c }
738+
739+
/**
740+
* Gets this argument's position.
741+
*/
742+
int getPosition() { result = i }
739743
}
740744

741745
/**

java/ql/lib/semmle/code/java/dataflow/internal/DataFlowDispatch.qll

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,14 @@ private module DispatchImpl {
171171
/** Holds if arguments at position `apos` match parameters at position `ppos`. */
172172
pragma[inline]
173173
predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) { ppos = apos }
174+
175+
/**
176+
* Holds if flow from `call`'s argument `arg` to parameter `p` is permissible.
177+
*
178+
* This is a filter on top of the language-neutral argument/parameter matching implemented by `viableParamArg`.
179+
*/
180+
pragma[inline]
181+
predicate viableParamArgSpecific(DataFlowCall call, ParameterNode p, ArgumentNode arg) { any() }
174182
}
175183

176184
import DispatchImpl

0 commit comments

Comments
 (0)