Skip to content

Commit 0d39a15

Browse files
committed
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.
1 parent e7a3050 commit 0d39a15

File tree

5 files changed

+30
-16
lines changed

5 files changed

+30
-16
lines changed

ruby/ql/lib/codeql/ruby/ast/Variable.qll

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,3 +193,6 @@ class ClassVariableReadAccess extends ClassVariableAccess, VariableReadAccess {
193193
class SelfVariableAccess extends VariableAccess instanceof SelfVariableAccessImpl {
194194
final override string getAPrimaryQlClass() { result = "SelfVariableAccess" }
195195
}
196+
197+
/** An access to the `self` variable where the value is read. */
198+
class SelfVariableReadAccess extends SelfVariableAccess, VariableReadAccess { }

ruby/ql/lib/codeql/ruby/ast/internal/AST.qll

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -236,8 +236,9 @@ private module Cached {
236236
isScopeResolutionMethodCall(g, i)
237237
} or
238238
TSelfReal(Ruby::Self g) or
239-
TSelfSynth(AST::AstNode parent, int i) { mkSynthChild(SelfKind(), parent, i) } or
240-
TSelfVariableAccessReal(Ruby::Self self, MethodBase::Range scope) { scopeOf(self) = scope } or
239+
TSelfSynth(AST::AstNode parent, int i, AST::SelfVariable v) {
240+
mkSynthChild(SelfKind(v), parent, i)
241+
} or
241242
TSimpleParameter(Ruby::Identifier g) { g instanceof Parameter::Range } or
242243
TSimpleSymbolLiteral(Ruby::SimpleSymbol g) or
243244
TSingletonClass(Ruby::SingletonClass g) or
@@ -478,7 +479,7 @@ private module Cached {
478479
or
479480
result = TRShiftExprSynth(parent, i)
480481
or
481-
result = TSelfSynth(parent, i)
482+
result = TSelfSynth(parent, i, _)
482483
or
483484
result = TSplatExprSynth(parent, i)
484485
or
@@ -706,4 +707,4 @@ class TInstanceVariableAccess = TInstanceVariableAccessReal or TInstanceVariable
706707

707708
class TClassVariableAccess = TClassVariableAccessReal or TClassVariableAccessSynth;
708709

709-
class TSelfVariableAccess = TSelfVariableAccessReal;
710+
class TSelfVariableAccess = TSelfReal or TSelfSynth;

ruby/ql/lib/codeql/ruby/ast/internal/Call.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ class IdentifierMethodCall extends MethodCallImpl, TIdentifierMethodCall {
6060

6161
final override string getMethodNameImpl() { result = g.getValue() }
6262

63-
final override AstNode getReceiverImpl() { result = TSelfSynth(this, 0) }
63+
final override AstNode getReceiverImpl() { result = TSelfSynth(this, 0, _) }
6464

6565
final override Expr getArgumentImpl(int n) { none() }
6666

@@ -97,7 +97,7 @@ class RegularMethodCall extends MethodCallImpl, TRegularMethodCall {
9797
not exists(g.getReceiver()) and
9898
toGenerated(result) = g.getMethod().(Ruby::ScopeResolution).getScope()
9999
or
100-
result = TSelfSynth(this, 0)
100+
result = TSelfSynth(this, 0, _)
101101
}
102102

103103
final override string getMethodNameImpl() {

ruby/ql/lib/codeql/ruby/ast/internal/Synthesis.qll

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ private import TreeSitter
55
private import codeql.ruby.ast.internal.Call
66
private import codeql.ruby.ast.internal.Variable
77
private import codeql.ruby.ast.internal.Pattern
8+
private import codeql.ruby.ast.internal.Scope
89
private import codeql.ruby.AST
910

1011
/** A synthesized AST node kind. */
@@ -34,7 +35,7 @@ newtype SynthKind =
3435
RShiftExprKind() or
3536
SplatExprKind() or
3637
StmtSequenceKind() or
37-
SelfKind() or
38+
SelfKind(SelfVariable v) or
3839
SubExprKind() or
3940
ConstantReadAccessKind(string value) { any(Synthesis s).constantReadAccess(value) }
4041

@@ -142,7 +143,7 @@ private predicate hasLocation(AstNode n, Location l) {
142143
private module ImplicitSelfSynthesis {
143144
pragma[nomagic]
144145
private predicate identifierMethodCallSelfSynthesis(AstNode mc, int i, Child child) {
145-
child = SynthChild(SelfKind()) and
146+
child = SynthChild(SelfKind(TSelfVariable(scopeOf(toGenerated(mc))))) and
146147
mc = TIdentifierMethodCall(_) and
147148
i = 0
148149
}
@@ -163,7 +164,7 @@ private module ImplicitSelfSynthesis {
163164
not exists(g.(Ruby::Call).getReceiver()) and
164165
not exists(g.(Ruby::Call).getMethod().(Ruby::ScopeResolution).getScope())
165166
) and
166-
child = SynthChild(SelfKind()) and
167+
child = SynthChild(SelfKind(TSelfVariable(scopeOf(toGenerated(mc))))) and
167168
i = 0
168169
}
169170

ruby/ql/lib/codeql/ruby/ast/internal/Variable.qll

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,8 @@ private module Cached {
308308
access(this, _) or
309309
this instanceof Ruby::GlobalVariable or
310310
this instanceof Ruby::InstanceVariable or
311-
this instanceof Ruby::ClassVariable
311+
this instanceof Ruby::ClassVariable or
312+
this instanceof Ruby::Self
312313
}
313314
}
314315

@@ -619,15 +620,23 @@ private class ClassVariableAccessSynth extends ClassVariableAccessRealImpl,
619620

620621
abstract class SelfVariableAccessImpl extends VariableAccessImpl, TSelfVariableAccess { }
621622

622-
private class SelfVariableAccessReal extends SelfVariableAccessImpl, TSelfVariableAccessReal {
623+
private class SelfVariableAccessReal extends SelfVariableAccessImpl, TSelfReal {
623624
private Ruby::Self self;
624625
private SelfVariable var;
625626

626-
SelfVariableAccessReal() {
627-
exists(MethodBase::Range scope |
628-
var = TSelfVariable(scope) and this = TSelfVariableAccessReal(self, scope)
629-
)
630-
}
627+
SelfVariableAccessReal() { this = TSelfReal(self) and var = TSelfVariable(scopeOf(self)) }
631628

632629
final override SelfVariable getVariableImpl() { result = var }
630+
631+
final override string toString() { result = var.toString() }
632+
}
633+
634+
private class SelfVariableAccessSynth extends SelfVariableAccessImpl, TSelfSynth {
635+
private SelfVariable v;
636+
637+
SelfVariableAccessSynth() { this = TSelfSynth(_, _, v) }
638+
639+
final override LocalVariable getVariableImpl() { result = v }
640+
641+
final override string toString() { result = v.getName() }
633642
}

0 commit comments

Comments
 (0)