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

Skip to content

Commit e808d30

Browse files
committed
Python: Add magic to DataFlowCall
1 parent 4211f7f commit e808d30

3 files changed

Lines changed: 87 additions & 10 deletions

File tree

python/ql/src/experimental/dataflow/internal/DataFlowPrivate.qll

Lines changed: 58 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
private import python
22
private import DataFlowPublic
3+
import semmle.python.Magic
34

45
//--------
56
// Data flow graph
@@ -157,17 +158,67 @@ class DataFlowClassValue extends DataFlowCallable, TClassValue {
157158
override string getName() { result = c.getName() }
158159
}
159160

160-
/** Represents a call to a callable */
161-
class DataFlowCall extends CallNode {
162-
DataFlowCallable callable;
161+
newtype TDataFlowCall =
162+
TCallNode(CallNode call) or
163+
TMagicCall(MagicMethod::Actual magic)
163164

164-
DataFlowCall() { this = callable.getACall() }
165+
abstract class DataFlowCall extends TDataFlowCall {
166+
/** Gets a textual representation of this element. */
167+
abstract string toString();
165168

166169
/** Get the callable to which this call goes. */
167-
DataFlowCallable getCallable() { result = callable }
170+
abstract DataFlowCallable getCallable();
171+
172+
/** Get the specified arguemnt to this call. */
173+
abstract ControlFlowNode getArg(int n);
174+
175+
/** Get the control flow node representing this call. */
176+
abstract ControlFlowNode getNode();
168177

169178
/** Gets the enclosing callable of this call. */
170-
DataFlowCallable getEnclosingCallable() { result.getScope() = this.getNode().getScope() }
179+
abstract DataFlowCallable getEnclosingCallable();
180+
}
181+
182+
183+
/** Represents a call to a callable */
184+
class CallNodeCall extends DataFlowCall, TCallNode {
185+
CallNode call;
186+
DataFlowCallable callable;
187+
188+
CallNodeCall() {
189+
this = TCallNode(call) and
190+
call = callable.getACall()
191+
}
192+
193+
override string toString() { result = call.toString() }
194+
195+
override ControlFlowNode getArg(int n) {
196+
result = call.getArg(n)
197+
}
198+
199+
override ControlFlowNode getNode() { result = call }
200+
201+
override DataFlowCallable getCallable() { result = callable }
202+
203+
override DataFlowCallable getEnclosingCallable() { result.getScope() = call.getNode().getScope() }
204+
}
205+
206+
class MagicCall extends DataFlowCall, TMagicCall {
207+
MagicMethod::Actual magic;
208+
209+
MagicCall() { this = TMagicCall(magic) }
210+
211+
override string toString() { result = magic.toString() }
212+
213+
override ControlFlowNode getArg(int n) {
214+
result = magic.(MagicMethod::Potential).getArg(n)
215+
}
216+
217+
override ControlFlowNode getNode() { result = magic }
218+
219+
override DataFlowCallable getCallable() { result = TCallableValue(magic.getResolvedMagicMethod()) }
220+
221+
override DataFlowCallable getEnclosingCallable() { result.getScope() = magic.getNode().getScope() }
171222
}
172223

173224
/** A data flow node that represents a call argument. */
@@ -220,7 +271,7 @@ class OutNode extends CfgNode {
220271
* `kind`.
221272
*/
222273
OutNode getAnOutNode(DataFlowCall call, ReturnKind kind) {
223-
call = result.getNode() and
274+
call.getNode() = result.getNode() and
224275
kind = TNormalReturnKind()
225276
}
226277

python/ql/src/semmle/python/Magic.qll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ module MagicMethod {
44
abstract class Potential extends ControlFlowNode {
55
abstract string getMagicMethodName();
66
abstract ControlFlowNode getArg(int n);
7-
ControlFlowNode getSelf() { result = this.getArg(1) }
7+
ControlFlowNode getSelf() { result = this.getArg(0) }
88
}
99

1010
class Actual extends ControlFlowNode {
@@ -31,8 +31,8 @@ class MagicBinOp extends MagicMethod::Potential, BinaryExprNode {
3131
}
3232

3333
override ControlFlowNode getArg(int n) {
34-
n = 1 and result = this.getLeft()
34+
n = 0 and result = this.getLeft()
3535
or
36-
n = 2 and result = this.getRight()
36+
n = 1 and result = this.getRight()
3737
}
3838
}

python/ql/test/experimental/dataflow/coverage/classesCallGraph.expected

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,29 @@
44
| classes.py:182:7:182:26 | ControlFlowNode for dict() | classes.py:182:7:182:26 | ControlFlowNode for dict() |
55
| classes.py:303:28:303:51 | ControlFlowNode for dict() | classes.py:303:28:303:51 | ControlFlowNode for dict() |
66
| classes.py:466:12:466:24 | ControlFlowNode for Attribute() | classes.py:466:12:466:24 | ControlFlowNode for Attribute() |
7+
| classes.py:505:3:505:10 | ControlFlowNode for with_add | classes.py:499:15:499:18 | SSA variable self |
8+
| classes.py:505:14:505:21 | ControlFlowNode for with_add | classes.py:499:21:499:25 | SSA variable other |
9+
| classes.py:516:3:516:10 | ControlFlowNode for with_sub | classes.py:510:15:510:18 | SSA variable self |
10+
| classes.py:516:14:516:21 | ControlFlowNode for with_sub | classes.py:510:21:510:25 | SSA variable other |
11+
| classes.py:527:3:527:10 | ControlFlowNode for with_mul | classes.py:521:15:521:18 | SSA variable self |
12+
| classes.py:527:14:527:21 | ControlFlowNode for with_mul | classes.py:521:21:521:25 | SSA variable other |
13+
| classes.py:538:3:538:13 | ControlFlowNode for with_matmul | classes.py:532:18:532:21 | SSA variable self |
14+
| classes.py:538:17:538:27 | ControlFlowNode for with_matmul | classes.py:532:24:532:28 | SSA variable other |
15+
| classes.py:549:3:549:14 | ControlFlowNode for with_truediv | classes.py:543:19:543:22 | SSA variable self |
16+
| classes.py:549:18:549:29 | ControlFlowNode for with_truediv | classes.py:543:25:543:29 | SSA variable other |
17+
| classes.py:560:3:560:15 | ControlFlowNode for with_floordiv | classes.py:554:20:554:23 | SSA variable self |
18+
| classes.py:560:20:560:32 | ControlFlowNode for with_floordiv | classes.py:554:26:554:30 | SSA variable other |
19+
| classes.py:571:3:571:10 | ControlFlowNode for with_mod | classes.py:565:15:565:18 | SSA variable self |
20+
| classes.py:571:14:571:21 | ControlFlowNode for with_mod | classes.py:565:21:565:25 | SSA variable other |
21+
| classes.py:597:3:597:10 | ControlFlowNode for with_pow | classes.py:587:15:587:18 | SSA variable self |
22+
| classes.py:597:15:597:22 | ControlFlowNode for with_pow | classes.py:587:21:587:25 | SSA variable other |
23+
| classes.py:608:3:608:13 | ControlFlowNode for with_lshift | classes.py:602:18:602:21 | SSA variable self |
24+
| classes.py:608:18:608:28 | ControlFlowNode for with_lshift | classes.py:602:24:602:28 | SSA variable other |
25+
| classes.py:619:3:619:13 | ControlFlowNode for with_rshift | classes.py:613:18:613:21 | SSA variable self |
26+
| classes.py:619:18:619:28 | ControlFlowNode for with_rshift | classes.py:613:24:613:28 | SSA variable other |
27+
| classes.py:630:3:630:10 | ControlFlowNode for with_and | classes.py:624:15:624:18 | SSA variable self |
28+
| classes.py:630:14:630:21 | ControlFlowNode for with_and | classes.py:624:21:624:25 | SSA variable other |
29+
| classes.py:641:3:641:10 | ControlFlowNode for with_xor | classes.py:635:15:635:18 | SSA variable self |
30+
| classes.py:641:14:641:21 | ControlFlowNode for with_xor | classes.py:635:21:635:25 | SSA variable other |
31+
| classes.py:652:3:652:9 | ControlFlowNode for with_or | classes.py:646:14:646:17 | SSA variable self |
32+
| classes.py:652:13:652:19 | ControlFlowNode for with_or | classes.py:646:20:646:24 | SSA variable other |

0 commit comments

Comments
 (0)