Merge tag 'codeql-cli/latest' into auto/sync-main-pr

Compatible with the latest released version of the CodeQL CLI
This commit is contained in:
dilanbhalla
2025-04-22 14:59:21 +00:00
728 changed files with 31702 additions and 5048 deletions

View File

@@ -8,30 +8,18 @@ private import codeql.dataflow.internal.DataFlowImplConsistency
private module Input implements InputSig<Location, RubyDataFlow> {
private import RubyDataFlow
predicate postWithInFlowExclude(Node n) { n instanceof FlowSummaryNode }
predicate postWithInFlowExclude(Node n) {
n instanceof FlowSummaryNode
or
n.(PostUpdateNode).getPreUpdateNode().asExpr() = getPostUpdateReverseStep(_)
}
predicate argHasPostUpdateExclude(ArgumentNode n) {
n instanceof FlowSummaryNode
or
n instanceof SynthHashSplatArgumentNode
or
not isNonConstantExpr(getAPostUpdateNodeForArg(n.asExpr()))
}
predicate postHasUniquePreExclude(PostUpdateNode n) {
exists(CfgNodes::ExprCfgNode e, CfgNodes::ExprCfgNode arg |
e = getAPostUpdateNodeForArg(arg) and
e != arg and
n = TExprPostUpdateNode(e)
)
}
predicate uniquePostUpdateExclude(Node n) {
exists(CfgNodes::ExprCfgNode e, CfgNodes::ExprCfgNode arg |
e = getAPostUpdateNodeForArg(arg) and
e != arg and
n.asExpr() = arg
)
not isNonConstantExpr(n.asExpr())
}
predicate multipleArgumentCallExclude(ArgumentNode arg, DataFlowCall call) {

View File

@@ -1,3 +1,9 @@
## 4.1.4
### Minor Analysis Improvements
* 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)`.
## 4.1.3
No user-facing changes.

View File

@@ -0,0 +1,5 @@
## 4.1.4
### Minor Analysis Improvements
* 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)`.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 4.1.3
lastReleaseVersion: 4.1.4

View File

@@ -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" }
}
/**

View File

@@ -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
}
}

View File

@@ -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" }
}

View File

@@ -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;

View File

@@ -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() }
}

View File

@@ -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) }
}

View File

@@ -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 {

View File

@@ -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 { }

View File

@@ -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)
}
}
}

View File

@@ -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

View File

@@ -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) }
}

View File

@@ -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
@@ -66,10 +67,22 @@ private CfgNodes::ExprCfgNode getALastEvalNode(CfgNodes::ExprCfgNode n) {
)
}
/** Gets a node for which to construct a post-update node for argument `arg`. */
CfgNodes::ExprCfgNode getAPostUpdateNodeForArg(Argument arg) {
result = getALastEvalNode*(arg) and
not exists(getALastEvalNode(result))
/**
* Holds if a reverse local flow step should be added from the post-update node
* for `e` to the post-update node for the result.
*
* This is needed to allow for side-effects on compound expressions to propagate
* to sub components. For example, in
*
* ```ruby
* (foo1; foo2).set_field(taint)
* ```
*
* we add a reverse flow step from `[post] (foo1; foo2)` to `[post] foo2`,
* in order for the side-effect of `set_field` to reach `foo2`.
*/
CfgNodes::ExprCfgNode getPostUpdateReverseStep(CfgNodes::ExprCfgNode e) {
result = getALastEvalNode(e)
}
/** Gets the SSA definition node corresponding to parameter `p`. */
@@ -170,6 +183,9 @@ module LocalFlow {
)
or
nodeTo.(ImplicitBlockArgumentNode).getParameterNode(true) = nodeFrom
or
nodeTo.(PostUpdateNode).getPreUpdateNode().asExpr() =
getPostUpdateReverseStep(nodeFrom.(PostUpdateNode).getPreUpdateNode().asExpr())
}
predicate flowSummaryLocalStep(
@@ -468,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
@@ -486,7 +505,9 @@ private module Cached {
// filter out nodes that clearly don't need post-update nodes
isNonConstantExpr(n) and
(
n = getAPostUpdateNodeForArg(_)
n instanceof Argument
or
n = getPostUpdateReverseStep(any(PostUpdateNode p).getPreUpdateNode().asExpr())
or
n = any(CfgNodes::ExprNodes::InstanceVariableAccessCfgNode v).getReceiver()
)
@@ -1032,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 {
@@ -1298,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
@@ -1326,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 {
@@ -2018,18 +2080,7 @@ private module PostUpdateNodes {
ExprPostUpdateNode() { this = TExprPostUpdateNode(e) }
override ExprNode getPreUpdateNode() {
// For compound arguments, such as `m(if b then x else y)`, we want the leaf nodes
// `[post] x` and `[post] y` to have two pre-update nodes: (1) the compound argument,
// `if b then x else y`; and the (2) the underlying expressions; `x` and `y`,
// respectively.
//
// This ensures that we get flow out of the call into both leafs (1), while still
// maintaining the invariant that the underlying expression is a pre-update node (2).
e = getAPostUpdateNodeForArg(result.getExprNode())
or
e = result.getExprNode()
}
override ExprNode getPreUpdateNode() { e = result.getExprNode() }
override CfgScope getCfgScope() { result = e.getExpr().getCfgScope() }
@@ -2152,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())

View File

@@ -1,5 +1,5 @@
name: codeql/ruby-all
version: 4.1.3
version: 4.1.4
groups: ruby
extractor: ruby
dbscheme: ruby.dbscheme

View File

@@ -1,3 +1,10 @@
## 1.2.0
### Major Analysis Improvements
* The query `rb/useless-assignment-to-local` now comes with query help and has been tweaked to produce fewer false positives.
* The query `rb/uninitialized-local-variable` now only produces alerts when the variable is the receiver of a method call and should produce very few false positives. It also now comes with a help file.
## 1.1.15
No user-facing changes.

View File

@@ -0,0 +1,6 @@
## 1.2.0
### Major Analysis Improvements
* The query `rb/useless-assignment-to-local` now comes with query help and has been tweaked to produce fewer false positives.
* The query `rb/uninitialized-local-variable` now only produces alerts when the variable is the receiver of a method call and should produce very few false positives. It also now comes with a help file.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.1.15
lastReleaseVersion: 1.2.0

View File

@@ -1,4 +1,6 @@
- queries: .
- include:
id:
- rb/database-query-in-loop
- rb/database-query-in-loop
- rb/useless-assignment-to-local
- rb/uninitialized-local-variable

View File

@@ -1,5 +1,5 @@
name: codeql/ruby-queries
version: 1.1.15
version: 1.2.0
groups:
- ruby
- queries

View File

@@ -0,0 +1,49 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
A value is assigned to a local variable, but either that variable is never read
later on, or its value is always overwritten before being read. This means
that the original assignment has no effect, and could indicate a logic error or
incomplete code.
</p>
</overview>
<recommendation>
<p>
Ensure that you check the control and data flow in the method carefully.
If a value is really not needed, consider omitting the assignment. Be careful,
though: if the right-hand side has a side-effect (like performing a method call),
it is important to keep this to preserve the overall behavior.
</p>
</recommendation>
<example>
<p>
In the following example, the return value of the call to <code>send</code> on line 2
is assigned to the local variable <code>result</code>, but then never used.
</p>
<sample src="examples/DeadStoreOfLocal.rb" />
<p>
Assuming that <code>send</code> returns a status code indicating whether the operation
succeeded or not, the value of <code>result</code> should be checked, perhaps like this:
</p>
<sample src="examples/DeadStoreOfLocalGood.rb" />
</example>
<references>
<li>Wikipedia: <a href="http://en.wikipedia.org/wiki/Dead_store">Dead store</a>.</li>
</references>
</qhelp>

View File

@@ -7,16 +7,30 @@
* @id rb/useless-assignment-to-local
* @tags maintainability
* external/cwe/cwe-563
* @precision low
* @precision medium
*/
import codeql.ruby.AST
import codeql.ruby.CFG
import codeql.ruby.dataflow.SSA
import codeql.ruby.ApiGraphs
pragma[nomagic]
private predicate hasErbResultCall(CfgScope scope) {
scope = API::getTopLevelMember("ERB").getInstance().getAMethodCall("result").asExpr().getScope()
}
class RelevantLocalVariableWriteAccess extends LocalVariableWriteAccess {
RelevantLocalVariableWriteAccess() {
not this.getVariable().getName().charAt(0) = "_" and
not this = any(Parameter p).getAVariable().getDefiningAccess()
not this = any(Parameter p).getAVariable().getDefiningAccess() and
not hasErbResultCall(this.getCfgScope()) and
not exists(RetryStmt r | r.getCfgScope() = this.getCfgScope()) and
not exists(MethodCall c |
c.getReceiver() instanceof SelfVariableAccess and
c.getMethodName() = "binding" and
c.getCfgScope() = this.getCfgScope()
)
}
}

View File

@@ -0,0 +1,41 @@
# Method call on `nil`
## Description
In Ruby, it is not necessary to explicitly initialize variables.
If a local variable has not been explicitly initialized, it will have the value `nil`. If this happens unintended, though, the variable will not represent an object with the expected methods, and a method call on the variable will raise a `NoMethodError`.
## Recommendation
Ensure that the variable cannot be `nil` at the point hightligted by the alert.
This can be achieved by using a safe navigation or adding a check for `nil`.
Note: You do not need to explicitly initialize the variable, if you can make the program deal with the possible `nil` value. In particular, initializing the variable to `nil` will have no effect, as this is already the value of the variable. If `nil` is the only possibly default value, you need to handle the `nil` value instead of initializing the variable.
## Examples
In the following code, the call to `create_file` may fail and then the call `f.close` will raise a `NoMethodError` since `f` will be `nil` at that point.
```ruby
def dump(x)
f = create_file
f.puts(x)
ensure
f.close
end
```
We can fix this by using safe navigation:
```ruby
def dump(x)
f = create_file
f.puts(x)
ensure
f&.close
end
```
## References
- https://www.rubyguides.com/: [Nil](https://www.rubyguides.com/2018/01/ruby-nil/)
- https://ruby-doc.org/: [NoMethodError](https://ruby-doc.org/core-2.6.5/NoMethodError.html)

View File

@@ -5,20 +5,91 @@
* @kind problem
* @problem.severity error
* @id rb/uninitialized-local-variable
* @tags reliability
* @tags quality
* reliability
* correctness
* @precision low
* @precision high
*/
import codeql.ruby.AST
import codeql.ruby.dataflow.SSA
import codeql.ruby.controlflow.internal.Guards as Guards
import codeql.ruby.controlflow.CfgNodes
import codeql.ruby.ast.internal.Variable
class RelevantLocalVariableReadAccess extends LocalVariableReadAccess {
RelevantLocalVariableReadAccess() {
not exists(MethodCall c |
c.getReceiver() = this and
private predicate isInBooleanContext(AstNode n) {
exists(ConditionalExpr i |
n = i.getCondition()
or
isInBooleanContext(i) and
n = i.getBranch(_)
)
or
n = any(ConditionalLoop parent).getCondition()
or
n = any(InClause parent).getCondition()
or
n = any(LogicalAndExpr op).getAnOperand()
or
n = any(LogicalOrExpr op).getAnOperand()
or
n = any(NotExpr op).getOperand()
or
n = any(StmtSequence parent | isInBooleanContext(parent)).getLastStmt()
or
exists(CaseExpr c, WhenClause w |
not exists(c.getValue()) and
c.getABranch() = w
|
w.getPattern(_) = n
or
w = n
)
}
private predicate isGuarded(LocalVariableReadAccess read) {
exists(AstCfgNode guard, boolean branch |
Guards::guardControlsBlock(guard, read.getAControlFlowNode().getBasicBlock(), branch)
|
// guard is `var`
guard.getAstNode() = read.getVariable().getAnAccess() and
branch = true
or
// guard is `var.nil?`
exists(MethodCall c | guard.getAstNode() = c |
c.getReceiver() = read.getVariable().getAnAccess() and
c.getMethodName() = "nil?"
)
) and
branch = false
)
}
private predicate isNilChecked(LocalVariableReadAccess read) {
exists(MethodCall c | c.getReceiver() = read |
c.getMethodName() = "nil?"
or
c.isSafeNavigation()
)
}
/**
* Holds if `name` is the name of a method defined on `nil`.
* See https://ruby-doc.org/core-2.5.8/NilClass.html
*/
private predicate isNilMethodName(string name) {
name in [
"inspect", "instance_of?", "is_a?", "kind_of?", "method", "nil?", "rationalize", "to_a",
"to_c", "to_f", "to_h", "to_i", "to_r", "to_s"
]
}
class RelevantLocalVariableReadAccess extends LocalVariableReadAccess instanceof TVariableAccessReal
{
RelevantLocalVariableReadAccess() {
not isInBooleanContext(this) and
not isNilChecked(this) and
not isGuarded(this) and
this = any(MethodCall m | not isNilMethodName(m.getMethodName())).getReceiver()
}
}

View File

@@ -0,0 +1,5 @@
def f(x)
result = send(x)
waitForResponse
return getResponse
end

View File

@@ -0,0 +1,9 @@
def f(x)
result = send(x)
# check for error
if (result == -1)
raise "Unable to send, check network."
end
waitForResponse
return getResponse
end

View File

@@ -0,0 +1,14 @@
def m
puts "m"
end
def foo
m # calls m above
if false
m = "0"
m # reads local variable m
else
end
m.strip # reads uninitialized local variable m, `nil`, and crashes
m2 # undefined local variable or method 'm2' for main (NameError)
end

View File

@@ -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"

View File

@@ -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

View File

@@ -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 |

View File

@@ -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 |

View File

@@ -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)

View File

@@ -197,18 +197,18 @@ edges
| instance_variables.rb:70:16:70:24 | call to taint | instance_variables.rb:10:19:10:19 | x | provenance | |
| instance_variables.rb:70:16:70:24 | call to taint | instance_variables.rb:70:1:70:4 | [post] foo3 : Foo [@field] | provenance | |
| instance_variables.rb:71:6:71:9 | foo3 : Foo [@field] | instance_variables.rb:71:6:71:15 | call to field | provenance | |
| instance_variables.rb:78:2:78:5 | [post] foo5 : Foo [@field] | instance_variables.rb:79:6:79:9 | foo5 : Foo [@field] | provenance | |
| instance_variables.rb:78:2:78:5 | [post] foo5 : Foo [@field] | instance_variables.rb:84:6:84:9 | foo5 : Foo [@field] | provenance | |
| instance_variables.rb:78:1:78:6 | [post] ( ... ) : Foo [@field] | instance_variables.rb:79:6:79:9 | foo5 : Foo [@field] | provenance | |
| instance_variables.rb:78:1:78:6 | [post] ( ... ) : Foo [@field] | instance_variables.rb:84:6:84:9 | foo5 : Foo [@field] | provenance | |
| instance_variables.rb:78:18:78:26 | call to taint | captured_variables.rb:57:19:57:19 | x | provenance | |
| instance_variables.rb:78:18:78:26 | call to taint | instance_variables.rb:10:19:10:19 | x | provenance | |
| instance_variables.rb:78:18:78:26 | call to taint | instance_variables.rb:78:2:78:5 | [post] foo5 : Foo [@field] | provenance | |
| instance_variables.rb:78:18:78:26 | call to taint | instance_variables.rb:78:1:78:6 | [post] ( ... ) : Foo [@field] | provenance | |
| instance_variables.rb:79:6:79:9 | foo5 : Foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | provenance | |
| instance_variables.rb:79:6:79:9 | foo5 : Foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | provenance | |
| instance_variables.rb:79:6:79:9 | foo5 : Foo [@field] | instance_variables.rb:79:6:79:19 | call to get_field | provenance | |
| instance_variables.rb:82:15:82:18 | [post] foo6 : Foo [@field] | instance_variables.rb:85:6:85:9 | foo6 : Foo [@field] | provenance | |
| instance_variables.rb:82:1:82:20 | [post] ( ... ) : Foo [@field] | instance_variables.rb:85:6:85:9 | foo6 : Foo [@field] | provenance | |
| instance_variables.rb:82:32:82:40 | call to taint | captured_variables.rb:57:19:57:19 | x | provenance | |
| instance_variables.rb:82:32:82:40 | call to taint | instance_variables.rb:10:19:10:19 | x | provenance | |
| instance_variables.rb:82:32:82:40 | call to taint | instance_variables.rb:82:15:82:18 | [post] foo6 : Foo [@field] | provenance | |
| instance_variables.rb:82:32:82:40 | call to taint | instance_variables.rb:82:1:82:20 | [post] ( ... ) : Foo [@field] | provenance | |
| instance_variables.rb:83:6:83:9 | foo3 : Foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | provenance | |
| instance_variables.rb:83:6:83:9 | foo3 : Foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | provenance | |
| instance_variables.rb:83:6:83:9 | foo3 : Foo [@field] | instance_variables.rb:83:6:83:19 | call to get_field | provenance | |
@@ -218,24 +218,22 @@ edges
| instance_variables.rb:85:6:85:9 | foo6 : Foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | provenance | |
| instance_variables.rb:85:6:85:9 | foo6 : Foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | provenance | |
| instance_variables.rb:85:6:85:9 | foo6 : Foo [@field] | instance_variables.rb:85:6:85:19 | call to get_field | provenance | |
| instance_variables.rb:89:15:89:18 | [post] foo7 : Foo [@field] | instance_variables.rb:90:6:90:9 | foo7 : Foo [@field] | provenance | |
| instance_variables.rb:89:25:89:28 | [post] foo8 : Foo [@field] | instance_variables.rb:91:6:91:9 | foo8 : Foo [@field] | provenance | |
| instance_variables.rb:89:1:89:33 | [post] ( ... ) : Foo [@field] | instance_variables.rb:90:6:90:9 | foo7 : Foo [@field] | provenance | |
| instance_variables.rb:89:1:89:33 | [post] ( ... ) : Foo [@field] | instance_variables.rb:91:6:91:9 | foo8 : Foo [@field] | provenance | |
| instance_variables.rb:89:45:89:53 | call to taint | captured_variables.rb:57:19:57:19 | x | provenance | |
| instance_variables.rb:89:45:89:53 | call to taint | instance_variables.rb:10:19:10:19 | x | provenance | |
| instance_variables.rb:89:45:89:53 | call to taint | instance_variables.rb:89:15:89:18 | [post] foo7 : Foo [@field] | provenance | |
| instance_variables.rb:89:45:89:53 | call to taint | instance_variables.rb:89:25:89:28 | [post] foo8 : Foo [@field] | provenance | |
| instance_variables.rb:89:45:89:53 | call to taint | instance_variables.rb:89:1:89:33 | [post] ( ... ) : Foo [@field] | provenance | |
| instance_variables.rb:90:6:90:9 | foo7 : Foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | provenance | |
| instance_variables.rb:90:6:90:9 | foo7 : Foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | provenance | |
| instance_variables.rb:90:6:90:9 | foo7 : Foo [@field] | instance_variables.rb:90:6:90:19 | call to get_field | provenance | |
| instance_variables.rb:91:6:91:9 | foo8 : Foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | provenance | |
| instance_variables.rb:91:6:91:9 | foo8 : Foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | provenance | |
| instance_variables.rb:91:6:91:9 | foo8 : Foo [@field] | instance_variables.rb:91:6:91:19 | call to get_field | provenance | |
| instance_variables.rb:95:22:95:25 | [post] foo9 : Foo [@field] | instance_variables.rb:96:6:96:9 | foo9 : Foo [@field] | provenance | |
| instance_variables.rb:95:32:95:36 | [post] foo10 : Foo [@field] | instance_variables.rb:97:6:97:10 | foo10 : Foo [@field] | provenance | |
| instance_variables.rb:95:1:95:41 | [post] ( ... ) : Foo [@field] | instance_variables.rb:96:6:96:9 | foo9 : Foo [@field] | provenance | |
| instance_variables.rb:95:1:95:41 | [post] ( ... ) : Foo [@field] | instance_variables.rb:97:6:97:10 | foo10 : Foo [@field] | provenance | |
| instance_variables.rb:95:53:95:61 | call to taint | captured_variables.rb:57:19:57:19 | x | provenance | |
| instance_variables.rb:95:53:95:61 | call to taint | instance_variables.rb:10:19:10:19 | x | provenance | |
| instance_variables.rb:95:53:95:61 | call to taint | instance_variables.rb:95:22:95:25 | [post] foo9 : Foo [@field] | provenance | |
| instance_variables.rb:95:53:95:61 | call to taint | instance_variables.rb:95:32:95:36 | [post] foo10 : Foo [@field] | provenance | |
| instance_variables.rb:95:53:95:61 | call to taint | instance_variables.rb:95:1:95:41 | [post] ( ... ) : Foo [@field] | provenance | |
| instance_variables.rb:96:6:96:9 | foo9 : Foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | provenance | |
| instance_variables.rb:96:6:96:9 | foo9 : Foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | provenance | |
| instance_variables.rb:96:6:96:9 | foo9 : Foo [@field] | instance_variables.rb:96:6:96:19 | call to get_field | provenance | |
@@ -243,8 +241,8 @@ edges
| instance_variables.rb:97:6:97:10 | foo10 : Foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | provenance | |
| instance_variables.rb:97:6:97:10 | foo10 : Foo [@field] | instance_variables.rb:97:6:97:20 | call to get_field | provenance | |
| instance_variables.rb:99:18:99:18 | x [Return] : Foo [@field] | instance_variables.rb:104:14:104:18 | [post] foo11 : Foo [@field] | provenance | |
| instance_variables.rb:99:18:99:18 | x [Return] : Foo [@field] | instance_variables.rb:108:15:108:19 | [post] foo12 : Foo [@field] | provenance | |
| instance_variables.rb:99:18:99:18 | x [Return] : Foo [@field] | instance_variables.rb:113:22:113:26 | [post] foo13 : Foo [@field] | provenance | |
| instance_variables.rb:99:18:99:18 | x [Return] : Foo [@field] | instance_variables.rb:108:14:108:20 | [post] ( ... ) : Foo [@field] | provenance | |
| instance_variables.rb:99:18:99:18 | x [Return] : Foo [@field] | instance_variables.rb:113:14:113:26 | [post] ... = ... : Foo [@field] | provenance | |
| instance_variables.rb:100:5:100:5 | [post] x : Foo [@field] | instance_variables.rb:99:18:99:18 | x [Return] : Foo [@field] | provenance | |
| instance_variables.rb:100:17:100:25 | call to taint | captured_variables.rb:57:19:57:19 | x | provenance | |
| instance_variables.rb:100:17:100:25 | call to taint | instance_variables.rb:10:19:10:19 | x | provenance | |
@@ -253,11 +251,11 @@ edges
| instance_variables.rb:105:6:105:10 | foo11 : Foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | provenance | |
| instance_variables.rb:105:6:105:10 | foo11 : Foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | provenance | |
| instance_variables.rb:105:6:105:10 | foo11 : Foo [@field] | instance_variables.rb:105:6:105:20 | call to get_field | provenance | |
| instance_variables.rb:108:15:108:19 | [post] foo12 : Foo [@field] | instance_variables.rb:109:6:109:10 | foo12 : Foo [@field] | provenance | |
| instance_variables.rb:108:14:108:20 | [post] ( ... ) : Foo [@field] | instance_variables.rb:109:6:109:10 | foo12 : Foo [@field] | provenance | |
| instance_variables.rb:109:6:109:10 | foo12 : Foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | provenance | |
| instance_variables.rb:109:6:109:10 | foo12 : Foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | provenance | |
| instance_variables.rb:109:6:109:10 | foo12 : Foo [@field] | instance_variables.rb:109:6:109:20 | call to get_field | provenance | |
| instance_variables.rb:113:22:113:26 | [post] foo13 : Foo [@field] | instance_variables.rb:114:6:114:10 | foo13 : Foo [@field] | provenance | |
| instance_variables.rb:113:14:113:26 | [post] ... = ... : Foo [@field] | instance_variables.rb:114:6:114:10 | foo13 : Foo [@field] | provenance | |
| instance_variables.rb:114:6:114:10 | foo13 : Foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | provenance | |
| instance_variables.rb:114:6:114:10 | foo13 : Foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | provenance | |
| instance_variables.rb:114:6:114:10 | foo13 : Foo [@field] | instance_variables.rb:114:6:114:20 | call to get_field | provenance | |
@@ -475,11 +473,11 @@ nodes
| instance_variables.rb:70:16:70:24 | call to taint | semmle.label | call to taint |
| instance_variables.rb:71:6:71:9 | foo3 : Foo [@field] | semmle.label | foo3 : Foo [@field] |
| instance_variables.rb:71:6:71:15 | call to field | semmle.label | call to field |
| instance_variables.rb:78:2:78:5 | [post] foo5 : Foo [@field] | semmle.label | [post] foo5 : Foo [@field] |
| instance_variables.rb:78:1:78:6 | [post] ( ... ) : Foo [@field] | semmle.label | [post] ( ... ) : Foo [@field] |
| instance_variables.rb:78:18:78:26 | call to taint | semmle.label | call to taint |
| instance_variables.rb:79:6:79:9 | foo5 : Foo [@field] | semmle.label | foo5 : Foo [@field] |
| instance_variables.rb:79:6:79:19 | call to get_field | semmle.label | call to get_field |
| instance_variables.rb:82:15:82:18 | [post] foo6 : Foo [@field] | semmle.label | [post] foo6 : Foo [@field] |
| instance_variables.rb:82:1:82:20 | [post] ( ... ) : Foo [@field] | semmle.label | [post] ( ... ) : Foo [@field] |
| instance_variables.rb:82:32:82:40 | call to taint | semmle.label | call to taint |
| instance_variables.rb:83:6:83:9 | foo3 : Foo [@field] | semmle.label | foo3 : Foo [@field] |
| instance_variables.rb:83:6:83:19 | call to get_field | semmle.label | call to get_field |
@@ -487,15 +485,13 @@ nodes
| instance_variables.rb:84:6:84:19 | call to get_field | semmle.label | call to get_field |
| instance_variables.rb:85:6:85:9 | foo6 : Foo [@field] | semmle.label | foo6 : Foo [@field] |
| instance_variables.rb:85:6:85:19 | call to get_field | semmle.label | call to get_field |
| instance_variables.rb:89:15:89:18 | [post] foo7 : Foo [@field] | semmle.label | [post] foo7 : Foo [@field] |
| instance_variables.rb:89:25:89:28 | [post] foo8 : Foo [@field] | semmle.label | [post] foo8 : Foo [@field] |
| instance_variables.rb:89:1:89:33 | [post] ( ... ) : Foo [@field] | semmle.label | [post] ( ... ) : Foo [@field] |
| instance_variables.rb:89:45:89:53 | call to taint | semmle.label | call to taint |
| instance_variables.rb:90:6:90:9 | foo7 : Foo [@field] | semmle.label | foo7 : Foo [@field] |
| instance_variables.rb:90:6:90:19 | call to get_field | semmle.label | call to get_field |
| instance_variables.rb:91:6:91:9 | foo8 : Foo [@field] | semmle.label | foo8 : Foo [@field] |
| instance_variables.rb:91:6:91:19 | call to get_field | semmle.label | call to get_field |
| instance_variables.rb:95:22:95:25 | [post] foo9 : Foo [@field] | semmle.label | [post] foo9 : Foo [@field] |
| instance_variables.rb:95:32:95:36 | [post] foo10 : Foo [@field] | semmle.label | [post] foo10 : Foo [@field] |
| instance_variables.rb:95:1:95:41 | [post] ( ... ) : Foo [@field] | semmle.label | [post] ( ... ) : Foo [@field] |
| instance_variables.rb:95:53:95:61 | call to taint | semmle.label | call to taint |
| instance_variables.rb:96:6:96:9 | foo9 : Foo [@field] | semmle.label | foo9 : Foo [@field] |
| instance_variables.rb:96:6:96:19 | call to get_field | semmle.label | call to get_field |
@@ -507,10 +503,10 @@ nodes
| instance_variables.rb:104:14:104:18 | [post] foo11 : Foo [@field] | semmle.label | [post] foo11 : Foo [@field] |
| instance_variables.rb:105:6:105:10 | foo11 : Foo [@field] | semmle.label | foo11 : Foo [@field] |
| instance_variables.rb:105:6:105:20 | call to get_field | semmle.label | call to get_field |
| instance_variables.rb:108:15:108:19 | [post] foo12 : Foo [@field] | semmle.label | [post] foo12 : Foo [@field] |
| instance_variables.rb:108:14:108:20 | [post] ( ... ) : Foo [@field] | semmle.label | [post] ( ... ) : Foo [@field] |
| instance_variables.rb:109:6:109:10 | foo12 : Foo [@field] | semmle.label | foo12 : Foo [@field] |
| instance_variables.rb:109:6:109:20 | call to get_field | semmle.label | call to get_field |
| instance_variables.rb:113:22:113:26 | [post] foo13 : Foo [@field] | semmle.label | [post] foo13 : Foo [@field] |
| instance_variables.rb:113:14:113:26 | [post] ... = ... : Foo [@field] | semmle.label | [post] ... = ... : Foo [@field] |
| instance_variables.rb:114:6:114:10 | foo13 : Foo [@field] | semmle.label | foo13 : Foo [@field] |
| instance_variables.rb:114:6:114:20 | call to get_field | semmle.label | call to get_field |
| instance_variables.rb:116:1:116:5 | foo15 : Foo [@field] | semmle.label | foo15 : Foo [@field] |
@@ -565,30 +561,26 @@ subpaths
| instance_variables.rb:67:6:67:9 | foo2 [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | instance_variables.rb:14:9:14:21 | return | instance_variables.rb:67:6:67:19 | call to get_field |
| instance_variables.rb:70:16:70:24 | call to taint | captured_variables.rb:57:19:57:19 | x | captured_variables.rb:57:5:59:7 | self in set_field [Return] : Foo [@field] | instance_variables.rb:70:1:70:4 | [post] foo3 : Foo [@field] |
| instance_variables.rb:70:16:70:24 | call to taint | instance_variables.rb:10:19:10:19 | x | instance_variables.rb:10:5:12:7 | self in set_field [Return] : Foo [@field] | instance_variables.rb:70:1:70:4 | [post] foo3 : Foo [@field] |
| instance_variables.rb:78:18:78:26 | call to taint | captured_variables.rb:57:19:57:19 | x | captured_variables.rb:57:5:59:7 | self in set_field [Return] : Foo [@field] | instance_variables.rb:78:2:78:5 | [post] foo5 : Foo [@field] |
| instance_variables.rb:78:18:78:26 | call to taint | instance_variables.rb:10:19:10:19 | x | instance_variables.rb:10:5:12:7 | self in set_field [Return] : Foo [@field] | instance_variables.rb:78:2:78:5 | [post] foo5 : Foo [@field] |
| instance_variables.rb:78:18:78:26 | call to taint | captured_variables.rb:57:19:57:19 | x | captured_variables.rb:57:5:59:7 | self in set_field [Return] : Foo [@field] | instance_variables.rb:78:1:78:6 | [post] ( ... ) : Foo [@field] |
| instance_variables.rb:78:18:78:26 | call to taint | instance_variables.rb:10:19:10:19 | x | instance_variables.rb:10:5:12:7 | self in set_field [Return] : Foo [@field] | instance_variables.rb:78:1:78:6 | [post] ( ... ) : Foo [@field] |
| instance_variables.rb:79:6:79:9 | foo5 : Foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | captured_variables.rb:61:9:61:21 | return | instance_variables.rb:79:6:79:19 | call to get_field |
| instance_variables.rb:79:6:79:9 | foo5 : Foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | instance_variables.rb:14:9:14:21 | return | instance_variables.rb:79:6:79:19 | call to get_field |
| instance_variables.rb:82:32:82:40 | call to taint | captured_variables.rb:57:19:57:19 | x | captured_variables.rb:57:5:59:7 | self in set_field [Return] : Foo [@field] | instance_variables.rb:82:15:82:18 | [post] foo6 : Foo [@field] |
| instance_variables.rb:82:32:82:40 | call to taint | instance_variables.rb:10:19:10:19 | x | instance_variables.rb:10:5:12:7 | self in set_field [Return] : Foo [@field] | instance_variables.rb:82:15:82:18 | [post] foo6 : Foo [@field] |
| instance_variables.rb:82:32:82:40 | call to taint | captured_variables.rb:57:19:57:19 | x | captured_variables.rb:57:5:59:7 | self in set_field [Return] : Foo [@field] | instance_variables.rb:82:1:82:20 | [post] ( ... ) : Foo [@field] |
| instance_variables.rb:82:32:82:40 | call to taint | instance_variables.rb:10:19:10:19 | x | instance_variables.rb:10:5:12:7 | self in set_field [Return] : Foo [@field] | instance_variables.rb:82:1:82:20 | [post] ( ... ) : Foo [@field] |
| instance_variables.rb:83:6:83:9 | foo3 : Foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | captured_variables.rb:61:9:61:21 | return | instance_variables.rb:83:6:83:19 | call to get_field |
| instance_variables.rb:83:6:83:9 | foo3 : Foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | instance_variables.rb:14:9:14:21 | return | instance_variables.rb:83:6:83:19 | call to get_field |
| instance_variables.rb:84:6:84:9 | foo5 : Foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | captured_variables.rb:61:9:61:21 | return | instance_variables.rb:84:6:84:19 | call to get_field |
| instance_variables.rb:84:6:84:9 | foo5 : Foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | instance_variables.rb:14:9:14:21 | return | instance_variables.rb:84:6:84:19 | call to get_field |
| instance_variables.rb:85:6:85:9 | foo6 : Foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | captured_variables.rb:61:9:61:21 | return | instance_variables.rb:85:6:85:19 | call to get_field |
| instance_variables.rb:85:6:85:9 | foo6 : Foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | instance_variables.rb:14:9:14:21 | return | instance_variables.rb:85:6:85:19 | call to get_field |
| instance_variables.rb:89:45:89:53 | call to taint | captured_variables.rb:57:19:57:19 | x | captured_variables.rb:57:5:59:7 | self in set_field [Return] : Foo [@field] | instance_variables.rb:89:15:89:18 | [post] foo7 : Foo [@field] |
| instance_variables.rb:89:45:89:53 | call to taint | captured_variables.rb:57:19:57:19 | x | captured_variables.rb:57:5:59:7 | self in set_field [Return] : Foo [@field] | instance_variables.rb:89:25:89:28 | [post] foo8 : Foo [@field] |
| instance_variables.rb:89:45:89:53 | call to taint | instance_variables.rb:10:19:10:19 | x | instance_variables.rb:10:5:12:7 | self in set_field [Return] : Foo [@field] | instance_variables.rb:89:15:89:18 | [post] foo7 : Foo [@field] |
| instance_variables.rb:89:45:89:53 | call to taint | instance_variables.rb:10:19:10:19 | x | instance_variables.rb:10:5:12:7 | self in set_field [Return] : Foo [@field] | instance_variables.rb:89:25:89:28 | [post] foo8 : Foo [@field] |
| instance_variables.rb:89:45:89:53 | call to taint | captured_variables.rb:57:19:57:19 | x | captured_variables.rb:57:5:59:7 | self in set_field [Return] : Foo [@field] | instance_variables.rb:89:1:89:33 | [post] ( ... ) : Foo [@field] |
| instance_variables.rb:89:45:89:53 | call to taint | instance_variables.rb:10:19:10:19 | x | instance_variables.rb:10:5:12:7 | self in set_field [Return] : Foo [@field] | instance_variables.rb:89:1:89:33 | [post] ( ... ) : Foo [@field] |
| instance_variables.rb:90:6:90:9 | foo7 : Foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | captured_variables.rb:61:9:61:21 | return | instance_variables.rb:90:6:90:19 | call to get_field |
| instance_variables.rb:90:6:90:9 | foo7 : Foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | instance_variables.rb:14:9:14:21 | return | instance_variables.rb:90:6:90:19 | call to get_field |
| instance_variables.rb:91:6:91:9 | foo8 : Foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | captured_variables.rb:61:9:61:21 | return | instance_variables.rb:91:6:91:19 | call to get_field |
| instance_variables.rb:91:6:91:9 | foo8 : Foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | instance_variables.rb:14:9:14:21 | return | instance_variables.rb:91:6:91:19 | call to get_field |
| instance_variables.rb:95:53:95:61 | call to taint | captured_variables.rb:57:19:57:19 | x | captured_variables.rb:57:5:59:7 | self in set_field [Return] : Foo [@field] | instance_variables.rb:95:22:95:25 | [post] foo9 : Foo [@field] |
| instance_variables.rb:95:53:95:61 | call to taint | captured_variables.rb:57:19:57:19 | x | captured_variables.rb:57:5:59:7 | self in set_field [Return] : Foo [@field] | instance_variables.rb:95:32:95:36 | [post] foo10 : Foo [@field] |
| instance_variables.rb:95:53:95:61 | call to taint | instance_variables.rb:10:19:10:19 | x | instance_variables.rb:10:5:12:7 | self in set_field [Return] : Foo [@field] | instance_variables.rb:95:22:95:25 | [post] foo9 : Foo [@field] |
| instance_variables.rb:95:53:95:61 | call to taint | instance_variables.rb:10:19:10:19 | x | instance_variables.rb:10:5:12:7 | self in set_field [Return] : Foo [@field] | instance_variables.rb:95:32:95:36 | [post] foo10 : Foo [@field] |
| instance_variables.rb:95:53:95:61 | call to taint | captured_variables.rb:57:19:57:19 | x | captured_variables.rb:57:5:59:7 | self in set_field [Return] : Foo [@field] | instance_variables.rb:95:1:95:41 | [post] ( ... ) : Foo [@field] |
| instance_variables.rb:95:53:95:61 | call to taint | instance_variables.rb:10:19:10:19 | x | instance_variables.rb:10:5:12:7 | self in set_field [Return] : Foo [@field] | instance_variables.rb:95:1:95:41 | [post] ( ... ) : Foo [@field] |
| instance_variables.rb:96:6:96:9 | foo9 : Foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | captured_variables.rb:61:9:61:21 | return | instance_variables.rb:96:6:96:19 | call to get_field |
| instance_variables.rb:96:6:96:9 | foo9 : Foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field : Foo [@field] | instance_variables.rb:14:9:14:21 | return | instance_variables.rb:96:6:96:19 | call to get_field |
| instance_variables.rb:97:6:97:10 | foo10 : Foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field : Foo [@field] | captured_variables.rb:61:9:61:21 | return | instance_variables.rb:97:6:97:20 | call to get_field |

View File

@@ -2910,6 +2910,8 @@
| local_dataflow.rb:141:19:141:37 | [false] ( ... ) | local_dataflow.rb:141:8:141:37 | [false] ... \|\| ... |
| local_dataflow.rb:141:19:141:37 | [input] SSA phi read(self) | local_dataflow.rb:141:38:142:9 | [input] SSA phi read(self) |
| local_dataflow.rb:141:19:141:37 | [input] SSA phi read(x) | local_dataflow.rb:141:38:142:9 | [input] SSA phi read(x) |
| local_dataflow.rb:141:19:141:37 | [post] [false] ( ... ) | local_dataflow.rb:141:20:141:36 | [post] [false] ... && ... |
| local_dataflow.rb:141:19:141:37 | [post] [true] ( ... ) | local_dataflow.rb:141:20:141:36 | [post] [true] ... && ... |
| local_dataflow.rb:141:19:141:37 | [true] ( ... ) | local_dataflow.rb:141:8:141:37 | [true] ... \|\| ... |
| local_dataflow.rb:141:20:141:25 | [input] SSA phi read(self) | local_dataflow.rb:143:11:143:16 | self |
| local_dataflow.rb:141:20:141:25 | [input] SSA phi read(x) | local_dataflow.rb:143:15:143:15 | x |

View File

@@ -3405,6 +3405,8 @@
| local_dataflow.rb:141:19:141:37 | [false] ( ... ) | local_dataflow.rb:141:8:141:37 | [false] ... \|\| ... |
| local_dataflow.rb:141:19:141:37 | [input] SSA phi read(self) | local_dataflow.rb:141:38:142:9 | [input] SSA phi read(self) |
| local_dataflow.rb:141:19:141:37 | [input] SSA phi read(x) | local_dataflow.rb:141:38:142:9 | [input] SSA phi read(x) |
| local_dataflow.rb:141:19:141:37 | [post] [false] ( ... ) | local_dataflow.rb:141:20:141:36 | [post] [false] ... && ... |
| local_dataflow.rb:141:19:141:37 | [post] [true] ( ... ) | local_dataflow.rb:141:20:141:36 | [post] [true] ... && ... |
| local_dataflow.rb:141:19:141:37 | [true] ( ... ) | local_dataflow.rb:141:8:141:37 | [true] ... \|\| ... |
| local_dataflow.rb:141:20:141:25 | [input] SSA phi read(self) | local_dataflow.rb:143:11:143:16 | self |
| local_dataflow.rb:141:20:141:25 | [input] SSA phi read(x) | local_dataflow.rb:143:15:143:15 | x |

File diff suppressed because it is too large Load Diff

View File

@@ -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 |

View File

@@ -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

View File

@@ -0,0 +1 @@
| DeadStoreOfLocal.rb:2:5:2:5 | y | This assignment to $@ is useless, since its value is never read. | DeadStoreOfLocal.rb:2:5:2:5 | y | y |

View File

@@ -0,0 +1,2 @@
query: queries/variables/DeadStoreOfLocal.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -0,0 +1,36 @@
def test_basic(x)
y = x #$ Alert
y = x + 2
return y
end
def test_retry
x = 0
begin
if x == 0
raise "error"
end
rescue
x = 2 # OK - the retry will allow a later read
retry
end
return 42
end
def test_binding
x = 4 # OK - the binding collects the value of x
return binding
end
class Sup
def m(x)
print(x + 1)
end
end
class Sub < Sup
def m(y)
y = 3 # OK - the call to `super` sees the value of `y``
super
end
end

View File

@@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
require 'erb'
template = ERB.new <<EOF
<%#-*- coding: Big5 -*-%>
\_\_ENCODING\_\_ is <%= \_\_ENCODING\_\_ %>.
x is <%= x %>.
EOF
x = 5 # OK - the template can see the value of x
puts template.result

View File

@@ -0,0 +1,4 @@
| UninitializedLocal.rb:12:3:12:3 | m | Local variable $@ may be used before it is initialized. | UninitializedLocal.rb:8:7:8:7 | m | m |
| UninitializedLocal.rb:34:5:34:5 | b | Local variable $@ may be used before it is initialized. | UninitializedLocal.rb:27:9:27:9 | b | b |
| UninitializedLocal.rb:34:23:34:23 | b | Local variable $@ may be used before it is initialized. | UninitializedLocal.rb:27:9:27:9 | b | b |
| UninitializedLocal.rb:76:5:76:5 | i | Local variable $@ may be used before it is initialized. | UninitializedLocal.rb:73:9:73:9 | i | i |

View File

@@ -0,0 +1,2 @@
query: queries/variables/UninitializedLocal.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -0,0 +1,77 @@
def m
puts "m"
end
def foo
m # calls m above
if false
m = "0"
m # reads local variable m
else
end
m.strip #$ Alert
m2 # undefined local variable or method 'm2' for main (NameError)
end
def test_guards
if (a = "3" && a) # OK - a is in a Boolean context
a.strip
end
if (a = "3") && a # OK - a is assigned in the previous conjunct
a.strip
end
if !(a = "3") or a # OK - a is assigned in the previous conjunct
a.strip
end
if false
b = "0"
end
b.nil?
b || 0 # OK
b&.strip # OK - safe navigation
b.strip if b # OK
b.close if b && !b.closed # OK
b.blowup if b || !b.blownup #$ Alert
if false
c = "0"
end
unless c
return
end
c.strip # OK - given above unless
if false
d = "0"
end
if (d.nil?)
return
end
d.strip # OK - given above check
if false
e = "0"
end
unless (!e.nil?)
return
end
e.strip # OK - given above unless
end
def test_loop
begin
if false
a = 0
else
set_a
end
end until a # OK
a.strip # OK - given previous until
end
def test_for
for i in ["foo", "bar"] # OK - since 0..10 cannot raise
puts i.strip
end
i.strip #$ SPURIOUS: Alert
end