Remove VariableScope IPA type

This commit is contained in:
Arthur Baars
2021-03-09 10:13:43 +01:00
parent 00260db58f
commit 86a89ab1fe
4 changed files with 300 additions and 463 deletions

View File

@@ -5,20 +5,7 @@ private import codeql.Locations
private import internal.Variable
/** A scope in which variables can be declared. */
class VariableScope extends TScope {
VariableScope::Range range;
VariableScope() { range = this }
/** Gets a textual representation of this element. */
final string toString() { result = range.toString() }
/** Gets the program element this scope is associated with, if any. */
final AstNode getScopeElement() { result = range.getScopeElement() }
/** Gets the location of the program element this scope is associated with. */
final Location getLocation() { result = getScopeElement().getLocation() }
class VariableScope extends Scope {
/** Gets a variable that is declared in this scope. */
final Variable getAVariable() { result.getDeclaringScope() = this }
@@ -27,9 +14,6 @@ class VariableScope extends TScope {
result = this.getAVariable() and
result.getName() = name
}
/** Gets the scope in which this scope is nested, if any. */
VariableScope getOuterScope() { result = enclosingScope(this.getScopeElement()) }
}
/** A variable declared in a scope. */

View File

@@ -7,78 +7,37 @@ private import codeql_ruby.ast.internal.Method
private import codeql_ruby.ast.internal.Module
private import codeql_ruby.ast.internal.Pattern
private import codeql_ruby.ast.internal.Parameter
Generated::AstNode parentOf(Generated::AstNode n) {
exists(Generated::AstNode parent | parent = n.getParent() |
if
n =
[
parent.(Generated::Module).getName(), parent.(Generated::Class).getName(),
parent.(Generated::Class).getSuperclass(), parent.(Generated::SingletonClass).getValue(),
parent.(Generated::Method).getName(), parent.(Generated::SingletonMethod).getName(),
parent.(Generated::SingletonMethod).getObject()
]
then result = parent.getParent()
else result = parent
)
}
private Generated::AstNode parentOfNoScope(Generated::AstNode n) {
result = parentOf(n) and
not n = any(VariableScope::Range s).getScopeElement()
}
private import codeql_ruby.ast.internal.Scope
private predicate instanceVariableAccess(
Generated::InstanceVariable var, string name, VariableScope scope, boolean instance
Generated::InstanceVariable var, string name, Scope::Range scope, boolean instance
) {
name = var.getValue() and
scope = enclosingModuleOrClass(var) and
if hasEnclosingMethod(var) then instance = true else instance = false
}
private predicate classVariableAccess(Generated::ClassVariable var, string name, VariableScope scope) {
private predicate classVariableAccess(Generated::ClassVariable var, string name, Scope::Range scope) {
name = var.getValue() and
scope = enclosingModuleOrClass(var)
}
predicate hasEnclosingMethod(Generated::AstNode node) {
exists(Callable::Range method |
parentCallableScope*(enclosingScope(node)) = TCallableScope(method)
|
method instanceof Method::Range or
method instanceof SingletonMethod::Range
)
private predicate hasEnclosingMethod(Generated::AstNode node) {
exists(Scope::Range s | node = s.getADescendant() and exists(s.getEnclosingMethod()))
}
private TCallableScope parentCallableScope(TCallableScope scope) {
exists(Callable::Range c |
scope = TCallableScope(c) and
not c instanceof Method::Range and
not c instanceof SingletonMethod::Range
|
result = scope.(VariableScope::Range).getOuterScope()
)
private ModuleBase::Range enclosingModuleOrClass(Generated::AstNode node) {
exists(Scope::Range s | node = s.getADescendant() and result = s.getEnclosingModule())
}
private VariableScope::Range parentScope(VariableScope::Range scope) {
not scope instanceof ModuleOrClassScope and
result = scope.getOuterScope()
}
private ModuleOrClassScope enclosingModuleOrClass(Generated::AstNode node) {
result = parentScope*(enclosingScope(node))
}
private predicate parameterAssignment(
CallableScope::Range scope, string name, Generated::Identifier i
) {
implicitParameterAssignmentNode(i, scope.getScopeElement()) and
private predicate parameterAssignment(Callable::Range scope, string name, Generated::Identifier i) {
implicitParameterAssignmentNode(i, scope) and
name = i.getValue()
}
/** Holds if `scope` defines `name` in its parameter declaration at `i`. */
private predicate scopeDefinesParameterVariable(
CallableScope::Range scope, string name, Generated::Identifier i
Callable::Range scope, string name, Generated::Identifier i
) {
// In case of overlapping parameter names (e.g. `_`), only the first
// parameter will give rise to a variable
@@ -90,7 +49,7 @@ private predicate scopeDefinesParameterVariable(
)
or
exists(Parameter::Range p |
p = scope.getScopeElement().(Callable::Range).getParameter(_) and
p = scope.(Callable::Range).getParameter(_) and
name = p.(NamedParameter::Range).getName()
|
i = p.(Generated::BlockParameter).getName() or
@@ -102,7 +61,7 @@ private predicate scopeDefinesParameterVariable(
}
/** Holds if `name` is assigned in `scope` at `i`. */
private predicate scopeAssigns(VariableScope scope, string name, Generated::Identifier i) {
private predicate scopeAssigns(Scope::Range scope, string name, Generated::Identifier i) {
(explicitAssignmentNode(i, _) or implicitAssignmentNode(i)) and
name = i.getValue() and
scope = enclosingScope(i)
@@ -137,9 +96,7 @@ cached
private module Cached {
/** Gets the enclosing scope for `node`. */
cached
VariableScope::Range enclosingScope(Generated::AstNode node) {
result.getScopeElement() = parentOfNoScope*(parentOf(node))
}
Scope::Range enclosingScope(Generated::AstNode node) { result.getADescendant() = node }
cached
newtype TScope =
@@ -154,7 +111,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) {
TClassVariable(Scope::Range scope, string name, Generated::AstNode decl) {
decl =
min(Generated::ClassVariable other |
classVariableAccess(other, name, scope)
@@ -162,7 +119,7 @@ private module Cached {
other order by other.getLocation().getStartLine(), other.getLocation().getStartColumn()
)
} or
TInstanceVariable(VariableScope scope, string name, boolean instance, Generated::AstNode decl) {
TInstanceVariable(Scope::Range scope, string name, boolean instance, Generated::AstNode decl) {
decl =
min(Generated::InstanceVariable other |
instanceVariableAccess(other, name, scope, instance)
@@ -170,7 +127,7 @@ private module Cached {
other order by other.getLocation().getStartLine(), other.getLocation().getStartColumn()
)
} or
TLocalVariable(VariableScope::Range scope, string name, Generated::Identifier i) {
TLocalVariable(Scope::Range scope, string name, Generated::Identifier i) {
scopeDefinesParameterVariable(scope, name, i)
or
i =
@@ -180,7 +137,7 @@ private module Cached {
other order by other.getLocation().getStartLine(), other.getLocation().getStartColumn()
) and
not scopeDefinesParameterVariable(scope, name, _) and
not scope.inherits(name, _)
not inherits(scope, name, _)
}
// Db types that can be vcalls
@@ -330,10 +287,12 @@ private module Cached {
}
cached
predicate access(Generated::Identifier access, Variable variable) {
exists(string name | name = access.getValue() |
variable.getDeclaringScope() = enclosingScope(access) and
predicate access(Generated::Identifier access, Variable::Range variable) {
exists(string name |
variable.getName() = name and
name = access.getValue()
|
variable.getDeclaringScope() = enclosingScope(access) and
not strictlyBefore(access.getLocation(), variable.getLocation()) and
// In case of overlapping parameter names, later parameters should not
// be considered accesses to the first parameter
@@ -341,9 +300,9 @@ private module Cached {
then scopeDefinesParameterVariable(_, _, access)
else any()
or
exists(VariableScope declScope |
variable = declScope.getVariable(name) and
enclosingScope(access).inherits(name, declScope)
exists(Scope::Range declScope |
variable.getDeclaringScope() = declScope and
inherits(enclosingScope(access), name, declScope)
)
)
}
@@ -371,7 +330,7 @@ private module Cached {
cached
predicate instanceVariableAccess(Generated::InstanceVariable var, InstanceVariable v) {
exists(string name, VariableScope scope, boolean instance |
exists(string name, Scope::Range scope, boolean instance |
v = TInstanceVariable(scope, name, instance, _) and
instanceVariableAccess(var, name, scope, instance)
)
@@ -379,7 +338,7 @@ private module Cached {
cached
predicate classVariableAccess(Generated::ClassVariable var, ClassVariable variable) {
exists(VariableScope scope, string name |
exists(Scope::Range scope, string name |
variable = TClassVariable(scope, name, _) and
classVariableAccess(var, name, scope)
)
@@ -388,125 +347,22 @@ private module Cached {
import Cached
module VariableScope {
abstract class Range extends TScope {
abstract string toString();
abstract Generated::AstNode getScopeElement();
abstract predicate isCapturing();
VariableScope::Range getOuterScope() { result = enclosingScope(this.getScopeElement()) }
/** Holds if this scope inherits `name` from an outer scope `outer`. */
predicate inherits(string name, VariableScope::Range outer) {
this.isCapturing() and
not scopeDefinesParameterVariable(this, name, _) and
(
outer = this.getOuterScope() and
(
scopeDefinesParameterVariable(outer, name, _)
or
exists(Generated::Identifier i |
scopeAssigns(outer, name, i) and
strictlyBefore(i.getLocation(), this.getLocation())
)
)
or
this.getOuterScope().inherits(name, outer)
/** Holds if this scope inherits `name` from an outer scope `outer`. */
private predicate inherits(Block::Range scope, string name, Scope::Range outer) {
not scopeDefinesParameterVariable(scope, name, _) and
(
outer = scope.getOuterScope() and
(
scopeDefinesParameterVariable(outer, name, _)
or
exists(Generated::Identifier i |
scopeAssigns(outer, name, i) and
strictlyBefore(i.getLocation(), scope.(Generated::AstNode).getLocation())
)
}
final Location getLocation() { result = getScopeElement().getLocation() }
}
}
module GlobalScope {
class Range extends VariableScope::Range, TGlobalScope {
override string toString() { result = "global scope" }
override Generated::AstNode getScopeElement() { none() }
override predicate isCapturing() { none() }
}
}
module TopLevelScope {
class Range extends VariableScope::Range, TTopLevelScope {
Generated::Program program;
Range() { TTopLevelScope(program) = this }
override string toString() {
result = "top-level scope for " + program.getLocation().getFile().getBaseName()
}
override Generated::AstNode getScopeElement() { result = program }
override predicate isCapturing() { none() }
}
}
module ModuleScope {
class Range extends VariableScope::Range, TModuleScope {
Generated::Module mdl;
Range() { TModuleScope(mdl) = this }
override string toString() { result = "module scope for " + mdl.(Module::Range).getName() }
override Generated::AstNode getScopeElement() { result = mdl }
override predicate isCapturing() { none() }
}
}
module ClassScope {
class Range extends VariableScope::Range, TClassScope {
Generated::AstNode cls;
Range() { TClassScope(cls) = this }
override string toString() {
result = "class scope for " + cls.(Class::Range).getName()
or
cls instanceof Generated::SingletonClass and result = "class scope"
}
override Generated::AstNode getScopeElement() { result = cls }
override predicate isCapturing() { none() }
}
}
module CallableScope {
class Range extends VariableScope::Range, TCallableScope {
private Generated::AstNode c;
Range() { this = TCallableScope(c) }
override string toString() {
result = "method scope for " + c.(SingletonMethod).getName()
or
result = "method scope for " + c.(Method).getName()
or
c instanceof Lambda and
result = "lambda scope"
or
c instanceof Block and
result = "block scope"
}
override Generated::AstNode getScopeElement() { TCallableScope(result) = this }
override predicate isCapturing() {
c instanceof Generated::Lambda
or
c instanceof Generated::Block
or
c instanceof Generated::DoBlock
}
}
)
or
inherits(scope.getOuterScope(), name, outer)
)
}
module Variable {
@@ -517,13 +373,13 @@ module Variable {
abstract Location getLocation();
abstract VariableScope getDeclaringScope();
abstract Scope::Range getDeclaringScope();
}
}
module LocalVariable {
class Range extends Variable::Range, TLocalVariable {
private VariableScope scope;
private Scope::Range scope;
private string name;
private Generated::Identifier i;
@@ -533,7 +389,7 @@ module LocalVariable {
final override Location getLocation() { result = i.getLocation() }
final override VariableScope getDeclaringScope() { result = scope }
final override Scope::Range getDeclaringScope() { result = scope }
final VariableAccess getDefiningAccess() { result = getNodeForIdentifier(i) }
}
@@ -549,7 +405,7 @@ module GlobalVariable {
final override Location getLocation() { none() }
final override VariableScope getDeclaringScope() { result = TGlobalScope() }
final override Scope::Range getDeclaringScope() { none() }
}
}
@@ -557,7 +413,7 @@ private class ModuleOrClassScope = TClassScope or TModuleScope or TTopLevelScope
module InstanceVariable {
class Range extends Variable::Range, TInstanceVariable {
private ModuleOrClassScope scope;
private ModuleBase::Range scope;
private boolean instance;
private string name;
private Generated::AstNode decl;
@@ -570,13 +426,13 @@ module InstanceVariable {
final override Location getLocation() { result = decl.getLocation() }
final override VariableScope getDeclaringScope() { result = scope }
final override Scope::Range getDeclaringScope() { result = scope }
}
}
module ClassVariable {
class Range extends Variable::Range, TClassVariable {
private ModuleOrClassScope scope;
private ModuleBase::Range scope;
private string name;
private Generated::AstNode decl;
@@ -586,7 +442,7 @@ module ClassVariable {
final override Location getLocation() { result = decl.getLocation() }
final override VariableScope getDeclaringScope() { result = scope }
final override Scope::Range getDeclaringScope() { result = scope }
}
}