Skip to content

Commit 67b1414

Browse files
committed
Python: Highlight even more cases for multipleArgumentCallExclude
1 parent f9d7bec commit 67b1414

File tree

1 file changed

+40
-0
lines changed

1 file changed

+40
-0
lines changed

python/ql/consistency-queries/DataFlowConsistency.ql

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
private import python
77
import semmle.python.dataflow.new.DataFlow::DataFlow
88
private import semmle.python.dataflow.new.internal.DataFlowImplSpecific
9+
private import semmle.python.dataflow.new.internal.DataFlowDispatch
910
private import semmle.python.dataflow.new.internal.TaintTrackingImplSpecific
1011
private import codeql.dataflow.internal.DataFlowImplConsistency
1112

@@ -60,6 +61,45 @@ private module Input implements InputSig<PythonDataFlow> {
6061
isArgumentNode(arg, call, _) and
6162
isArgumentNode(arg, other, _)
6263
)
64+
or
65+
// bound methods that refer to the same self argument.
66+
// Example: In `bm = self.foo; bm(); bm()` both bm() calls use the same `self` as
67+
// the (pos self) argument
68+
exists(AttrRead attr, DataFlowCall other | other != call |
69+
any(CfgNode n | n.asCfgNode() = call.getNode().(CallNode).getFunction()).getALocalSource() =
70+
attr and
71+
any(CfgNode n | n.asCfgNode() = other.getNode().(CallNode).getFunction()).getALocalSource() =
72+
attr and
73+
arg = call.getArgument(any(ArgumentPosition p | p.isSelf())) and
74+
arg = other.getArgument(any(ArgumentPosition p | p.isSelf()))
75+
)
76+
or
77+
// `f = getattr(obj, "foo"); f()` where `obj` is used as (pos self) argument for
78+
// `f()` call
79+
exists(DataFlowCall getAttrCall, DataFlowCall methodCall, AttrRead attr |
80+
call in [getAttrCall, methodCall]
81+
|
82+
arg = getAttrCall.getArgument(any(ArgumentPosition p | p.isPositional(0))) and
83+
arg = methodCall.getArgument(any(ArgumentPosition p | p.isSelf())) and
84+
attr.getObject() = arg and
85+
attr.(CfgNode).getNode() = getAttrCall.getNode()
86+
)
87+
or
88+
// In the code `super(Base, self).foo()` we use `self` as an argument in both the
89+
// super() call (pos 1) and in the .foo() call (pos self).
90+
exists(DataFlowCall superCall, DataFlowCall methodCall | call in [superCall, methodCall] |
91+
exists(superCallTwoArgumentTracker(_, arg)) and
92+
arg = superCall.getArgument(any(ArgumentPosition p | p.isPositional(1))) and
93+
arg = methodCall.getArgument(any(ArgumentPosition p | p.isSelf()))
94+
)
95+
or
96+
// in the code `def func(self): super().foo(); super.bar()` we use `self` as the
97+
// (pos self) argument in both .foo() and .bar() calls.
98+
exists(Function f |
99+
exprNode(f.getArg(0)) = arg and
100+
call.getNode().getScope() = f and
101+
arg = call.getArgument(any(ArgumentPosition p | p.isSelf()))
102+
)
63103
}
64104
}
65105

0 commit comments

Comments
 (0)