Merge pull request #4077 from yoff/MagicMethods

Python: Add support for magic methods
This commit is contained in:
Taus
2020-08-27 13:20:56 +02:00
committed by GitHub
8 changed files with 1347 additions and 805 deletions

View File

@@ -1,5 +1,6 @@
private import python
private import DataFlowPublic
import semmle.python.SpecialMethods
//--------
// Data flow graph
@@ -164,17 +165,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
TSpecialCall(SpecialMethodCallNode special)
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 argument 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() }
}
/** Represents a call to a special method. */
class SpecialCall extends DataFlowCall, TSpecialCall {
SpecialMethodCallNode special;
SpecialCall() { this = TSpecialCall(special) }
override string toString() { result = special.toString() }
override ControlFlowNode getArg(int n) { result = special.(SpecialMethod::Potential).getArg(n) }
override ControlFlowNode getNode() { result = special }
override DataFlowCallable getCallable() {
result = TCallableValue(special.getResolvedSpecialMethod())
}
override DataFlowCallable getEnclosingCallable() {
result.getScope() = special.getNode().getScope()
}
}
/** A data flow node that represents a call argument. */
@@ -227,7 +278,7 @@ class OutNode extends CfgNode {
* `kind`.
*/
OutNode getAnOutNode(DataFlowCall call, ReturnKind kind) {
call = result.getNode() and
call.getNode() = result.getNode() and
kind = TNormalReturnKind()
}