mirror of
https://github.com/github/codeql.git
synced 2025-12-24 04:36:35 +01:00
add self parameters to API-graphs, and add support for self parameters in MaD
This commit is contained in:
@@ -136,6 +136,9 @@ module API {
|
||||
result = this.getASuccessor(Label::keywordParameter(name))
|
||||
}
|
||||
|
||||
/** Gets the node representing the self parameter */
|
||||
Node getSelfParameter() { result = this.getASuccessor(Label::selfParameter()) }
|
||||
|
||||
/**
|
||||
* Gets the number of parameters of the function represented by this node.
|
||||
*/
|
||||
@@ -315,6 +318,12 @@ module API {
|
||||
/** Gets the API node for a parameter of this invocation. */
|
||||
Node getAParameter() { result = this.getParameter(_) }
|
||||
|
||||
/** Gets the object that this method-call is being called on, if this is a method-call */
|
||||
Node getSelfParameter() {
|
||||
result.getARhs() = this.(DataFlow::MethodCallNode).getObject() and
|
||||
result = callee.getSelfParameter()
|
||||
}
|
||||
|
||||
/** Gets the API node for the keyword parameter `name` of this invocation. */
|
||||
Node getKeywordParameter(string name) {
|
||||
result = callee.getKeywordParameter(name) and
|
||||
@@ -595,6 +604,9 @@ module API {
|
||||
lbl = Label::keywordParameter(name) and
|
||||
ref.asExpr() = fn.getInnerScope().getArgByName(name)
|
||||
)
|
||||
or
|
||||
lbl = Label::selfParameter() and
|
||||
ref.asExpr() = any(PY::Parameter p | p = fn.getInnerScope().getAnArg() and p.isSelf())
|
||||
)
|
||||
or
|
||||
// Built-ins, treated as members of the module `builtins`
|
||||
@@ -661,6 +673,9 @@ module API {
|
||||
exists(string name | lbl = Label::keywordParameter(name) |
|
||||
arg = pred.getACall().getArgByName(name)
|
||||
)
|
||||
or
|
||||
lbl = Label::selfParameter() and
|
||||
arg = pred.getACall().(DataFlow::MethodCallNode).getObject()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -777,6 +792,7 @@ module API {
|
||||
or
|
||||
exists(any(PY::Function f).getArgByName(name))
|
||||
} or
|
||||
MkLabelSelfParameter() or
|
||||
MkLabelReturn() or
|
||||
MkLabelSubclass() or
|
||||
MkLabelAwait()
|
||||
@@ -834,6 +850,11 @@ module API {
|
||||
string getName() { result = name }
|
||||
}
|
||||
|
||||
/** A label for the self parameter. */
|
||||
class LabelSelfParameter extends ApiLabel, MkLabelSelfParameter {
|
||||
override string toString() { result = "getSelfParameter()" }
|
||||
}
|
||||
|
||||
/** A label that gets the return value of a function. */
|
||||
class LabelReturn extends ApiLabel, MkLabelReturn {
|
||||
override string toString() { result = "getReturn()" }
|
||||
@@ -873,6 +894,9 @@ module API {
|
||||
/** Gets the `parameter` edge label for the keyword parameter `name`. */
|
||||
LabelKeywordParameter keywordParameter(string name) { result.getName() = name }
|
||||
|
||||
/** Gets the edge label for the self parameter. */
|
||||
LabelSelfParameter selfParameter() { any() }
|
||||
|
||||
/** Gets the `return` edge label. */
|
||||
LabelReturn return() { any() }
|
||||
|
||||
|
||||
@@ -63,6 +63,10 @@ API::Node getExtraSuccessorFromNode(API::Node node, AccessPathToken token) {
|
||||
or
|
||||
token.getName() = "Method" and
|
||||
result = node.getMember(token.getAnArgument()).getReturn()
|
||||
or
|
||||
token.getName() = ["Argument", "Parameter"] and
|
||||
token.getAnArgument() = "self" and
|
||||
result = node.getSelfParameter()
|
||||
// Some features don't have MaD tokens yet, they would need to be added to API-graphs first.
|
||||
// - decorators ("DecoratedClass", "DecoratedMember", "DecoratedParameter")
|
||||
// - Array/Map elements ("ArrayElement", "Element", "MapKey", "MapValue")
|
||||
@@ -78,7 +82,7 @@ API::Node getExtraSuccessorFromInvoke(API::CallNode node, AccessPathToken token)
|
||||
or
|
||||
token.getName() = "Argument" and
|
||||
token.getAnArgument() = "self" and
|
||||
result.getARhs() = node.(DataFlow::MethodCallNode).getObject() // TODO: Get proper support for this in API-graphs?
|
||||
result = node.getSelfParameter()
|
||||
or
|
||||
token.getName() = "Argument" and
|
||||
exists(string arg | arg + ":" = token.getAnArgument() | result = node.getKeywordParameter(arg))
|
||||
|
||||
@@ -23,6 +23,7 @@ isSink
|
||||
| test.py:33:22:33:24 | ControlFlowNode for one | test-source |
|
||||
| test.py:33:27:33:29 | ControlFlowNode for two | test-source |
|
||||
| test.py:33:32:33:36 | ControlFlowNode for three | test-source |
|
||||
| test.py:57:7:57:12 | ControlFlowNode for ArgPos | test-source |
|
||||
isSource
|
||||
| test.py:3:5:3:15 | ControlFlowNode for getSource() | test-source |
|
||||
| test.py:9:8:9:14 | ControlFlowNode for alias() | test-source |
|
||||
@@ -43,6 +44,7 @@ isSource
|
||||
| test.py:46:7:46:16 | ControlFlowNode for SubClass() | test-source |
|
||||
| test.py:51:8:51:18 | ControlFlowNode for Sub2Class() | test-source |
|
||||
| test.py:53:7:53:16 | ControlFlowNode for Attribute() | test-source |
|
||||
| test.py:60:13:60:16 | ControlFlowNode for self | test-source |
|
||||
syntaxErrors
|
||||
| Member[foo |
|
||||
| Member[foo] .Member[bar] |
|
||||
|
||||
@@ -50,4 +50,12 @@ class Sub2Class (CommonTokens.Class):
|
||||
|
||||
sub2 = Sub2Class()
|
||||
|
||||
val = inst.foo()
|
||||
val = inst.foo()
|
||||
|
||||
from testlib import ArgPos
|
||||
|
||||
val = ArgPos.selfThing(arg, named=2)
|
||||
|
||||
class SubClass (ArgPos.MyClass):
|
||||
def foo(self, arg, named=2):
|
||||
pass
|
||||
@@ -49,11 +49,12 @@ class Sinks extends ModelInput::SinkModelCsv {
|
||||
// callsite filter.
|
||||
"testlib;;Member[CallFilter].Member[arityOne].WithArity[1].Argument[0..];test-source", //
|
||||
"testlib;;Member[CallFilter].Member[twoOrMore].WithArity[2..].Argument[0..];test-source", //
|
||||
// testing non-positional arguments
|
||||
"testlib;;Member[ArgPos].Member[selfThing].Argument[self];test-source", //
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Uniform tokens for fields
|
||||
// TODO: Non-positional arguments (including Named parameters)
|
||||
// TODO: Any argument
|
||||
// TODO: Test taint steps.
|
||||
@@ -75,6 +76,8 @@ class Sources extends ModelInput::SourceModelCsv {
|
||||
"testlib;;Member[CommonTokens].Member[Super].Subclass.Instance;test-source", //
|
||||
// method
|
||||
"testlib;;Member[CommonTokens].Member[Class].Instance.Method[foo];test-source", //
|
||||
// testing non-positional arguments
|
||||
"testlib;;Member[ArgPos].Member[MyClass].Subclass.Member[foo].Parameter[self];test-source", //
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user