diff --git a/ql/src/codeql_ruby/ast/Variable.qll b/ql/src/codeql_ruby/ast/Variable.qll index aa7fc50ef51..fb9e1538814 100644 --- a/ql/src/codeql_ruby/ast/Variable.qll +++ b/ql/src/codeql_ruby/ast/Variable.qll @@ -95,6 +95,13 @@ class InstanceVariable extends Variable, TInstanceVariable { final override InstanceVariableAccess getAnAccess() { result.getVariable() = this } } +/** A class variable. */ +class ClassVariable extends Variable, TClassVariable { + override ClassVariable::Range range; + + final override ClassVariableAccess getAnAccess() { result.getVariable() = this } +} + /** An access to a variable. */ class VariableAccess extends Expr { override VariableAccess::Range range; @@ -213,3 +220,12 @@ class InstanceVariableAccess extends VariableAccess, @token_instance_variable { final override string getAPrimaryQlClass() { result = "InstanceVariableAccess" } } +/** An access to a class variable. */ +class ClassVariableAccess extends VariableAccess, @token_class_variable { + final override ClassVariableAccess::Range range; + + /** Gets the variable this identifier refers to. */ + final override ClassVariable getVariable() { result = range.getVariable() } + + final override string getAPrimaryQlClass() { result = "ClassVariableAccess" } +} diff --git a/ql/src/codeql_ruby/ast/internal/Variable.qll b/ql/src/codeql_ruby/ast/internal/Variable.qll index dc84d1114d5..fe02d5563b2 100644 --- a/ql/src/codeql_ruby/ast/internal/Variable.qll +++ b/ql/src/codeql_ruby/ast/internal/Variable.qll @@ -145,6 +145,7 @@ private module Cached { cached newtype TVariable = TGlobalVariable(string name) { name = any(Generated::GlobalVariable var).getValue() } or + TClassVariable(VariableScope scope, string name, Generated::AstNode decl) { none() } or TInstanceVariable(VariableScope scope, string name, boolean instance, Generated::AstNode decl) { decl = min(Generated::InstanceVariable other | @@ -477,6 +478,22 @@ module InstanceVariable { } } +module ClassVariable { + class Range extends Variable::Range, TClassVariable { + private ModuleOrClassScope scope; + private string name; + private Generated::AstNode decl; + + Range() { this = TClassVariable(scope, name, decl) } + + final override string getName() { result = name } + + final override Location getLocation() { result = decl.getLocation() } + + final override VariableScope getDeclaringScope() { result = scope } + } +} + module VariableAccess { abstract class Range extends Expr::Range { abstract Variable getVariable(); @@ -527,3 +544,13 @@ module InstanceVariableAccess { final override InstanceVariable getVariable() { result = variable } } } + +module ClassVariableAccess { + class Range extends VariableAccess::Range, @token_class_variable { + ClassVariable variable; + + Range() { this.(Generated::ClassVariable).getValue() = variable.getName() } + + final override ClassVariable getVariable() { result = variable } + } +}