mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Merge pull request #19206 from hvitved/ruby/super-implicit-args-synth
Ruby: Synthesize implicit super arguments
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Calls to `super` without explict arguments now have their implicit arguments generated. For example, in `def foo(x, y) { super } end` the call to `super` becomes `super(x, y)`.
|
||||
@@ -248,13 +248,7 @@ class ParenthesizedExpr extends StmtSequence, TParenthesizedExpr {
|
||||
* baz(qux: 1)
|
||||
* ```
|
||||
*/
|
||||
class Pair extends Expr, TPair {
|
||||
private Ruby::Pair g;
|
||||
|
||||
Pair() { this = TPair(g) }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "Pair" }
|
||||
|
||||
class Pair extends Expr instanceof PairImpl {
|
||||
/**
|
||||
* Gets the key expression of this pair. For example, the `SymbolLiteral`
|
||||
* representing the keyword `foo` in the following example:
|
||||
@@ -266,7 +260,7 @@ class Pair extends Expr, TPair {
|
||||
* { 'foo' => 123 }
|
||||
* ```
|
||||
*/
|
||||
final Expr getKey() { toGenerated(result) = g.getKey() }
|
||||
final Expr getKey() { result = PairImpl.super.getKey() }
|
||||
|
||||
/**
|
||||
* Gets the value expression of this pair. For example, the `IntegerLiteral`
|
||||
@@ -275,20 +269,9 @@ class Pair extends Expr, TPair {
|
||||
* { 'foo' => 123 }
|
||||
* ```
|
||||
*/
|
||||
final Expr getValue() {
|
||||
toGenerated(result) = g.getValue() or
|
||||
synthChild(this, 0, result)
|
||||
}
|
||||
final Expr getValue() { result = PairImpl.super.getValue() }
|
||||
|
||||
final override string toString() { result = "Pair" }
|
||||
|
||||
final override AstNode getAChild(string pred) {
|
||||
result = super.getAChild(pred)
|
||||
or
|
||||
pred = "getKey" and result = this.getKey()
|
||||
or
|
||||
pred = "getValue" and result = this.getValue()
|
||||
}
|
||||
final override string getAPrimaryQlClass() { result = "Pair" }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -305,7 +305,9 @@ class StringlikeLiteral extends Literal instanceof StringlikeLiteralImpl {
|
||||
final override AstNode getAChild(string pred) {
|
||||
result = Literal.super.getAChild(pred)
|
||||
or
|
||||
pred = "getComponent" and result = this.getComponent(_)
|
||||
pred = "getComponent" and
|
||||
result = this.getComponent(_) and
|
||||
not this instanceof SimpleSymbolLiteralSynth
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -92,10 +92,6 @@ class SplatExpr extends UnaryOperation, TSplatExpr {
|
||||
* ```
|
||||
*/
|
||||
class HashSplatExpr extends UnaryOperation, THashSplatExpr {
|
||||
private Ruby::HashSplatArgument g;
|
||||
|
||||
HashSplatExpr() { this = THashSplatExpr(g) }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "HashSplatExpr" }
|
||||
}
|
||||
|
||||
|
||||
@@ -164,7 +164,8 @@ private module Cached {
|
||||
THashKeySymbolLiteral(Ruby::HashKeySymbol g) or
|
||||
THashLiteral(Ruby::Hash g) or
|
||||
THashPattern(Ruby::HashPattern g) or
|
||||
THashSplatExpr(Ruby::HashSplatArgument g) or
|
||||
THashSplatExprReal(Ruby::HashSplatArgument g) or
|
||||
THashSplatExprSynth(Ast::AstNode parent, int i) { mkSynthChild(HashSplatExprKind(), parent, i) } or
|
||||
THashSplatNilParameter(Ruby::HashSplatNil g) { not g.getParent() instanceof Ruby::HashPattern } or
|
||||
THashSplatParameter(Ruby::HashSplatParameter g) {
|
||||
not g.getParent() instanceof Ruby::HashPattern
|
||||
@@ -232,7 +233,8 @@ private module Cached {
|
||||
TNotExprReal(Ruby::Unary g) { g instanceof @ruby_unary_bang or g instanceof @ruby_unary_not } or
|
||||
TNotExprSynth(Ast::AstNode parent, int i) { mkSynthChild(NotExprKind(), parent, i) } or
|
||||
TOptionalParameter(Ruby::OptionalParameter g) or
|
||||
TPair(Ruby::Pair g) or
|
||||
TPairReal(Ruby::Pair g) or
|
||||
TPairSynth(Ast::AstNode parent, int i) { mkSynthChild(PairExprKind(), parent, i) } or
|
||||
TParenthesizedExpr(Ruby::ParenthesizedStatements g) or
|
||||
TParenthesizedPattern(Ruby::ParenthesizedPattern g) or
|
||||
TRShiftExprReal(Ruby::Binary g) { g instanceof @ruby_binary_ranglerangle } or
|
||||
@@ -274,7 +276,10 @@ private module Cached {
|
||||
TSimpleParameterSynth(Ast::AstNode parent, int i) {
|
||||
mkSynthChild(SimpleParameterKind(), parent, i)
|
||||
} or
|
||||
TSimpleSymbolLiteral(Ruby::SimpleSymbol g) or
|
||||
TSimpleSymbolLiteralReal(Ruby::SimpleSymbol g) or
|
||||
TSimpleSymbolLiteralSynth(Ast::AstNode parent, int i, string value) {
|
||||
mkSynthChild(SymbolLiteralExprKind(value), parent, i)
|
||||
} or
|
||||
TSingletonClass(Ruby::SingletonClass g) or
|
||||
TSingletonMethod(Ruby::SingletonMethod g) or
|
||||
TSpaceshipExpr(Ruby::Binary g) { g instanceof @ruby_binary_langleequalrangle } or
|
||||
@@ -362,19 +367,19 @@ private module Cached {
|
||||
TEnsure or TEqExpr or TExponentExprReal or TFalseLiteral or TFile or TFindPattern or
|
||||
TFloatLiteral or TForExpr or TForwardParameter or TForwardArgument or TGEExpr or TGTExpr or
|
||||
TGlobalVariableAccessReal or THashKeySymbolLiteral or THashLiteral or THashPattern or
|
||||
THashSplatExpr or THashSplatNilParameter or THashSplatParameter or THereDoc or
|
||||
THashSplatExprReal or THashSplatNilParameter or THashSplatParameter or THereDoc or
|
||||
TIdentifierMethodCall or TIfReal or TIfModifierExpr or TInClauseReal or
|
||||
TInstanceVariableAccessReal or TIntegerLiteralReal or TKeywordParameter or TLEExpr or
|
||||
TLShiftExprReal or TLTExpr or TLambda or TLeftAssignmentList or TLine or
|
||||
TLocalVariableAccessReal or TLogicalAndExprReal or TLogicalOrExprReal or TMethod or
|
||||
TMatchPattern or TModuleDeclaration or TModuloExprReal or TMulExprReal or TNEExpr or
|
||||
TNextStmt or TNilLiteralReal or TNoRegExpMatchExpr or TNotExprReal or TOptionalParameter or
|
||||
TPair or TParenthesizedExpr or TParenthesizedPattern or TRShiftExprReal or
|
||||
TPairReal or TParenthesizedExpr or TParenthesizedPattern or TRShiftExprReal or
|
||||
TRangeLiteralReal or TRationalLiteral or TRedoStmt or TRegExpLiteral or TRegExpMatchExpr or
|
||||
TRegularArrayLiteral or TRegularMethodCall or TRegularStringLiteral or TRegularSuperCall or
|
||||
TRescueClause or TRescueModifierExpr or TRetryStmt or TReturnStmt or
|
||||
TScopeResolutionConstantAccess or TSelfReal or TSimpleParameterReal or
|
||||
TSimpleSymbolLiteral or TSingletonClass or TSingletonMethod or TSpaceshipExpr or
|
||||
TSimpleSymbolLiteralReal or TSingletonClass or TSingletonMethod or TSpaceshipExpr or
|
||||
TSplatExprReal or TSplatParameter or TStringArrayLiteral or TStringConcatenation or
|
||||
TStringEscapeSequenceComponent or TStringInterpolationComponent or TStringTextComponent or
|
||||
TSubExprReal or TSubshellLiteral or TSymbolArrayLiteral or TTernaryIfExpr or TTestPattern or
|
||||
@@ -392,7 +397,8 @@ private module Cached {
|
||||
TLShiftExprSynth or TLocalVariableAccessSynth or TLogicalAndExprSynth or
|
||||
TLogicalOrExprSynth or TMethodCallSynth or TModuloExprSynth or TMulExprSynth or
|
||||
TNilLiteralSynth or TRShiftExprSynth or TRangeLiteralSynth or TSelfSynth or
|
||||
TSimpleParameterSynth or TSplatExprSynth or TStmtSequenceSynth or TSubExprSynth;
|
||||
TSimpleParameterSynth or TSplatExprSynth or THashSplatExprSynth or TStmtSequenceSynth or
|
||||
TSubExprSynth or TPairSynth or TSimpleSymbolLiteralSynth;
|
||||
|
||||
/**
|
||||
* Gets the underlying TreeSitter entity for a given AST node. This does not
|
||||
@@ -468,7 +474,7 @@ private module Cached {
|
||||
n = THashKeySymbolLiteral(result) or
|
||||
n = THashLiteral(result) or
|
||||
n = THashPattern(result) or
|
||||
n = THashSplatExpr(result) or
|
||||
n = THashSplatExprReal(result) or
|
||||
n = THashSplatNilParameter(result) or
|
||||
n = THashSplatParameter(result) or
|
||||
n = THereDoc(result) or
|
||||
@@ -499,7 +505,7 @@ private module Cached {
|
||||
n = TNoRegExpMatchExpr(result) or
|
||||
n = TNotExprReal(result) or
|
||||
n = TOptionalParameter(result) or
|
||||
n = TPair(result) or
|
||||
n = TPairReal(result) or
|
||||
n = TParenthesizedExpr(result) or
|
||||
n = TParenthesizedPattern(result) or
|
||||
n = TRangeLiteralReal(result) or
|
||||
@@ -519,7 +525,7 @@ private module Cached {
|
||||
n = TScopeResolutionConstantAccess(result, _) or
|
||||
n = TSelfReal(result) or
|
||||
n = TSimpleParameterReal(result) or
|
||||
n = TSimpleSymbolLiteral(result) or
|
||||
n = TSimpleSymbolLiteralReal(result) or
|
||||
n = TSingletonClass(result) or
|
||||
n = TSingletonMethod(result) or
|
||||
n = TSpaceshipExpr(result) or
|
||||
@@ -633,9 +639,15 @@ private module Cached {
|
||||
or
|
||||
result = TSplatExprSynth(parent, i)
|
||||
or
|
||||
result = THashSplatExprSynth(parent, i)
|
||||
or
|
||||
result = TStmtSequenceSynth(parent, i)
|
||||
or
|
||||
result = TSubExprSynth(parent, i)
|
||||
or
|
||||
result = TPairSynth(parent, i)
|
||||
or
|
||||
result = TSimpleSymbolLiteralSynth(parent, i, _)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -726,6 +738,8 @@ class TSelf = TSelfReal or TSelfSynth;
|
||||
|
||||
class TDestructuredLhsExpr = TDestructuredLeftAssignment or TLeftAssignmentList;
|
||||
|
||||
class TPair = TPairReal or TPairSynth;
|
||||
|
||||
class TExpr =
|
||||
TSelf or TArgumentList or TRescueClause or TRescueModifierExpr or TPair or TStringConcatenation or
|
||||
TCall or TBlockArgument or TConstantAccess or TControlExpr or TLiteral or TCallable or
|
||||
@@ -734,6 +748,8 @@ class TExpr =
|
||||
|
||||
class TSplatExpr = TSplatExprReal or TSplatExprSynth;
|
||||
|
||||
class THashSplatExpr = THashSplatExprReal or THashSplatExprSynth;
|
||||
|
||||
class TElse = TElseReal or TElseSynth;
|
||||
|
||||
class TStmtSequence =
|
||||
@@ -768,13 +784,16 @@ class TStringInterpolationComponent =
|
||||
TStringInterpolationComponentNonRegexp or TStringInterpolationComponentRegexp;
|
||||
|
||||
class TStringComponent =
|
||||
TStringTextComponent or TStringEscapeSequenceComponent or TStringInterpolationComponent;
|
||||
TStringTextComponent or TStringEscapeSequenceComponent or TStringInterpolationComponent or
|
||||
TSimpleSymbolLiteralSynth;
|
||||
|
||||
class TStringlikeLiteral =
|
||||
TStringLiteral or TRegExpLiteral or TSymbolLiteral or TSubshellLiteral or THereDoc;
|
||||
|
||||
class TStringLiteral = TRegularStringLiteral or TBareStringLiteral;
|
||||
|
||||
class TSimpleSymbolLiteral = TSimpleSymbolLiteralReal or TSimpleSymbolLiteralSynth;
|
||||
|
||||
class TSymbolLiteral = TSimpleSymbolLiteral or TComplexSymbolLiteral or THashKeySymbolLiteral;
|
||||
|
||||
class TComplexSymbolLiteral = TDelimitedSymbolLiteral or TBareSymbolLiteral;
|
||||
|
||||
@@ -2,6 +2,7 @@ private import TreeSitter
|
||||
private import Variable
|
||||
private import codeql.ruby.AST
|
||||
private import codeql.ruby.ast.internal.AST
|
||||
private import codeql.ruby.ast.internal.Scope
|
||||
|
||||
predicate isIdentifierMethodCall(Ruby::Identifier g) { vcall(g) and not access(g, _) }
|
||||
|
||||
@@ -133,18 +134,61 @@ private string getSuperMethodName(Ruby::Super sup) {
|
||||
)
|
||||
}
|
||||
|
||||
private Ruby::Identifier getParameter(Ruby::Method m, int pos, Ruby::AstNode param) {
|
||||
scopeDefinesParameterVariable(m, _, result, pos) and
|
||||
param = m.getParameters().getChild(pos)
|
||||
}
|
||||
|
||||
class TokenSuperCall extends SuperCallImpl, TTokenSuperCall {
|
||||
private Ruby::Super g;
|
||||
|
||||
TokenSuperCall() { this = TTokenSuperCall(g) }
|
||||
|
||||
Ruby::Method getEnclosingMethod() { result = scopeOf(toGenerated(this)).getEnclosingMethod() }
|
||||
|
||||
int getNumberOfImplicitArguments() {
|
||||
exists(Ruby::Method encl |
|
||||
encl = this.getEnclosingMethod() and
|
||||
result = count(getParameter(encl, _, _))
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the local variable defined by parameter `param` which is used as an
|
||||
* implicit argument at position `pos`.
|
||||
*
|
||||
* For example, in
|
||||
*
|
||||
* ```ruby
|
||||
* class Sup
|
||||
* def m(x)
|
||||
* end
|
||||
* end
|
||||
*
|
||||
* class Sub < Sup
|
||||
* def m(x)
|
||||
* super
|
||||
* end
|
||||
* end
|
||||
* ```
|
||||
*
|
||||
* `x` is an implicit argument at position 0 of the `super` call in `Sub#m`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
LocalVariableReal getImplicitArgument(int pos, Ruby::AstNode param) {
|
||||
exists(Ruby::Method encl |
|
||||
encl = this.getEnclosingMethod() and
|
||||
toGenerated(result.getDefiningAccessImpl()) = getParameter(encl, pos, param)
|
||||
)
|
||||
}
|
||||
|
||||
final override string getMethodNameImpl() { result = getSuperMethodName(g) }
|
||||
|
||||
final override Expr getReceiverImpl() { none() }
|
||||
|
||||
final override Expr getArgumentImpl(int n) { none() }
|
||||
final override Expr getArgumentImpl(int n) { synthChild(this, n, result) }
|
||||
|
||||
final override int getNumberOfArgumentsImpl() { result = 0 }
|
||||
final override int getNumberOfArgumentsImpl() { result = this.getNumberOfImplicitArguments() }
|
||||
|
||||
final override Block getBlockImpl() { none() }
|
||||
}
|
||||
|
||||
@@ -120,3 +120,38 @@ class LeftAssignmentListImpl extends DestructuredLhsExprImpl, Ruby::LeftAssignme
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
abstract class PairImpl extends Expr, TPair {
|
||||
abstract Expr getKey();
|
||||
|
||||
abstract Expr getValue();
|
||||
|
||||
final override string toString() { result = "Pair" }
|
||||
|
||||
final override AstNode getAChild(string pred) {
|
||||
result = super.getAChild(pred)
|
||||
or
|
||||
pred = "getKey" and result = this.getKey()
|
||||
or
|
||||
pred = "getValue" and result = this.getValue()
|
||||
}
|
||||
}
|
||||
|
||||
class PairReal extends PairImpl, TPairReal {
|
||||
private Ruby::Pair g;
|
||||
|
||||
PairReal() { this = TPairReal(g) }
|
||||
|
||||
final override Expr getKey() { toGenerated(result) = g.getKey() }
|
||||
|
||||
final override Expr getValue() {
|
||||
toGenerated(result) = g.getValue() or
|
||||
synthChild(this, 0, result)
|
||||
}
|
||||
}
|
||||
|
||||
class PairSynth extends PairImpl, TPairSynth {
|
||||
final override Expr getKey() { synthChild(this, 0, result) }
|
||||
|
||||
final override Expr getValue() { synthChild(this, 1, result) }
|
||||
}
|
||||
|
||||
@@ -608,16 +608,32 @@ class BareStringLiteral extends StringLiteralImpl, TBareStringLiteral {
|
||||
|
||||
abstract class SymbolLiteralImpl extends StringlikeLiteralImpl, TSymbolLiteral { }
|
||||
|
||||
class SimpleSymbolLiteral extends SymbolLiteralImpl, TSimpleSymbolLiteral {
|
||||
abstract class SimpleSymbolLiteralImpl extends SymbolLiteralImpl, TSimpleSymbolLiteral { }
|
||||
|
||||
class SimpleSymbolLiteralReal extends SimpleSymbolLiteralImpl, TSimpleSymbolLiteral {
|
||||
private Ruby::SimpleSymbol g;
|
||||
|
||||
SimpleSymbolLiteral() { this = TSimpleSymbolLiteral(g) }
|
||||
SimpleSymbolLiteralReal() { this = TSimpleSymbolLiteralReal(g) }
|
||||
|
||||
final override StringComponent getComponentImpl(int n) { n = 0 and toGenerated(result) = g }
|
||||
|
||||
final override string toString() { result = g.getValue() }
|
||||
}
|
||||
|
||||
class SimpleSymbolLiteralSynth extends SimpleSymbolLiteralImpl, TSimpleSymbolLiteralSynth,
|
||||
StringComponentImpl
|
||||
{
|
||||
private string value;
|
||||
|
||||
SimpleSymbolLiteralSynth() { this = TSimpleSymbolLiteralSynth(_, _, value) }
|
||||
|
||||
final override string getValue() { result = value }
|
||||
|
||||
final override StringComponent getComponentImpl(int n) { n = 0 and result = this }
|
||||
|
||||
final override string toString() { result = value }
|
||||
}
|
||||
|
||||
abstract class ComplexSymbolLiteral extends SymbolLiteralImpl, TComplexSymbolLiteral { }
|
||||
|
||||
class DelimitedSymbolLiteral extends ComplexSymbolLiteral, TDelimitedSymbolLiteral {
|
||||
|
||||
@@ -45,36 +45,42 @@ class NotExprSynth extends NotExprImpl, TNotExprSynth {
|
||||
final override Expr getOperandImpl() { synthChild(this, 0, result) }
|
||||
}
|
||||
|
||||
class SplatExprReal extends UnaryOperationImpl, TSplatExprReal {
|
||||
abstract class SplatExprImpl extends UnaryOperationImpl, TSplatExpr {
|
||||
final override string getOperatorImpl() { result = "*" }
|
||||
}
|
||||
|
||||
class SplatExprReal extends SplatExprImpl, TSplatExprReal {
|
||||
private Ruby::SplatArgument g;
|
||||
|
||||
SplatExprReal() { this = TSplatExprReal(g) }
|
||||
|
||||
final override string getOperatorImpl() { result = "*" }
|
||||
|
||||
final override Expr getOperandImpl() {
|
||||
toGenerated(result) = g.getChild() or
|
||||
synthChild(this, 0, result)
|
||||
}
|
||||
}
|
||||
|
||||
class SplatExprSynth extends UnaryOperationImpl, TSplatExprSynth {
|
||||
final override string getOperatorImpl() { result = "*" }
|
||||
|
||||
class SplatExprSynth extends SplatExprImpl, TSplatExprSynth {
|
||||
final override Expr getOperandImpl() { synthChild(this, 0, result) }
|
||||
}
|
||||
|
||||
class HashSplatExprImpl extends UnaryOperationImpl, THashSplatExpr {
|
||||
abstract class HashSplatExprImpl extends UnaryOperationImpl, THashSplatExpr {
|
||||
final override string getOperatorImpl() { result = "**" }
|
||||
}
|
||||
|
||||
class HashSplatExprReal extends HashSplatExprImpl, THashSplatExprReal {
|
||||
private Ruby::HashSplatArgument g;
|
||||
|
||||
HashSplatExprImpl() { this = THashSplatExpr(g) }
|
||||
HashSplatExprReal() { this = THashSplatExprReal(g) }
|
||||
|
||||
final override Expr getOperandImpl() {
|
||||
toGenerated(result) = g.getChild() or
|
||||
synthChild(this, 0, result)
|
||||
}
|
||||
}
|
||||
|
||||
final override string getOperatorImpl() { result = "**" }
|
||||
class HashSplatExprSynth extends HashSplatExprImpl, THashSplatExprSynth {
|
||||
final override Expr getOperandImpl() { synthChild(this, 0, result) }
|
||||
}
|
||||
|
||||
abstract class DefinedExprImpl extends UnaryOperationImpl, TDefinedExpr { }
|
||||
|
||||
@@ -11,7 +11,7 @@ private import codeql.ruby.ast.internal.Scope
|
||||
private import codeql.ruby.AST
|
||||
|
||||
/** A synthesized AST node kind. */
|
||||
newtype SynthKind =
|
||||
newtype TSynthKind =
|
||||
AddExprKind() or
|
||||
AssignExprKind() or
|
||||
BitwiseAndExprKind() or
|
||||
@@ -42,16 +42,107 @@ newtype SynthKind =
|
||||
MulExprKind() or
|
||||
NilLiteralKind() or
|
||||
NotExprKind() or
|
||||
PairExprKind() or
|
||||
RangeLiteralKind(boolean inclusive) { inclusive in [false, true] } or
|
||||
RShiftExprKind() or
|
||||
SimpleParameterKind() or
|
||||
SplatExprKind() or
|
||||
HashSplatExprKind() or
|
||||
SymbolLiteralExprKind(string value) {
|
||||
value = any(Ruby::SimpleSymbol s).getValue()
|
||||
or
|
||||
value = any(Ruby::KeywordParameter p).getName().getValue()
|
||||
} or
|
||||
StmtSequenceKind() or
|
||||
SelfKind(SelfVariable v) or
|
||||
SubExprKind() or
|
||||
ConstantReadAccessKind(string value) { any(Synthesis s).constantReadAccess(value) } or
|
||||
ConstantWriteAccessKind(string value) { any(Synthesis s).constantWriteAccess(value) }
|
||||
|
||||
class SynthKind extends TSynthKind {
|
||||
string toString() {
|
||||
this = AddExprKind() and result = "AddExprKind"
|
||||
or
|
||||
this = AssignExprKind() and result = "AssignExprKind"
|
||||
or
|
||||
this = BitwiseAndExprKind() and result = "BitwiseAndExprKind"
|
||||
or
|
||||
this = BitwiseOrExprKind() and result = "BitwiseOrExprKind"
|
||||
or
|
||||
this = BitwiseXorExprKind() and result = "BitwiseXorExprKind"
|
||||
or
|
||||
this = BooleanLiteralKind(_) and result = "BooleanLiteralKind"
|
||||
or
|
||||
this = BraceBlockKind() and result = "BraceBlockKind"
|
||||
or
|
||||
this = CaseMatchKind() and result = "CaseMatchKind"
|
||||
or
|
||||
this = ClassVariableAccessKind(_) and result = "ClassVariableAccessKind"
|
||||
or
|
||||
this = DefinedExprKind() and result = "DefinedExprKind"
|
||||
or
|
||||
this = DivExprKind() and result = "DivExprKind"
|
||||
or
|
||||
this = ElseKind() and result = "ElseKind"
|
||||
or
|
||||
this = ExponentExprKind() and result = "ExponentExprKind"
|
||||
or
|
||||
this = GlobalVariableAccessKind(_) and result = "GlobalVariableAccessKind"
|
||||
or
|
||||
this = IfKind() and result = "IfKind"
|
||||
or
|
||||
this = InClauseKind() and result = "InClauseKind"
|
||||
or
|
||||
this = InstanceVariableAccessKind(_) and result = "InstanceVariableAccessKind"
|
||||
or
|
||||
this = IntegerLiteralKind(_) and result = "IntegerLiteralKind"
|
||||
or
|
||||
this = LShiftExprKind() and result = "LShiftExprKind"
|
||||
or
|
||||
this = LocalVariableAccessRealKind(_) and result = "LocalVariableAccessRealKind"
|
||||
or
|
||||
this = LocalVariableAccessSynthKind(_) and result = "LocalVariableAccessSynthKind"
|
||||
or
|
||||
this = LogicalAndExprKind() and result = "LogicalAndExprKind"
|
||||
or
|
||||
this = LogicalOrExprKind() and result = "LogicalOrExprKind"
|
||||
or
|
||||
this = MethodCallKind(_, _, _) and result = "MethodCallKind"
|
||||
or
|
||||
this = ModuloExprKind() and result = "ModuloExprKind"
|
||||
or
|
||||
this = MulExprKind() and result = "MulExprKind"
|
||||
or
|
||||
this = NilLiteralKind() and result = "NilLiteralKind"
|
||||
or
|
||||
this = NotExprKind() and result = "NotExprKind"
|
||||
or
|
||||
this = PairExprKind() and result = "PairExprKind"
|
||||
or
|
||||
this = RangeLiteralKind(_) and result = "RangeLiteralKind"
|
||||
or
|
||||
this = RShiftExprKind() and result = "RShiftExprKind"
|
||||
or
|
||||
this = SimpleParameterKind() and result = "SimpleParameterKind"
|
||||
or
|
||||
this = SplatExprKind() and result = "SplatExprKind"
|
||||
or
|
||||
this = HashSplatExprKind() and result = "HashSplatExprKind"
|
||||
or
|
||||
this = SymbolLiteralExprKind(_) and result = "SymbolLiteralExprKind"
|
||||
or
|
||||
this = StmtSequenceKind() and result = "StmtSequenceKind"
|
||||
or
|
||||
this = SubExprKind() and result = "SubExprKind"
|
||||
or
|
||||
this = SelfKind(_) and result = "SelfKind"
|
||||
or
|
||||
this = ConstantReadAccessKind(_) and result = "ConstantReadAccessKind"
|
||||
or
|
||||
this = ConstantWriteAccessKind(_) and result = "ConstantWriteAccessKind"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An AST child.
|
||||
*
|
||||
@@ -441,7 +532,7 @@ private module AssignOperationDesugar {
|
||||
pragma[nomagic]
|
||||
SynthKind getVariableAccessKind() {
|
||||
result in [
|
||||
LocalVariableAccessRealKind(v).(SynthKind), InstanceVariableAccessKind(v),
|
||||
LocalVariableAccessRealKind(v).(TSynthKind), InstanceVariableAccessKind(v),
|
||||
ClassVariableAccessKind(v), GlobalVariableAccessKind(v)
|
||||
]
|
||||
}
|
||||
@@ -1802,3 +1893,59 @@ private module MatchPatternDesugar {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private module ImplicitSuperArgsSynthesis {
|
||||
pragma[nomagic]
|
||||
private predicate superCallSynthesis(AstNode parent, int i, Child child) {
|
||||
exists(TokenSuperCall call, SynthChild access, int pos, Ruby::AstNode param |
|
||||
access = SynthChild(LocalVariableAccessRealKind(call.getImplicitArgument(pos, param)))
|
||||
|
|
||||
parent = call and
|
||||
param instanceof Ruby::Identifier and
|
||||
i = pos and
|
||||
child = access
|
||||
or
|
||||
param instanceof Ruby::SplatParameter and
|
||||
(
|
||||
parent = call and
|
||||
i = pos and
|
||||
child = SynthChild(SplatExprKind())
|
||||
or
|
||||
parent = TSplatExprSynth(call, pos) and
|
||||
i = 0 and
|
||||
child = access
|
||||
)
|
||||
or
|
||||
param instanceof Ruby::HashSplatParameter and
|
||||
(
|
||||
parent = call and
|
||||
i = pos and
|
||||
child = SynthChild(HashSplatExprKind())
|
||||
or
|
||||
parent = THashSplatExprSynth(call, pos) and
|
||||
i = 0 and
|
||||
child = access
|
||||
)
|
||||
or
|
||||
exists(string name | name = param.(Ruby::KeywordParameter).getName().getValue() |
|
||||
parent = call and
|
||||
i = pos and
|
||||
child = SynthChild(PairExprKind())
|
||||
or
|
||||
parent = TPairSynth(call, pos) and
|
||||
i = 0 and
|
||||
child = SynthChild(SymbolLiteralExprKind(name))
|
||||
or
|
||||
parent = TPairSynth(call, pos) and
|
||||
i = 1 and
|
||||
child = access
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private class SuperCallSynthesis extends Synthesis {
|
||||
final override predicate child(AstNode parent, int i, Child child) {
|
||||
superCallSynthesis(parent, i, child)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,11 +49,11 @@ predicate implicitAssignmentNode(Ruby::AstNode n) {
|
||||
}
|
||||
|
||||
/** Holds if `n` is inside a parameter. */
|
||||
predicate implicitParameterAssignmentNode(Ruby::AstNode n, Callable::Range c) {
|
||||
n = c.getParameter(_) or
|
||||
n = c.(Ruby::Block).getParameters().getLocals(_) or
|
||||
n = c.(Ruby::DoBlock).getParameters().getLocals(_) or
|
||||
implicitParameterAssignmentNode(n.getParent().(Ruby::DestructuredParameter), c)
|
||||
predicate implicitParameterAssignmentNode(Ruby::AstNode n, Callable::Range c, int pos) {
|
||||
n = c.getParameter(pos) or
|
||||
n = c.(Ruby::Block).getParameters().getLocals(pos) or
|
||||
n = c.(Ruby::DoBlock).getParameters().getLocals(pos) or
|
||||
implicitParameterAssignmentNode(n.getParent().(Ruby::DestructuredParameter), c, pos)
|
||||
}
|
||||
|
||||
private predicate instanceVariableAccess(
|
||||
@@ -77,26 +77,29 @@ private ModuleBase::Range enclosingModuleOrClass(Ruby::AstNode node) {
|
||||
exists(Scope::Range s | scopeOf(node) = s and result = s.getEnclosingModule())
|
||||
}
|
||||
|
||||
private predicate parameterAssignment(Callable::Range scope, string name, Ruby::Identifier i) {
|
||||
implicitParameterAssignmentNode(i, scope) and
|
||||
private predicate parameterAssignment(
|
||||
Callable::Range scope, string name, Ruby::Identifier i, int pos
|
||||
) {
|
||||
implicitParameterAssignmentNode(i, scope, pos) and
|
||||
name = i.getValue()
|
||||
}
|
||||
|
||||
/** Holds if `scope` defines `name` in its parameter declaration at `i`. */
|
||||
private predicate scopeDefinesParameterVariable(
|
||||
Callable::Range scope, string name, Ruby::Identifier i
|
||||
predicate scopeDefinesParameterVariable(
|
||||
Callable::Range scope, string name, Ruby::Identifier i, int pos
|
||||
) {
|
||||
// In case of overlapping parameter names (e.g. `_`), only the first
|
||||
// parameter will give rise to a variable
|
||||
i =
|
||||
min(Ruby::Identifier other |
|
||||
parameterAssignment(scope, name, other)
|
||||
parameterAssignment(scope, name, other, _)
|
||||
|
|
||||
other order by other.getLocation().getStartLine(), other.getLocation().getStartColumn()
|
||||
)
|
||||
) and
|
||||
parameterAssignment(scope, name, _, pos)
|
||||
or
|
||||
exists(Parameter::Range p |
|
||||
p = scope.getParameter(_) and
|
||||
p = scope.getParameter(pos) and
|
||||
name = i.getValue()
|
||||
|
|
||||
i = p.(Ruby::BlockParameter).getName() or
|
||||
@@ -153,7 +156,7 @@ private module Cached {
|
||||
)
|
||||
} or
|
||||
TLocalVariableReal(Scope::Range scope, string name, Ruby::AstNode i) {
|
||||
scopeDefinesParameterVariable(scope, name, i)
|
||||
scopeDefinesParameterVariable(scope, name, i, _)
|
||||
or
|
||||
i =
|
||||
min(Ruby::AstNode other |
|
||||
@@ -161,7 +164,7 @@ private module Cached {
|
||||
|
|
||||
other order by other.getLocation().getStartLine(), other.getLocation().getStartColumn()
|
||||
) and
|
||||
not scopeDefinesParameterVariable(scope, name, _) and
|
||||
not scopeDefinesParameterVariable(scope, name, _, _) and
|
||||
not inherits(scope, name, _)
|
||||
} or
|
||||
TSelfVariable(SelfBase::Range scope) or
|
||||
@@ -330,8 +333,8 @@ private module Cached {
|
||||
not access.getLocation().strictlyBefore(variable.getLocationImpl()) and
|
||||
// In case of overlapping parameter names, later parameters should not
|
||||
// be considered accesses to the first parameter
|
||||
if parameterAssignment(_, _, access)
|
||||
then scopeDefinesParameterVariable(_, _, access)
|
||||
if parameterAssignment(_, _, access, _)
|
||||
then scopeDefinesParameterVariable(_, _, access, _)
|
||||
else any()
|
||||
or
|
||||
exists(Scope::Range declScope |
|
||||
@@ -360,7 +363,7 @@ private module Cached {
|
||||
predicate implicitWriteAccess(Access access) {
|
||||
implicitAssignmentNode(access)
|
||||
or
|
||||
scopeDefinesParameterVariable(_, _, access)
|
||||
scopeDefinesParameterVariable(_, _, access, _)
|
||||
}
|
||||
|
||||
cached
|
||||
@@ -399,11 +402,11 @@ private predicate inherits(Scope::Range scope, string name, Scope::Range outer)
|
||||
scope instanceof Ruby::DoBlock or
|
||||
scope instanceof Ruby::Lambda
|
||||
) and
|
||||
not scopeDefinesParameterVariable(scope, name, _) and
|
||||
not scopeDefinesParameterVariable(scope, name, _, _) and
|
||||
(
|
||||
outer = scope.getOuterScope() and
|
||||
(
|
||||
scopeDefinesParameterVariable(outer, name, _)
|
||||
scopeDefinesParameterVariable(outer, name, _, _)
|
||||
or
|
||||
exists(Ruby::AstNode i |
|
||||
scopeAssigns(outer, name, i) and
|
||||
|
||||
@@ -1430,7 +1430,10 @@ module Trees {
|
||||
}
|
||||
|
||||
private class StringlikeLiteralTree extends StandardPostOrderTree instanceof StringlikeLiteral {
|
||||
StringlikeLiteralTree() { not this instanceof HereDoc }
|
||||
StringlikeLiteralTree() {
|
||||
not this instanceof HereDoc and
|
||||
not this instanceof AstInternal::TSimpleSymbolLiteralSynth
|
||||
}
|
||||
|
||||
final override ControlFlowTree getChildNode(int i) { result = super.getComponent(i) }
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
private import codeql.util.Boolean
|
||||
private import codeql.util.Unit
|
||||
private import codeql.ruby.AST
|
||||
private import codeql.ruby.ast.internal.Call
|
||||
private import codeql.ruby.ast.internal.Synthesis
|
||||
private import codeql.ruby.CFG
|
||||
private import codeql.ruby.dataflow.SSA
|
||||
@@ -483,9 +484,12 @@ private module Cached {
|
||||
TSelfToplevelParameterNode(Toplevel t) or
|
||||
TLambdaSelfReferenceNode(Callable c) { lambdaCreationExpr(_, _, c) } or
|
||||
TImplicitBlockParameterNode(MethodBase m) { not m.getAParameter() instanceof BlockParameter } or
|
||||
TImplicitBlockArgumentNode(CfgNodes::ExprNodes::CallCfgNode yield) {
|
||||
TImplicitYieldBlockArgumentNode(CfgNodes::ExprNodes::CallCfgNode yield) {
|
||||
yield = any(BlockParameterNode b).getAYieldCall()
|
||||
} or
|
||||
TImplicitSuperBlockArgumentNode(CfgNodes::ExprNodes::CallCfgNode sup) {
|
||||
sup = any(BlockParameterNode b).getASuperCall()
|
||||
} or
|
||||
TSynthHashSplatParameterNode(DataFlowCallable c) {
|
||||
isParameterNode(_, c, any(ParameterPosition p | p.isKeyword(_)))
|
||||
} or
|
||||
@@ -1049,6 +1053,11 @@ private module ParameterNodes {
|
||||
CfgNodes::ExprNodes::CallCfgNode getAYieldCall() {
|
||||
this.getMethod() = result.getExpr().(YieldCall).getEnclosingMethod()
|
||||
}
|
||||
|
||||
CfgNodes::ExprNodes::CallCfgNode getASuperCall() {
|
||||
this.getMethod() = result.getExpr().getEnclosingMethod() and
|
||||
result.getExpr() instanceof TokenSuperCall
|
||||
}
|
||||
}
|
||||
|
||||
private class ExplicitBlockParameterNode extends BlockParameterNode, NormalParameterNode {
|
||||
@@ -1315,15 +1324,23 @@ module ArgumentNodes {
|
||||
}
|
||||
}
|
||||
|
||||
class ImplicitBlockArgumentNode extends NodeImpl, ArgumentNode, TImplicitBlockArgumentNode {
|
||||
abstract class ImplicitBlockArgumentNode extends NodeImpl, ArgumentNode {
|
||||
pragma[nomagic]
|
||||
abstract BlockParameterNode getParameterNode(boolean inSameScope);
|
||||
|
||||
override string toStringImpl() { result = "yield block argument" }
|
||||
}
|
||||
|
||||
class ImplicitYieldBlockArgumentNode extends ImplicitBlockArgumentNode,
|
||||
TImplicitYieldBlockArgumentNode
|
||||
{
|
||||
CfgNodes::ExprNodes::CallCfgNode yield;
|
||||
|
||||
ImplicitBlockArgumentNode() { this = TImplicitBlockArgumentNode(yield) }
|
||||
ImplicitYieldBlockArgumentNode() { this = TImplicitYieldBlockArgumentNode(yield) }
|
||||
|
||||
CfgNodes::ExprNodes::CallCfgNode getYieldCall() { result = yield }
|
||||
|
||||
pragma[nomagic]
|
||||
BlockParameterNode getParameterNode(boolean inSameScope) {
|
||||
override BlockParameterNode getParameterNode(boolean inSameScope) {
|
||||
result.getAYieldCall() = yield and
|
||||
if nodeGetEnclosingCallable(this) = nodeGetEnclosingCallable(result)
|
||||
then inSameScope = true
|
||||
@@ -1343,8 +1360,36 @@ module ArgumentNodes {
|
||||
override CfgScope getCfgScope() { result = yield.getScope() }
|
||||
|
||||
override Location getLocationImpl() { result = yield.getLocation() }
|
||||
}
|
||||
|
||||
override string toStringImpl() { result = "yield block argument" }
|
||||
class ImplicitSuperBlockArgumentNode extends ImplicitBlockArgumentNode,
|
||||
TImplicitSuperBlockArgumentNode
|
||||
{
|
||||
CfgNodes::ExprNodes::CallCfgNode sup;
|
||||
|
||||
ImplicitSuperBlockArgumentNode() { this = TImplicitSuperBlockArgumentNode(sup) }
|
||||
|
||||
CfgNodes::ExprNodes::CallCfgNode getSuperCall() { result = sup }
|
||||
|
||||
override BlockParameterNode getParameterNode(boolean inSameScope) {
|
||||
result.getASuperCall() = sup and
|
||||
if nodeGetEnclosingCallable(this) = nodeGetEnclosingCallable(result)
|
||||
then inSameScope = true
|
||||
else inSameScope = false
|
||||
}
|
||||
|
||||
override predicate sourceArgumentOf(CfgNodes::ExprNodes::CallCfgNode call, ArgumentPosition pos) {
|
||||
call = sup and
|
||||
pos.isBlock()
|
||||
}
|
||||
|
||||
override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
|
||||
this.sourceArgumentOf(call.asCall(), pos)
|
||||
}
|
||||
|
||||
override CfgScope getCfgScope() { result = sup.getScope() }
|
||||
|
||||
override Location getLocationImpl() { result = sup.getLocation() }
|
||||
}
|
||||
|
||||
private class SummaryArgumentNode extends FlowSummaryNode, ArgumentNode {
|
||||
@@ -2158,7 +2203,7 @@ private predicate lambdaCallExpr(
|
||||
*/
|
||||
predicate lambdaSourceCall(CfgNodes::ExprNodes::CallCfgNode call, LambdaCallKind kind, Node receiver) {
|
||||
kind = TYieldCallKind() and
|
||||
call = receiver.(ImplicitBlockArgumentNode).getYieldCall()
|
||||
call = receiver.(ImplicitYieldBlockArgumentNode).getYieldCall()
|
||||
or
|
||||
kind = TLambdaCallKind() and
|
||||
lambdaCallExpr(call, receiver.asExpr())
|
||||
|
||||
@@ -3153,6 +3153,54 @@ params/params.rb:
|
||||
# 95| getReceiver: [LocalVariableAccess] hash
|
||||
# 95| getArgument: [HashSplatExpr] ** ...
|
||||
# 95| getAnOperand/getOperand/getReceiver: [LocalVariableAccess] __synth__0
|
||||
# 98| getStmt: [ClassDeclaration] Sup
|
||||
# 99| getStmt: [Method] m
|
||||
# 99| getParameter: [SimpleParameter] x
|
||||
# 99| getDefiningAccess: [LocalVariableAccess] x
|
||||
# 99| getParameter: [SplatParameter] *rest
|
||||
# 99| getDefiningAccess: [LocalVariableAccess] rest
|
||||
# 99| getParameter: [KeywordParameter] k
|
||||
# 99| getDefiningAccess: [LocalVariableAccess] k
|
||||
# 99| getParameter: [HashSplatParameter] **kwargs
|
||||
# 99| getDefiningAccess: [LocalVariableAccess] kwargs
|
||||
# 100| getStmt: [MethodCall] call to print
|
||||
# 100| getReceiver: [SelfVariableAccess] self
|
||||
# 100| getArgument: [AddExpr] ... + ...
|
||||
# 100| getAnOperand/getLeftOperand/getReceiver: [LocalVariableAccess] x
|
||||
# 100| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
|
||||
# 101| getStmt: [MethodCall] call to print
|
||||
# 101| getReceiver: [SelfVariableAccess] self
|
||||
# 101| getArgument: [AddExpr] ... + ...
|
||||
# 101| getAnOperand/getLeftOperand/getReceiver: [LocalVariableAccess] k
|
||||
# 101| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
|
||||
# 105| getStmt: [ClassDeclaration] Sub
|
||||
# 105| getSuperclassExpr: [ConstantReadAccess] Sup
|
||||
# 106| getStmt: [Method] m
|
||||
# 106| getParameter: [SimpleParameter] y
|
||||
# 106| getDefiningAccess: [LocalVariableAccess] y
|
||||
# 106| getParameter: [SplatParameter] *rest
|
||||
# 106| getDefiningAccess: [LocalVariableAccess] rest
|
||||
# 106| getParameter: [KeywordParameter] k
|
||||
# 106| getDefiningAccess: [LocalVariableAccess] k
|
||||
# 106| getParameter: [HashSplatParameter] **kwargs
|
||||
# 106| getDefiningAccess: [LocalVariableAccess] kwargs
|
||||
# 107| getStmt: [SuperCall] super call to m
|
||||
# 107| getArgument: [HashSplatExpr] ** ...
|
||||
# 107| getAnOperand/getOperand/getReceiver: [LocalVariableAccess] kwargs
|
||||
# 107| getArgument: [Pair] Pair
|
||||
# 107| getKey: [SymbolLiteral] k
|
||||
# 107| getValue: [LocalVariableAccess] k
|
||||
# 107| getArgument: [SplatExpr] * ...
|
||||
# 107| getAnOperand/getOperand/getReceiver: [LocalVariableAccess] rest
|
||||
# 107| getArgument: [LocalVariableAccess] y
|
||||
# 111| getStmt: [MethodCall] call to m
|
||||
# 111| getReceiver: [MethodCall] call to new
|
||||
# 111| getReceiver: [ConstantReadAccess] Sub
|
||||
# 111| getArgument: [IntegerLiteral] 42
|
||||
# 111| getArgument: [Pair] Pair
|
||||
# 111| getKey: [SymbolLiteral] :k
|
||||
# 111| getComponent: [StringTextComponent] k
|
||||
# 111| getValue: [IntegerLiteral] 22
|
||||
erb/template.html.erb:
|
||||
# 19| [Toplevel] template.html.erb
|
||||
# 19| getStmt: [StringLiteral] "hello world"
|
||||
|
||||
@@ -6192,6 +6192,96 @@ params/params.rb:
|
||||
# 95| 0: [ReservedWord] **
|
||||
# 95| 2: [ReservedWord] )
|
||||
# 96| 4: [ReservedWord] end
|
||||
# 98| 25: [Class] Class
|
||||
# 98| 0: [ReservedWord] class
|
||||
# 98| 1: [Constant] Sup
|
||||
# 99| 2: [BodyStatement] BodyStatement
|
||||
# 99| 0: [Method] Method
|
||||
# 99| 0: [ReservedWord] def
|
||||
# 99| 1: [Identifier] m
|
||||
# 99| 2: [MethodParameters] MethodParameters
|
||||
# 99| 0: [ReservedWord] (
|
||||
# 99| 1: [Identifier] x
|
||||
# 99| 2: [ReservedWord] ,
|
||||
# 99| 3: [SplatParameter] SplatParameter
|
||||
# 99| 0: [ReservedWord] *
|
||||
# 99| 1: [Identifier] rest
|
||||
# 99| 4: [ReservedWord] ,
|
||||
# 99| 5: [KeywordParameter] KeywordParameter
|
||||
# 99| 0: [Identifier] k
|
||||
# 99| 1: [ReservedWord] :
|
||||
# 99| 6: [ReservedWord] ,
|
||||
# 99| 7: [HashSplatParameter] HashSplatParameter
|
||||
# 99| 0: [ReservedWord] **
|
||||
# 99| 1: [Identifier] kwargs
|
||||
# 99| 8: [ReservedWord] )
|
||||
# 100| 3: [BodyStatement] BodyStatement
|
||||
# 100| 0: [Call] Call
|
||||
# 100| 0: [Identifier] print
|
||||
# 100| 1: [ArgumentList] ArgumentList
|
||||
# 100| 0: [ReservedWord] (
|
||||
# 100| 1: [Binary] Binary
|
||||
# 100| 0: [Identifier] x
|
||||
# 100| 1: [ReservedWord] +
|
||||
# 100| 2: [Integer] 1
|
||||
# 100| 2: [ReservedWord] )
|
||||
# 101| 1: [Call] Call
|
||||
# 101| 0: [Identifier] print
|
||||
# 101| 1: [ArgumentList] ArgumentList
|
||||
# 101| 0: [ReservedWord] (
|
||||
# 101| 1: [Binary] Binary
|
||||
# 101| 0: [Identifier] k
|
||||
# 101| 1: [ReservedWord] +
|
||||
# 101| 2: [Integer] 1
|
||||
# 101| 2: [ReservedWord] )
|
||||
# 102| 4: [ReservedWord] end
|
||||
# 103| 3: [ReservedWord] end
|
||||
# 105| 26: [Class] Class
|
||||
# 105| 0: [ReservedWord] class
|
||||
# 105| 1: [Constant] Sub
|
||||
# 105| 2: [Superclass] Superclass
|
||||
# 105| 0: [ReservedWord] <
|
||||
# 105| 1: [Constant] Sup
|
||||
# 106| 3: [BodyStatement] BodyStatement
|
||||
# 106| 0: [Method] Method
|
||||
# 106| 0: [ReservedWord] def
|
||||
# 106| 1: [Identifier] m
|
||||
# 106| 2: [MethodParameters] MethodParameters
|
||||
# 106| 0: [ReservedWord] (
|
||||
# 106| 1: [Identifier] y
|
||||
# 106| 2: [ReservedWord] ,
|
||||
# 106| 3: [SplatParameter] SplatParameter
|
||||
# 106| 0: [ReservedWord] *
|
||||
# 106| 1: [Identifier] rest
|
||||
# 106| 4: [ReservedWord] ,
|
||||
# 106| 5: [KeywordParameter] KeywordParameter
|
||||
# 106| 0: [Identifier] k
|
||||
# 106| 1: [ReservedWord] :
|
||||
# 106| 6: [ReservedWord] ,
|
||||
# 106| 7: [HashSplatParameter] HashSplatParameter
|
||||
# 106| 0: [ReservedWord] **
|
||||
# 106| 1: [Identifier] kwargs
|
||||
# 106| 8: [ReservedWord] )
|
||||
# 107| 3: [BodyStatement] BodyStatement
|
||||
# 107| 0: [Super] super
|
||||
# 108| 4: [ReservedWord] end
|
||||
# 109| 4: [ReservedWord] end
|
||||
# 111| 27: [Call] Call
|
||||
# 111| 0: [Call] Call
|
||||
# 111| 0: [Constant] Sub
|
||||
# 111| 1: [ReservedWord] .
|
||||
# 111| 2: [Identifier] new
|
||||
# 111| 1: [ReservedWord] .
|
||||
# 111| 2: [Identifier] m
|
||||
# 111| 3: [ArgumentList] ArgumentList
|
||||
# 111| 0: [ReservedWord] (
|
||||
# 111| 1: [Integer] 42
|
||||
# 111| 2: [ReservedWord] ,
|
||||
# 111| 3: [Pair] Pair
|
||||
# 111| 0: [HashKeySymbol] k
|
||||
# 111| 1: [ReservedWord] :
|
||||
# 111| 2: [Integer] 22
|
||||
# 111| 4: [ReservedWord] )
|
||||
# 1| [Comment] # Tests for the different kinds and contexts of parameters.
|
||||
# 3| [Comment] # Method containing identifier parameters
|
||||
# 7| [Comment] # Block containing identifier parameters
|
||||
|
||||
@@ -941,6 +941,12 @@ exprValue
|
||||
| params/params.rb:65:41:65:42 | 99 | 99 | int |
|
||||
| params/params.rb:70:42:70:45 | 1000 | 1000 | int |
|
||||
| params/params.rb:70:52:70:53 | 20 | 20 | int |
|
||||
| params/params.rb:100:15:100:15 | 1 | 1 | int |
|
||||
| params/params.rb:101:15:101:15 | 1 | 1 | int |
|
||||
| params/params.rb:107:5:107:9 | k | :k | symbol |
|
||||
| params/params.rb:111:11:111:12 | 42 | 42 | int |
|
||||
| params/params.rb:111:15:111:15 | :k | :k | symbol |
|
||||
| params/params.rb:111:18:111:19 | 22 | 22 | int |
|
||||
exprCfgNodeValue
|
||||
| calls/calls.rb:8:1:8:3 | 123 | 123 | int |
|
||||
| calls/calls.rb:11:5:11:5 | 0 | 0 | int |
|
||||
@@ -1855,3 +1861,9 @@ exprCfgNodeValue
|
||||
| params/params.rb:65:41:65:42 | 99 | 99 | int |
|
||||
| params/params.rb:70:42:70:45 | 1000 | 1000 | int |
|
||||
| params/params.rb:70:52:70:53 | 20 | 20 | int |
|
||||
| params/params.rb:100:15:100:15 | 1 | 1 | int |
|
||||
| params/params.rb:101:15:101:15 | 1 | 1 | int |
|
||||
| params/params.rb:107:5:107:9 | k | :k | symbol |
|
||||
| params/params.rb:111:11:111:12 | 42 | 42 | int |
|
||||
| params/params.rb:111:15:111:15 | :k | :k | symbol |
|
||||
| params/params.rb:111:18:111:19 | 22 | 22 | int |
|
||||
|
||||
@@ -39,6 +39,14 @@ idParams
|
||||
| params.rb:86:14:86:14 | x | x |
|
||||
| params.rb:89:31:89:35 | array | array |
|
||||
| params.rb:94:36:94:39 | hash | hash |
|
||||
| params.rb:99:9:99:9 | x | x |
|
||||
| params.rb:99:12:99:16 | *rest | rest |
|
||||
| params.rb:99:19:99:19 | k | k |
|
||||
| params.rb:99:23:99:30 | **kwargs | kwargs |
|
||||
| params.rb:106:9:106:9 | y | y |
|
||||
| params.rb:106:12:106:16 | *rest | rest |
|
||||
| params.rb:106:19:106:19 | k | k |
|
||||
| params.rb:106:23:106:30 | **kwargs | kwargs |
|
||||
blockParams
|
||||
| params.rb:46:28:46:33 | &block | block |
|
||||
| params.rb:62:29:62:34 | &block | block |
|
||||
@@ -56,10 +64,14 @@ splatParams
|
||||
| params.rb:30:31:30:36 | *splat | splat |
|
||||
| params.rb:34:21:34:26 | *splat | splat |
|
||||
| params.rb:38:29:38:33 | *blah | blah |
|
||||
| params.rb:99:12:99:16 | *rest | rest |
|
||||
| params.rb:106:12:106:16 | *rest | rest |
|
||||
hashSplatParams
|
||||
| params.rb:30:39:30:52 | **double_splat | double_splat |
|
||||
| params.rb:34:29:34:42 | **double_splat | double_splat |
|
||||
| params.rb:38:36:38:43 | **wibble | wibble |
|
||||
| params.rb:99:23:99:30 | **kwargs | kwargs |
|
||||
| params.rb:106:23:106:30 | **kwargs | kwargs |
|
||||
keywordParams
|
||||
| params.rb:41:35:41:37 | foo | foo | (none) |
|
||||
| params.rb:41:41:41:43 | bar | bar | 7 |
|
||||
@@ -67,6 +79,8 @@ keywordParams
|
||||
| params.rb:49:33:49:34 | yy | yy | 100 |
|
||||
| params.rb:53:37:53:37 | y | y | (none) |
|
||||
| params.rb:53:41:53:41 | z | z | 3 |
|
||||
| params.rb:99:19:99:19 | k | k | (none) |
|
||||
| params.rb:106:19:106:19 | k | k | (none) |
|
||||
optionalParams
|
||||
| params.rb:58:39:58:42 | val2 | val2 | params.rb:58:46:58:46 | 0 |
|
||||
| params.rb:58:49:58:52 | val3 | val3 | params.rb:58:56:58:58 | 100 |
|
||||
@@ -97,6 +111,14 @@ paramsInMethods
|
||||
| params.rb:89:1:91:3 | anonymous_splat_parameter | 1 | params.rb:89:38:89:38 | * | SplatParameter |
|
||||
| params.rb:94:1:96:3 | anonymous_hash_splat_parameter | 0 | params.rb:94:36:94:39 | hash | SimpleParameter |
|
||||
| params.rb:94:1:96:3 | anonymous_hash_splat_parameter | 1 | params.rb:94:42:94:43 | ** | HashSplatParameter |
|
||||
| params.rb:99:3:102:5 | m | 0 | params.rb:99:9:99:9 | x | SimpleParameter |
|
||||
| params.rb:99:3:102:5 | m | 1 | params.rb:99:12:99:16 | *rest | SplatParameter |
|
||||
| params.rb:99:3:102:5 | m | 2 | params.rb:99:19:99:19 | k | KeywordParameter |
|
||||
| params.rb:99:3:102:5 | m | 3 | params.rb:99:23:99:30 | **kwargs | HashSplatParameter |
|
||||
| params.rb:106:3:108:5 | m | 0 | params.rb:106:9:106:9 | y | SimpleParameter |
|
||||
| params.rb:106:3:108:5 | m | 1 | params.rb:106:12:106:16 | *rest | SplatParameter |
|
||||
| params.rb:106:3:108:5 | m | 2 | params.rb:106:19:106:19 | k | KeywordParameter |
|
||||
| params.rb:106:3:108:5 | m | 3 | params.rb:106:23:106:30 | **kwargs | HashSplatParameter |
|
||||
paramsInBlocks
|
||||
| params.rb:9:11:11:3 | do ... end | 0 | params.rb:9:15:9:17 | key | SimpleParameter |
|
||||
| params.rb:9:11:11:3 | do ... end | 1 | params.rb:9:20:9:24 | value | SimpleParameter |
|
||||
@@ -175,3 +197,11 @@ params
|
||||
| params.rb:89:38:89:38 | * | 1 | SplatParameter |
|
||||
| params.rb:94:36:94:39 | hash | 0 | SimpleParameter |
|
||||
| params.rb:94:42:94:43 | ** | 1 | HashSplatParameter |
|
||||
| params.rb:99:9:99:9 | x | 0 | SimpleParameter |
|
||||
| params.rb:99:12:99:16 | *rest | 1 | SplatParameter |
|
||||
| params.rb:99:19:99:19 | k | 2 | KeywordParameter |
|
||||
| params.rb:99:23:99:30 | **kwargs | 3 | HashSplatParameter |
|
||||
| params.rb:106:9:106:9 | y | 0 | SimpleParameter |
|
||||
| params.rb:106:12:106:16 | *rest | 1 | SplatParameter |
|
||||
| params.rb:106:19:106:19 | k | 2 | KeywordParameter |
|
||||
| params.rb:106:23:106:30 | **kwargs | 3 | HashSplatParameter |
|
||||
|
||||
@@ -94,3 +94,18 @@ end
|
||||
def anonymous_hash_splat_parameter(hash, **)
|
||||
hash.merge(**)
|
||||
end
|
||||
|
||||
class Sup
|
||||
def m(x, *rest, k:, **kwargs)
|
||||
print(x + 1)
|
||||
print(k + 1)
|
||||
end
|
||||
end
|
||||
|
||||
class Sub < Sup
|
||||
def m(y, *rest, k:, **kwargs)
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
Sub.new.m(42, k: 22)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -174,6 +174,34 @@ edges
|
||||
| params_flow.rb:192:24:192:32 | call to taint | params_flow.rb:181:28:181:29 | p2 | provenance | |
|
||||
| params_flow.rb:192:24:192:32 | call to taint | params_flow.rb:192:20:192:21 | [post] p1 : [collection] [element 0] | provenance | |
|
||||
| params_flow.rb:193:6:193:7 | p1 : [collection] [element 0] | params_flow.rb:193:6:193:10 | ...[...] | provenance | |
|
||||
| params_flow.rb:210:11:210:11 | x | params_flow.rb:211:14:211:14 | x | provenance | |
|
||||
| params_flow.rb:210:14:210:18 | *rest : [collection] [element 0] | params_flow.rb:212:14:212:17 | rest : [collection] [element 0] | provenance | |
|
||||
| params_flow.rb:210:14:210:18 | *rest : [collection] [element 2] | params_flow.rb:214:14:214:17 | rest : [collection] [element 2] | provenance | |
|
||||
| params_flow.rb:210:21:210:22 | k1 | params_flow.rb:215:14:215:15 | k1 | provenance | |
|
||||
| params_flow.rb:210:26:210:33 | **kwargs : Hash [element :k2] | params_flow.rb:216:14:216:19 | kwargs : Hash [element :k2] | provenance | |
|
||||
| params_flow.rb:212:14:212:17 | rest : [collection] [element 0] | params_flow.rb:212:14:212:20 | ...[...] | provenance | |
|
||||
| params_flow.rb:214:14:214:17 | rest : [collection] [element 2] | params_flow.rb:214:14:214:20 | ...[...] | provenance | |
|
||||
| params_flow.rb:216:14:216:19 | kwargs : Hash [element :k2] | params_flow.rb:216:14:216:24 | ...[...] | provenance | |
|
||||
| params_flow.rb:217:15:217:23 | call to taint | params_flow.rb:227:81:227:81 | x | provenance | |
|
||||
| params_flow.rb:222:11:222:11 | x | params_flow.rb:223:9:223:13 | x | provenance | |
|
||||
| params_flow.rb:222:14:222:18 | *rest : [collection] [element 0] | params_flow.rb:223:9:223:13 | rest : [collection] [element 0] | provenance | |
|
||||
| params_flow.rb:222:14:222:18 | *rest : [collection] [element 2] | params_flow.rb:223:9:223:13 | rest : [collection] [element 2] | provenance | |
|
||||
| params_flow.rb:222:21:222:22 | k1 | params_flow.rb:223:9:223:13 | k1 | provenance | |
|
||||
| params_flow.rb:222:26:222:33 | **kwargs : Hash [element :k2] | params_flow.rb:223:9:223:13 | kwargs : Hash [element :k2] | provenance | |
|
||||
| params_flow.rb:223:9:223:13 | * ... : [collection] [element 0] | params_flow.rb:210:14:210:18 | *rest : [collection] [element 0] | provenance | |
|
||||
| params_flow.rb:223:9:223:13 | * ... : [collection] [element 2] | params_flow.rb:210:14:210:18 | *rest : [collection] [element 2] | provenance | |
|
||||
| params_flow.rb:223:9:223:13 | ** ... : Hash [element :k2] | params_flow.rb:210:26:210:33 | **kwargs : Hash [element :k2] | provenance | |
|
||||
| params_flow.rb:223:9:223:13 | k1 | params_flow.rb:210:21:210:22 | k1 | provenance | |
|
||||
| params_flow.rb:223:9:223:13 | kwargs : Hash [element :k2] | params_flow.rb:223:9:223:13 | ** ... : Hash [element :k2] | provenance | |
|
||||
| params_flow.rb:223:9:223:13 | rest : [collection] [element 0] | params_flow.rb:223:9:223:13 | * ... : [collection] [element 0] | provenance | |
|
||||
| params_flow.rb:223:9:223:13 | rest : [collection] [element 2] | params_flow.rb:223:9:223:13 | * ... : [collection] [element 2] | provenance | |
|
||||
| params_flow.rb:223:9:223:13 | x | params_flow.rb:210:11:210:11 | x | provenance | |
|
||||
| params_flow.rb:227:11:227:19 | call to taint | params_flow.rb:222:11:222:11 | x | provenance | |
|
||||
| params_flow.rb:227:22:227:30 | call to taint | params_flow.rb:222:14:222:18 | *rest : [collection] [element 0] | provenance | |
|
||||
| params_flow.rb:227:36:227:44 | call to taint | params_flow.rb:222:14:222:18 | *rest : [collection] [element 2] | provenance | |
|
||||
| params_flow.rb:227:51:227:59 | call to taint | params_flow.rb:222:21:222:22 | k1 | provenance | |
|
||||
| params_flow.rb:227:66:227:74 | call to taint | params_flow.rb:222:26:222:33 | **kwargs : Hash [element :k2] | provenance | |
|
||||
| params_flow.rb:227:81:227:81 | x | params_flow.rb:228:10:228:10 | x | provenance | |
|
||||
nodes
|
||||
| params_flow.rb:9:16:9:17 | p1 | semmle.label | p1 |
|
||||
| params_flow.rb:9:20:9:21 | p2 | semmle.label | p2 |
|
||||
@@ -373,6 +401,40 @@ nodes
|
||||
| params_flow.rb:192:24:192:32 | call to taint | semmle.label | call to taint |
|
||||
| params_flow.rb:193:6:193:7 | p1 : [collection] [element 0] | semmle.label | p1 : [collection] [element 0] |
|
||||
| params_flow.rb:193:6:193:10 | ...[...] | semmle.label | ...[...] |
|
||||
| params_flow.rb:210:11:210:11 | x | semmle.label | x |
|
||||
| params_flow.rb:210:14:210:18 | *rest : [collection] [element 0] | semmle.label | *rest : [collection] [element 0] |
|
||||
| params_flow.rb:210:14:210:18 | *rest : [collection] [element 2] | semmle.label | *rest : [collection] [element 2] |
|
||||
| params_flow.rb:210:21:210:22 | k1 | semmle.label | k1 |
|
||||
| params_flow.rb:210:26:210:33 | **kwargs : Hash [element :k2] | semmle.label | **kwargs : Hash [element :k2] |
|
||||
| params_flow.rb:211:14:211:14 | x | semmle.label | x |
|
||||
| params_flow.rb:212:14:212:17 | rest : [collection] [element 0] | semmle.label | rest : [collection] [element 0] |
|
||||
| params_flow.rb:212:14:212:20 | ...[...] | semmle.label | ...[...] |
|
||||
| params_flow.rb:214:14:214:17 | rest : [collection] [element 2] | semmle.label | rest : [collection] [element 2] |
|
||||
| params_flow.rb:214:14:214:20 | ...[...] | semmle.label | ...[...] |
|
||||
| params_flow.rb:215:14:215:15 | k1 | semmle.label | k1 |
|
||||
| params_flow.rb:216:14:216:19 | kwargs : Hash [element :k2] | semmle.label | kwargs : Hash [element :k2] |
|
||||
| params_flow.rb:216:14:216:24 | ...[...] | semmle.label | ...[...] |
|
||||
| params_flow.rb:217:15:217:23 | call to taint | semmle.label | call to taint |
|
||||
| params_flow.rb:222:11:222:11 | x | semmle.label | x |
|
||||
| params_flow.rb:222:14:222:18 | *rest : [collection] [element 0] | semmle.label | *rest : [collection] [element 0] |
|
||||
| params_flow.rb:222:14:222:18 | *rest : [collection] [element 2] | semmle.label | *rest : [collection] [element 2] |
|
||||
| params_flow.rb:222:21:222:22 | k1 | semmle.label | k1 |
|
||||
| params_flow.rb:222:26:222:33 | **kwargs : Hash [element :k2] | semmle.label | **kwargs : Hash [element :k2] |
|
||||
| params_flow.rb:223:9:223:13 | * ... : [collection] [element 0] | semmle.label | * ... : [collection] [element 0] |
|
||||
| params_flow.rb:223:9:223:13 | * ... : [collection] [element 2] | semmle.label | * ... : [collection] [element 2] |
|
||||
| params_flow.rb:223:9:223:13 | ** ... : Hash [element :k2] | semmle.label | ** ... : Hash [element :k2] |
|
||||
| params_flow.rb:223:9:223:13 | k1 | semmle.label | k1 |
|
||||
| params_flow.rb:223:9:223:13 | kwargs : Hash [element :k2] | semmle.label | kwargs : Hash [element :k2] |
|
||||
| params_flow.rb:223:9:223:13 | rest : [collection] [element 0] | semmle.label | rest : [collection] [element 0] |
|
||||
| params_flow.rb:223:9:223:13 | rest : [collection] [element 2] | semmle.label | rest : [collection] [element 2] |
|
||||
| params_flow.rb:223:9:223:13 | x | semmle.label | x |
|
||||
| params_flow.rb:227:11:227:19 | call to taint | semmle.label | call to taint |
|
||||
| params_flow.rb:227:22:227:30 | call to taint | semmle.label | call to taint |
|
||||
| params_flow.rb:227:36:227:44 | call to taint | semmle.label | call to taint |
|
||||
| params_flow.rb:227:51:227:59 | call to taint | semmle.label | call to taint |
|
||||
| params_flow.rb:227:66:227:74 | call to taint | semmle.label | call to taint |
|
||||
| params_flow.rb:227:81:227:81 | x | semmle.label | x |
|
||||
| params_flow.rb:228:10:228:10 | x | semmle.label | x |
|
||||
subpaths
|
||||
| params_flow.rb:164:31:164:39 | call to taint | params_flow.rb:153:28:153:29 | p2 | params_flow.rb:153:23:153:24 | p1 [Return] : [collection] [element 0] | params_flow.rb:164:23:164:24 | [post] p1 : [collection] [element 0] |
|
||||
| params_flow.rb:192:24:192:32 | call to taint | params_flow.rb:181:28:181:29 | p2 | params_flow.rb:181:24:181:25 | p1 [Return] : [collection] [element 0] | params_flow.rb:192:20:192:21 | [post] p1 : [collection] [element 0] |
|
||||
@@ -430,3 +492,9 @@ testFailures
|
||||
| params_flow.rb:134:10:134:16 | ...[...] | params_flow.rb:137:23:137:31 | call to taint | params_flow.rb:134:10:134:16 | ...[...] | $@ | params_flow.rb:137:23:137:31 | call to taint | call to taint |
|
||||
| params_flow.rb:165:6:165:10 | ...[...] | params_flow.rb:164:31:164:39 | call to taint | params_flow.rb:165:6:165:10 | ...[...] | $@ | params_flow.rb:164:31:164:39 | call to taint | call to taint |
|
||||
| params_flow.rb:193:6:193:10 | ...[...] | params_flow.rb:192:24:192:32 | call to taint | params_flow.rb:193:6:193:10 | ...[...] | $@ | params_flow.rb:192:24:192:32 | call to taint | call to taint |
|
||||
| params_flow.rb:211:14:211:14 | x | params_flow.rb:227:11:227:19 | call to taint | params_flow.rb:211:14:211:14 | x | $@ | params_flow.rb:227:11:227:19 | call to taint | call to taint |
|
||||
| params_flow.rb:212:14:212:20 | ...[...] | params_flow.rb:227:22:227:30 | call to taint | params_flow.rb:212:14:212:20 | ...[...] | $@ | params_flow.rb:227:22:227:30 | call to taint | call to taint |
|
||||
| params_flow.rb:214:14:214:20 | ...[...] | params_flow.rb:227:36:227:44 | call to taint | params_flow.rb:214:14:214:20 | ...[...] | $@ | params_flow.rb:227:36:227:44 | call to taint | call to taint |
|
||||
| params_flow.rb:215:14:215:15 | k1 | params_flow.rb:227:51:227:59 | call to taint | params_flow.rb:215:14:215:15 | k1 | $@ | params_flow.rb:227:51:227:59 | call to taint | call to taint |
|
||||
| params_flow.rb:216:14:216:24 | ...[...] | params_flow.rb:227:66:227:74 | call to taint | params_flow.rb:216:14:216:24 | ...[...] | $@ | params_flow.rb:227:66:227:74 | call to taint | call to taint |
|
||||
| params_flow.rb:228:10:228:10 | x | params_flow.rb:217:15:217:23 | call to taint | params_flow.rb:228:10:228:10 | x | $@ | params_flow.rb:217:15:217:23 | call to taint | call to taint |
|
||||
|
||||
@@ -205,3 +205,25 @@ def foo(x, y)
|
||||
end
|
||||
|
||||
foo(*int_hash)
|
||||
|
||||
class Sup
|
||||
def m(x, *rest, k1:, **kwargs)
|
||||
sink(x) # $ hasValueFlow=81
|
||||
sink(rest[0]) # $ hasValueFlow=82
|
||||
sink(rest[1])
|
||||
sink(rest[2]) # $ hasValueFlow=83
|
||||
sink(k1) # $ hasValueFlow=84
|
||||
sink(kwargs[:k2]) # $ hasValueFlow=85
|
||||
yield taint(86)
|
||||
end
|
||||
end
|
||||
|
||||
class Sub < Sup
|
||||
def m(x, *rest, k1:, **kwargs)
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
Sub.new.m(taint(81), taint(82), 0, taint(83), k1: taint(84), k2: taint(85)) do |x|
|
||||
sink(x) # $ hasValueFlow=86
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user