diff --git a/ql/src/codeql_ruby/AST.qll b/ql/src/codeql_ruby/AST.qll index 11f201ac6dd..518f42c69d9 100644 --- a/ql/src/codeql_ruby/AST.qll +++ b/ql/src/codeql_ruby/AST.qll @@ -13,6 +13,7 @@ import ast.Scope import ast.Statement import ast.Variable private import ast.internal.AST +private import ast.internal.Scope /** * A node in the abstract syntax tree. This class is the base class for all Ruby @@ -28,6 +29,20 @@ class AstNode extends TAstNode { */ string getAPrimaryQlClass() { result = "???" } + /** Gets the enclosing module, if any. */ + ModuleBase getEnclosingModule() { + exists(Scope::Range s | + s = scopeOf(toGenerated(this)) and toGenerated(result) = s.getEnclosingModule() + ) + } + + /** Gets the enclosing method, if any. */ + MethodBase getEnclosingMethod() { + exists(Scope::Range s | + s = scopeOf(toGenerated(this)) and toGenerated(result) = s.getEnclosingMethod() + ) + } + /** Gets a textual representation of this node. */ cached string toString() { none() } diff --git a/ql/src/codeql_ruby/ast/Scope.qll b/ql/src/codeql_ruby/ast/Scope.qll index 2f4b941a56e..a726236e410 100644 --- a/ql/src/codeql_ruby/ast/Scope.qll +++ b/ql/src/codeql_ruby/ast/Scope.qll @@ -8,18 +8,9 @@ class Scope extends AstNode, TScopeType { Scope() { range = toGenerated(this) } - /** Gets the enclosing module, if any. */ - ModuleBase getEnclosingModule() { toGenerated(result) = range.getEnclosingModule() } - - /** Gets the enclosing method, if any. */ - MethodBase getEnclosingMethod() { toGenerated(result) = range.getEnclosingMethod() } - /** Gets the scope in which this scope is nested, if any. */ Scope getOuterScope() { toGenerated(result) = range.getOuterScope() } - /** Gets the scope in which this scope is nested, if any. */ - AstNode getADescendant() { range = scopeOf(toGenerated(result)) } - /** Gets a variable that is declared in this scope. */ final Variable getAVariable() { result.getDeclaringScope() = this } diff --git a/ql/src/codeql_ruby/ast/internal/Module.qll b/ql/src/codeql_ruby/ast/internal/Module.qll index 84a2adc68d7..b8a45fdd610 100644 --- a/ql/src/codeql_ruby/ast/internal/Module.qll +++ b/ql/src/codeql_ruby/ast/internal/Module.qll @@ -23,7 +23,7 @@ private predicate isToplevel(ConstantAccess n) { ( n.hasGlobalScope() or - exists(Scope x | x.getADescendant() = n and x.getEnclosingModule() instanceof Toplevel) + n.getEnclosingModule() instanceof Toplevel ) } @@ -48,7 +48,7 @@ private string resolveScopeExpr0(ConstantReadAccess n) { ModuleBase enclosing(ModuleBase m, int level) { result = m and level = 0 or - result = enclosing(m.getOuterScope().getEnclosingModule(), level - 1) + result = enclosing(m.getEnclosingModule(), level - 1) } bindingset[qualifier, name] @@ -59,9 +59,8 @@ private string scopeAppend(string qualifier, string name) { private string resolveRelativeToEnclosing(ConstantAccess n, int i) { not isToplevel(n) and not exists(n.getScopeExpr()) and - exists(Scope s, ModuleBase enclosing | - n = s.getADescendant() and - enclosing = enclosing(s.getEnclosingModule(), i) and + exists(ModuleBase enclosing | + enclosing = enclosing(n.getEnclosingModule(), i) and result = scopeAppend(constantDefinition0(enclosing), n.getName()) and (result = builtin() or result = constantDefinition0(_) or n instanceof ConstantWriteAccess) ) @@ -75,12 +74,12 @@ private class IncludeOrPrependCall extends MethodCall { string getTarget() { result = resolveScopeExpr0(this.getReceiver()) or - exists(Scope s | - s.getADescendant() = this and + exists(ModuleBase enclosing | + enclosing = this.getEnclosingModule() and ( - result = constantDefinition0(s.getEnclosingModule()) + result = constantDefinition0(enclosing) or - result = "Object" and s.getEnclosingModule() instanceof Toplevel + result = "Object" and enclosing instanceof Toplevel ) | this.getReceiver() instanceof Self @@ -171,10 +170,7 @@ private string containsIgnoringSuper(string qname, string name) { private string resolveRelativeToAncestors(ConstantReadAccess n) { not isToplevel(n) and not exists(n.getScopeExpr()) and - exists(Scope s, ModuleBase enclosing | - n = s.getADescendant() and - enclosing = s.getEnclosingModule() - | + exists(ModuleBase enclosing | enclosing = n.getEnclosingModule() | result = contains(constantDefinition(enclosing), n.getName()) or enclosing instanceof Toplevel and result = contains("Object", n.getName())