mirror of
https://github.com/github/codeql.git
synced 2025-12-25 05:06:34 +01:00
Resolve instance method calls
This commit is contained in:
@@ -110,7 +110,7 @@ private predicate isDefinedConstant(string qualifiedModuleName) {
|
||||
* definition is a Namespace then it is returned, if it's a constant assignment then
|
||||
* the right-hand side of the assignment is resolved.
|
||||
*/
|
||||
private TResolved resolveScopeExpr(ConstantReadAccess r) {
|
||||
TResolved resolveScopeExpr(ConstantReadAccess r) {
|
||||
exists(string qname |
|
||||
qname =
|
||||
min(string qn, int p |
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
private import ruby
|
||||
private import codeql_ruby.CFG
|
||||
private import DataFlowPrivate
|
||||
private import codeql_ruby.typetracking.TypeTracker
|
||||
private import codeql_ruby.dataflow.internal.DataFlowPublic as DataFlow
|
||||
private import codeql_ruby.ast.internal.Module
|
||||
|
||||
newtype TReturnKind =
|
||||
TNormalReturnKind() or
|
||||
@@ -42,12 +45,66 @@ class DataFlowCall extends CfgNodes::ExprNodes::CallCfgNode {
|
||||
DataFlowCallable getEnclosingCallable() { result = this.getScope() }
|
||||
|
||||
DataFlowCallable getTarget() {
|
||||
// TODO: this is a placeholder that finds a method with the same name, iff it's uniquely named.
|
||||
result =
|
||||
unique(DataFlowCallable c | c.(Method).getName() = this.getNode().(MethodCall).getMethodName())
|
||||
exists(MethodCall mcall, Module tp |
|
||||
mcall = this.getExpr() and
|
||||
result = lookupMethod(tp, mcall.getMethodName())
|
||||
|
|
||||
exists(DataFlow::Node nodeTo |
|
||||
nodeTo.asExpr() = this.getReceiver() and
|
||||
trackInstance(tp).flowsTo(nodeTo)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private DataFlow::LocalSourceNode trackInstance(Module tp, TypeTracker t) {
|
||||
t.start() and
|
||||
(
|
||||
exists(CfgNodes::ExprNodes::CallCfgNode call, DataFlow::Node nodeTo |
|
||||
call.getExpr().(MethodCall).getMethodName() = "new" and
|
||||
nodeTo.asExpr() = call.getReceiver() and
|
||||
trackModule(tp).flowsTo(nodeTo) and
|
||||
result.asExpr() = call
|
||||
)
|
||||
or
|
||||
// `self` in method
|
||||
exists(Self self, Method enclosing |
|
||||
self = result.asExpr().getExpr() and
|
||||
enclosing = self.getEnclosingMethod() and
|
||||
tp = enclosing.getEnclosingModule().getModule() and
|
||||
not self.getEnclosingModule().getEnclosingMethod() = enclosing
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(TypeTracker t2 | result = trackInstance(tp, t2).track(t2, t))
|
||||
}
|
||||
|
||||
private DataFlow::LocalSourceNode trackInstance(Module tp) {
|
||||
result = trackInstance(tp, TypeTracker::end())
|
||||
}
|
||||
|
||||
private DataFlow::LocalSourceNode trackModule(Module tp, TypeTracker t) {
|
||||
t.start() and
|
||||
(
|
||||
// ConstantReadAccess to Module
|
||||
resolveScopeExpr(result.asExpr().getExpr()) = tp
|
||||
or
|
||||
// `self` reference to Module
|
||||
exists(Self self, ModuleBase enclosing |
|
||||
self = result.asExpr().getExpr() and
|
||||
enclosing = self.getEnclosingModule() and
|
||||
tp = enclosing.getModule() and
|
||||
not self.getEnclosingMethod().getEnclosingModule() = enclosing
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(TypeTracker t2 | result = trackModule(tp, t2).track(t2, t))
|
||||
}
|
||||
|
||||
private DataFlow::LocalSourceNode trackModule(Module tp) {
|
||||
result = trackModule(tp, TypeTracker::end())
|
||||
}
|
||||
|
||||
/** Gets a viable run-time target for the call `call`. */
|
||||
DataFlowCallable viableCallable(DataFlowCall call) { none() }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user