Python: Add magic to DataFlowCall

This commit is contained in:
Rasmus Lerchedahl Petersen
2020-08-14 14:19:18 +02:00
parent 4211f7f346
commit e808d3033a
3 changed files with 87 additions and 10 deletions

View File

@@ -1,5 +1,6 @@
private import python
private import DataFlowPublic
import semmle.python.Magic
//--------
// Data flow graph
@@ -157,17 +158,67 @@ class DataFlowClassValue extends DataFlowCallable, TClassValue {
override string getName() { result = c.getName() }
}
/** Represents a call to a callable */
class DataFlowCall extends CallNode {
DataFlowCallable callable;
newtype TDataFlowCall =
TCallNode(CallNode call) or
TMagicCall(MagicMethod::Actual magic)
DataFlowCall() { this = callable.getACall() }
abstract class DataFlowCall extends TDataFlowCall {
/** Gets a textual representation of this element. */
abstract string toString();
/** Get the callable to which this call goes. */
DataFlowCallable getCallable() { result = callable }
abstract DataFlowCallable getCallable();
/** Get the specified arguemnt to this call. */
abstract ControlFlowNode getArg(int n);
/** Get the control flow node representing this call. */
abstract ControlFlowNode getNode();
/** Gets the enclosing callable of this call. */
DataFlowCallable getEnclosingCallable() { result.getScope() = this.getNode().getScope() }
abstract DataFlowCallable getEnclosingCallable();
}
/** Represents a call to a callable */
class CallNodeCall extends DataFlowCall, TCallNode {
CallNode call;
DataFlowCallable callable;
CallNodeCall() {
this = TCallNode(call) and
call = callable.getACall()
}
override string toString() { result = call.toString() }
override ControlFlowNode getArg(int n) {
result = call.getArg(n)
}
override ControlFlowNode getNode() { result = call }
override DataFlowCallable getCallable() { result = callable }
override DataFlowCallable getEnclosingCallable() { result.getScope() = call.getNode().getScope() }
}
class MagicCall extends DataFlowCall, TMagicCall {
MagicMethod::Actual magic;
MagicCall() { this = TMagicCall(magic) }
override string toString() { result = magic.toString() }
override ControlFlowNode getArg(int n) {
result = magic.(MagicMethod::Potential).getArg(n)
}
override ControlFlowNode getNode() { result = magic }
override DataFlowCallable getCallable() { result = TCallableValue(magic.getResolvedMagicMethod()) }
override DataFlowCallable getEnclosingCallable() { result.getScope() = magic.getNode().getScope() }
}
/** A data flow node that represents a call argument. */
@@ -220,7 +271,7 @@ class OutNode extends CfgNode {
* `kind`.
*/
OutNode getAnOutNode(DataFlowCall call, ReturnKind kind) {
call = result.getNode() and
call.getNode() = result.getNode() and
kind = TNormalReturnKind()
}

View File

@@ -4,7 +4,7 @@ module MagicMethod {
abstract class Potential extends ControlFlowNode {
abstract string getMagicMethodName();
abstract ControlFlowNode getArg(int n);
ControlFlowNode getSelf() { result = this.getArg(1) }
ControlFlowNode getSelf() { result = this.getArg(0) }
}
class Actual extends ControlFlowNode {
@@ -31,8 +31,8 @@ class MagicBinOp extends MagicMethod::Potential, BinaryExprNode {
}
override ControlFlowNode getArg(int n) {
n = 1 and result = this.getLeft()
n = 0 and result = this.getLeft()
or
n = 2 and result = this.getRight()
n = 1 and result = this.getRight()
}
}

View File

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