diff --git a/ql/src/codeql_ruby/AST.qll b/ql/src/codeql_ruby/AST.qll index 0171cf2bfa2..1e47ac4b82e 100644 --- a/ql/src/codeql_ruby/AST.qll +++ b/ql/src/codeql_ruby/AST.qll @@ -1,6 +1,8 @@ import codeql.Locations import codeql_ruby.ast.Method import codeql_ruby.ast.Parameter +import codeql_ruby.ast.Pattern +import codeql_ruby.ast.Variable private import codeql_ruby.Generated /** @@ -26,29 +28,4 @@ class AstNode extends @ast_node { /** Gets the location if this node. */ Location getLocation() { result = generated.getLocation() } - - /** - * Gets the parent of this node in the abstract syntax tree, if it has one. - */ - AstNode getParent() { result = generated.getParent() } - - /** - * Gets the index (position) of this node in the parent node's list of - * children. - */ - int getParentIndex() { result = generated.getParentIndex() } -} - -/** - * Models program elements for destructured patterns. - */ -abstract class Pattern extends AstNode { - /** Gets the number of elements in this pattern. */ - abstract int getNumberOfElements(); - - /** Gets the nth element in this pattern. */ - abstract AstNode getElement(int n); - - /** Gets an element in this pattern. */ - AstNode getAnElement() { result = this.getElement(_) } } diff --git a/ql/src/codeql_ruby/ast/Method.qll b/ql/src/codeql_ruby/ast/Method.qll index 6aa5e61c027..80849be07d7 100644 --- a/ql/src/codeql_ruby/ast/Method.qll +++ b/ql/src/codeql_ruby/ast/Method.qll @@ -1,17 +1,30 @@ import codeql_ruby.AST private import codeql_ruby.Generated +private import internal.Method -/** A Ruby method. */ -class Method extends @method, AstNode { - Generated::Method generated; +/** A callable. */ +class Callable extends AstNode { + Callable() { this instanceof CallableRange } - Method() { generated = this } + /** Gets the number of parameters of this callable. */ + final int getNumberOfParameters() { result = count(this.getAParameter()) } + + /** Gets a parameter of this callable. */ + final Parameter getAParameter() { result = this.getParameter(_) } + + /** Gets the nth parameter of this callable. */ + final Parameter getParameter(int n) { result = this.(CallableRange).getParameter(n) } +} + +/** A method. */ +class Method extends Callable, @method { + final override Generated::Method generated; override string describeQlClass() { result = "Method" } override string toString() { result = this.getName() } - /** Gets the name of the method. */ + /** Gets the name of this method. */ string getName() { result = generated.getName().(Generated::Token).getValue() or // TODO: use hand-written Symbol class @@ -21,7 +34,7 @@ class Method extends @method, AstNode { /** * Holds if this is a setter method, as in the following example: - * ``` + * ```rb * class Person * def name=(n) * @name = n @@ -30,90 +43,63 @@ class Method extends @method, AstNode { * ``` */ predicate isSetter() { generated.getName() instanceof Generated::Setter } +} - /** Gets the number of parameters of this method. */ - int getNumberOfParameters() { result = count(this.getAParameter()) } +/** A singleton method. */ +class SingletonMethod extends Callable, @singleton_method { + final override Generated::SingletonMethod generated; - /** Gets a parameter of this method. */ - Parameter getAParameter() { result = this.getParameter(_) } + override string describeQlClass() { result = "SingletonMethod" } - /** Gets the nth parameter of this method. */ - Parameter getParameter(int n) { result = generated.getParameters().getChild(n) } + override string toString() { result = this.getName() } + + /** Gets the name of this method. */ + string getName() { + result = generated.getName().(Generated::Token).getValue() or + // TODO: use hand-written Symbol class + result = generated.getName().(Generated::Symbol).toString() or + result = generated.getName().(Generated::Setter).getName().getValue() + "=" + } } /** - * A Ruby lambda (anonymous method). For example: - * ``` + * A lambda (anonymous method). For example: + * ```rb * -> (x) { x + 1 } * ``` */ -class Lambda extends @lambda, AstNode { - Generated::Lambda generated; - - Lambda() { generated = this } +class Lambda extends Callable, @lambda { + final override Generated::Lambda generated; override string describeQlClass() { result = "Lambda" } override string toString() { result = "-> { ... }" } - - /** Gets the number of parameters of this lambda. */ - int getNumberOfParameters() { result = count(this.getAParameter()) } - - /** Gets a parameter of this lambda. */ - Parameter getAParameter() { result = this.getParameter(_) } - - /** Gets the nth parameter of this lambda. */ - Parameter getParameter(int n) { result = generated.getParameters().getChild(n) } } -/** A Ruby block. */ -abstract class Block extends AstNode { - /** Gets the number of parameters of this block. */ - abstract int getNumberOfParameters(); - - /** Gets the nth parameter of this block. */ - abstract Parameter getParameter(int n); - - /** Gets a parameter of this block. */ - Parameter getAParameter() { result = this.getParameter(_) } - // TODO: body/statements +/** A block. */ +class Block extends AstNode, Callable { + Block() { this instanceof BlockRange } } -/** A Ruby block enclosed within `do` and `end`. */ -class DoBlock extends @do_block, Block { - Generated::DoBlock generated; - - DoBlock() { generated = this } +/** A block enclosed within `do` and `end`. */ +class DoBlock extends Block, @do_block { + final override Generated::DoBlock generated; override string describeQlClass() { result = "DoBlock" } override string toString() { result = "| ... |" } - - /** Gets the number of parameters of this block. */ - override int getNumberOfParameters() { result = count(this.getAParameter()) } - - /** Gets the nth parameter of this block. */ - override Parameter getParameter(int n) { result = generated.getParameters().getChild(n) } } /** - * A Ruby block defined using curly braces, e.g. in the following code: - * ``` + * A block defined using curly braces, e.g. in the following code: + * ```rb * names.each { |name| puts name } * ``` */ -class BraceBlock extends @block, Block { - Generated::Block generated; - - BraceBlock() { generated = this } +class BraceBlock extends Block, @block { + final override Generated::Block generated; override string describeQlClass() { result = "BraceBlock" } override string toString() { result = "{ ... }" } - - /** Gets the number of parameters of this block. */ - override int getNumberOfParameters() { result = count(this.getAParameter()) } - - /** Gets the nth parameter of this block. */ - override Parameter getParameter(int n) { result = generated.getParameters().getChild(n) } } diff --git a/ql/src/codeql_ruby/ast/Parameter.qll b/ql/src/codeql_ruby/ast/Parameter.qll index 0f6cb8fa419..f870a62d7f3 100644 --- a/ql/src/codeql_ruby/ast/Parameter.qll +++ b/ql/src/codeql_ruby/ast/Parameter.qll @@ -1,105 +1,123 @@ import codeql_ruby.AST private import codeql_ruby.Generated +private import Variable +private import Pattern +private import internal.Variable + +/** A parameter. */ +class Parameter extends AstNode { + private int pos; + + Parameter() { + this = any(Generated::BlockParameters bp).getChild(pos) + or + this = any(Generated::MethodParameters mp).getChild(pos) + or + this = any(Generated::LambdaParameters lp).getChild(pos) + } + + /** Gets the callable that this parameter belongs to. */ + Callable getCallable() { result.getAParameter() = this } + + /** Gets the zero-based position of this parameter. */ + int getPosition() { result = pos } +} /** - * A parameter to a block, lambda, or method. + * A parameter defined using a pattern. + * + * This includes both simple parameters and tuple parameters. */ -abstract class Parameter extends AstNode { - /** - * Gets the position of this parameter in the parent block, lambda, or - * method's parameter list. - */ - int getPosition() { - exists(Method m | m.getParameter(result) = this) or - exists(Block b | b.getParameter(result) = this) or - exists(Lambda l | l.getParameter(result) = this) - } +class PatternParameter extends Parameter, Pattern { + override string toString() { result = Pattern.super.toString() } + + override Location getLocation() { result = Pattern.super.getLocation() } +} + +/** A parameter defined using a tuple pattern. */ +class TuplePatternParameter extends PatternParameter, TuplePattern { + override string toString() { result = TuplePattern.super.toString() } + + override string describeQlClass() { result = "TuplePatternParameter" } +} + +/** A named parameter. */ +class NamedParameter extends Parameter { + NamedParameter() { not this instanceof TuplePattern } + + /** Gets the name of this parameter. */ + string getName() { none() } + + /** Gets the variable introduced by this parameter. */ + Variable getVariable() { none() } + + /** Gets an access to this parameter. */ + final VariableAccess getAnAccess() { result = this.getVariable().getAnAccess() } +} + +/** A simple (normal) parameter. */ +class SimpleParameter extends NamedParameter, PatternParameter, VariablePattern { + override string getName() { result = VariablePattern.super.getName() } + + final override Variable getVariable() { result = TLocalVariable(_, _, this) } + + override string describeQlClass() { result = "SimpleParameter" } + + override string toString() { result = this.getName() } } /** * A parameter that is a block. For example, `&bar` in the following code: - * ``` + * ```rb * def foo(&bar) * bar.call if block_given? * end * ``` */ -class BlockParameter extends @block_parameter, Parameter { - Generated::BlockParameter generated; +class BlockParameter extends @block_parameter, NamedParameter { + override Generated::BlockParameter generated; - BlockParameter() { generated = this } + final override Variable getVariable() { result = TLocalVariable(_, _, generated.getName()) } override string describeQlClass() { result = "BlockParameter" } override string toString() { result = "&" + this.getName() } - /** Gets the name of the parameter. */ - string getName() { result = generated.getName().getValue() } -} - -/** - * A parameter that is destructured. For example, the parameter `(a, b)` in the - * following code: - * ``` - * pairs.each do |(a, b)| - * puts a + b - * end - * ``` - */ -class PatternParameter extends @destructured_parameter, Parameter, Pattern { - Generated::DestructuredParameter generated; - - PatternParameter() { generated = this } - - override string describeQlClass() { result = "PatternParameter" } - - override string toString() { result = "(..., ...)" } - - /** - * Gets the number of parameters of this destructuring. - */ - override int getNumberOfElements() { result = count(this.getElement(_)) } - - /** - * Gets the nth parameter of this pattern. - */ - override AstNode getElement(int n) { result = generated.getChild(n) } + override string getName() { result = generated.getName().getValue() } } /** * A hash-splat (or double-splat) parameter. For example, `**options` in the * following code: - * ``` + * ```rb * def foo(bar, **options) * ... * end * ``` */ -class HashSplatParameter extends @hash_splat_parameter, Parameter { - Generated::HashSplatParameter generated; +class HashSplatParameter extends @hash_splat_parameter, NamedParameter { + override Generated::HashSplatParameter generated; - HashSplatParameter() { generated = this } + final override Variable getVariable() { result = TLocalVariable(_, _, generated.getName()) } override string describeQlClass() { result = "HashSplatParameter" } override string toString() { result = "**" + this.getName() } - /** Gets the name of the parameter. */ - string getName() { result = generated.getName().getValue() } + override string getName() { result = generated.getName().getValue() } } /** * TODO */ -class KeywordParameter extends @keyword_parameter, Parameter { - Generated::KeywordParameter generated; +class KeywordParameter extends @keyword_parameter, NamedParameter { + override Generated::KeywordParameter generated; - KeywordParameter() { generated = this } + final override Variable getVariable() { result = TLocalVariable(_, _, generated.getName()) } override string describeQlClass() { result = "KeywordParameter" } - /** Gets the name of the parameter. */ - string getName() { result = generated.getName().getValue() } + override string getName() { result = generated.getName().getValue() } /** * Gets the default value, i.e. the value assigned to the parameter when one @@ -115,23 +133,22 @@ class KeywordParameter extends @keyword_parameter, Parameter { /** * An optional parameter. For example, the parameter `name` in the following * code: - * ``` + * ```rb * def say_hello(name = 'Anon') * puts "hello #{name}" * end * ``` */ -class OptionalParameter extends @optional_parameter, Parameter { - Generated::OptionalParameter generated; +class OptionalParameter extends @optional_parameter, NamedParameter { + override Generated::OptionalParameter generated; - OptionalParameter() { generated = this } + final override Variable getVariable() { result = TLocalVariable(_, _, generated.getName()) } override string describeQlClass() { result = "OptionalParameter" } override string toString() { result = this.getName() } - /** Gets the name of the parameter. */ - string getName() { result = generated.getName().getValue() } + override string getName() { result = generated.getName().getValue() } /** * Gets the default value, i.e. the value assigned to the parameter when one @@ -143,40 +160,20 @@ class OptionalParameter extends @optional_parameter, Parameter { /** * A splat parameter. For example, `*values` in the following code: - * ``` + * ```rb * def foo(bar, *values) * ... * end * ``` */ -class SplatParameter extends @splat_parameter, Parameter { - Generated::SplatParameter generated; +class SplatParameter extends @splat_parameter, NamedParameter { + override Generated::SplatParameter generated; - SplatParameter() { generated = this } + final override Variable getVariable() { result = TLocalVariable(_, _, generated.getName()) } override string describeQlClass() { result = "SplatParameter" } override string toString() { result = this.getName() } - /** Gets the name of the parameter. */ - string getName() { result = generated.getName().getValue() } -} - -/** - * An identifier that is a parameter in a block, lambda, or method. - */ -class IdentifierParameter extends @token_identifier, Parameter { - IdentifierParameter() { - block_parameters_child(_, _, this) or - destructured_parameter_child(_, _, this) or - lambda_parameters_child(_, _, this) or - method_parameters_child(_, _, this) - } - - override string describeQlClass() { result = "IdentifierParameter" } - - override string toString() { result = this.getName() } - - /** Gets the name of the parameter. */ - string getName() { result = this.(Generated::Identifier).getValue() } + override string getName() { result = generated.getName().getValue() } } diff --git a/ql/src/codeql_ruby/ast/Pattern.qll b/ql/src/codeql_ruby/ast/Pattern.qll new file mode 100644 index 00000000000..a6464e6be66 --- /dev/null +++ b/ql/src/codeql_ruby/ast/Pattern.qll @@ -0,0 +1,40 @@ +import codeql_ruby.AST +private import codeql_ruby.Generated +private import codeql.Locations +private import internal.Pattern +private import Variable + +/** A pattern. */ +class Pattern extends AstNode { + Pattern() { this instanceof PatternRange } +} + +/** A simple variable pattern. */ +class VariablePattern extends Pattern { + override Generated::Identifier generated; + + /** Gets the name of the variable used in this pattern. */ + string getName() { result = generated.getValue() } + + /** Gets the variable used in this pattern. */ + Variable getVariable() { this = result.getAnAccess() } + + override string toString() { result = this.getName() } +} + +/** + * A tuple pattern. + * + * This includes both tuple patterns in parameters and assignments. + */ +class TuplePattern extends Pattern { + TuplePattern() { this instanceof TuplePatternRange } + + /** Gets the `i`th pattern in this tuple pattern. */ + final Pattern getElement(int i) { result = this.(TuplePatternRange).getElement(i) } + + /** Gets a sub pattern in this tuple pattern. */ + final Pattern getAnElement() { result = this.getElement(_) } + + override string toString() { result = "(..., ...)" } +} diff --git a/ql/src/codeql_ruby/ast/Variable.qll b/ql/src/codeql_ruby/ast/Variable.qll index 50eb92532d8..9a3acce53da 100644 --- a/ql/src/codeql_ruby/ast/Variable.qll +++ b/ql/src/codeql_ruby/ast/Variable.qll @@ -1,140 +1,9 @@ /** Provides classes for modeling program variables. */ -private import codeql_ruby.Generated::Generated +import codeql_ruby.AST +private import codeql_ruby.Generated private import codeql.Locations - -private AstNode parent(AstNode n) { - result = n.getParent() and - not n = any(VariableScope s).getScopeElement() -} - -/** Gets the enclosing scope for `node`. */ -private VariableScope enclosingScope(AstNode node) { - result.getScopeElement() = parent*(node.getParent()) -} - -/** A parameter. */ -class Parameter extends AstNode { - private int position; - private VariableScope scope; - - Parameter() { - this = - scope.(BlockScope).getScopeElement().getAFieldOrChild().(BlockParameters).getChild(position) - or - this = - scope.(MethodScope).getScopeElement().getAFieldOrChild().(MethodParameters).getChild(position) - } - - /** Gets the (zero-based) position of this parameter. */ - final int getPosition() { result = position } - - /** Gets the scope this parameter is declared in. */ - final VariableScope getDeclaringScope() { result = scope } - - /** Gets an access to this parameter. */ - final ParameterAccess getAnAccess() { result.getParameter() = this } -} - -private Identifier parameterIdentifier(Parameter p) { - result = p or - result = p.(SplatParameter).getName() or - result = p.(HashSplatParameter).getName() or - result = p.(BlockParameter).getName() or - result = p.(OptionalParameter).getName() or - result = p.(KeywordParameter).getName() or - result = destructuredIdentifier(p.(DestructuredParameter)) -} - -private Identifier destructuredIdentifier(AstNode node) { - result = node or - result = destructuredIdentifier(node.(DestructuredParameter).getAFieldOrChild()) -} - -/** Holds if `scope` defines `name` in its parameter declaration. */ -private predicate scopeDefinesParameter(VariableScope scope, string name, Location location) { - location = - min(Parameter p, Identifier i | - scope = p.getDeclaringScope() and - i = parameterIdentifier(p) and - name = i.getValue() - | - i.getLocation() as loc order by loc.getStartLine(), loc.getStartColumn() - ) -} - -/** Holds if `var` is assigned in `scope`. */ -private predicate scopeAssigns(VariableScope scope, Identifier var) { - var in [any(Assignment assign).getLeft(), any(OperatorAssignment assign).getLeft()] and - scope = enclosingScope(var) -} - -/** Holds if location `one` starts strictly before location `two` */ -pragma[inline] -predicate strictlyBefore(Location one, Location two) { - one.getStartLine() < two.getStartLine() - or - one.getStartLine() = two.getStartLine() and one.getStartColumn() < two.getStartColumn() -} - -/** Holds if block scope `scope` inherits `var` from an outer scope `outer`. */ -private predicate blockScopeInherits(BlockScope scope, string var, VariableScope outer) { - not scopeDefinesParameter(scope, var, _) and - ( - outer = scope.getOuterScope() and - ( - scopeDefinesParameter(outer, var, _) - or - exists(Identifier i | i.getValue() = var | - scopeAssigns(outer, i) and - strictlyBefore(i.getLocation(), scope.getLocation()) - ) - ) - or - blockScopeInherits(scope.getOuterScope(), var, outer) - ) -} - -cached -private module Cached { - cached - newtype TScope = - TTopLevelScope(Program node) or - TModuleScope(Module node) or - TClassScope(AstNode cls) { cls instanceof Class or cls instanceof SingletonClass } or - TMethodScope(AstNode method) { method instanceof Method or method instanceof SingletonMethod } or - TBlockScope(AstNode block) { block instanceof Block or block instanceof DoBlock } - - cached - newtype TVariable = - TLocalVariable(VariableScope scope, string name, Location location) { - scopeDefinesParameter(scope, name, location) - or - not scopeDefinesParameter(scope, name, _) and - not blockScopeInherits(scope, name, _) and - location = - min(Location loc, Identifier other | - loc = other.getLocation() and name = other.getValue() and scopeAssigns(scope, other) - | - loc order by loc.getStartLine(), loc.getStartColumn() - ) - } - - cached - predicate access(Identifier access, Variable variable) { - exists(string name | name = access.getValue() | - variable = enclosingScope(access).getVariable(name) and - not strictlyBefore(access.getLocation(), variable.getLocation()) - or - exists(VariableScope declScope | - variable = declScope.getVariable(name) and - blockScopeInherits(enclosingScope(access), name, declScope) - ) - ) - } -} - -private import Cached +private import internal.Variable /** A scope in which variables can be declared. */ class VariableScope extends TScope { @@ -157,6 +26,47 @@ class VariableScope extends TScope { } } +/** A top-level scope. */ +class TopLevelScope extends VariableScope, TTopLevelScope { + final override string toString() { result = "top-level scope" } + + final override AstNode getScopeElement() { TTopLevelScope(result) = this } +} + +/** A module scope. */ +class ModuleScope extends VariableScope, TModuleScope { + final override string toString() { result = "module scope" } + + final override AstNode getScopeElement() { TModuleScope(result) = this } +} + +/** A class scope. */ +class ClassScope extends VariableScope, TClassScope { + final override string toString() { result = "class scope" } + + final override AstNode getScopeElement() { TClassScope(result) = this } +} + +/** A callable scope. */ +class CallableScope extends VariableScope, TCallableScope { + private Callable c; + + CallableScope() { this = TCallableScope(c) } + + final override string toString() { + (c instanceof Method or c instanceof SingletonMethod) and + result = "method scope" + or + c instanceof Lambda and + result = "lambda scope" + or + c instanceof Block and + result = "block scope" + } + + final override Callable getScopeElement() { TCallableScope(result) = this } +} + /** A variable declared in a scope. */ class Variable extends TVariable { /** Gets the name of this variable. */ @@ -179,78 +89,37 @@ class Variable extends TVariable { class LocalVariable extends Variable { private VariableScope scope; private string name; - private Location location; + private Generated::Identifier i; - LocalVariable() { this = TLocalVariable(scope, name, location) } + LocalVariable() { this = TLocalVariable(scope, name, i) } final override string getName() { result = name } - final override Location getLocation() { result = location } + final override Location getLocation() { result = i.getLocation() } final override VariableScope getDeclaringScope() { result = scope } + + final override LocalVariableAccess getAnAccess() { result.getVariable() = this } } -/** An identifier that refers to a variable. */ -class VariableAccess extends Identifier { +/** An access to a variable. */ +class VariableAccess extends AstNode, @token_identifier { + override Generated::Identifier generated; Variable variable; VariableAccess() { access(this, variable) } - /** - * Gets the variable this identifier refers to. - */ + /** Gets the variable this identifier refers to. */ Variable getVariable() { result = variable } + + override string toString() { result = variable.getName() } } -/** An identifier that refers to a parameter. */ -class ParameterAccess extends VariableAccess { - Parameter parameter; +/** An access to a local variable. */ +class LocalVariableAccess extends VariableAccess { + override LocalVariable variable; - ParameterAccess() { - exists(Identifier i | - i = parameterIdentifier(parameter) and - variable.getDeclaringScope() = parameter.getDeclaringScope() and - variable.getLocation() = i.getLocation() - ) - } + override LocalVariable getVariable() { result = variable } - final Parameter getParameter() { result = parameter } -} - -/** A top-level scope. */ -class TopLevelScope extends VariableScope, TTopLevelScope { - final override string toString() { result = "top-level scope" } - - final override AstNode getScopeElement() { TTopLevelScope(result) = this } -} - -/** A module scope. */ -class ModuleScope extends VariableScope, TModuleScope { - final override string toString() { result = "module scope" } - - final override Module getScopeElement() { TModuleScope(result) = this } -} - -/** A class scope. */ -class ClassScope extends VariableScope, TClassScope { - final override string toString() { result = "class scope" } - - final override AstNode getScopeElement() { TClassScope(result) = this } -} - -/** A method scope. */ -class MethodScope extends VariableScope, TMethodScope { - final override string toString() { result = "method scope" } - - final override AstNode getScopeElement() { TMethodScope(result) = this } -} - -/** A block scope. */ -class BlockScope extends VariableScope, TBlockScope { - final override string toString() { result = "block scope" } - - final override AstNode getScopeElement() { TBlockScope(result) = this } - - /** Gets the scope in which this scope is nested, if any. */ - final VariableScope getOuterScope() { result = enclosingScope(this.getScopeElement()) } + override string toString() { result = variable.getName() } } diff --git a/ql/src/codeql_ruby/ast/internal/Method.qll b/ql/src/codeql_ruby/ast/internal/Method.qll new file mode 100644 index 00000000000..b2519a8e3d0 --- /dev/null +++ b/ql/src/codeql_ruby/ast/internal/Method.qll @@ -0,0 +1,42 @@ +import codeql_ruby.AST +private import codeql_ruby.Generated + +abstract class CallableRange extends AstNode { + abstract Parameter getParameter(int n); +} + +private class MethodRange extends CallableRange, @method { + final override Generated::Method generated; + + override Parameter getParameter(int n) { result = generated.getParameters().getChild(n) } +} + +private class SingletonMethodRange extends CallableRange, @singleton_method { + final override Generated::SingletonMethod generated; + + override Parameter getParameter(int n) { result = generated.getParameters().getChild(n) } +} + +private class LambdaRange extends CallableRange, @lambda { + final override Generated::Lambda generated; + + final override Parameter getParameter(int n) { result = generated.getParameters().getChild(n) } +} + +abstract class BlockRange extends CallableRange { + Generated::BlockParameters params; + + final override Parameter getParameter(int n) { result = params.getChild(n) } +} + +private class DoBlockRange extends BlockRange, @do_block { + final override Generated::DoBlock generated; + + DoBlockRange() { params = generated.getParameters() } +} + +private class BraceBlockRange extends BlockRange, @block { + final override Generated::Block generated; + + BraceBlockRange() { params = generated.getParameters() } +} diff --git a/ql/src/codeql_ruby/ast/internal/Pattern.qll b/ql/src/codeql_ruby/ast/internal/Pattern.qll new file mode 100644 index 00000000000..35ebc7c69d5 --- /dev/null +++ b/ql/src/codeql_ruby/ast/internal/Pattern.qll @@ -0,0 +1,65 @@ +import codeql_ruby.AST +private import codeql_ruby.Generated +private import codeql.Locations + +private predicate tuplePatternNode(Generated::AstNode n, boolean parameter) { + n instanceof Generated::DestructuredParameter and + parameter = true + or + n instanceof Generated::DestructuredLeftAssignment and + parameter = false + or + n instanceof Generated::LeftAssignmentList and + parameter = false + or + tuplePatternNode(n.getParent(), parameter) +} + +private predicate patternNode(Generated::AstNode n, boolean parameter) { + tuplePatternNode(n, parameter) + or + parameter = true and + n = any(Callable c).getAParameter() + or + parameter = false and + n in [ + any(Generated::Assignment assign).getLeft(), + any(Generated::OperatorAssignment assign).getLeft() + ] +} + +/** + * Holds if a variable is assigned at `i`. `parameter` indicates whether it is + * an implicit parameter assignment. + */ +predicate assignment(Generated::Identifier i, boolean parameter) { patternNode(i, parameter) } + +abstract class PatternRange extends AstNode { + PatternRange() { patternNode(this, _) } +} + +private class VariablePatternRange extends PatternRange { + override Generated::Identifier generated; +} + +abstract class TuplePatternRange extends PatternRange { + abstract Pattern getElement(int i); +} + +private class ParameterTuplePatternRange extends TuplePatternRange { + override Generated::DestructuredParameter generated; + + override Pattern getElement(int i) { result = generated.getChild(i) } +} + +private class AssignmentTuplePatternRange extends TuplePatternRange { + override Generated::DestructuredLeftAssignment generated; + + override Pattern getElement(int i) { result = generated.getChild(i) } +} + +private class AssignmentListPatternRange extends TuplePatternRange { + override Generated::LeftAssignmentList generated; + + override Pattern getElement(int i) { result = generated.getChild(i) } +} diff --git a/ql/src/codeql_ruby/ast/internal/Variable.qll b/ql/src/codeql_ruby/ast/internal/Variable.qll new file mode 100644 index 00000000000..8cbda5c70b8 --- /dev/null +++ b/ql/src/codeql_ruby/ast/internal/Variable.qll @@ -0,0 +1,130 @@ +import codeql_ruby.AST +private import codeql_ruby.Generated +private import codeql.Locations +private import Pattern + +private Generated::AstNode parent(Generated::AstNode n) { + result = n.getParent() and + not n = any(VariableScope s).getScopeElement() +} + +/** Gets the enclosing scope for `node`. */ +private VariableScope enclosingScope(Generated::AstNode node) { + result.getScopeElement() = parent*(node.getParent()) +} + +/** Holds if `scope` defines `name` in its parameter declaration at `i`. */ +private predicate scopeDefinesParameterVariable( + CallableScope scope, string name, Generated::Identifier i +) { + assignment(i, true) and + scope = enclosingScope(i) and + name = i.getValue() + or + exists(Parameter p | + p = scope.getScopeElement().getAParameter() and + name = p.(NamedParameter).getName() + | + i = p.(Generated::BlockParameter).getName() or + i = p.(Generated::HashSplatParameter).getName() or + i = p.(Generated::KeywordParameter).getName() or + i = p.(Generated::OptionalParameter).getName() or + i = p.(Generated::SplatParameter).getName() + ) +} + +/** Holds if `name` is assigned in `scope` at `i`. */ +private predicate scopeAssigns(VariableScope scope, string name, Generated::Identifier i) { + assignment(i, false) and + name = i.getValue() and + scope = enclosingScope(i) +} + +/** Holds if location `one` starts strictly before location `two` */ +pragma[inline] +private predicate strictlyBefore(Location one, Location two) { + one.getStartLine() < two.getStartLine() + or + one.getStartLine() = two.getStartLine() and one.getStartColumn() < two.getStartColumn() +} + +/** A scope that may capture outer local variables. */ +private class CapturingScope extends CallableScope { + CapturingScope() { + exists(Callable c | c = this.getScopeElement() | + c instanceof Block + or + c instanceof DoBlock + or + c instanceof Lambda // TODO: Check if this is actually the case + ) + } + + /** Gets the scope in which this scope is nested, if any. */ + private VariableScope getOuterScope() { result = enclosingScope(this.getScopeElement()) } + + /** Holds if this scope inherits `name` from an outer scope `outer`. */ + predicate inherits(string name, VariableScope outer) { + 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().(CapturingScope).inherits(name, outer) + ) + } +} + +cached +private module Cached { + cached + newtype TScope = + TTopLevelScope(Generated::Program node) or + TModuleScope(Generated::Module node) or + TClassScope(AstNode cls) { + cls instanceof Generated::Class or cls instanceof Generated::SingletonClass + } or + TCallableScope(Callable c) + + cached + newtype TVariable = + TLocalVariable(VariableScope scope, string name, Generated::Identifier i) { + scopeDefinesParameterVariable(scope, name, i) + or + scopeAssigns(scope, name, i) and + i = + min(Generated::Identifier other | + scopeAssigns(scope, name, other) + | + other order by other.getLocation().getStartLine(), other.getLocation().getStartColumn() + ) and + not scopeDefinesParameterVariable(scope, name, _) and + not scope.(CapturingScope).inherits(name, _) + } + + cached + predicate access(Generated::Identifier access, Variable variable) { + exists(string name | + name = access.getValue() and + // Do not generate an access at the defining location + not variable = TLocalVariable(_, name, access) + | + variable = enclosingScope(access).getVariable(name) and + not strictlyBefore(access.getLocation(), variable.getLocation()) + or + exists(VariableScope declScope | + variable = declScope.getVariable(name) and + enclosingScope(access).(CapturingScope).inherits(name, declScope) + ) + ) + } +} + +import Cached diff --git a/ql/test/library-tests/ast/params/params.expected b/ql/test/library-tests/ast/params/params.expected index c3fde5ca2d0..5f3ac3db14c 100644 --- a/ql/test/library-tests/ast/params/params.expected +++ b/ql/test/library-tests/ast/params/params.expected @@ -6,23 +6,33 @@ idParams | params.rb:9:20:9:24 | value | value | | params.rb:14:11:14:13 | foo | foo | | params.rb:14:16:14:18 | bar | bar | -| params.rb:17:32:17:32 | a | a | -| params.rb:17:35:17:35 | b | b | -| params.rb:17:38:17:38 | c | c | -| params.rb:22:16:22:16 | a | a | -| params.rb:22:19:22:19 | b | b | -| params.rb:25:24:25:28 | first | first | -| params.rb:25:31:25:36 | second | second | -| params.rb:25:41:25:45 | third | third | -| params.rb:25:48:25:53 | fourth | fourth | | params.rb:30:23:30:28 | wibble | wibble | +| params.rb:30:31:30:36 | splat | splat | +| params.rb:30:39:30:52 | **double_splat | double_splat | | params.rb:34:16:34:18 | val | val | +| params.rb:34:21:34:26 | splat | splat | +| params.rb:34:29:34:42 | **double_splat | double_splat | | params.rb:38:26:38:26 | x | x | +| params.rb:38:29:38:33 | blah | blah | +| params.rb:38:36:38:43 | **wibble | wibble | | params.rb:41:32:41:32 | x | x | +| params.rb:41:35:41:38 | foo | foo | +| params.rb:41:41:41:46 | bar | bar | +| params.rb:46:28:46:33 | &block | block | +| params.rb:49:28:49:30 | xx | xx | +| params.rb:49:33:49:39 | yy | yy | | params.rb:53:34:53:34 | x | x | +| params.rb:53:37:53:38 | y | y | +| params.rb:53:41:53:44 | z | z | | params.rb:58:33:58:36 | val1 | val1 | +| params.rb:58:39:58:46 | val2 | val2 | +| params.rb:58:49:58:58 | val3 | val3 | +| params.rb:62:29:62:34 | &block | block | | params.rb:65:29:65:32 | name | name | +| params.rb:65:35:65:42 | age | age | | params.rb:70:35:70:35 | a | a | +| params.rb:70:38:70:45 | b | b | +| params.rb:70:48:70:53 | c | c | blockParams | params.rb:46:28:46:33 | &block | block | | params.rb:62:29:62:34 | &block | block | @@ -58,82 +68,82 @@ optionalParams | params.rb:70:38:70:45 | b | b | params.rb:70:42:70:45 | AstNode | | params.rb:70:48:70:53 | c | c | params.rb:70:52:70:53 | AstNode | paramsInMethods -| params.rb:4:1:5:3 | identifier_method_params | 0 | params.rb:4:30:4:32 | foo | IdentifierParameter | -| params.rb:4:1:5:3 | identifier_method_params | 1 | params.rb:4:35:4:37 | bar | IdentifierParameter | -| params.rb:4:1:5:3 | identifier_method_params | 2 | params.rb:4:40:4:42 | baz | IdentifierParameter | -| params.rb:17:1:18:3 | destructured_method_param | 0 | params.rb:17:31:17:39 | (..., ...) | PatternParameter | -| params.rb:30:1:31:3 | method_with_splat | 0 | params.rb:30:23:30:28 | wibble | IdentifierParameter | +| params.rb:4:1:5:3 | identifier_method_params | 0 | params.rb:4:30:4:32 | foo | SimpleParameter | +| params.rb:4:1:5:3 | identifier_method_params | 1 | params.rb:4:35:4:37 | bar | SimpleParameter | +| params.rb:4:1:5:3 | identifier_method_params | 2 | params.rb:4:40:4:42 | baz | SimpleParameter | +| params.rb:17:1:18:3 | destructured_method_param | 0 | params.rb:17:31:17:39 | (..., ...) | TuplePatternParameter | +| params.rb:30:1:31:3 | method_with_splat | 0 | params.rb:30:23:30:28 | wibble | SimpleParameter | | params.rb:30:1:31:3 | method_with_splat | 1 | params.rb:30:31:30:36 | splat | SplatParameter | | params.rb:30:1:31:3 | method_with_splat | 2 | params.rb:30:39:30:52 | **double_splat | HashSplatParameter | -| params.rb:41:1:43:3 | method_with_keyword_params | 0 | params.rb:41:32:41:32 | x | IdentifierParameter | +| params.rb:41:1:43:3 | method_with_keyword_params | 0 | params.rb:41:32:41:32 | x | SimpleParameter | | params.rb:41:1:43:3 | method_with_keyword_params | 1 | params.rb:41:35:41:38 | foo | KeywordParameter | | params.rb:41:1:43:3 | method_with_keyword_params | 2 | params.rb:41:41:41:46 | bar | KeywordParameter | | params.rb:46:1:48:3 | use_block_with_keyword | 0 | params.rb:46:28:46:33 | &block | BlockParameter | -| params.rb:58:1:59:3 | method_with_optional_params | 0 | params.rb:58:33:58:36 | val1 | IdentifierParameter | +| params.rb:58:1:59:3 | method_with_optional_params | 0 | params.rb:58:33:58:36 | val1 | SimpleParameter | | params.rb:58:1:59:3 | method_with_optional_params | 1 | params.rb:58:39:58:46 | val2 | OptionalParameter | | params.rb:58:1:59:3 | method_with_optional_params | 2 | params.rb:58:49:58:58 | val3 | OptionalParameter | | params.rb:62:1:64:3 | use_block_with_optional | 0 | params.rb:62:29:62:34 | &block | BlockParameter | paramsInBlocks -| params.rb:9:11:11:3 | \| ... \| | 0 | params.rb:9:15:9:17 | key | IdentifierParameter | -| params.rb:9:11:11:3 | \| ... \| | 1 | params.rb:9:20:9:24 | value | IdentifierParameter | -| params.rb:22:12:22:32 | { ... } | 0 | params.rb:22:15:22:20 | (..., ...) | PatternParameter | -| params.rb:34:12:35:3 | \| ... \| | 0 | params.rb:34:16:34:18 | val | IdentifierParameter | +| params.rb:9:11:11:3 | \| ... \| | 0 | params.rb:9:15:9:17 | key | SimpleParameter | +| params.rb:9:11:11:3 | \| ... \| | 1 | params.rb:9:20:9:24 | value | SimpleParameter | +| params.rb:22:12:22:32 | { ... } | 0 | params.rb:22:15:22:20 | (..., ...) | TuplePatternParameter | +| params.rb:34:12:35:3 | \| ... \| | 0 | params.rb:34:16:34:18 | val | SimpleParameter | | params.rb:34:12:35:3 | \| ... \| | 1 | params.rb:34:21:34:26 | splat | SplatParameter | | params.rb:34:12:35:3 | \| ... \| | 2 | params.rb:34:29:34:42 | **double_splat | HashSplatParameter | | params.rb:49:24:51:3 | \| ... \| | 0 | params.rb:49:28:49:30 | xx | KeywordParameter | | params.rb:49:24:51:3 | \| ... \| | 1 | params.rb:49:33:49:39 | yy | KeywordParameter | -| params.rb:65:25:67:3 | \| ... \| | 0 | params.rb:65:29:65:32 | name | IdentifierParameter | +| params.rb:65:25:67:3 | \| ... \| | 0 | params.rb:65:29:65:32 | name | SimpleParameter | | params.rb:65:25:67:3 | \| ... \| | 1 | params.rb:65:35:65:42 | age | OptionalParameter | paramsInLambdas -| params.rb:14:7:14:33 | -> { ... } | 0 | params.rb:14:11:14:13 | foo | IdentifierParameter | -| params.rb:14:7:14:33 | -> { ... } | 1 | params.rb:14:16:14:18 | bar | IdentifierParameter | -| params.rb:25:19:27:1 | -> { ... } | 0 | params.rb:25:23:25:37 | (..., ...) | PatternParameter | -| params.rb:25:19:27:1 | -> { ... } | 1 | params.rb:25:40:25:54 | (..., ...) | PatternParameter | -| params.rb:38:22:38:47 | -> { ... } | 0 | params.rb:38:26:38:26 | x | IdentifierParameter | +| params.rb:14:7:14:33 | -> { ... } | 0 | params.rb:14:11:14:13 | foo | SimpleParameter | +| params.rb:14:7:14:33 | -> { ... } | 1 | params.rb:14:16:14:18 | bar | SimpleParameter | +| params.rb:25:19:27:1 | -> { ... } | 0 | params.rb:25:23:25:37 | (..., ...) | TuplePatternParameter | +| params.rb:25:19:27:1 | -> { ... } | 1 | params.rb:25:40:25:54 | (..., ...) | TuplePatternParameter | +| params.rb:38:22:38:47 | -> { ... } | 0 | params.rb:38:26:38:26 | x | SimpleParameter | | params.rb:38:22:38:47 | -> { ... } | 1 | params.rb:38:29:38:33 | blah | SplatParameter | | params.rb:38:22:38:47 | -> { ... } | 2 | params.rb:38:36:38:43 | **wibble | HashSplatParameter | -| params.rb:53:30:55:1 | -> { ... } | 0 | params.rb:53:34:53:34 | x | IdentifierParameter | +| params.rb:53:30:55:1 | -> { ... } | 0 | params.rb:53:34:53:34 | x | SimpleParameter | | params.rb:53:30:55:1 | -> { ... } | 1 | params.rb:53:37:53:38 | y | KeywordParameter | | params.rb:53:30:55:1 | -> { ... } | 2 | params.rb:53:41:53:44 | z | KeywordParameter | -| params.rb:70:31:70:64 | -> { ... } | 0 | params.rb:70:35:70:35 | a | IdentifierParameter | +| params.rb:70:31:70:64 | -> { ... } | 0 | params.rb:70:35:70:35 | a | SimpleParameter | | params.rb:70:31:70:64 | -> { ... } | 1 | params.rb:70:38:70:45 | b | OptionalParameter | | params.rb:70:31:70:64 | -> { ... } | 2 | params.rb:70:48:70:53 | c | OptionalParameter | #select -| params.rb:4:30:4:32 | foo | 0 | IdentifierParameter | -| params.rb:4:35:4:37 | bar | 1 | IdentifierParameter | -| params.rb:4:40:4:42 | baz | 2 | IdentifierParameter | -| params.rb:9:15:9:17 | key | 0 | IdentifierParameter | -| params.rb:9:20:9:24 | value | 1 | IdentifierParameter | -| params.rb:14:11:14:13 | foo | 0 | IdentifierParameter | -| params.rb:14:16:14:18 | bar | 1 | IdentifierParameter | -| params.rb:17:31:17:39 | (..., ...) | 0 | PatternParameter | -| params.rb:22:15:22:20 | (..., ...) | 0 | PatternParameter | -| params.rb:25:23:25:37 | (..., ...) | 0 | PatternParameter | -| params.rb:25:40:25:54 | (..., ...) | 1 | PatternParameter | -| params.rb:30:23:30:28 | wibble | 0 | IdentifierParameter | +| params.rb:4:30:4:32 | foo | 0 | SimpleParameter | +| params.rb:4:35:4:37 | bar | 1 | SimpleParameter | +| params.rb:4:40:4:42 | baz | 2 | SimpleParameter | +| params.rb:9:15:9:17 | key | 0 | SimpleParameter | +| params.rb:9:20:9:24 | value | 1 | SimpleParameter | +| params.rb:14:11:14:13 | foo | 0 | SimpleParameter | +| params.rb:14:16:14:18 | bar | 1 | SimpleParameter | +| params.rb:17:31:17:39 | (..., ...) | 0 | TuplePatternParameter | +| params.rb:22:15:22:20 | (..., ...) | 0 | TuplePatternParameter | +| params.rb:25:23:25:37 | (..., ...) | 0 | TuplePatternParameter | +| params.rb:25:40:25:54 | (..., ...) | 1 | TuplePatternParameter | +| params.rb:30:23:30:28 | wibble | 0 | SimpleParameter | | params.rb:30:31:30:36 | splat | 1 | SplatParameter | | params.rb:30:39:30:52 | **double_splat | 2 | HashSplatParameter | -| params.rb:34:16:34:18 | val | 0 | IdentifierParameter | +| params.rb:34:16:34:18 | val | 0 | SimpleParameter | | params.rb:34:21:34:26 | splat | 1 | SplatParameter | | params.rb:34:29:34:42 | **double_splat | 2 | HashSplatParameter | -| params.rb:38:26:38:26 | x | 0 | IdentifierParameter | +| params.rb:38:26:38:26 | x | 0 | SimpleParameter | | params.rb:38:29:38:33 | blah | 1 | SplatParameter | | params.rb:38:36:38:43 | **wibble | 2 | HashSplatParameter | -| params.rb:41:32:41:32 | x | 0 | IdentifierParameter | +| params.rb:41:32:41:32 | x | 0 | SimpleParameter | | params.rb:41:35:41:38 | foo | 1 | KeywordParameter | | params.rb:41:41:41:46 | bar | 2 | KeywordParameter | | params.rb:46:28:46:33 | &block | 0 | BlockParameter | | params.rb:49:28:49:30 | xx | 0 | KeywordParameter | | params.rb:49:33:49:39 | yy | 1 | KeywordParameter | -| params.rb:53:34:53:34 | x | 0 | IdentifierParameter | +| params.rb:53:34:53:34 | x | 0 | SimpleParameter | | params.rb:53:37:53:38 | y | 1 | KeywordParameter | | params.rb:53:41:53:44 | z | 2 | KeywordParameter | -| params.rb:58:33:58:36 | val1 | 0 | IdentifierParameter | +| params.rb:58:33:58:36 | val1 | 0 | SimpleParameter | | params.rb:58:39:58:46 | val2 | 1 | OptionalParameter | | params.rb:58:49:58:58 | val3 | 2 | OptionalParameter | | params.rb:62:29:62:34 | &block | 0 | BlockParameter | -| params.rb:65:29:65:32 | name | 0 | IdentifierParameter | +| params.rb:65:29:65:32 | name | 0 | SimpleParameter | | params.rb:65:35:65:42 | age | 1 | OptionalParameter | -| params.rb:70:35:70:35 | a | 0 | IdentifierParameter | +| params.rb:70:35:70:35 | a | 0 | SimpleParameter | | params.rb:70:38:70:45 | b | 1 | OptionalParameter | | params.rb:70:48:70:53 | c | 2 | OptionalParameter | diff --git a/ql/test/library-tests/ast/params/params.ql b/ql/test/library-tests/ast/params/params.ql index c17f921d3f2..0ae480f0100 100644 --- a/ql/test/library-tests/ast/params/params.ql +++ b/ql/test/library-tests/ast/params/params.ql @@ -2,12 +2,12 @@ import ruby //////////////////////////////////////////////////////////////////////////////// // Query predicates for various types of parameter -query predicate idParams(IdentifierParameter ip, string name) { name = ip.getName() } +query predicate idParams(NamedParameter np, string name) { name = np.getName() } query predicate blockParams(BlockParameter bp, string name) { name = bp.getName() } -query predicate patternParams(PatternParameter pp, Parameter child, int childIndex) { - pp.getElement(childIndex) = child +query predicate patternParams(TuplePatternParameter tpp, Pattern child, int childIndex) { + tpp.getElement(childIndex) = child } query predicate splatParams(SplatParameter sp, string name) { name = sp.getName() } diff --git a/ql/test/library-tests/variables/parameter.expected b/ql/test/library-tests/variables/parameter.expected index 1e3167d187d..1a881a81b78 100644 --- a/ql/test/library-tests/variables/parameter.expected +++ b/ql/test/library-tests/variables/parameter.expected @@ -1,29 +1,29 @@ parameter | nested_scopes.rb:15:23:15:23 | a | nested_scopes.rb:15:23:15:23 | a | -| nested_scopes.rb:16:26:16:26 | x | nested_scopes.rb:16:26:16:26 | x | | nested_scopes.rb:16:29:16:29 | a | nested_scopes.rb:16:29:16:29 | a | -| nested_scopes.rb:18:26:18:26 | x | nested_scopes.rb:18:26:18:26 | x | | nested_scopes.rb:22:21:22:21 | a | nested_scopes.rb:22:21:22:21 | a | | parameters.rb:1:14:1:14 | x | parameters.rb:1:14:1:14 | x | | parameters.rb:1:18:1:18 | y | parameters.rb:1:18:1:18 | y | | parameters.rb:7:17:7:22 | client | parameters.rb:7:17:7:22 | client | -| parameters.rb:7:25:7:31 | SplatParameter | parameters.rb:7:26:7:31 | pizzas | -| parameters.rb:15:15:15:19 | HashSplatParameter | parameters.rb:15:17:15:19 | map | +| parameters.rb:7:25:7:31 | pizzas | parameters.rb:7:26:7:31 | pizzas | +| parameters.rb:15:15:15:19 | **map | parameters.rb:15:17:15:19 | map | | parameters.rb:16:16:16:18 | key | parameters.rb:16:16:16:18 | key | | parameters.rb:16:21:16:25 | value | parameters.rb:16:21:16:25 | value | -| parameters.rb:21:16:21:21 | BlockParameter | parameters.rb:21:17:21:21 | block | -| parameters.rb:25:15:25:30 | OptionalParameter | parameters.rb:25:15:25:18 | name | -| parameters.rb:25:33:25:50 | OptionalParameter | parameters.rb:25:33:25:36 | size | -| parameters.rb:30:15:30:20 | KeywordParameter | parameters.rb:30:15:30:19 | first | -| parameters.rb:30:24:30:33 | KeywordParameter | parameters.rb:30:24:30:29 | middle | -| parameters.rb:30:36:30:40 | KeywordParameter | parameters.rb:30:36:30:39 | last | -| parameters.rb:35:11:35:21 | OptionalParameter | parameters.rb:35:11:35:11 | a | -| parameters.rb:40:12:40:19 | KeywordParameter | parameters.rb:40:12:40:12 | d | +| parameters.rb:21:16:21:21 | &block | parameters.rb:21:17:21:21 | block | +| parameters.rb:25:15:25:30 | name | parameters.rb:25:15:25:18 | name | +| parameters.rb:25:33:25:50 | size | parameters.rb:25:33:25:36 | size | +| parameters.rb:30:15:30:20 | first | parameters.rb:30:15:30:19 | first | +| parameters.rb:30:24:30:33 | middle | parameters.rb:30:24:30:29 | middle | +| parameters.rb:30:36:30:40 | last | parameters.rb:30:36:30:39 | last | +| parameters.rb:35:11:35:21 | a | parameters.rb:35:11:35:11 | a | +| parameters.rb:40:12:40:19 | d | parameters.rb:40:12:40:12 | d | | parameters.rb:45:20:45:20 | _ | parameters.rb:45:20:45:20 | _ | -| parameters.rb:49:12:49:16 | DestructuredParameter | parameters.rb:49:13:49:13 | a | -| parameters.rb:49:12:49:16 | DestructuredParameter | parameters.rb:49:15:49:15 | b | -| parameters.rb:54:14:54:24 | OptionalParameter | parameters.rb:54:14:54:14 | y | -| scopes.rb:2:14:2:14 | x | scopes.rb:2:14:2:14 | x | -| scopes.rb:9:14:9:14 | x | scopes.rb:9:14:9:14 | x | +| parameters.rb:45:20:45:20 | _ | parameters.rb:45:22:45:22 | _ | +| parameters.rb:45:22:45:22 | _ | parameters.rb:45:20:45:20 | _ | +| parameters.rb:45:22:45:22 | _ | parameters.rb:45:22:45:22 | _ | +| parameters.rb:54:14:54:24 | y | parameters.rb:54:14:54:14 | y | parameterNoAcess -| parameters.rb:45:22:45:22 | _ | +| nested_scopes.rb:16:26:16:26 | x | +| nested_scopes.rb:18:26:18:26 | x | +| scopes.rb:2:14:2:14 | x | +| scopes.rb:9:14:9:14 | x | diff --git a/ql/test/library-tests/variables/parameter.ql b/ql/test/library-tests/variables/parameter.ql index 254abfc2dae..5826fca9e29 100644 --- a/ql/test/library-tests/variables/parameter.ql +++ b/ql/test/library-tests/variables/parameter.ql @@ -1,5 +1,5 @@ import codeql_ruby.ast.Variable -query predicate parameter(Parameter p, Variable v) { p.getAnAccess().getVariable() = v } +query predicate parameter(NamedParameter p, Variable v) { p.getAnAccess().getVariable() = v } -query predicate parameterNoAcess(Parameter p) { not exists(p.getAnAccess()) } +query predicate parameterNoAcess(NamedParameter p) { not exists(p.getAnAccess()) } diff --git a/ql/test/library-tests/variables/scopes.rb b/ql/test/library-tests/variables/scopes.rb index 9ecbad96c5c..1219acef8cc 100644 --- a/ql/test/library-tests/variables/scopes.rb +++ b/ql/test/library-tests/variables/scopes.rb @@ -10,4 +10,9 @@ puts a puts a # local variable from top-level a = 3 puts a # local variable from top-level + a, b, (c, d) = [4, 5, [6, 7]] + puts a # local variable from top-level + puts b # new local variable + puts c # new local variable + puts d # new local variable end \ No newline at end of file diff --git a/ql/test/library-tests/variables/varaccess.expected b/ql/test/library-tests/variables/varaccess.expected index afb0bdab854..3b076a124e2 100644 --- a/ql/test/library-tests/variables/varaccess.expected +++ b/ql/test/library-tests/variables/varaccess.expected @@ -1,173 +1,52 @@ -variableAccess -| nested_scopes.rb:5:3:5:3 | a | nested_scopes.rb:5:3:5:3 | a | nested_scopes.rb:4:1:39:3 | class scope | -| nested_scopes.rb:7:5:7:5 | a | nested_scopes.rb:7:5:7:5 | a | nested_scopes.rb:6:3:37:5 | module scope | -| nested_scopes.rb:9:7:9:7 | a | nested_scopes.rb:9:7:9:7 | a | nested_scopes.rb:8:5:35:7 | module scope | -| nested_scopes.rb:11:9:11:9 | a | nested_scopes.rb:11:9:11:9 | a | nested_scopes.rb:10:7:26:9 | class scope | -| nested_scopes.rb:13:11:13:11 | a | nested_scopes.rb:13:11:13:11 | a | nested_scopes.rb:12:9:21:11 | method scope | | nested_scopes.rb:14:16:14:16 | a | nested_scopes.rb:13:11:13:11 | a | nested_scopes.rb:12:9:21:11 | method scope | | nested_scopes.rb:15:11:15:11 | a | nested_scopes.rb:13:11:13:11 | a | nested_scopes.rb:12:9:21:11 | method scope | -| nested_scopes.rb:15:23:15:23 | a | nested_scopes.rb:15:23:15:23 | a | nested_scopes.rb:15:19:20:13 | block scope | | nested_scopes.rb:16:13:16:13 | a | nested_scopes.rb:15:23:15:23 | a | nested_scopes.rb:15:19:20:13 | block scope | -| nested_scopes.rb:16:26:16:26 | x | nested_scopes.rb:16:26:16:26 | x | nested_scopes.rb:16:21:19:15 | block scope | -| nested_scopes.rb:16:29:16:29 | a | nested_scopes.rb:16:29:16:29 | a | nested_scopes.rb:16:21:19:15 | block scope | | nested_scopes.rb:17:15:17:15 | a | nested_scopes.rb:16:29:16:29 | a | nested_scopes.rb:16:21:19:15 | block scope | | nested_scopes.rb:18:15:18:15 | a | nested_scopes.rb:16:29:16:29 | a | nested_scopes.rb:16:21:19:15 | block scope | -| nested_scopes.rb:18:26:18:26 | x | nested_scopes.rb:18:26:18:26 | x | nested_scopes.rb:18:23:18:36 | block scope | | nested_scopes.rb:18:34:18:34 | a | nested_scopes.rb:16:29:16:29 | a | nested_scopes.rb:16:21:19:15 | block scope | -| nested_scopes.rb:22:21:22:21 | a | nested_scopes.rb:22:21:22:21 | a | nested_scopes.rb:22:9:24:11 | method scope | | nested_scopes.rb:23:16:23:16 | a | nested_scopes.rb:22:21:22:21 | a | nested_scopes.rb:22:9:24:11 | method scope | | nested_scopes.rb:25:14:25:14 | a | nested_scopes.rb:11:9:11:9 | a | nested_scopes.rb:10:7:26:9 | class scope | -| nested_scopes.rb:31:11:31:11 | a | nested_scopes.rb:31:11:31:11 | a | nested_scopes.rb:30:7:33:9 | class scope | | nested_scopes.rb:32:16:32:16 | a | nested_scopes.rb:31:11:31:11 | a | nested_scopes.rb:30:7:33:9 | class scope | | nested_scopes.rb:34:12:34:12 | a | nested_scopes.rb:9:7:9:7 | a | nested_scopes.rb:8:5:35:7 | module scope | | nested_scopes.rb:36:10:36:10 | a | nested_scopes.rb:7:5:7:5 | a | nested_scopes.rb:6:3:37:5 | module scope | | nested_scopes.rb:38:8:38:8 | a | nested_scopes.rb:5:3:5:3 | a | nested_scopes.rb:4:1:39:3 | class scope | -| nested_scopes.rb:40:1:40:1 | d | nested_scopes.rb:40:1:40:1 | d | nested_scopes.rb:1:1:42:1 | top-level scope | | nested_scopes.rb:41:1:41:1 | d | nested_scopes.rb:40:1:40:1 | d | nested_scopes.rb:1:1:42:1 | top-level scope | -| parameters.rb:1:14:1:14 | x | parameters.rb:1:14:1:14 | x | parameters.rb:1:9:5:3 | block scope | -| parameters.rb:1:18:1:18 | y | parameters.rb:1:18:1:18 | y | parameters.rb:1:9:5:3 | block scope | | parameters.rb:2:4:2:4 | y | parameters.rb:1:18:1:18 | y | parameters.rb:1:9:5:3 | block scope | | parameters.rb:3:9:3:9 | x | parameters.rb:1:14:1:14 | x | parameters.rb:1:9:5:3 | block scope | | parameters.rb:4:9:4:9 | y | parameters.rb:1:18:1:18 | y | parameters.rb:1:9:5:3 | block scope | -| parameters.rb:7:17:7:22 | client | parameters.rb:7:17:7:22 | client | parameters.rb:7:1:13:3 | method scope | -| parameters.rb:7:26:7:31 | pizzas | parameters.rb:7:26:7:31 | pizzas | parameters.rb:7:1:13:3 | method scope | | parameters.rb:8:6:8:11 | pizzas | parameters.rb:7:26:7:31 | pizzas | parameters.rb:7:1:13:3 | method scope | | parameters.rb:9:25:9:30 | client | parameters.rb:7:17:7:22 | client | parameters.rb:7:1:13:3 | method scope | | parameters.rb:11:14:11:19 | pizzas | parameters.rb:7:26:7:31 | pizzas | parameters.rb:7:1:13:3 | method scope | | parameters.rb:11:41:11:46 | client | parameters.rb:7:17:7:22 | client | parameters.rb:7:1:13:3 | method scope | -| parameters.rb:15:17:15:19 | map | parameters.rb:15:17:15:19 | map | parameters.rb:15:1:19:3 | method scope | | parameters.rb:16:3:16:5 | map | parameters.rb:15:17:15:19 | map | parameters.rb:15:1:19:3 | method scope | -| parameters.rb:16:16:16:18 | key | parameters.rb:16:16:16:18 | key | parameters.rb:16:12:18:5 | block scope | -| parameters.rb:16:21:16:25 | value | parameters.rb:16:21:16:25 | value | parameters.rb:16:12:18:5 | block scope | | parameters.rb:17:13:17:15 | key | parameters.rb:16:16:16:18 | key | parameters.rb:16:12:18:5 | block scope | | parameters.rb:17:22:17:26 | value | parameters.rb:16:21:16:25 | value | parameters.rb:16:12:18:5 | block scope | -| parameters.rb:21:17:21:21 | block | parameters.rb:21:17:21:21 | block | parameters.rb:21:1:23:3 | method scope | | parameters.rb:22:3:22:7 | block | parameters.rb:21:17:21:21 | block | parameters.rb:21:1:23:3 | method scope | -| parameters.rb:25:15:25:18 | name | parameters.rb:25:15:25:18 | name | parameters.rb:25:1:28:3 | method scope | -| parameters.rb:25:33:25:36 | size | parameters.rb:25:33:25:36 | size | parameters.rb:25:1:28:3 | method scope | | parameters.rb:25:40:25:43 | name | parameters.rb:25:15:25:18 | name | parameters.rb:25:1:28:3 | method scope | | parameters.rb:26:8:26:11 | name | parameters.rb:25:15:25:18 | name | parameters.rb:25:1:28:3 | method scope | | parameters.rb:27:8:27:11 | size | parameters.rb:25:33:25:36 | size | parameters.rb:25:1:28:3 | method scope | -| parameters.rb:30:15:30:19 | first | parameters.rb:30:15:30:19 | first | parameters.rb:30:1:32:3 | method scope | -| parameters.rb:30:24:30:29 | middle | parameters.rb:30:24:30:29 | middle | parameters.rb:30:1:32:3 | method scope | -| parameters.rb:30:36:30:39 | last | parameters.rb:30:36:30:39 | last | parameters.rb:30:1:32:3 | method scope | | parameters.rb:31:11:31:15 | first | parameters.rb:30:15:30:19 | first | parameters.rb:30:1:32:3 | method scope | | parameters.rb:31:20:31:25 | middle | parameters.rb:30:24:30:29 | middle | parameters.rb:30:1:32:3 | method scope | | parameters.rb:31:30:31:33 | last | parameters.rb:30:36:30:39 | last | parameters.rb:30:1:32:3 | method scope | -| parameters.rb:34:1:34:1 | b | parameters.rb:34:1:34:1 | b | parameters.rb:1:1:58:1 | top-level scope | -| parameters.rb:35:11:35:11 | a | parameters.rb:35:11:35:11 | a | parameters.rb:35:1:38:3 | method scope | -| parameters.rb:35:16:35:16 | b | parameters.rb:35:16:35:16 | b | parameters.rb:35:1:38:3 | method scope | | parameters.rb:37:11:37:11 | a | parameters.rb:35:11:35:11 | a | parameters.rb:35:1:38:3 | method scope | | parameters.rb:37:16:37:16 | b | parameters.rb:35:16:35:16 | b | parameters.rb:35:1:38:3 | method scope | -| parameters.rb:40:12:40:12 | d | parameters.rb:40:12:40:12 | d | parameters.rb:40:1:43:3 | method scope | -| parameters.rb:40:15:40:15 | e | parameters.rb:40:15:40:15 | e | parameters.rb:40:1:43:3 | method scope | | parameters.rb:42:11:42:11 | d | parameters.rb:40:12:40:12 | d | parameters.rb:40:1:43:3 | method scope | | parameters.rb:42:16:42:16 | e | parameters.rb:40:15:40:15 | e | parameters.rb:40:1:43:3 | method scope | -| parameters.rb:45:20:45:20 | _ | parameters.rb:45:20:45:20 | _ | parameters.rb:45:1:47:3 | method scope | | parameters.rb:45:22:45:22 | _ | parameters.rb:45:20:45:20 | _ | parameters.rb:45:1:47:3 | method scope | | parameters.rb:46:8:46:8 | _ | parameters.rb:45:20:45:20 | _ | parameters.rb:45:1:47:3 | method scope | -| parameters.rb:49:13:49:13 | a | parameters.rb:49:13:49:13 | a | parameters.rb:49:1:51:3 | method scope | -| parameters.rb:49:15:49:15 | b | parameters.rb:49:15:49:15 | b | parameters.rb:49:1:51:3 | method scope | +| parameters.rb:46:8:46:8 | _ | parameters.rb:45:22:45:22 | _ | parameters.rb:45:1:47:3 | method scope | | parameters.rb:50:11:50:11 | a | parameters.rb:49:13:49:13 | a | parameters.rb:49:1:51:3 | method scope | | parameters.rb:50:16:50:16 | b | parameters.rb:49:15:49:15 | b | parameters.rb:49:1:51:3 | method scope | -| parameters.rb:53:1:53:1 | x | parameters.rb:53:1:53:1 | x | parameters.rb:1:1:58:1 | top-level scope | -| parameters.rb:54:14:54:14 | y | parameters.rb:54:14:54:14 | y | parameters.rb:54:9:57:3 | block scope | | parameters.rb:54:19:54:19 | x | parameters.rb:53:1:53:1 | x | parameters.rb:1:1:58:1 | top-level scope | | parameters.rb:55:9:55:9 | x | parameters.rb:53:1:53:1 | x | parameters.rb:1:1:58:1 | top-level scope | | parameters.rb:56:9:56:9 | y | parameters.rb:54:14:54:14 | y | parameters.rb:54:9:57:3 | block scope | -| scopes.rb:2:14:2:14 | x | scopes.rb:2:14:2:14 | x | scopes.rb:2:9:6:3 | block scope | -| scopes.rb:4:4:4:4 | a | scopes.rb:4:4:4:4 | a | scopes.rb:2:9:6:3 | block scope | | scopes.rb:5:9:5:9 | a | scopes.rb:4:4:4:4 | a | scopes.rb:2:9:6:3 | block scope | -| scopes.rb:7:1:7:1 | a | scopes.rb:7:1:7:1 | a | scopes.rb:1:1:13:3 | top-level scope | -| scopes.rb:8:6:8:6 | a | scopes.rb:7:1:7:1 | a | scopes.rb:1:1:13:3 | top-level scope | -| scopes.rb:9:14:9:14 | x | scopes.rb:9:14:9:14 | x | scopes.rb:9:9:13:3 | block scope | -| scopes.rb:10:9:10:9 | a | scopes.rb:7:1:7:1 | a | scopes.rb:1:1:13:3 | top-level scope | -| scopes.rb:11:4:11:4 | a | scopes.rb:7:1:7:1 | a | scopes.rb:1:1:13:3 | top-level scope | -| scopes.rb:12:9:12:9 | a | scopes.rb:7:1:7:1 | a | scopes.rb:1:1:13:3 | top-level scope | -parameterAccess -| nested_scopes.rb:15:23:15:23 | a | nested_scopes.rb:15:23:15:23 | a | nested_scopes.rb:15:19:20:13 | block scope | -| nested_scopes.rb:16:13:16:13 | a | nested_scopes.rb:15:23:15:23 | a | nested_scopes.rb:15:19:20:13 | block scope | -| nested_scopes.rb:16:26:16:26 | x | nested_scopes.rb:16:26:16:26 | x | nested_scopes.rb:16:21:19:15 | block scope | -| nested_scopes.rb:16:29:16:29 | a | nested_scopes.rb:16:29:16:29 | a | nested_scopes.rb:16:21:19:15 | block scope | -| nested_scopes.rb:17:15:17:15 | a | nested_scopes.rb:16:29:16:29 | a | nested_scopes.rb:16:21:19:15 | block scope | -| nested_scopes.rb:18:15:18:15 | a | nested_scopes.rb:16:29:16:29 | a | nested_scopes.rb:16:21:19:15 | block scope | -| nested_scopes.rb:18:26:18:26 | x | nested_scopes.rb:18:26:18:26 | x | nested_scopes.rb:18:23:18:36 | block scope | -| nested_scopes.rb:18:34:18:34 | a | nested_scopes.rb:16:29:16:29 | a | nested_scopes.rb:16:21:19:15 | block scope | -| nested_scopes.rb:22:21:22:21 | a | nested_scopes.rb:22:21:22:21 | a | nested_scopes.rb:22:9:24:11 | method scope | -| nested_scopes.rb:23:16:23:16 | a | nested_scopes.rb:22:21:22:21 | a | nested_scopes.rb:22:9:24:11 | method scope | -| parameters.rb:1:14:1:14 | x | parameters.rb:1:14:1:14 | x | parameters.rb:1:9:5:3 | block scope | -| parameters.rb:1:18:1:18 | y | parameters.rb:1:18:1:18 | y | parameters.rb:1:9:5:3 | block scope | -| parameters.rb:2:4:2:4 | y | parameters.rb:1:18:1:18 | y | parameters.rb:1:9:5:3 | block scope | -| parameters.rb:3:9:3:9 | x | parameters.rb:1:14:1:14 | x | parameters.rb:1:9:5:3 | block scope | -| parameters.rb:4:9:4:9 | y | parameters.rb:1:18:1:18 | y | parameters.rb:1:9:5:3 | block scope | -| parameters.rb:7:17:7:22 | client | parameters.rb:7:17:7:22 | client | parameters.rb:7:1:13:3 | method scope | -| parameters.rb:7:26:7:31 | pizzas | parameters.rb:7:26:7:31 | pizzas | parameters.rb:7:1:13:3 | method scope | -| parameters.rb:8:6:8:11 | pizzas | parameters.rb:7:26:7:31 | pizzas | parameters.rb:7:1:13:3 | method scope | -| parameters.rb:9:25:9:30 | client | parameters.rb:7:17:7:22 | client | parameters.rb:7:1:13:3 | method scope | -| parameters.rb:11:14:11:19 | pizzas | parameters.rb:7:26:7:31 | pizzas | parameters.rb:7:1:13:3 | method scope | -| parameters.rb:11:41:11:46 | client | parameters.rb:7:17:7:22 | client | parameters.rb:7:1:13:3 | method scope | -| parameters.rb:15:17:15:19 | map | parameters.rb:15:17:15:19 | map | parameters.rb:15:1:19:3 | method scope | -| parameters.rb:16:3:16:5 | map | parameters.rb:15:17:15:19 | map | parameters.rb:15:1:19:3 | method scope | -| parameters.rb:16:16:16:18 | key | parameters.rb:16:16:16:18 | key | parameters.rb:16:12:18:5 | block scope | -| parameters.rb:16:21:16:25 | value | parameters.rb:16:21:16:25 | value | parameters.rb:16:12:18:5 | block scope | -| parameters.rb:17:13:17:15 | key | parameters.rb:16:16:16:18 | key | parameters.rb:16:12:18:5 | block scope | -| parameters.rb:17:22:17:26 | value | parameters.rb:16:21:16:25 | value | parameters.rb:16:12:18:5 | block scope | -| parameters.rb:21:17:21:21 | block | parameters.rb:21:17:21:21 | block | parameters.rb:21:1:23:3 | method scope | -| parameters.rb:22:3:22:7 | block | parameters.rb:21:17:21:21 | block | parameters.rb:21:1:23:3 | method scope | -| parameters.rb:25:15:25:18 | name | parameters.rb:25:15:25:18 | name | parameters.rb:25:1:28:3 | method scope | -| parameters.rb:25:33:25:36 | size | parameters.rb:25:33:25:36 | size | parameters.rb:25:1:28:3 | method scope | -| parameters.rb:25:40:25:43 | name | parameters.rb:25:15:25:18 | name | parameters.rb:25:1:28:3 | method scope | -| parameters.rb:26:8:26:11 | name | parameters.rb:25:15:25:18 | name | parameters.rb:25:1:28:3 | method scope | -| parameters.rb:27:8:27:11 | size | parameters.rb:25:33:25:36 | size | parameters.rb:25:1:28:3 | method scope | -| parameters.rb:30:15:30:19 | first | parameters.rb:30:15:30:19 | first | parameters.rb:30:1:32:3 | method scope | -| parameters.rb:30:24:30:29 | middle | parameters.rb:30:24:30:29 | middle | parameters.rb:30:1:32:3 | method scope | -| parameters.rb:30:36:30:39 | last | parameters.rb:30:36:30:39 | last | parameters.rb:30:1:32:3 | method scope | -| parameters.rb:31:11:31:15 | first | parameters.rb:30:15:30:19 | first | parameters.rb:30:1:32:3 | method scope | -| parameters.rb:31:20:31:25 | middle | parameters.rb:30:24:30:29 | middle | parameters.rb:30:1:32:3 | method scope | -| parameters.rb:31:30:31:33 | last | parameters.rb:30:36:30:39 | last | parameters.rb:30:1:32:3 | method scope | -| parameters.rb:35:11:35:11 | a | parameters.rb:35:11:35:11 | a | parameters.rb:35:1:38:3 | method scope | -| parameters.rb:37:11:37:11 | a | parameters.rb:35:11:35:11 | a | parameters.rb:35:1:38:3 | method scope | -| parameters.rb:40:12:40:12 | d | parameters.rb:40:12:40:12 | d | parameters.rb:40:1:43:3 | method scope | -| parameters.rb:42:11:42:11 | d | parameters.rb:40:12:40:12 | d | parameters.rb:40:1:43:3 | method scope | -| parameters.rb:45:20:45:20 | _ | parameters.rb:45:20:45:20 | _ | parameters.rb:45:1:47:3 | method scope | -| parameters.rb:45:22:45:22 | _ | parameters.rb:45:20:45:20 | _ | parameters.rb:45:1:47:3 | method scope | -| parameters.rb:46:8:46:8 | _ | parameters.rb:45:20:45:20 | _ | parameters.rb:45:1:47:3 | method scope | -| parameters.rb:49:13:49:13 | a | parameters.rb:49:13:49:13 | a | parameters.rb:49:1:51:3 | method scope | -| parameters.rb:49:15:49:15 | b | parameters.rb:49:15:49:15 | b | parameters.rb:49:1:51:3 | method scope | -| parameters.rb:50:11:50:11 | a | parameters.rb:49:13:49:13 | a | parameters.rb:49:1:51:3 | method scope | -| parameters.rb:50:16:50:16 | b | parameters.rb:49:15:49:15 | b | parameters.rb:49:1:51:3 | method scope | -| parameters.rb:54:14:54:14 | y | parameters.rb:54:14:54:14 | y | parameters.rb:54:9:57:3 | block scope | -| parameters.rb:56:9:56:9 | y | parameters.rb:54:14:54:14 | y | parameters.rb:54:9:57:3 | block scope | -| scopes.rb:2:14:2:14 | x | scopes.rb:2:14:2:14 | x | scopes.rb:2:9:6:3 | block scope | -| scopes.rb:9:14:9:14 | x | scopes.rb:9:14:9:14 | x | scopes.rb:9:9:13:3 | block scope | -localVariableAccess -| nested_scopes.rb:5:3:5:3 | a | nested_scopes.rb:5:3:5:3 | a | nested_scopes.rb:4:1:39:3 | class scope | -| nested_scopes.rb:7:5:7:5 | a | nested_scopes.rb:7:5:7:5 | a | nested_scopes.rb:6:3:37:5 | module scope | -| nested_scopes.rb:9:7:9:7 | a | nested_scopes.rb:9:7:9:7 | a | nested_scopes.rb:8:5:35:7 | module scope | -| nested_scopes.rb:11:9:11:9 | a | nested_scopes.rb:11:9:11:9 | a | nested_scopes.rb:10:7:26:9 | class scope | -| nested_scopes.rb:13:11:13:11 | a | nested_scopes.rb:13:11:13:11 | a | nested_scopes.rb:12:9:21:11 | method scope | -| nested_scopes.rb:14:16:14:16 | a | nested_scopes.rb:13:11:13:11 | a | nested_scopes.rb:12:9:21:11 | method scope | -| nested_scopes.rb:15:11:15:11 | a | nested_scopes.rb:13:11:13:11 | a | nested_scopes.rb:12:9:21:11 | method scope | -| nested_scopes.rb:25:14:25:14 | a | nested_scopes.rb:11:9:11:9 | a | nested_scopes.rb:10:7:26:9 | class scope | -| nested_scopes.rb:31:11:31:11 | a | nested_scopes.rb:31:11:31:11 | a | nested_scopes.rb:30:7:33:9 | class scope | -| nested_scopes.rb:32:16:32:16 | a | nested_scopes.rb:31:11:31:11 | a | nested_scopes.rb:30:7:33:9 | class scope | -| nested_scopes.rb:34:12:34:12 | a | nested_scopes.rb:9:7:9:7 | a | nested_scopes.rb:8:5:35:7 | module scope | -| nested_scopes.rb:36:10:36:10 | a | nested_scopes.rb:7:5:7:5 | a | nested_scopes.rb:6:3:37:5 | module scope | -| nested_scopes.rb:38:8:38:8 | a | nested_scopes.rb:5:3:5:3 | a | nested_scopes.rb:4:1:39:3 | class scope | -| nested_scopes.rb:40:1:40:1 | d | nested_scopes.rb:40:1:40:1 | d | nested_scopes.rb:1:1:42:1 | top-level scope | -| nested_scopes.rb:41:1:41:1 | d | nested_scopes.rb:40:1:40:1 | d | nested_scopes.rb:1:1:42:1 | top-level scope | -| parameters.rb:34:1:34:1 | b | parameters.rb:34:1:34:1 | b | parameters.rb:1:1:58:1 | top-level scope | -| parameters.rb:35:16:35:16 | b | parameters.rb:35:16:35:16 | b | parameters.rb:35:1:38:3 | method scope | -| parameters.rb:37:16:37:16 | b | parameters.rb:35:16:35:16 | b | parameters.rb:35:1:38:3 | method scope | -| parameters.rb:40:15:40:15 | e | parameters.rb:40:15:40:15 | e | parameters.rb:40:1:43:3 | method scope | -| parameters.rb:42:16:42:16 | e | parameters.rb:40:15:40:15 | e | parameters.rb:40:1:43:3 | method scope | -| parameters.rb:53:1:53:1 | x | parameters.rb:53:1:53:1 | x | parameters.rb:1:1:58:1 | top-level scope | -| parameters.rb:54:19:54:19 | x | parameters.rb:53:1:53:1 | x | parameters.rb:1:1:58:1 | top-level scope | -| parameters.rb:55:9:55:9 | x | parameters.rb:53:1:53:1 | x | parameters.rb:1:1:58:1 | top-level scope | -| scopes.rb:4:4:4:4 | a | scopes.rb:4:4:4:4 | a | scopes.rb:2:9:6:3 | block scope | -| scopes.rb:5:9:5:9 | a | scopes.rb:4:4:4:4 | a | scopes.rb:2:9:6:3 | block scope | -| scopes.rb:7:1:7:1 | a | scopes.rb:7:1:7:1 | a | scopes.rb:1:1:13:3 | top-level scope | -| scopes.rb:8:6:8:6 | a | scopes.rb:7:1:7:1 | a | scopes.rb:1:1:13:3 | top-level scope | -| scopes.rb:10:9:10:9 | a | scopes.rb:7:1:7:1 | a | scopes.rb:1:1:13:3 | top-level scope | -| scopes.rb:11:4:11:4 | a | scopes.rb:7:1:7:1 | a | scopes.rb:1:1:13:3 | top-level scope | -| scopes.rb:12:9:12:9 | a | scopes.rb:7:1:7:1 | a | scopes.rb:1:1:13:3 | top-level scope | +| scopes.rb:8:6:8:6 | a | scopes.rb:7:1:7:1 | a | scopes.rb:1:1:18:3 | top-level scope | +| scopes.rb:10:9:10:9 | a | scopes.rb:7:1:7:1 | a | scopes.rb:1:1:18:3 | top-level scope | +| scopes.rb:11:4:11:4 | a | scopes.rb:7:1:7:1 | a | scopes.rb:1:1:18:3 | top-level scope | +| scopes.rb:12:9:12:9 | a | scopes.rb:7:1:7:1 | a | scopes.rb:1:1:18:3 | top-level scope | +| scopes.rb:13:4:13:4 | a | scopes.rb:7:1:7:1 | a | scopes.rb:1:1:18:3 | top-level scope | +| scopes.rb:14:9:14:9 | a | scopes.rb:7:1:7:1 | a | scopes.rb:1:1:18:3 | top-level scope | +| scopes.rb:15:9:15:9 | b | scopes.rb:13:7:13:7 | b | scopes.rb:9:9:18:3 | block scope | +| scopes.rb:16:9:16:9 | c | scopes.rb:13:11:13:11 | c | scopes.rb:9:9:18:3 | block scope | +| scopes.rb:17:9:17:9 | d | scopes.rb:13:14:13:14 | d | scopes.rb:9:9:18:3 | block scope | diff --git a/ql/test/library-tests/variables/varaccess.ql b/ql/test/library-tests/variables/varaccess.ql index 2c62bc563a3..11282910461 100644 --- a/ql/test/library-tests/variables/varaccess.ql +++ b/ql/test/library-tests/variables/varaccess.ql @@ -4,16 +4,3 @@ query predicate variableAccess(VariableAccess access, Variable variable, Variabl variable = access.getVariable() and scope = variable.getDeclaringScope() } - -query predicate parameterAccess(ParameterAccess access, LocalVariable variable, VariableScope scope) { - variable = access.getVariable() and - scope = variable.getDeclaringScope() -} - -query predicate localVariableAccess( - VariableAccess access, LocalVariable variable, VariableScope scope -) { - not access instanceof ParameterAccess and - variable = access.getVariable() and - scope = variable.getDeclaringScope() -} diff --git a/ql/test/library-tests/variables/variable.expected b/ql/test/library-tests/variables/variable.expected index a9b283555f7..71196968565 100644 --- a/ql/test/library-tests/variables/variable.expected +++ b/ql/test/library-tests/variables/variable.expected @@ -1,4 +1,3 @@ -variable | nested_scopes.rb:5:3:5:3 | a | | nested_scopes.rb:7:5:7:5 | a | | nested_scopes.rb:9:7:9:7 | a | @@ -30,6 +29,7 @@ variable | parameters.rb:40:12:40:12 | d | | parameters.rb:40:15:40:15 | e | | parameters.rb:45:20:45:20 | _ | +| parameters.rb:45:22:45:22 | _ | | parameters.rb:49:13:49:13 | a | | parameters.rb:49:15:49:15 | b | | parameters.rb:53:1:53:1 | x | @@ -38,44 +38,6 @@ variable | scopes.rb:4:4:4:4 | a | | scopes.rb:7:1:7:1 | a | | scopes.rb:9:14:9:14 | x | -parameter -| nested_scopes.rb:15:23:15:23 | a | -| nested_scopes.rb:16:26:16:26 | x | -| nested_scopes.rb:16:29:16:29 | a | -| nested_scopes.rb:18:26:18:26 | x | -| nested_scopes.rb:22:21:22:21 | a | -| parameters.rb:1:14:1:14 | x | -| parameters.rb:1:18:1:18 | y | -| parameters.rb:7:17:7:22 | client | -| parameters.rb:7:26:7:31 | pizzas | -| parameters.rb:15:17:15:19 | map | -| parameters.rb:16:16:16:18 | key | -| parameters.rb:16:21:16:25 | value | -| parameters.rb:21:17:21:21 | block | -| parameters.rb:25:15:25:18 | name | -| parameters.rb:25:33:25:36 | size | -| parameters.rb:30:15:30:19 | first | -| parameters.rb:30:24:30:29 | middle | -| parameters.rb:30:36:30:39 | last | -| parameters.rb:35:11:35:11 | a | -| parameters.rb:40:12:40:12 | d | -| parameters.rb:45:20:45:20 | _ | -| parameters.rb:49:13:49:13 | a | -| parameters.rb:49:15:49:15 | b | -| parameters.rb:54:14:54:14 | y | -| scopes.rb:2:14:2:14 | x | -| scopes.rb:9:14:9:14 | x | -localVariable -| nested_scopes.rb:5:3:5:3 | a | -| nested_scopes.rb:7:5:7:5 | a | -| nested_scopes.rb:9:7:9:7 | a | -| nested_scopes.rb:11:9:11:9 | a | -| nested_scopes.rb:13:11:13:11 | a | -| nested_scopes.rb:31:11:31:11 | a | -| nested_scopes.rb:40:1:40:1 | d | -| parameters.rb:34:1:34:1 | b | -| parameters.rb:35:16:35:16 | b | -| parameters.rb:40:15:40:15 | e | -| parameters.rb:53:1:53:1 | x | -| scopes.rb:4:4:4:4 | a | -| scopes.rb:7:1:7:1 | a | +| scopes.rb:13:7:13:7 | b | +| scopes.rb:13:11:13:11 | c | +| scopes.rb:13:14:13:14 | d | diff --git a/ql/test/library-tests/variables/variable.ql b/ql/test/library-tests/variables/variable.ql index e63cb8ffeb1..32812d7d856 100644 --- a/ql/test/library-tests/variables/variable.ql +++ b/ql/test/library-tests/variables/variable.ql @@ -1,7 +1,3 @@ import codeql_ruby.ast.Variable query predicate variable(Variable v) { any() } - -query predicate parameter(LocalVariable v) { v.getAnAccess() instanceof ParameterAccess } - -query predicate localVariable(LocalVariable v) { not v.getAnAccess() instanceof ParameterAccess } diff --git a/ql/test/library-tests/variables/varscopes.expected b/ql/test/library-tests/variables/varscopes.expected index 7a09f598183..70c2d9283cf 100644 --- a/ql/test/library-tests/variables/varscopes.expected +++ b/ql/test/library-tests/variables/varscopes.expected @@ -25,6 +25,6 @@ | parameters.rb:49:1:51:3 | method scope | | parameters.rb:54:9:57:3 | block scope | | scopes.rb:1:1:1:15 | method scope | -| scopes.rb:1:1:13:3 | top-level scope | +| scopes.rb:1:1:18:3 | top-level scope | | scopes.rb:2:9:6:3 | block scope | -| scopes.rb:9:9:13:3 | block scope | +| scopes.rb:9:9:18:3 | block scope |