Python points-to: Fix up matching arguments to parameters.

This commit is contained in:
Mark Shannon
2019-04-08 15:46:44 +01:00
parent 662aedcb13
commit f543adcd38
4 changed files with 63 additions and 21 deletions

View File

@@ -46,6 +46,10 @@ abstract class CallableObjectInternal extends ObjectInternal {
CallNode getACall() { result = this.getACall(_) }
abstract NameNode getParameter(int n);
abstract NameNode getParameterByName(string name);
}
@@ -132,6 +136,14 @@ class PythonFunctionObjectInternal extends CallableObjectInternal, TPythonFuncti
)
}
override NameNode getParameter(int n) {
result.getNode() = this.getScope().getArg(n)
}
override NameNode getParameterByName(string name) {
result.getNode() = this.getScope().getArgByName(name)
}
}
@@ -229,6 +241,13 @@ class BuiltinFunctionObjectInternal extends CallableObjectInternal, TBuiltinFunc
PointsTo::pointsTo(result.getFunction(), ctx, this, _)
}
override NameNode getParameter(int n) {
none()
}
override NameNode getParameterByName(string name) {
none()
}
}
@@ -289,6 +308,14 @@ class BuiltinMethodObjectInternal extends CallableObjectInternal, TBuiltinMethod
PointsTo::pointsTo(result.getFunction(), ctx, this, _)
}
override NameNode getParameter(int n) {
none()
}
override NameNode getParameterByName(string name) {
none()
}
}
class BoundMethodObjectInternal extends CallableObjectInternal, TBoundMethod {
@@ -352,6 +379,14 @@ class BoundMethodObjectInternal extends CallableObjectInternal, TBoundMethod {
PointsTo::pointsTo(result.getFunction(), ctx, this, _)
}
override NameNode getParameter(int n) {
result = this.getFunction().getParameter(n+1)
}
override NameNode getParameterByName(string name) {
result = this.getFunction().getParameterByName(name)
}
}
class ClassMethodObjectInternal extends ObjectInternal, TClassMethod {

View File

@@ -57,21 +57,6 @@ class Value extends TObject {
result = this.(ObjectInternal).getSource()
}
/** Gets the `ControlFlowNode` that will be passed as the nth argument to `this` when called at `call`.
This predicate will correctly handle `x.y()`, treating `x` as the zeroth argument.
*/
ControlFlowNode getArgumentForCall(CallNode call, int n) {
// TO DO..
none()
}
/** Gets the `ControlFlowNode` that will be passed as the named argument to `this` when called at `call`.
This predicate will correctly handle `x.y()`, treating `x` as the self argument.
*/
ControlFlowNode getNamedArgumentForCall(CallNode call, string name) {
// TO DO..
none()
}
}
class ModuleValue extends Value {
@@ -130,6 +115,28 @@ class CallableValue extends Value {
result = this.(PythonFunctionObjectInternal).getScope()
}
NameNode getParameter(int n) {
result = this.(CallableObjectInternal).getParameter(n)
}
NameNode getParameterByName(string name) {
result = this.(CallableObjectInternal).getParameterByName(name)
}
ControlFlowNode getArgumentForCall(CallNode call, NameNode param) {
this.getACall() = call and
(
exists(int n | call.getArg(n) = result and param = this.getParameter(n))
or
exists(string name | call.getArgByName(name) = result and param = this.getParameterByName(name))
)
or
exists(BoundMethodObjectInternal bm |
result = getArgumentForCall(call, param) and
this = bm.getFunction()
)
}
}
class ClassValue extends Value {

View File

@@ -1204,13 +1204,13 @@ library module TaintFlowImplementation {
exists(ParameterDefinition def |
def.getDefiningNode() = param and
exists(CallableValue func, CallNode call |
exists(int n | argument = func.getArgumentForCall(call, n) and param.getNode() = func.getScope().getArg(n))
call.getFunction().pointsTo() = func and
callee = caller.getCallee(call) |
exists(int n | param = func.getParameter(n) and argument = call.getArg(n))
or
exists(string name | argument = func.getNamedArgumentForCall(call, name) and param.getNode() = func.getScope().getArgByName(name))
exists(string name | param = func.getParameterByName(name) and argument = call.getArgByName(name))
or
class_initializer_argument(_, _, call, func, argument, param)
|
callee = caller.getCallee(call)
)
)
}

View File

@@ -71,14 +71,14 @@ abstract class FunctionObject extends Object {
This predicate will correctly handle `x.y()`, treating `x` as the zeroth argument.
*/
ControlFlowNode getArgumentForCall(CallNode call, int n) {
result = theCallable().getArgumentForCall(call, n)
result = theCallable().getArgumentForCall(call, this.getFunction().getArg(n).asName().getAFlowNode())
}
/** Gets the `ControlFlowNode` that will be passed as the named argument to `this` when called at `call`.
This predicate will correctly handle `x.y()`, treating `x` as the self argument.
*/
ControlFlowNode getNamedArgumentForCall(CallNode call, string name) {
result = theCallable().getNamedArgumentForCall(call, name)
result = theCallable().getArgumentForCall(call, this.getFunction().getArgByName(name).asName().getAFlowNode())
}
/** Whether this function never returns. This is an approximation.