mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Model implicit reads of self variables
We already synthesise `self` nodes for method calls with no receiver. This change creates read accesses for each of these synthesised nodes.
This commit is contained in:
@@ -193,3 +193,6 @@ class ClassVariableReadAccess extends ClassVariableAccess, VariableReadAccess {
|
||||
class SelfVariableAccess extends VariableAccess instanceof SelfVariableAccessImpl {
|
||||
final override string getAPrimaryQlClass() { result = "SelfVariableAccess" }
|
||||
}
|
||||
|
||||
/** An access to the `self` variable where the value is read. */
|
||||
class SelfVariableReadAccess extends SelfVariableAccess, VariableReadAccess { }
|
||||
|
||||
@@ -236,8 +236,9 @@ private module Cached {
|
||||
isScopeResolutionMethodCall(g, i)
|
||||
} or
|
||||
TSelfReal(Ruby::Self g) or
|
||||
TSelfSynth(AST::AstNode parent, int i) { mkSynthChild(SelfKind(), parent, i) } or
|
||||
TSelfVariableAccessReal(Ruby::Self self, MethodBase::Range scope) { scopeOf(self) = scope } or
|
||||
TSelfSynth(AST::AstNode parent, int i, AST::SelfVariable v) {
|
||||
mkSynthChild(SelfKind(v), parent, i)
|
||||
} or
|
||||
TSimpleParameter(Ruby::Identifier g) { g instanceof Parameter::Range } or
|
||||
TSimpleSymbolLiteral(Ruby::SimpleSymbol g) or
|
||||
TSingletonClass(Ruby::SingletonClass g) or
|
||||
@@ -478,7 +479,7 @@ private module Cached {
|
||||
or
|
||||
result = TRShiftExprSynth(parent, i)
|
||||
or
|
||||
result = TSelfSynth(parent, i)
|
||||
result = TSelfSynth(parent, i, _)
|
||||
or
|
||||
result = TSplatExprSynth(parent, i)
|
||||
or
|
||||
@@ -706,4 +707,4 @@ class TInstanceVariableAccess = TInstanceVariableAccessReal or TInstanceVariable
|
||||
|
||||
class TClassVariableAccess = TClassVariableAccessReal or TClassVariableAccessSynth;
|
||||
|
||||
class TSelfVariableAccess = TSelfVariableAccessReal;
|
||||
class TSelfVariableAccess = TSelfReal or TSelfSynth;
|
||||
|
||||
@@ -60,7 +60,7 @@ class IdentifierMethodCall extends MethodCallImpl, TIdentifierMethodCall {
|
||||
|
||||
final override string getMethodNameImpl() { result = g.getValue() }
|
||||
|
||||
final override AstNode getReceiverImpl() { result = TSelfSynth(this, 0) }
|
||||
final override AstNode getReceiverImpl() { result = TSelfSynth(this, 0, _) }
|
||||
|
||||
final override Expr getArgumentImpl(int n) { none() }
|
||||
|
||||
@@ -97,7 +97,7 @@ class RegularMethodCall extends MethodCallImpl, TRegularMethodCall {
|
||||
not exists(g.getReceiver()) and
|
||||
toGenerated(result) = g.getMethod().(Ruby::ScopeResolution).getScope()
|
||||
or
|
||||
result = TSelfSynth(this, 0)
|
||||
result = TSelfSynth(this, 0, _)
|
||||
}
|
||||
|
||||
final override string getMethodNameImpl() {
|
||||
|
||||
@@ -5,6 +5,7 @@ private import TreeSitter
|
||||
private import codeql.ruby.ast.internal.Call
|
||||
private import codeql.ruby.ast.internal.Variable
|
||||
private import codeql.ruby.ast.internal.Pattern
|
||||
private import codeql.ruby.ast.internal.Scope
|
||||
private import codeql.ruby.AST
|
||||
|
||||
/** A synthesized AST node kind. */
|
||||
@@ -34,7 +35,7 @@ newtype SynthKind =
|
||||
RShiftExprKind() or
|
||||
SplatExprKind() or
|
||||
StmtSequenceKind() or
|
||||
SelfKind() or
|
||||
SelfKind(SelfVariable v) or
|
||||
SubExprKind() or
|
||||
ConstantReadAccessKind(string value) { any(Synthesis s).constantReadAccess(value) }
|
||||
|
||||
@@ -142,7 +143,7 @@ private predicate hasLocation(AstNode n, Location l) {
|
||||
private module ImplicitSelfSynthesis {
|
||||
pragma[nomagic]
|
||||
private predicate identifierMethodCallSelfSynthesis(AstNode mc, int i, Child child) {
|
||||
child = SynthChild(SelfKind()) and
|
||||
child = SynthChild(SelfKind(TSelfVariable(scopeOf(toGenerated(mc))))) and
|
||||
mc = TIdentifierMethodCall(_) and
|
||||
i = 0
|
||||
}
|
||||
@@ -163,7 +164,7 @@ private module ImplicitSelfSynthesis {
|
||||
not exists(g.(Ruby::Call).getReceiver()) and
|
||||
not exists(g.(Ruby::Call).getMethod().(Ruby::ScopeResolution).getScope())
|
||||
) and
|
||||
child = SynthChild(SelfKind()) and
|
||||
child = SynthChild(SelfKind(TSelfVariable(scopeOf(toGenerated(mc))))) and
|
||||
i = 0
|
||||
}
|
||||
|
||||
|
||||
@@ -308,7 +308,8 @@ private module Cached {
|
||||
access(this, _) or
|
||||
this instanceof Ruby::GlobalVariable or
|
||||
this instanceof Ruby::InstanceVariable or
|
||||
this instanceof Ruby::ClassVariable
|
||||
this instanceof Ruby::ClassVariable or
|
||||
this instanceof Ruby::Self
|
||||
}
|
||||
}
|
||||
|
||||
@@ -619,15 +620,23 @@ private class ClassVariableAccessSynth extends ClassVariableAccessRealImpl,
|
||||
|
||||
abstract class SelfVariableAccessImpl extends VariableAccessImpl, TSelfVariableAccess { }
|
||||
|
||||
private class SelfVariableAccessReal extends SelfVariableAccessImpl, TSelfVariableAccessReal {
|
||||
private class SelfVariableAccessReal extends SelfVariableAccessImpl, TSelfReal {
|
||||
private Ruby::Self self;
|
||||
private SelfVariable var;
|
||||
|
||||
SelfVariableAccessReal() {
|
||||
exists(MethodBase::Range scope |
|
||||
var = TSelfVariable(scope) and this = TSelfVariableAccessReal(self, scope)
|
||||
)
|
||||
}
|
||||
SelfVariableAccessReal() { this = TSelfReal(self) and var = TSelfVariable(scopeOf(self)) }
|
||||
|
||||
final override SelfVariable getVariableImpl() { result = var }
|
||||
|
||||
final override string toString() { result = var.toString() }
|
||||
}
|
||||
|
||||
private class SelfVariableAccessSynth extends SelfVariableAccessImpl, TSelfSynth {
|
||||
private SelfVariable v;
|
||||
|
||||
SelfVariableAccessSynth() { this = TSelfSynth(_, _, v) }
|
||||
|
||||
final override LocalVariable getVariableImpl() { result = v }
|
||||
|
||||
final override string toString() { result = v.getName() }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user