diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll index d6c1bad2744d..da828337e562 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll @@ -32,6 +32,12 @@ module Consistency { /** Holds if `n` should be excluded from the consistency test `reverseRead`. */ predicate reverseReadExclude(Node n) { none() } + + /** Holds if `n` should be excluded from the consistency test `postHasUniquePre`. */ + predicate postHasUniquePreExclude(PostUpdateNode n) { none() } + + /** Holds if `n` should be excluded from the consistency test `uniquePostUpdate`. */ + predicate uniquePostUpdateExclude(Node n) { none() } } private class RelevantNode extends Node { @@ -166,6 +172,7 @@ module Consistency { } query predicate postHasUniquePre(PostUpdateNode n, string msg) { + not any(ConsistencyConfiguration conf).postHasUniquePreExclude(n) and exists(int c | c = count(n.getPreUpdateNode()) and c != 1 and @@ -174,6 +181,7 @@ module Consistency { } query predicate uniquePostUpdate(Node n, string msg) { + not any(ConsistencyConfiguration conf).uniquePostUpdateExclude(n) and 1 < strictcount(PostUpdateNode post | post.getPreUpdateNode() = n) and msg = "Node has multiple PostUpdateNodes." } diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplConsistency.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplConsistency.qll index d6c1bad2744d..da828337e562 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplConsistency.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplConsistency.qll @@ -32,6 +32,12 @@ module Consistency { /** Holds if `n` should be excluded from the consistency test `reverseRead`. */ predicate reverseReadExclude(Node n) { none() } + + /** Holds if `n` should be excluded from the consistency test `postHasUniquePre`. */ + predicate postHasUniquePreExclude(PostUpdateNode n) { none() } + + /** Holds if `n` should be excluded from the consistency test `uniquePostUpdate`. */ + predicate uniquePostUpdateExclude(Node n) { none() } } private class RelevantNode extends Node { @@ -166,6 +172,7 @@ module Consistency { } query predicate postHasUniquePre(PostUpdateNode n, string msg) { + not any(ConsistencyConfiguration conf).postHasUniquePreExclude(n) and exists(int c | c = count(n.getPreUpdateNode()) and c != 1 and @@ -174,6 +181,7 @@ module Consistency { } query predicate uniquePostUpdate(Node n, string msg) { + not any(ConsistencyConfiguration conf).uniquePostUpdateExclude(n) and 1 < strictcount(PostUpdateNode post | post.getPreUpdateNode() = n) and msg = "Node has multiple PostUpdateNodes." } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll index d6c1bad2744d..da828337e562 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll @@ -32,6 +32,12 @@ module Consistency { /** Holds if `n` should be excluded from the consistency test `reverseRead`. */ predicate reverseReadExclude(Node n) { none() } + + /** Holds if `n` should be excluded from the consistency test `postHasUniquePre`. */ + predicate postHasUniquePreExclude(PostUpdateNode n) { none() } + + /** Holds if `n` should be excluded from the consistency test `uniquePostUpdate`. */ + predicate uniquePostUpdateExclude(Node n) { none() } } private class RelevantNode extends Node { @@ -166,6 +172,7 @@ module Consistency { } query predicate postHasUniquePre(PostUpdateNode n, string msg) { + not any(ConsistencyConfiguration conf).postHasUniquePreExclude(n) and exists(int c | c = count(n.getPreUpdateNode()) and c != 1 and @@ -174,6 +181,7 @@ module Consistency { } query predicate uniquePostUpdate(Node n, string msg) { + not any(ConsistencyConfiguration conf).uniquePostUpdateExclude(n) and 1 < strictcount(PostUpdateNode post | post.getPreUpdateNode() = n) and msg = "Node has multiple PostUpdateNodes." } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll index d6c1bad2744d..da828337e562 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll @@ -32,6 +32,12 @@ module Consistency { /** Holds if `n` should be excluded from the consistency test `reverseRead`. */ predicate reverseReadExclude(Node n) { none() } + + /** Holds if `n` should be excluded from the consistency test `postHasUniquePre`. */ + predicate postHasUniquePreExclude(PostUpdateNode n) { none() } + + /** Holds if `n` should be excluded from the consistency test `uniquePostUpdate`. */ + predicate uniquePostUpdateExclude(Node n) { none() } } private class RelevantNode extends Node { @@ -166,6 +172,7 @@ module Consistency { } query predicate postHasUniquePre(PostUpdateNode n, string msg) { + not any(ConsistencyConfiguration conf).postHasUniquePreExclude(n) and exists(int c | c = count(n.getPreUpdateNode()) and c != 1 and @@ -174,6 +181,7 @@ module Consistency { } query predicate uniquePostUpdate(Node n, string msg) { + not any(ConsistencyConfiguration conf).uniquePostUpdateExclude(n) and 1 < strictcount(PostUpdateNode post | post.getPreUpdateNode() = n) and msg = "Node has multiple PostUpdateNodes." } diff --git a/docs/ql-libraries/dataflow/dataflow.md b/docs/ql-libraries/dataflow/dataflow.md index 1b6d52ee994b..5cbe00a087fd 100644 --- a/docs/ql-libraries/dataflow/dataflow.md +++ b/docs/ql-libraries/dataflow/dataflow.md @@ -294,7 +294,10 @@ through an additional step targeting a `PostUpdateNode`). It is recommended to introduce `PostUpdateNode`s for all `ArgumentNode`s (this can be skipped for immutable arguments), and all field qualifiers for both -reads and stores. +reads and stores. Note also that in the case of compund arguments, such as +`b ? x : y`, it is recommented to have post-update nodes for `x` and `y` (and +not the compound argument itself), and let `[post update] x` have both `x` +and `b ? x : y` as pre-update nodes (and similarly for `[post update] y`). Remember to define local flow for `PostUpdateNode`s as well in `simpleLocalFlowStep`. In general out-going local flow from `PostUpdateNode`s diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll index d6c1bad2744d..da828337e562 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll @@ -32,6 +32,12 @@ module Consistency { /** Holds if `n` should be excluded from the consistency test `reverseRead`. */ predicate reverseReadExclude(Node n) { none() } + + /** Holds if `n` should be excluded from the consistency test `postHasUniquePre`. */ + predicate postHasUniquePreExclude(PostUpdateNode n) { none() } + + /** Holds if `n` should be excluded from the consistency test `uniquePostUpdate`. */ + predicate uniquePostUpdateExclude(Node n) { none() } } private class RelevantNode extends Node { @@ -166,6 +172,7 @@ module Consistency { } query predicate postHasUniquePre(PostUpdateNode n, string msg) { + not any(ConsistencyConfiguration conf).postHasUniquePreExclude(n) and exists(int c | c = count(n.getPreUpdateNode()) and c != 1 and @@ -174,6 +181,7 @@ module Consistency { } query predicate uniquePostUpdate(Node n, string msg) { + not any(ConsistencyConfiguration conf).uniquePostUpdateExclude(n) and 1 < strictcount(PostUpdateNode post | post.getPreUpdateNode() = n) and msg = "Node has multiple PostUpdateNodes." } diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplConsistency.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplConsistency.qll index d6c1bad2744d..da828337e562 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplConsistency.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplConsistency.qll @@ -32,6 +32,12 @@ module Consistency { /** Holds if `n` should be excluded from the consistency test `reverseRead`. */ predicate reverseReadExclude(Node n) { none() } + + /** Holds if `n` should be excluded from the consistency test `postHasUniquePre`. */ + predicate postHasUniquePreExclude(PostUpdateNode n) { none() } + + /** Holds if `n` should be excluded from the consistency test `uniquePostUpdate`. */ + predicate uniquePostUpdateExclude(Node n) { none() } } private class RelevantNode extends Node { @@ -166,6 +172,7 @@ module Consistency { } query predicate postHasUniquePre(PostUpdateNode n, string msg) { + not any(ConsistencyConfiguration conf).postHasUniquePreExclude(n) and exists(int c | c = count(n.getPreUpdateNode()) and c != 1 and @@ -174,6 +181,7 @@ module Consistency { } query predicate uniquePostUpdate(Node n, string msg) { + not any(ConsistencyConfiguration conf).uniquePostUpdateExclude(n) and 1 < strictcount(PostUpdateNode post | post.getPreUpdateNode() = n) and msg = "Node has multiple PostUpdateNodes." } diff --git a/ruby/ql/consistency-queries/DataFlowConsistency.ql b/ruby/ql/consistency-queries/DataFlowConsistency.ql index 87fb4650b0d5..67f30db5261b 100644 --- a/ruby/ql/consistency-queries/DataFlowConsistency.ql +++ b/ruby/ql/consistency-queries/DataFlowConsistency.ql @@ -1,4 +1,5 @@ import codeql.ruby.AST +import codeql.ruby.CFG import codeql.ruby.DataFlow::DataFlow import codeql.ruby.dataflow.internal.DataFlowPrivate import codeql.ruby.dataflow.internal.DataFlowImplConsistency::Consistency @@ -13,6 +14,22 @@ private class MyConsistencyConfiguration extends ConsistencyConfiguration { or n instanceof SynthHashSplatArgumentNode or - not isNonConstantExpr(n.asExpr()) + not isNonConstantExpr(getAPostUpdateNodeForArg(n.asExpr())) + } + + override predicate postHasUniquePreExclude(PostUpdateNode n) { + exists(CfgNodes::ExprCfgNode e, CfgNodes::ExprCfgNode arg | + e = getAPostUpdateNodeForArg(arg) and + e != arg and + n = TExprPostUpdateNode(e) + ) + } + + override predicate uniquePostUpdateExclude(Node n) { + exists(CfgNodes::ExprCfgNode e, CfgNodes::ExprCfgNode arg | + e = getAPostUpdateNodeForArg(arg) and + e != arg and + n.asExpr() = arg + ) } } diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplConsistency.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplConsistency.qll index d6c1bad2744d..da828337e562 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplConsistency.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplConsistency.qll @@ -32,6 +32,12 @@ module Consistency { /** Holds if `n` should be excluded from the consistency test `reverseRead`. */ predicate reverseReadExclude(Node n) { none() } + + /** Holds if `n` should be excluded from the consistency test `postHasUniquePre`. */ + predicate postHasUniquePreExclude(PostUpdateNode n) { none() } + + /** Holds if `n` should be excluded from the consistency test `uniquePostUpdate`. */ + predicate uniquePostUpdateExclude(Node n) { none() } } private class RelevantNode extends Node { @@ -166,6 +172,7 @@ module Consistency { } query predicate postHasUniquePre(PostUpdateNode n, string msg) { + not any(ConsistencyConfiguration conf).postHasUniquePreExclude(n) and exists(int c | c = count(n.getPreUpdateNode()) and c != 1 and @@ -174,6 +181,7 @@ module Consistency { } query predicate uniquePostUpdate(Node n, string msg) { + not any(ConsistencyConfiguration conf).uniquePostUpdateExclude(n) and 1 < strictcount(PostUpdateNode post | post.getPreUpdateNode() = n) and msg = "Node has multiple PostUpdateNodes." } diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll index 34d737e8c975..c0ac31de3ed8 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll @@ -43,6 +43,32 @@ private class ExprNodeImpl extends ExprNode, NodeImpl { override string toStringImpl() { result = this.getExprNode().toString() } } +/** + * Gets a node that may execute last in `n`, and which, when it executes last, + * will be the value of `n`. + */ +private CfgNodes::ExprCfgNode getALastEvalNode(CfgNodes::ExprCfgNode n) { + result = n.(CfgNodes::ExprNodes::StmtSequenceCfgNode).getLastStmt() + or + result = n.(CfgNodes::ExprNodes::ConditionalExprCfgNode).getBranch(_) + or + exists(CfgNodes::AstCfgNode branch | + branch = n.(CfgNodes::ExprNodes::CaseExprCfgNode).getBranch(_) + | + result = branch.(CfgNodes::ExprNodes::InClauseCfgNode).getBody() + or + result = branch.(CfgNodes::ExprNodes::WhenClauseCfgNode).getBody() + or + result = branch + ) +} + +/** 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)) +} + /** Provides predicates related to local data flow. */ module LocalFlow { private import codeql.ruby.dataflow.internal.SsaImpl @@ -135,19 +161,7 @@ module LocalFlow { or nodeFrom.asExpr() = nodeTo.asExpr().(CfgNodes::ExprNodes::BlockArgumentCfgNode).getValue() or - nodeFrom.asExpr() = nodeTo.asExpr().(CfgNodes::ExprNodes::StmtSequenceCfgNode).getLastStmt() - or - nodeFrom.asExpr() = nodeTo.asExpr().(CfgNodes::ExprNodes::ConditionalExprCfgNode).getBranch(_) - or - exists(CfgNodes::AstCfgNode branch | - branch = nodeTo.asExpr().(CfgNodes::ExprNodes::CaseExprCfgNode).getBranch(_) - | - nodeFrom.asExpr() = branch.(CfgNodes::ExprNodes::InClauseCfgNode).getBody() - or - nodeFrom.asExpr() = branch.(CfgNodes::ExprNodes::WhenClauseCfgNode).getBody() - or - nodeFrom.asExpr() = branch - ) + nodeFrom.asExpr() = getALastEvalNode(nodeTo.asExpr()) or exists(CfgNodes::ExprCfgNode exprTo, ReturningStatementNode n | nodeFrom = n and @@ -241,7 +255,8 @@ private module Cached { // filter out nodes that clearly don't need post-update nodes isNonConstantExpr(n) and ( - n instanceof Argument or + n = getAPostUpdateNodeForArg(_) + or n = any(CfgNodes::ExprNodes::InstanceVariableAccessCfgNode v).getReceiver() ) } or @@ -1127,7 +1142,18 @@ private module PostUpdateNodes { ExprPostUpdateNode() { this = TExprPostUpdateNode(e) } - override ExprNode getPreUpdateNode() { e = result.getExprNode() } + override ExprNode getPreUpdateNode() { + // For compund 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 compund 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 CfgScope getCfgScope() { result = e.getExpr().getCfgScope() } diff --git a/ruby/ql/test/library-tests/dataflow/global/Flow.expected b/ruby/ql/test/library-tests/dataflow/global/Flow.expected index 52d23cdaa65d..e124df458869 100644 --- a/ruby/ql/test/library-tests/dataflow/global/Flow.expected +++ b/ruby/ql/test/library-tests/dataflow/global/Flow.expected @@ -1,137 +1,337 @@ failures edges -| instance_variables.rb:2:19:2:19 | x : | instance_variables.rb:3:18:3:18 | x : | -| instance_variables.rb:2:19:2:19 | x : | instance_variables.rb:3:18:3:18 | x : | -| instance_variables.rb:3:18:3:18 | x : | instance_variables.rb:3:9:3:14 | [post] self [@field] : | -| instance_variables.rb:3:18:3:18 | x : | instance_variables.rb:3:9:3:14 | [post] self [@field] : | -| instance_variables.rb:5:5:7:7 | self in get_field [@field] : | instance_variables.rb:6:16:6:21 | self [@field] : | -| instance_variables.rb:5:5:7:7 | self in get_field [@field] : | instance_variables.rb:6:16:6:21 | self [@field] : | -| instance_variables.rb:6:16:6:21 | @field : | instance_variables.rb:6:9:6:21 | return : | -| instance_variables.rb:6:16:6:21 | @field : | instance_variables.rb:6:9:6:21 | return : | -| instance_variables.rb:6:16:6:21 | self [@field] : | instance_variables.rb:6:16:6:21 | @field : | -| instance_variables.rb:6:16:6:21 | self [@field] : | instance_variables.rb:6:16:6:21 | @field : | -| instance_variables.rb:8:5:10:7 | self in inc_field [@field] : | instance_variables.rb:9:9:9:14 | [post] self [@field] : | -| instance_variables.rb:9:9:9:14 | [post] self [@field] : | instance_variables.rb:9:9:9:14 | [post] self [@field] : | -| instance_variables.rb:11:5:11:8 | [post] self [@foo] : | instance_variables.rb:12:10:12:13 | self [@foo] : | -| instance_variables.rb:11:5:11:8 | [post] self [@foo] : | instance_variables.rb:12:10:12:13 | self [@foo] : | -| instance_variables.rb:11:12:11:22 | call to source : | instance_variables.rb:11:5:11:8 | [post] self [@foo] : | -| instance_variables.rb:11:12:11:22 | call to source : | instance_variables.rb:11:5:11:8 | [post] self [@foo] : | -| instance_variables.rb:12:10:12:13 | self [@foo] : | instance_variables.rb:12:10:12:13 | @foo | -| instance_variables.rb:12:10:12:13 | self [@foo] : | instance_variables.rb:12:10:12:13 | @foo | -| instance_variables.rb:16:1:16:3 | [post] foo [@field] : | instance_variables.rb:17:6:17:8 | foo [@field] : | -| instance_variables.rb:16:1:16:3 | [post] foo [@field] : | instance_variables.rb:17:6:17:8 | foo [@field] : | -| instance_variables.rb:16:15:16:24 | call to source : | instance_variables.rb:2:19:2:19 | x : | -| instance_variables.rb:16:15:16:24 | call to source : | instance_variables.rb:2:19:2:19 | x : | -| instance_variables.rb:16:15:16:24 | call to source : | instance_variables.rb:16:1:16:3 | [post] foo [@field] : | -| instance_variables.rb:16:15:16:24 | call to source : | instance_variables.rb:16:1:16:3 | [post] foo [@field] : | -| instance_variables.rb:17:6:17:8 | foo [@field] : | instance_variables.rb:5:5:7:7 | self in get_field [@field] : | -| instance_variables.rb:17:6:17:8 | foo [@field] : | instance_variables.rb:5:5:7:7 | self in get_field [@field] : | -| instance_variables.rb:17:6:17:8 | foo [@field] : | instance_variables.rb:17:6:17:18 | call to get_field | -| instance_variables.rb:17:6:17:8 | foo [@field] : | instance_variables.rb:17:6:17:18 | call to get_field | -| instance_variables.rb:20:1:20:3 | [post] bar [@field] : | instance_variables.rb:21:6:21:8 | bar [@field] : | -| instance_variables.rb:20:15:20:23 | call to source : | instance_variables.rb:2:19:2:19 | x : | -| instance_variables.rb:20:15:20:23 | call to source : | instance_variables.rb:20:1:20:3 | [post] bar [@field] : | -| instance_variables.rb:21:6:21:8 | bar [@field] : | instance_variables.rb:8:5:10:7 | self in inc_field [@field] : | -| instance_variables.rb:21:6:21:8 | bar [@field] : | instance_variables.rb:21:6:21:18 | call to inc_field | -| instance_variables.rb:24:1:24:4 | [post] foo1 [@field] : | instance_variables.rb:25:6:25:9 | foo1 [@field] : | -| instance_variables.rb:24:1:24:4 | [post] foo1 [@field] : | instance_variables.rb:25:6:25:9 | foo1 [@field] : | -| instance_variables.rb:24:14:24:23 | call to source : | instance_variables.rb:24:1:24:4 | [post] foo1 [@field] : | -| instance_variables.rb:24:14:24:23 | call to source : | instance_variables.rb:24:1:24:4 | [post] foo1 [@field] : | -| instance_variables.rb:25:6:25:9 | foo1 [@field] : | instance_variables.rb:25:6:25:15 | call to field | -| instance_variables.rb:25:6:25:9 | foo1 [@field] : | instance_variables.rb:25:6:25:15 | call to field | -| instance_variables.rb:28:1:28:4 | [post] foo2 [@field] : | instance_variables.rb:29:6:29:9 | foo2 [@field] : | -| instance_variables.rb:28:1:28:4 | [post] foo2 [@field] : | instance_variables.rb:29:6:29:9 | foo2 [@field] : | -| instance_variables.rb:28:14:28:23 | call to source : | instance_variables.rb:28:1:28:4 | [post] foo2 [@field] : | -| instance_variables.rb:28:14:28:23 | call to source : | instance_variables.rb:28:1:28:4 | [post] foo2 [@field] : | -| instance_variables.rb:29:6:29:9 | foo2 [@field] : | instance_variables.rb:5:5:7:7 | self in get_field [@field] : | -| instance_variables.rb:29:6:29:9 | foo2 [@field] : | instance_variables.rb:5:5:7:7 | self in get_field [@field] : | -| instance_variables.rb:29:6:29:9 | foo2 [@field] : | instance_variables.rb:29:6:29:19 | call to get_field | -| instance_variables.rb:29:6:29:9 | foo2 [@field] : | instance_variables.rb:29:6:29:19 | call to get_field | -| instance_variables.rb:32:1:32:4 | [post] foo3 [@field] : | instance_variables.rb:33:6:33:9 | foo3 [@field] : | -| instance_variables.rb:32:1:32:4 | [post] foo3 [@field] : | instance_variables.rb:33:6:33:9 | foo3 [@field] : | -| instance_variables.rb:32:16:32:25 | call to source : | instance_variables.rb:2:19:2:19 | x : | -| instance_variables.rb:32:16:32:25 | call to source : | instance_variables.rb:2:19:2:19 | x : | -| instance_variables.rb:32:16:32:25 | call to source : | instance_variables.rb:32:1:32:4 | [post] foo3 [@field] : | -| instance_variables.rb:32:16:32:25 | call to source : | instance_variables.rb:32:1:32:4 | [post] foo3 [@field] : | -| instance_variables.rb:33:6:33:9 | foo3 [@field] : | instance_variables.rb:33:6:33:15 | call to field | -| instance_variables.rb:33:6:33:9 | foo3 [@field] : | instance_variables.rb:33:6:33:15 | call to field | +| instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:18:11:18 | x : | +| instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:18:11:18 | x : | +| instance_variables.rb:11:18:11:18 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | +| instance_variables.rb:11:18:11:18 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | +| instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:16:14:21 | self [@field] : | +| instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:16:14:21 | self [@field] : | +| instance_variables.rb:14:16:14:21 | @field : | instance_variables.rb:14:9:14:21 | return : | +| instance_variables.rb:14:16:14:21 | @field : | instance_variables.rb:14:9:14:21 | return : | +| instance_variables.rb:14:16:14:21 | self [@field] : | instance_variables.rb:14:16:14:21 | @field : | +| instance_variables.rb:14:16:14:21 | self [@field] : | instance_variables.rb:14:16:14:21 | @field : | +| instance_variables.rb:16:5:18:7 | self in inc_field [@field] : | instance_variables.rb:17:9:17:14 | [post] self [@field] : | +| instance_variables.rb:17:9:17:14 | [post] self [@field] : | instance_variables.rb:17:9:17:14 | [post] self [@field] : | +| instance_variables.rb:19:5:19:8 | [post] self [@foo] : | instance_variables.rb:20:10:20:13 | self [@foo] : | +| instance_variables.rb:19:5:19:8 | [post] self [@foo] : | instance_variables.rb:20:10:20:13 | self [@foo] : | +| instance_variables.rb:19:12:19:21 | call to taint : | instance_variables.rb:19:5:19:8 | [post] self [@foo] : | +| instance_variables.rb:19:12:19:21 | call to taint : | instance_variables.rb:19:5:19:8 | [post] self [@foo] : | +| instance_variables.rb:20:10:20:13 | self [@foo] : | instance_variables.rb:20:10:20:13 | @foo | +| instance_variables.rb:20:10:20:13 | self [@foo] : | instance_variables.rb:20:10:20:13 | @foo | +| instance_variables.rb:24:1:24:3 | [post] foo [@field] : | instance_variables.rb:25:6:25:8 | foo [@field] : | +| instance_variables.rb:24:1:24:3 | [post] foo [@field] : | instance_variables.rb:25:6:25:8 | foo [@field] : | +| instance_variables.rb:24:15:24:23 | call to taint : | instance_variables.rb:10:19:10:19 | x : | +| instance_variables.rb:24:15:24:23 | call to taint : | instance_variables.rb:10:19:10:19 | x : | +| instance_variables.rb:24:15:24:23 | call to taint : | instance_variables.rb:24:1:24:3 | [post] foo [@field] : | +| instance_variables.rb:24:15:24:23 | call to taint : | instance_variables.rb:24:1:24:3 | [post] foo [@field] : | +| instance_variables.rb:25:6:25:8 | foo [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:25:6:25:8 | foo [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:25:6:25:8 | foo [@field] : | instance_variables.rb:25:6:25:18 | call to get_field | +| instance_variables.rb:25:6:25:8 | foo [@field] : | instance_variables.rb:25:6:25:18 | call to get_field | +| instance_variables.rb:28:1:28:3 | [post] bar [@field] : | instance_variables.rb:29:6:29:8 | bar [@field] : | +| instance_variables.rb:28:15:28:22 | call to taint : | instance_variables.rb:10:19:10:19 | x : | +| instance_variables.rb:28:15:28:22 | call to taint : | instance_variables.rb:28:1:28:3 | [post] bar [@field] : | +| instance_variables.rb:29:6:29:8 | bar [@field] : | instance_variables.rb:16:5:18:7 | self in inc_field [@field] : | +| instance_variables.rb:29:6:29:8 | bar [@field] : | instance_variables.rb:29:6:29:18 | call to inc_field | +| instance_variables.rb:32:1:32:4 | [post] foo1 [@field] : | instance_variables.rb:33:6:33:9 | foo1 [@field] : | +| instance_variables.rb:32:1:32:4 | [post] foo1 [@field] : | instance_variables.rb:33:6:33:9 | foo1 [@field] : | +| instance_variables.rb:32:14:32:22 | call to taint : | instance_variables.rb:32:1:32:4 | [post] foo1 [@field] : | +| instance_variables.rb:32:14:32:22 | call to taint : | instance_variables.rb:32:1:32:4 | [post] foo1 [@field] : | +| instance_variables.rb:33:6:33:9 | foo1 [@field] : | instance_variables.rb:33:6:33:15 | call to field | +| instance_variables.rb:33:6:33:9 | foo1 [@field] : | instance_variables.rb:33:6:33:15 | call to field | +| instance_variables.rb:36:1:36:4 | [post] foo2 [@field] : | instance_variables.rb:37:6:37:9 | foo2 [@field] : | +| instance_variables.rb:36:1:36:4 | [post] foo2 [@field] : | instance_variables.rb:37:6:37:9 | foo2 [@field] : | +| instance_variables.rb:36:14:36:22 | call to taint : | instance_variables.rb:36:1:36:4 | [post] foo2 [@field] : | +| instance_variables.rb:36:14:36:22 | call to taint : | instance_variables.rb:36:1:36:4 | [post] foo2 [@field] : | +| instance_variables.rb:37:6:37:9 | foo2 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:37:6:37:9 | foo2 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:37:6:37:9 | foo2 [@field] : | instance_variables.rb:37:6:37:19 | call to get_field | +| instance_variables.rb:37:6:37:9 | foo2 [@field] : | instance_variables.rb:37:6:37:19 | call to get_field | +| instance_variables.rb:40:1:40:4 | [post] foo3 [@field] : | instance_variables.rb:41:6:41:9 | foo3 [@field] : | +| instance_variables.rb:40:1:40:4 | [post] foo3 [@field] : | instance_variables.rb:41:6:41:9 | foo3 [@field] : | +| instance_variables.rb:40:1:40:4 | [post] foo3 [@field] : | instance_variables.rb:53:6:53:9 | foo3 [@field] : | +| instance_variables.rb:40:1:40:4 | [post] foo3 [@field] : | instance_variables.rb:53:6:53:9 | foo3 [@field] : | +| instance_variables.rb:40:16:40:24 | call to taint : | instance_variables.rb:10:19:10:19 | x : | +| instance_variables.rb:40:16:40:24 | call to taint : | instance_variables.rb:10:19:10:19 | x : | +| instance_variables.rb:40:16:40:24 | call to taint : | instance_variables.rb:40:1:40:4 | [post] foo3 [@field] : | +| instance_variables.rb:40:16:40:24 | call to taint : | instance_variables.rb:40:1:40:4 | [post] foo3 [@field] : | +| instance_variables.rb:41:6:41:9 | foo3 [@field] : | instance_variables.rb:41:6:41:15 | call to field | +| instance_variables.rb:41:6:41:9 | foo3 [@field] : | instance_variables.rb:41:6:41:15 | call to field | +| instance_variables.rb:48:2:48:5 | [post] foo5 [@field] : | instance_variables.rb:49:6:49:9 | foo5 [@field] : | +| instance_variables.rb:48:2:48:5 | [post] foo5 [@field] : | instance_variables.rb:49:6:49:9 | foo5 [@field] : | +| instance_variables.rb:48:2:48:5 | [post] foo5 [@field] : | instance_variables.rb:54:6:54:9 | foo5 [@field] : | +| instance_variables.rb:48:2:48:5 | [post] foo5 [@field] : | instance_variables.rb:54:6:54:9 | foo5 [@field] : | +| instance_variables.rb:48:18:48:26 | call to taint : | instance_variables.rb:10:19:10:19 | x : | +| instance_variables.rb:48:18:48:26 | call to taint : | instance_variables.rb:10:19:10:19 | x : | +| instance_variables.rb:48:18:48:26 | call to taint : | instance_variables.rb:48:2:48:5 | [post] foo5 [@field] : | +| instance_variables.rb:48:18:48:26 | call to taint : | instance_variables.rb:48:2:48:5 | [post] foo5 [@field] : | +| instance_variables.rb:49:6:49:9 | foo5 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:49:6:49:9 | foo5 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:49:6:49:9 | foo5 [@field] : | instance_variables.rb:49:6:49:19 | call to get_field | +| instance_variables.rb:49:6:49:9 | foo5 [@field] : | instance_variables.rb:49:6:49:19 | call to get_field | +| instance_variables.rb:52:15:52:18 | [post] foo6 [@field] : | instance_variables.rb:55:6:55:9 | foo6 [@field] : | +| instance_variables.rb:52:15:52:18 | [post] foo6 [@field] : | instance_variables.rb:55:6:55:9 | foo6 [@field] : | +| instance_variables.rb:52:32:52:40 | call to taint : | instance_variables.rb:10:19:10:19 | x : | +| instance_variables.rb:52:32:52:40 | call to taint : | instance_variables.rb:10:19:10:19 | x : | +| instance_variables.rb:52:32:52:40 | call to taint : | instance_variables.rb:52:15:52:18 | [post] foo6 [@field] : | +| instance_variables.rb:52:32:52:40 | call to taint : | instance_variables.rb:52:15:52:18 | [post] foo6 [@field] : | +| instance_variables.rb:53:6:53:9 | foo3 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:53:6:53:9 | foo3 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:53:6:53:9 | foo3 [@field] : | instance_variables.rb:53:6:53:19 | call to get_field | +| instance_variables.rb:53:6:53:9 | foo3 [@field] : | instance_variables.rb:53:6:53:19 | call to get_field | +| instance_variables.rb:54:6:54:9 | foo5 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:54:6:54:9 | foo5 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:54:6:54:9 | foo5 [@field] : | instance_variables.rb:54:6:54:19 | call to get_field | +| instance_variables.rb:54:6:54:9 | foo5 [@field] : | instance_variables.rb:54:6:54:19 | call to get_field | +| instance_variables.rb:55:6:55:9 | foo6 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:55:6:55:9 | foo6 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:55:6:55:9 | foo6 [@field] : | instance_variables.rb:55:6:55:19 | call to get_field | +| instance_variables.rb:55:6:55:9 | foo6 [@field] : | instance_variables.rb:55:6:55:19 | call to get_field | +| instance_variables.rb:59:15:59:18 | [post] foo7 [@field] : | instance_variables.rb:60:6:60:9 | foo7 [@field] : | +| instance_variables.rb:59:15:59:18 | [post] foo7 [@field] : | instance_variables.rb:60:6:60:9 | foo7 [@field] : | +| instance_variables.rb:59:25:59:28 | [post] foo8 [@field] : | instance_variables.rb:61:6:61:9 | foo8 [@field] : | +| instance_variables.rb:59:25:59:28 | [post] foo8 [@field] : | instance_variables.rb:61:6:61:9 | foo8 [@field] : | +| instance_variables.rb:59:45:59:53 | call to taint : | instance_variables.rb:10:19:10:19 | x : | +| instance_variables.rb:59:45:59:53 | call to taint : | instance_variables.rb:10:19:10:19 | x : | +| instance_variables.rb:59:45:59:53 | call to taint : | instance_variables.rb:59:15:59:18 | [post] foo7 [@field] : | +| instance_variables.rb:59:45:59:53 | call to taint : | instance_variables.rb:59:15:59:18 | [post] foo7 [@field] : | +| instance_variables.rb:59:45:59:53 | call to taint : | instance_variables.rb:59:25:59:28 | [post] foo8 [@field] : | +| instance_variables.rb:59:45:59:53 | call to taint : | instance_variables.rb:59:25:59:28 | [post] foo8 [@field] : | +| instance_variables.rb:60:6:60:9 | foo7 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:60:6:60:9 | foo7 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:60:6:60:9 | foo7 [@field] : | instance_variables.rb:60:6:60:19 | call to get_field | +| instance_variables.rb:60:6:60:9 | foo7 [@field] : | instance_variables.rb:60:6:60:19 | call to get_field | +| instance_variables.rb:61:6:61:9 | foo8 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:61:6:61:9 | foo8 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:61:6:61:9 | foo8 [@field] : | instance_variables.rb:61:6:61:19 | call to get_field | +| instance_variables.rb:61:6:61:9 | foo8 [@field] : | instance_variables.rb:61:6:61:19 | call to get_field | +| instance_variables.rb:65:22:65:25 | [post] foo9 [@field] : | instance_variables.rb:66:6:66:9 | foo9 [@field] : | +| instance_variables.rb:65:22:65:25 | [post] foo9 [@field] : | instance_variables.rb:66:6:66:9 | foo9 [@field] : | +| instance_variables.rb:65:32:65:36 | [post] foo10 [@field] : | instance_variables.rb:67:6:67:10 | foo10 [@field] : | +| instance_variables.rb:65:32:65:36 | [post] foo10 [@field] : | instance_variables.rb:67:6:67:10 | foo10 [@field] : | +| instance_variables.rb:65:53:65:61 | call to taint : | instance_variables.rb:10:19:10:19 | x : | +| instance_variables.rb:65:53:65:61 | call to taint : | instance_variables.rb:10:19:10:19 | x : | +| instance_variables.rb:65:53:65:61 | call to taint : | instance_variables.rb:65:22:65:25 | [post] foo9 [@field] : | +| instance_variables.rb:65:53:65:61 | call to taint : | instance_variables.rb:65:22:65:25 | [post] foo9 [@field] : | +| instance_variables.rb:65:53:65:61 | call to taint : | instance_variables.rb:65:32:65:36 | [post] foo10 [@field] : | +| instance_variables.rb:65:53:65:61 | call to taint : | instance_variables.rb:65:32:65:36 | [post] foo10 [@field] : | +| instance_variables.rb:66:6:66:9 | foo9 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:66:6:66:9 | foo9 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:66:6:66:9 | foo9 [@field] : | instance_variables.rb:66:6:66:19 | call to get_field | +| instance_variables.rb:66:6:66:9 | foo9 [@field] : | instance_variables.rb:66:6:66:19 | call to get_field | +| instance_variables.rb:67:6:67:10 | foo10 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:67:6:67:10 | foo10 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:67:6:67:10 | foo10 [@field] : | instance_variables.rb:67:6:67:20 | call to get_field | +| instance_variables.rb:67:6:67:10 | foo10 [@field] : | instance_variables.rb:67:6:67:20 | call to get_field | +| instance_variables.rb:70:5:70:5 | [post] x [@field] : | instance_variables.rb:74:14:74:18 | [post] foo11 [@field] : | +| instance_variables.rb:70:5:70:5 | [post] x [@field] : | instance_variables.rb:74:14:74:18 | [post] foo11 [@field] : | +| instance_variables.rb:70:5:70:5 | [post] x [@field] : | instance_variables.rb:78:15:78:19 | [post] foo12 [@field] : | +| instance_variables.rb:70:5:70:5 | [post] x [@field] : | instance_variables.rb:78:15:78:19 | [post] foo12 [@field] : | +| instance_variables.rb:70:17:70:25 | call to taint : | instance_variables.rb:10:19:10:19 | x : | +| instance_variables.rb:70:17:70:25 | call to taint : | instance_variables.rb:10:19:10:19 | x : | +| instance_variables.rb:70:17:70:25 | call to taint : | instance_variables.rb:70:5:70:5 | [post] x [@field] : | +| instance_variables.rb:70:17:70:25 | call to taint : | instance_variables.rb:70:5:70:5 | [post] x [@field] : | +| instance_variables.rb:74:14:74:18 | [post] foo11 [@field] : | instance_variables.rb:75:6:75:10 | foo11 [@field] : | +| instance_variables.rb:74:14:74:18 | [post] foo11 [@field] : | instance_variables.rb:75:6:75:10 | foo11 [@field] : | +| instance_variables.rb:75:6:75:10 | foo11 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:75:6:75:10 | foo11 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:75:6:75:10 | foo11 [@field] : | instance_variables.rb:75:6:75:20 | call to get_field | +| instance_variables.rb:75:6:75:10 | foo11 [@field] : | instance_variables.rb:75:6:75:20 | call to get_field | +| instance_variables.rb:78:15:78:19 | [post] foo12 [@field] : | instance_variables.rb:79:6:79:10 | foo12 [@field] : | +| instance_variables.rb:78:15:78:19 | [post] foo12 [@field] : | instance_variables.rb:79:6:79:10 | foo12 [@field] : | +| instance_variables.rb:79:6:79:10 | foo12 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:79:6:79:10 | foo12 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | +| instance_variables.rb:79:6:79:10 | foo12 [@field] : | instance_variables.rb:79:6:79:20 | call to get_field | +| instance_variables.rb:79:6:79:10 | foo12 [@field] : | instance_variables.rb:79:6:79:20 | call to get_field | nodes -| instance_variables.rb:2:19:2:19 | x : | semmle.label | x : | -| instance_variables.rb:2:19:2:19 | x : | semmle.label | x : | -| instance_variables.rb:3:9:3:14 | [post] self [@field] : | semmle.label | [post] self [@field] : | -| instance_variables.rb:3:9:3:14 | [post] self [@field] : | semmle.label | [post] self [@field] : | -| instance_variables.rb:3:18:3:18 | x : | semmle.label | x : | -| instance_variables.rb:3:18:3:18 | x : | semmle.label | x : | -| instance_variables.rb:5:5:7:7 | self in get_field [@field] : | semmle.label | self in get_field [@field] : | -| instance_variables.rb:5:5:7:7 | self in get_field [@field] : | semmle.label | self in get_field [@field] : | -| instance_variables.rb:6:9:6:21 | return : | semmle.label | return : | -| instance_variables.rb:6:9:6:21 | return : | semmle.label | return : | -| instance_variables.rb:6:16:6:21 | @field : | semmle.label | @field : | -| instance_variables.rb:6:16:6:21 | @field : | semmle.label | @field : | -| instance_variables.rb:6:16:6:21 | self [@field] : | semmle.label | self [@field] : | -| instance_variables.rb:6:16:6:21 | self [@field] : | semmle.label | self [@field] : | -| instance_variables.rb:8:5:10:7 | self in inc_field [@field] : | semmle.label | self in inc_field [@field] : | -| instance_variables.rb:9:9:9:14 | [post] self [@field] : | semmle.label | [post] self [@field] : | -| instance_variables.rb:11:5:11:8 | [post] self [@foo] : | semmle.label | [post] self [@foo] : | -| instance_variables.rb:11:5:11:8 | [post] self [@foo] : | semmle.label | [post] self [@foo] : | -| instance_variables.rb:11:12:11:22 | call to source : | semmle.label | call to source : | -| instance_variables.rb:11:12:11:22 | call to source : | semmle.label | call to source : | -| instance_variables.rb:12:10:12:13 | @foo | semmle.label | @foo | -| instance_variables.rb:12:10:12:13 | @foo | semmle.label | @foo | -| instance_variables.rb:12:10:12:13 | self [@foo] : | semmle.label | self [@foo] : | -| instance_variables.rb:12:10:12:13 | self [@foo] : | semmle.label | self [@foo] : | -| instance_variables.rb:16:1:16:3 | [post] foo [@field] : | semmle.label | [post] foo [@field] : | -| instance_variables.rb:16:1:16:3 | [post] foo [@field] : | semmle.label | [post] foo [@field] : | -| instance_variables.rb:16:15:16:24 | call to source : | semmle.label | call to source : | -| instance_variables.rb:16:15:16:24 | call to source : | semmle.label | call to source : | -| instance_variables.rb:17:6:17:8 | foo [@field] : | semmle.label | foo [@field] : | -| instance_variables.rb:17:6:17:8 | foo [@field] : | semmle.label | foo [@field] : | -| instance_variables.rb:17:6:17:18 | call to get_field | semmle.label | call to get_field | -| instance_variables.rb:17:6:17:18 | call to get_field | semmle.label | call to get_field | -| instance_variables.rb:20:1:20:3 | [post] bar [@field] : | semmle.label | [post] bar [@field] : | -| instance_variables.rb:20:15:20:23 | call to source : | semmle.label | call to source : | -| instance_variables.rb:21:6:21:8 | bar [@field] : | semmle.label | bar [@field] : | -| instance_variables.rb:21:6:21:18 | call to inc_field | semmle.label | call to inc_field | -| instance_variables.rb:24:1:24:4 | [post] foo1 [@field] : | semmle.label | [post] foo1 [@field] : | -| instance_variables.rb:24:1:24:4 | [post] foo1 [@field] : | semmle.label | [post] foo1 [@field] : | -| instance_variables.rb:24:14:24:23 | call to source : | semmle.label | call to source : | -| instance_variables.rb:24:14:24:23 | call to source : | semmle.label | call to source : | -| instance_variables.rb:25:6:25:9 | foo1 [@field] : | semmle.label | foo1 [@field] : | -| instance_variables.rb:25:6:25:9 | foo1 [@field] : | semmle.label | foo1 [@field] : | -| instance_variables.rb:25:6:25:15 | call to field | semmle.label | call to field | -| instance_variables.rb:25:6:25:15 | call to field | semmle.label | call to field | -| instance_variables.rb:28:1:28:4 | [post] foo2 [@field] : | semmle.label | [post] foo2 [@field] : | -| instance_variables.rb:28:1:28:4 | [post] foo2 [@field] : | semmle.label | [post] foo2 [@field] : | -| instance_variables.rb:28:14:28:23 | call to source : | semmle.label | call to source : | -| instance_variables.rb:28:14:28:23 | call to source : | semmle.label | call to source : | -| instance_variables.rb:29:6:29:9 | foo2 [@field] : | semmle.label | foo2 [@field] : | -| instance_variables.rb:29:6:29:9 | foo2 [@field] : | semmle.label | foo2 [@field] : | -| instance_variables.rb:29:6:29:19 | call to get_field | semmle.label | call to get_field | -| instance_variables.rb:29:6:29:19 | call to get_field | semmle.label | call to get_field | -| instance_variables.rb:32:1:32:4 | [post] foo3 [@field] : | semmle.label | [post] foo3 [@field] : | -| instance_variables.rb:32:1:32:4 | [post] foo3 [@field] : | semmle.label | [post] foo3 [@field] : | -| instance_variables.rb:32:16:32:25 | call to source : | semmle.label | call to source : | -| instance_variables.rb:32:16:32:25 | call to source : | semmle.label | call to source : | -| instance_variables.rb:33:6:33:9 | foo3 [@field] : | semmle.label | foo3 [@field] : | -| instance_variables.rb:33:6:33:9 | foo3 [@field] : | semmle.label | foo3 [@field] : | +| instance_variables.rb:10:19:10:19 | x : | semmle.label | x : | +| instance_variables.rb:10:19:10:19 | x : | semmle.label | x : | +| instance_variables.rb:11:9:11:14 | [post] self [@field] : | semmle.label | [post] self [@field] : | +| instance_variables.rb:11:9:11:14 | [post] self [@field] : | semmle.label | [post] self [@field] : | +| instance_variables.rb:11:18:11:18 | x : | semmle.label | x : | +| instance_variables.rb:11:18:11:18 | x : | semmle.label | x : | +| instance_variables.rb:13:5:15:7 | self in get_field [@field] : | semmle.label | self in get_field [@field] : | +| instance_variables.rb:13:5:15:7 | self in get_field [@field] : | semmle.label | self in get_field [@field] : | +| instance_variables.rb:14:9:14:21 | return : | semmle.label | return : | +| instance_variables.rb:14:9:14:21 | return : | semmle.label | return : | +| instance_variables.rb:14:16:14:21 | @field : | semmle.label | @field : | +| instance_variables.rb:14:16:14:21 | @field : | semmle.label | @field : | +| instance_variables.rb:14:16:14:21 | self [@field] : | semmle.label | self [@field] : | +| instance_variables.rb:14:16:14:21 | self [@field] : | semmle.label | self [@field] : | +| instance_variables.rb:16:5:18:7 | self in inc_field [@field] : | semmle.label | self in inc_field [@field] : | +| instance_variables.rb:17:9:17:14 | [post] self [@field] : | semmle.label | [post] self [@field] : | +| instance_variables.rb:19:5:19:8 | [post] self [@foo] : | semmle.label | [post] self [@foo] : | +| instance_variables.rb:19:5:19:8 | [post] self [@foo] : | semmle.label | [post] self [@foo] : | +| instance_variables.rb:19:12:19:21 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:19:12:19:21 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:20:10:20:13 | @foo | semmle.label | @foo | +| instance_variables.rb:20:10:20:13 | @foo | semmle.label | @foo | +| instance_variables.rb:20:10:20:13 | self [@foo] : | semmle.label | self [@foo] : | +| instance_variables.rb:20:10:20:13 | self [@foo] : | semmle.label | self [@foo] : | +| instance_variables.rb:24:1:24:3 | [post] foo [@field] : | semmle.label | [post] foo [@field] : | +| instance_variables.rb:24:1:24:3 | [post] foo [@field] : | semmle.label | [post] foo [@field] : | +| instance_variables.rb:24:15:24:23 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:24:15:24:23 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:25:6:25:8 | foo [@field] : | semmle.label | foo [@field] : | +| instance_variables.rb:25:6:25:8 | foo [@field] : | semmle.label | foo [@field] : | +| instance_variables.rb:25:6:25:18 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:25:6:25:18 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:28:1:28:3 | [post] bar [@field] : | semmle.label | [post] bar [@field] : | +| instance_variables.rb:28:15:28:22 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:29:6:29:8 | bar [@field] : | semmle.label | bar [@field] : | +| instance_variables.rb:29:6:29:18 | call to inc_field | semmle.label | call to inc_field | +| instance_variables.rb:32:1:32:4 | [post] foo1 [@field] : | semmle.label | [post] foo1 [@field] : | +| instance_variables.rb:32:1:32:4 | [post] foo1 [@field] : | semmle.label | [post] foo1 [@field] : | +| instance_variables.rb:32:14:32:22 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:32:14:32:22 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:33:6:33:9 | foo1 [@field] : | semmle.label | foo1 [@field] : | +| instance_variables.rb:33:6:33:9 | foo1 [@field] : | semmle.label | foo1 [@field] : | | instance_variables.rb:33:6:33:15 | call to field | semmle.label | call to field | | instance_variables.rb:33:6:33:15 | call to field | semmle.label | call to field | +| instance_variables.rb:36:1:36:4 | [post] foo2 [@field] : | semmle.label | [post] foo2 [@field] : | +| instance_variables.rb:36:1:36:4 | [post] foo2 [@field] : | semmle.label | [post] foo2 [@field] : | +| instance_variables.rb:36:14:36:22 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:36:14:36:22 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:37:6:37:9 | foo2 [@field] : | semmle.label | foo2 [@field] : | +| instance_variables.rb:37:6:37:9 | foo2 [@field] : | semmle.label | foo2 [@field] : | +| instance_variables.rb:37:6:37:19 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:37:6:37:19 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:40:1:40:4 | [post] foo3 [@field] : | semmle.label | [post] foo3 [@field] : | +| instance_variables.rb:40:1:40:4 | [post] foo3 [@field] : | semmle.label | [post] foo3 [@field] : | +| instance_variables.rb:40:16:40:24 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:40:16:40:24 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:41:6:41:9 | foo3 [@field] : | semmle.label | foo3 [@field] : | +| instance_variables.rb:41:6:41:9 | foo3 [@field] : | semmle.label | foo3 [@field] : | +| instance_variables.rb:41:6:41:15 | call to field | semmle.label | call to field | +| instance_variables.rb:41:6:41:15 | call to field | semmle.label | call to field | +| instance_variables.rb:48:2:48:5 | [post] foo5 [@field] : | semmle.label | [post] foo5 [@field] : | +| instance_variables.rb:48:2:48:5 | [post] foo5 [@field] : | semmle.label | [post] foo5 [@field] : | +| instance_variables.rb:48:18:48:26 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:48:18:48:26 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:49:6:49:9 | foo5 [@field] : | semmle.label | foo5 [@field] : | +| instance_variables.rb:49:6:49:9 | foo5 [@field] : | semmle.label | foo5 [@field] : | +| instance_variables.rb:49:6:49:19 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:49:6:49:19 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:52:15:52:18 | [post] foo6 [@field] : | semmle.label | [post] foo6 [@field] : | +| instance_variables.rb:52:15:52:18 | [post] foo6 [@field] : | semmle.label | [post] foo6 [@field] : | +| instance_variables.rb:52:32:52:40 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:52:32:52:40 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:53:6:53:9 | foo3 [@field] : | semmle.label | foo3 [@field] : | +| instance_variables.rb:53:6:53:9 | foo3 [@field] : | semmle.label | foo3 [@field] : | +| instance_variables.rb:53:6:53:19 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:53:6:53:19 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:54:6:54:9 | foo5 [@field] : | semmle.label | foo5 [@field] : | +| instance_variables.rb:54:6:54:9 | foo5 [@field] : | semmle.label | foo5 [@field] : | +| instance_variables.rb:54:6:54:19 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:54:6:54:19 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:55:6:55:9 | foo6 [@field] : | semmle.label | foo6 [@field] : | +| instance_variables.rb:55:6:55:9 | foo6 [@field] : | semmle.label | foo6 [@field] : | +| instance_variables.rb:55:6:55:19 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:55:6:55:19 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:59:15:59:18 | [post] foo7 [@field] : | semmle.label | [post] foo7 [@field] : | +| instance_variables.rb:59:15:59:18 | [post] foo7 [@field] : | semmle.label | [post] foo7 [@field] : | +| instance_variables.rb:59:25:59:28 | [post] foo8 [@field] : | semmle.label | [post] foo8 [@field] : | +| instance_variables.rb:59:25:59:28 | [post] foo8 [@field] : | semmle.label | [post] foo8 [@field] : | +| instance_variables.rb:59:45:59:53 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:59:45:59:53 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:60:6:60:9 | foo7 [@field] : | semmle.label | foo7 [@field] : | +| instance_variables.rb:60:6:60:9 | foo7 [@field] : | semmle.label | foo7 [@field] : | +| instance_variables.rb:60:6:60:19 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:60:6:60:19 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:61:6:61:9 | foo8 [@field] : | semmle.label | foo8 [@field] : | +| instance_variables.rb:61:6:61:9 | foo8 [@field] : | semmle.label | foo8 [@field] : | +| instance_variables.rb:61:6:61:19 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:61:6:61:19 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:65:22:65:25 | [post] foo9 [@field] : | semmle.label | [post] foo9 [@field] : | +| instance_variables.rb:65:22:65:25 | [post] foo9 [@field] : | semmle.label | [post] foo9 [@field] : | +| instance_variables.rb:65:32:65:36 | [post] foo10 [@field] : | semmle.label | [post] foo10 [@field] : | +| instance_variables.rb:65:32:65:36 | [post] foo10 [@field] : | semmle.label | [post] foo10 [@field] : | +| instance_variables.rb:65:53:65:61 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:65:53:65:61 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:66:6:66:9 | foo9 [@field] : | semmle.label | foo9 [@field] : | +| instance_variables.rb:66:6:66:9 | foo9 [@field] : | semmle.label | foo9 [@field] : | +| instance_variables.rb:66:6:66:19 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:66:6:66:19 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:67:6:67:10 | foo10 [@field] : | semmle.label | foo10 [@field] : | +| instance_variables.rb:67:6:67:10 | foo10 [@field] : | semmle.label | foo10 [@field] : | +| instance_variables.rb:67:6:67:20 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:67:6:67:20 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:70:5:70:5 | [post] x [@field] : | semmle.label | [post] x [@field] : | +| instance_variables.rb:70:5:70:5 | [post] x [@field] : | semmle.label | [post] x [@field] : | +| instance_variables.rb:70:17:70:25 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:70:17:70:25 | call to taint : | semmle.label | call to taint : | +| instance_variables.rb:74:14:74:18 | [post] foo11 [@field] : | semmle.label | [post] foo11 [@field] : | +| instance_variables.rb:74:14:74:18 | [post] foo11 [@field] : | semmle.label | [post] foo11 [@field] : | +| instance_variables.rb:75:6:75:10 | foo11 [@field] : | semmle.label | foo11 [@field] : | +| instance_variables.rb:75:6:75:10 | foo11 [@field] : | semmle.label | foo11 [@field] : | +| instance_variables.rb:75:6:75:20 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:75:6:75:20 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:78:15:78:19 | [post] foo12 [@field] : | semmle.label | [post] foo12 [@field] : | +| instance_variables.rb:78:15:78:19 | [post] foo12 [@field] : | semmle.label | [post] foo12 [@field] : | +| instance_variables.rb:79:6:79:10 | foo12 [@field] : | semmle.label | foo12 [@field] : | +| instance_variables.rb:79:6:79:10 | foo12 [@field] : | semmle.label | foo12 [@field] : | +| instance_variables.rb:79:6:79:20 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:79:6:79:20 | call to get_field | semmle.label | call to get_field | subpaths -| instance_variables.rb:16:15:16:24 | call to source : | instance_variables.rb:2:19:2:19 | x : | instance_variables.rb:3:9:3:14 | [post] self [@field] : | instance_variables.rb:16:1:16:3 | [post] foo [@field] : | -| instance_variables.rb:16:15:16:24 | call to source : | instance_variables.rb:2:19:2:19 | x : | instance_variables.rb:3:9:3:14 | [post] self [@field] : | instance_variables.rb:16:1:16:3 | [post] foo [@field] : | -| instance_variables.rb:17:6:17:8 | foo [@field] : | instance_variables.rb:5:5:7:7 | self in get_field [@field] : | instance_variables.rb:6:9:6:21 | return : | instance_variables.rb:17:6:17:18 | call to get_field | -| instance_variables.rb:17:6:17:8 | foo [@field] : | instance_variables.rb:5:5:7:7 | self in get_field [@field] : | instance_variables.rb:6:9:6:21 | return : | instance_variables.rb:17:6:17:18 | call to get_field | -| instance_variables.rb:20:15:20:23 | call to source : | instance_variables.rb:2:19:2:19 | x : | instance_variables.rb:3:9:3:14 | [post] self [@field] : | instance_variables.rb:20:1:20:3 | [post] bar [@field] : | -| instance_variables.rb:21:6:21:8 | bar [@field] : | instance_variables.rb:8:5:10:7 | self in inc_field [@field] : | instance_variables.rb:8:5:10:7 | self in inc_field [@field] : | instance_variables.rb:21:6:21:18 | call to inc_field | -| instance_variables.rb:21:6:21:8 | bar [@field] : | instance_variables.rb:8:5:10:7 | self in inc_field [@field] : | instance_variables.rb:9:9:9:14 | [post] self [@field] : | instance_variables.rb:21:6:21:18 | call to inc_field | -| instance_variables.rb:29:6:29:9 | foo2 [@field] : | instance_variables.rb:5:5:7:7 | self in get_field [@field] : | instance_variables.rb:6:9:6:21 | return : | instance_variables.rb:29:6:29:19 | call to get_field | -| instance_variables.rb:29:6:29:9 | foo2 [@field] : | instance_variables.rb:5:5:7:7 | self in get_field [@field] : | instance_variables.rb:6:9:6:21 | return : | instance_variables.rb:29:6:29:19 | call to get_field | -| instance_variables.rb:32:16:32:25 | call to source : | instance_variables.rb:2:19:2:19 | x : | instance_variables.rb:3:9:3:14 | [post] self [@field] : | instance_variables.rb:32:1:32:4 | [post] foo3 [@field] : | -| instance_variables.rb:32:16:32:25 | call to source : | instance_variables.rb:2:19:2:19 | x : | instance_variables.rb:3:9:3:14 | [post] self [@field] : | instance_variables.rb:32:1:32:4 | [post] foo3 [@field] : | +| instance_variables.rb:24:15:24:23 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:24:1:24:3 | [post] foo [@field] : | +| instance_variables.rb:24:15:24:23 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:24:1:24:3 | [post] foo [@field] : | +| instance_variables.rb:25:6:25:8 | foo [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:25:6:25:18 | call to get_field | +| instance_variables.rb:25:6:25:8 | foo [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:25:6:25:18 | call to get_field | +| instance_variables.rb:28:15:28:22 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:28:1:28:3 | [post] bar [@field] : | +| instance_variables.rb:29:6:29:8 | bar [@field] : | instance_variables.rb:16:5:18:7 | self in inc_field [@field] : | instance_variables.rb:16:5:18:7 | self in inc_field [@field] : | instance_variables.rb:29:6:29:18 | call to inc_field | +| instance_variables.rb:29:6:29:8 | bar [@field] : | instance_variables.rb:16:5:18:7 | self in inc_field [@field] : | instance_variables.rb:17:9:17:14 | [post] self [@field] : | instance_variables.rb:29:6:29:18 | call to inc_field | +| instance_variables.rb:37:6:37:9 | foo2 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:37:6:37:19 | call to get_field | +| instance_variables.rb:37:6:37:9 | foo2 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:37:6:37:19 | call to get_field | +| instance_variables.rb:40:16:40:24 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:40:1:40:4 | [post] foo3 [@field] : | +| instance_variables.rb:40:16:40:24 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:40:1:40:4 | [post] foo3 [@field] : | +| instance_variables.rb:48:18:48:26 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:48:2:48:5 | [post] foo5 [@field] : | +| instance_variables.rb:48:18:48:26 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:48:2:48:5 | [post] foo5 [@field] : | +| instance_variables.rb:49:6:49:9 | foo5 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:49:6:49:19 | call to get_field | +| instance_variables.rb:49:6:49:9 | foo5 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:49:6:49:19 | call to get_field | +| instance_variables.rb:52:32:52:40 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:52:15:52:18 | [post] foo6 [@field] : | +| instance_variables.rb:52:32:52:40 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:52:15:52:18 | [post] foo6 [@field] : | +| instance_variables.rb:53:6:53:9 | foo3 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:53:6:53:19 | call to get_field | +| instance_variables.rb:53:6:53:9 | foo3 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:53:6:53:19 | call to get_field | +| instance_variables.rb:54:6:54:9 | foo5 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:54:6:54:19 | call to get_field | +| instance_variables.rb:54:6:54:9 | foo5 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:54:6:54:19 | call to get_field | +| instance_variables.rb:55:6:55:9 | foo6 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:55:6:55:19 | call to get_field | +| instance_variables.rb:55:6:55:9 | foo6 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:55:6:55:19 | call to get_field | +| instance_variables.rb:59:45:59:53 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:59:15:59:18 | [post] foo7 [@field] : | +| instance_variables.rb:59:45:59:53 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:59:15:59:18 | [post] foo7 [@field] : | +| instance_variables.rb:59:45:59:53 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:59:25:59:28 | [post] foo8 [@field] : | +| instance_variables.rb:59:45:59:53 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:59:25:59:28 | [post] foo8 [@field] : | +| instance_variables.rb:60:6:60:9 | foo7 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:60:6:60:19 | call to get_field | +| instance_variables.rb:60:6:60:9 | foo7 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:60:6:60:19 | call to get_field | +| instance_variables.rb:61:6:61:9 | foo8 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:61:6:61:19 | call to get_field | +| instance_variables.rb:61:6:61:9 | foo8 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:61:6:61:19 | call to get_field | +| instance_variables.rb:65:53:65:61 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:65:22:65:25 | [post] foo9 [@field] : | +| instance_variables.rb:65:53:65:61 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:65:22:65:25 | [post] foo9 [@field] : | +| instance_variables.rb:65:53:65:61 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:65:32:65:36 | [post] foo10 [@field] : | +| instance_variables.rb:65:53:65:61 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:65:32:65:36 | [post] foo10 [@field] : | +| instance_variables.rb:66:6:66:9 | foo9 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:66:6:66:19 | call to get_field | +| instance_variables.rb:66:6:66:9 | foo9 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:66:6:66:19 | call to get_field | +| instance_variables.rb:67:6:67:10 | foo10 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:67:6:67:20 | call to get_field | +| instance_variables.rb:67:6:67:10 | foo10 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:67:6:67:20 | call to get_field | +| instance_variables.rb:70:17:70:25 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:70:5:70:5 | [post] x [@field] : | +| instance_variables.rb:70:17:70:25 | call to taint : | instance_variables.rb:10:19:10:19 | x : | instance_variables.rb:11:9:11:14 | [post] self [@field] : | instance_variables.rb:70:5:70:5 | [post] x [@field] : | +| instance_variables.rb:75:6:75:10 | foo11 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:75:6:75:20 | call to get_field | +| instance_variables.rb:75:6:75:10 | foo11 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:75:6:75:20 | call to get_field | +| instance_variables.rb:79:6:79:10 | foo12 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:79:6:79:20 | call to get_field | +| instance_variables.rb:79:6:79:10 | foo12 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | instance_variables.rb:14:9:14:21 | return : | instance_variables.rb:79:6:79:20 | call to get_field | #select -| instance_variables.rb:12:10:12:13 | @foo | instance_variables.rb:11:12:11:22 | call to source : | instance_variables.rb:12:10:12:13 | @foo | $@ | instance_variables.rb:11:12:11:22 | call to source : | call to source : | -| instance_variables.rb:17:6:17:18 | call to get_field | instance_variables.rb:16:15:16:24 | call to source : | instance_variables.rb:17:6:17:18 | call to get_field | $@ | instance_variables.rb:16:15:16:24 | call to source : | call to source : | -| instance_variables.rb:21:6:21:18 | call to inc_field | instance_variables.rb:20:15:20:23 | call to source : | instance_variables.rb:21:6:21:18 | call to inc_field | $@ | instance_variables.rb:20:15:20:23 | call to source : | call to source : | -| instance_variables.rb:25:6:25:15 | call to field | instance_variables.rb:24:14:24:23 | call to source : | instance_variables.rb:25:6:25:15 | call to field | $@ | instance_variables.rb:24:14:24:23 | call to source : | call to source : | -| instance_variables.rb:29:6:29:19 | call to get_field | instance_variables.rb:28:14:28:23 | call to source : | instance_variables.rb:29:6:29:19 | call to get_field | $@ | instance_variables.rb:28:14:28:23 | call to source : | call to source : | -| instance_variables.rb:33:6:33:15 | call to field | instance_variables.rb:32:16:32:25 | call to source : | instance_variables.rb:33:6:33:15 | call to field | $@ | instance_variables.rb:32:16:32:25 | call to source : | call to source : | +| instance_variables.rb:20:10:20:13 | @foo | instance_variables.rb:19:12:19:21 | call to taint : | instance_variables.rb:20:10:20:13 | @foo | $@ | instance_variables.rb:19:12:19:21 | call to taint : | call to taint : | +| instance_variables.rb:25:6:25:18 | call to get_field | instance_variables.rb:24:15:24:23 | call to taint : | instance_variables.rb:25:6:25:18 | call to get_field | $@ | instance_variables.rb:24:15:24:23 | call to taint : | call to taint : | +| instance_variables.rb:29:6:29:18 | call to inc_field | instance_variables.rb:28:15:28:22 | call to taint : | instance_variables.rb:29:6:29:18 | call to inc_field | $@ | instance_variables.rb:28:15:28:22 | call to taint : | call to taint : | +| instance_variables.rb:33:6:33:15 | call to field | instance_variables.rb:32:14:32:22 | call to taint : | instance_variables.rb:33:6:33:15 | call to field | $@ | instance_variables.rb:32:14:32:22 | call to taint : | call to taint : | +| instance_variables.rb:37:6:37:19 | call to get_field | instance_variables.rb:36:14:36:22 | call to taint : | instance_variables.rb:37:6:37:19 | call to get_field | $@ | instance_variables.rb:36:14:36:22 | call to taint : | call to taint : | +| instance_variables.rb:41:6:41:15 | call to field | instance_variables.rb:40:16:40:24 | call to taint : | instance_variables.rb:41:6:41:15 | call to field | $@ | instance_variables.rb:40:16:40:24 | call to taint : | call to taint : | +| instance_variables.rb:49:6:49:19 | call to get_field | instance_variables.rb:48:18:48:26 | call to taint : | instance_variables.rb:49:6:49:19 | call to get_field | $@ | instance_variables.rb:48:18:48:26 | call to taint : | call to taint : | +| instance_variables.rb:53:6:53:19 | call to get_field | instance_variables.rb:40:16:40:24 | call to taint : | instance_variables.rb:53:6:53:19 | call to get_field | $@ | instance_variables.rb:40:16:40:24 | call to taint : | call to taint : | +| instance_variables.rb:54:6:54:19 | call to get_field | instance_variables.rb:48:18:48:26 | call to taint : | instance_variables.rb:54:6:54:19 | call to get_field | $@ | instance_variables.rb:48:18:48:26 | call to taint : | call to taint : | +| instance_variables.rb:55:6:55:19 | call to get_field | instance_variables.rb:52:32:52:40 | call to taint : | instance_variables.rb:55:6:55:19 | call to get_field | $@ | instance_variables.rb:52:32:52:40 | call to taint : | call to taint : | +| instance_variables.rb:60:6:60:19 | call to get_field | instance_variables.rb:59:45:59:53 | call to taint : | instance_variables.rb:60:6:60:19 | call to get_field | $@ | instance_variables.rb:59:45:59:53 | call to taint : | call to taint : | +| instance_variables.rb:61:6:61:19 | call to get_field | instance_variables.rb:59:45:59:53 | call to taint : | instance_variables.rb:61:6:61:19 | call to get_field | $@ | instance_variables.rb:59:45:59:53 | call to taint : | call to taint : | +| instance_variables.rb:66:6:66:19 | call to get_field | instance_variables.rb:65:53:65:61 | call to taint : | instance_variables.rb:66:6:66:19 | call to get_field | $@ | instance_variables.rb:65:53:65:61 | call to taint : | call to taint : | +| instance_variables.rb:67:6:67:20 | call to get_field | instance_variables.rb:65:53:65:61 | call to taint : | instance_variables.rb:67:6:67:20 | call to get_field | $@ | instance_variables.rb:65:53:65:61 | call to taint : | call to taint : | +| instance_variables.rb:75:6:75:20 | call to get_field | instance_variables.rb:70:17:70:25 | call to taint : | instance_variables.rb:75:6:75:20 | call to get_field | $@ | instance_variables.rb:70:17:70:25 | call to taint : | call to taint : | +| instance_variables.rb:79:6:79:20 | call to get_field | instance_variables.rb:70:17:70:25 | call to taint : | instance_variables.rb:79:6:79:20 | call to get_field | $@ | instance_variables.rb:70:17:70:25 | call to taint : | call to taint : | diff --git a/ruby/ql/test/library-tests/dataflow/global/instance_variables.rb b/ruby/ql/test/library-tests/dataflow/global/instance_variables.rb index 056fe98a7b75..7b5f8bbea43b 100644 --- a/ruby/ql/test/library-tests/dataflow/global/instance_variables.rb +++ b/ruby/ql/test/library-tests/dataflow/global/instance_variables.rb @@ -1,3 +1,11 @@ +def taint x + x +end + +def sink x + puts "SINK: #{x}" +end + class Foo def set_field x @field = x @@ -8,30 +16,64 @@ def get_field def inc_field @field += 1 end - @foo = source("7") + @foo = taint("7") sink(@foo) # $ hasValueFlow=7 end foo = Foo.new -foo.set_field(source(42)) +foo.set_field(taint(42)) sink(foo.get_field) # $ hasValueFlow=42 bar = Foo.new -bar.set_field(source(5)) +bar.set_field(taint(5)) sink(bar.inc_field) # $ hasTaintFlow=5 foo1 = Foo.new -foo1.field = source(20) +foo1.field = taint(20) sink(foo1.field) # $ hasValueFlow=20 foo2 = Foo.new -foo2.field = source(21) +foo2.field = taint(21) sink(foo2.get_field) # $ hasValueFlow=21 foo3 = Foo.new -foo3.set_field(source(22)) +foo3.set_field(taint(22)) sink(foo3.field) # $ hasValueFlow=22 foo4 = "hello" -foo4.other = source(23) +foo4.other = taint(23) sink(foo4.other) # no field flow for constants + +foo5 = Foo.new +(foo5).set_field(taint(24)) +sink(foo5.get_field) # $ hasValueFlow=24 + +foo6 = Foo.new +(foo3; (foo5; foo6)).set_field(taint(25)) +sink(foo3.get_field) # $ hasValueFlow=22 +sink(foo5.get_field) # $ hasValueFlow=24 +sink(foo6.get_field) # $ hasValueFlow=25 + +foo7 = Foo.new +foo8 = Foo.new +(if foo7 then foo7 else foo8 end).set_field(taint(26)) +sink(foo7.get_field) # $ hasValueFlow=26 +sink(foo8.get_field) # $ hasValueFlow=26 + +foo9 = Foo.new +foo10 = Foo.new +(case when foo9 then foo9 else foo10 end).set_field(taint(27)) +sink(foo9.get_field) # $ hasValueFlow=27 +sink(foo10.get_field) # $ hasValueFlow=27 + +def set_field_on x + x.set_field(taint(28)) +end + +foo11 = Foo.new +set_field_on(foo11) +sink(foo11.get_field) # $ hasValueFlow=28 + +foo12 = Foo.new +set_field_on (foo12) # space after `set_field_on` is important for this test +sink(foo12.get_field) # $ hasValueFlow=28 diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImplConsistency.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImplConsistency.qll index d6c1bad2744d..da828337e562 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImplConsistency.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImplConsistency.qll @@ -32,6 +32,12 @@ module Consistency { /** Holds if `n` should be excluded from the consistency test `reverseRead`. */ predicate reverseReadExclude(Node n) { none() } + + /** Holds if `n` should be excluded from the consistency test `postHasUniquePre`. */ + predicate postHasUniquePreExclude(PostUpdateNode n) { none() } + + /** Holds if `n` should be excluded from the consistency test `uniquePostUpdate`. */ + predicate uniquePostUpdateExclude(Node n) { none() } } private class RelevantNode extends Node { @@ -166,6 +172,7 @@ module Consistency { } query predicate postHasUniquePre(PostUpdateNode n, string msg) { + not any(ConsistencyConfiguration conf).postHasUniquePreExclude(n) and exists(int c | c = count(n.getPreUpdateNode()) and c != 1 and @@ -174,6 +181,7 @@ module Consistency { } query predicate uniquePostUpdate(Node n, string msg) { + not any(ConsistencyConfiguration conf).uniquePostUpdateExclude(n) and 1 < strictcount(PostUpdateNode post | post.getPreUpdateNode() = n) and msg = "Node has multiple PostUpdateNodes." }