mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Ruby: Implement ContentSet
This commit is contained in:
@@ -32,7 +32,9 @@ module SummaryComponent {
|
||||
SummaryComponent block() { result = argument(any(ParameterPosition pos | pos.isBlock())) }
|
||||
|
||||
/** Gets a summary component that represents an element in an array at an unknown index. */
|
||||
SummaryComponent arrayElementUnknown() { result = SC::content(TUnknownArrayElementContent()) }
|
||||
SummaryComponent arrayElementUnknown() {
|
||||
result = SC::content(TSingletonContent(TUnknownArrayElementContent()))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a summary component that represents an element in an array at a known index.
|
||||
@@ -42,7 +44,7 @@ module SummaryComponent {
|
||||
*/
|
||||
bindingset[i]
|
||||
SummaryComponent arrayElementKnown(int i) {
|
||||
result = SC::content(TKnownArrayElementContent(i))
|
||||
result = SC::content(TSingletonContent(TKnownArrayElementContent(i)))
|
||||
or
|
||||
// `i` may be out of range
|
||||
i >= 0 and
|
||||
@@ -134,7 +136,7 @@ abstract class SummarizedCallable extends LibraryCallable {
|
||||
* arguments at position `pos` to this callable.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate clearsContent(ParameterPosition pos, DataFlow::Content content) { none() }
|
||||
predicate clearsContent(ParameterPosition pos, DataFlow::ContentSet content) { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -161,7 +163,7 @@ private class SummarizedCallableAdapter extends Impl::Public::SummarizedCallable
|
||||
sc.propagatesFlow(input, output, preservesValue)
|
||||
}
|
||||
|
||||
final override predicate clearsContent(ParameterPosition pos, DataFlow::Content content) {
|
||||
final override predicate clearsContent(ParameterPosition pos, DataFlow::ContentSet content) {
|
||||
sc.clearsContent(pos, content)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -316,11 +316,15 @@ private module Cached {
|
||||
entrySsaDefinition(n)
|
||||
}
|
||||
|
||||
cached
|
||||
newtype TContentSet =
|
||||
TSingletonContent(Content c) or
|
||||
TAnyArrayElementContent()
|
||||
|
||||
cached
|
||||
newtype TContent =
|
||||
TKnownArrayElementContent(int i) { i in [0 .. 10] } or
|
||||
TUnknownArrayElementContent() or
|
||||
TAnyArrayElementContent()
|
||||
TUnknownArrayElementContent()
|
||||
|
||||
/**
|
||||
* Holds if `e` is an `ExprNode` that may be returned by a call to `c`.
|
||||
@@ -776,18 +780,12 @@ predicate jumpStep(Node pred, Node succ) {
|
||||
succ.asExpr().getExpr().(ConstantReadAccess).getValue() = pred.asExpr().getExpr()
|
||||
}
|
||||
|
||||
predicate storeStep(Node node1, Content c, Node node2) {
|
||||
predicate storeStep(Node node1, ContentSet c, Node node2) {
|
||||
FlowSummaryImpl::Private::Steps::summaryStoreStep(node1, c, node2)
|
||||
}
|
||||
|
||||
predicate readStep(Node node1, Content c, Node node2) {
|
||||
exists(Content c0 | FlowSummaryImpl::Private::Steps::summaryReadStep(node1, c0, node2) |
|
||||
if c0 = TAnyArrayElementContent()
|
||||
then
|
||||
c instanceof TUnknownArrayElementContent or
|
||||
c instanceof TKnownArrayElementContent
|
||||
else c = c0
|
||||
)
|
||||
predicate readStep(Node node1, ContentSet c, Node node2) {
|
||||
FlowSummaryImpl::Private::Steps::summaryReadStep(node1, c, node2)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -795,7 +793,7 @@ predicate readStep(Node node1, Content c, Node node2) {
|
||||
* any value stored inside `f` is cleared at the pre-update node associated with `x`
|
||||
* in `x.f = newValue`.
|
||||
*/
|
||||
predicate clearsContent(Node n, Content c) {
|
||||
predicate clearsContent(Node n, ContentSet c) {
|
||||
FlowSummaryImpl::Private::Steps::summaryClearsContent(n, c)
|
||||
}
|
||||
|
||||
@@ -875,7 +873,7 @@ int accessPathLimit() { result = 5 }
|
||||
* Holds if access paths with `c` at their head always should be tracked at high
|
||||
* precision. This disables adaptive access path precision for such access paths.
|
||||
*/
|
||||
predicate forceHighPrecision(Content c) { none() }
|
||||
predicate forceHighPrecision(Content c) { c instanceof Content::ArrayElementContent }
|
||||
|
||||
/** The unit type. */
|
||||
private newtype TUnit = TMkUnit()
|
||||
|
||||
@@ -194,14 +194,46 @@ module Content {
|
||||
class UnknownArrayElementContent extends ArrayElementContent, TUnknownArrayElementContent {
|
||||
override string toString() { result = "array element" }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used internally only, to represent the union of `KnownArrayElementContent`
|
||||
* and `UnknownArrayElementContent`, to avoid combinatorial explosions in
|
||||
* `SummaryComponentStack`s in flow summaries.
|
||||
*/
|
||||
private class AnyArrayElementContent extends Content, TAnyArrayElementContent {
|
||||
override string toString() { result = "any array element" }
|
||||
/**
|
||||
* An entity that represents a set of `Content`s.
|
||||
*
|
||||
* The set may be interpreted differently depending on whether it is
|
||||
* stored into (`getAStoreContent`) or read from (`getAReadContent`).
|
||||
*/
|
||||
class ContentSet extends TContentSet {
|
||||
/** Holds if this content set is the singleton `{c}`. */
|
||||
predicate isSingleton(Content c) { this = TSingletonContent(c) }
|
||||
|
||||
/** Holds if this content set represent all `ArrayElementContent`s. */
|
||||
predicate isAnyArrayElement() { this = TAnyArrayElementContent() }
|
||||
|
||||
/** Gets a textual representation of this content set. */
|
||||
string toString() {
|
||||
exists(Content c |
|
||||
this.isSingleton(c) and
|
||||
result = c.toString()
|
||||
)
|
||||
or
|
||||
this.isAnyArrayElement() and
|
||||
result = "any array element"
|
||||
}
|
||||
|
||||
/** Gets a content that may be stored into when storing into this set. */
|
||||
Content getAStoreContent() {
|
||||
this.isSingleton(result)
|
||||
or
|
||||
this.isAnyArrayElement() and
|
||||
result = TUnknownArrayElementContent()
|
||||
}
|
||||
|
||||
/** Gets a content that may be read from when reading from this set. */
|
||||
Content getAReadContent() {
|
||||
this.isSingleton(result)
|
||||
or
|
||||
this.isAnyArrayElement() and
|
||||
result instanceof Content::ArrayElementContent
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ Node summaryNode(SummarizedCallable c, SummaryNodeState state) { result = TSumma
|
||||
SummaryCall summaryDataFlowCall(Node receiver) { receiver = result.getReceiver() }
|
||||
|
||||
/** Gets the type of content `c`. */
|
||||
DataFlowType getContentType(Content c) { any() }
|
||||
DataFlowType getContentType(ContentSet c) { any() }
|
||||
|
||||
/** Gets the return type of kind `rk` for callable `c`. */
|
||||
bindingset[c, rk]
|
||||
|
||||
@@ -22,7 +22,7 @@ predicate defaultTaintSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
* of `c` at sinks and inputs to additional taint steps.
|
||||
*/
|
||||
bindingset[node]
|
||||
predicate defaultImplicitTaintRead(DataFlow::Node node, DataFlow::Content c) { none() }
|
||||
predicate defaultImplicitTaintRead(DataFlow::Node node, DataFlow::ContentSet c) { none() }
|
||||
|
||||
private CfgNodes::ExprNodes::VariableWriteAccessCfgNode variablesInPattern(
|
||||
CfgNodes::ExprNodes::CasePatternCfgNode p
|
||||
@@ -95,10 +95,14 @@ private module Cached {
|
||||
or
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom, nodeTo, false)
|
||||
or
|
||||
// Although flow through arrays is modelled precisely using stores/reads, we still
|
||||
// allow flow out of a _tainted_ array. This is needed in order to support taint-
|
||||
// tracking configurations where the source is an array.
|
||||
readStep(nodeFrom, any(DataFlow::Content::ArrayElementContent c), nodeTo)
|
||||
// Although flow through collections is modelled precisely using stores/reads, we still
|
||||
// allow flow out of a _tainted_ collection. This is needed in order to support taint-
|
||||
// tracking configurations where the source is a collection.
|
||||
exists(DataFlow::ContentSet c | readStep(nodeFrom, c, nodeTo) |
|
||||
c.isSingleton(any(DataFlow::Content::ArrayElementContent aec))
|
||||
or
|
||||
c.isAnyArrayElement()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -334,9 +334,9 @@ module Array {
|
||||
preservesValue = true
|
||||
}
|
||||
|
||||
override predicate clearsContent(ParameterPosition pos, DataFlow::Content content) {
|
||||
override predicate clearsContent(ParameterPosition pos, DataFlow::ContentSet content) {
|
||||
pos.isSelf() and
|
||||
content = c
|
||||
content.isSingleton(c)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -380,9 +380,9 @@ module Array {
|
||||
)
|
||||
}
|
||||
|
||||
override predicate clearsContent(ParameterPosition pos, DataFlow::Content content) {
|
||||
override predicate clearsContent(ParameterPosition pos, DataFlow::ContentSet content) {
|
||||
pos.isSelf() and
|
||||
content instanceof DataFlow::Content::KnownArrayElementContent
|
||||
content.isAnyArrayElement()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -458,9 +458,9 @@ module Array {
|
||||
private class ClearSummary extends SimpleSummarizedCallable {
|
||||
ClearSummary() { this = "clear" }
|
||||
|
||||
override predicate clearsContent(ParameterPosition pos, DataFlow::Content content) {
|
||||
override predicate clearsContent(ParameterPosition pos, DataFlow::ContentSet content) {
|
||||
pos.isSelf() and
|
||||
content instanceof DataFlow::Content::ArrayElementContent
|
||||
content.isAnyArrayElement()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -540,9 +540,9 @@ module Array {
|
||||
preservesValue = true
|
||||
}
|
||||
|
||||
override predicate clearsContent(ParameterPosition pos, DataFlow::Content content) {
|
||||
override predicate clearsContent(ParameterPosition pos, DataFlow::ContentSet content) {
|
||||
pos.isSelf() and
|
||||
content instanceof DataFlow::Content::ArrayElementContent
|
||||
content.isAnyArrayElement()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -552,9 +552,9 @@ module Array {
|
||||
bindingset[this]
|
||||
DeleteAtSummary() { mc.getMethodName() = "delete_at" }
|
||||
|
||||
override predicate clearsContent(ParameterPosition pos, DataFlow::Content content) {
|
||||
override predicate clearsContent(ParameterPosition pos, DataFlow::ContentSet content) {
|
||||
pos.isSelf() and
|
||||
content instanceof DataFlow::Content::ArrayElementContent
|
||||
content.isAnyArrayElement()
|
||||
}
|
||||
|
||||
override MethodCall getACall() { result = mc }
|
||||
@@ -612,9 +612,9 @@ module Array {
|
||||
preservesValue = true
|
||||
}
|
||||
|
||||
override predicate clearsContent(ParameterPosition pos, DataFlow::Content content) {
|
||||
override predicate clearsContent(ParameterPosition pos, DataFlow::ContentSet content) {
|
||||
pos.isSelf() and
|
||||
content instanceof DataFlow::Content::ArrayElementContent
|
||||
content.isAnyArrayElement()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -798,9 +798,9 @@ module Array {
|
||||
if exists(mc.getBlock()) then mc.getNumberOfArguments() = 0 else mc.getNumberOfArguments() = 1
|
||||
}
|
||||
|
||||
override predicate clearsContent(ParameterPosition pos, DataFlow::Content content) {
|
||||
override predicate clearsContent(ParameterPosition pos, DataFlow::ContentSet content) {
|
||||
pos.isSelf() and
|
||||
content instanceof DataFlow::Content::ArrayElementContent
|
||||
content.isAnyArrayElement()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -848,9 +848,9 @@ module Array {
|
||||
preservesValue = true
|
||||
}
|
||||
|
||||
override predicate clearsContent(ParameterPosition pos, DataFlow::Content content) {
|
||||
override predicate clearsContent(ParameterPosition pos, DataFlow::ContentSet content) {
|
||||
pos.isSelf() and
|
||||
content instanceof DataFlow::Content::ArrayElementContent
|
||||
content.isAnyArrayElement()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -910,9 +910,9 @@ module Array {
|
||||
)
|
||||
}
|
||||
|
||||
override predicate clearsContent(ParameterPosition pos, DataFlow::Content content) {
|
||||
override predicate clearsContent(ParameterPosition pos, DataFlow::ContentSet content) {
|
||||
pos.isSelf() and
|
||||
content instanceof DataFlow::Content::KnownArrayElementContent
|
||||
content.isAnyArrayElement()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -966,9 +966,9 @@ module Array {
|
||||
preservesValue = true
|
||||
}
|
||||
|
||||
override predicate clearsContent(ParameterPosition pos, DataFlow::Content content) {
|
||||
override predicate clearsContent(ParameterPosition pos, DataFlow::ContentSet content) {
|
||||
pos.isSelf() and
|
||||
content instanceof DataFlow::Content::ArrayElementContent
|
||||
content.isAnyArrayElement()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1089,9 +1089,9 @@ module Array {
|
||||
)
|
||||
}
|
||||
|
||||
override predicate clearsContent(ParameterPosition pos, DataFlow::Content content) {
|
||||
override predicate clearsContent(ParameterPosition pos, DataFlow::ContentSet content) {
|
||||
pos.isSelf() and
|
||||
content instanceof DataFlow::Content::KnownArrayElementContent
|
||||
content.isAnyArrayElement()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1147,9 +1147,9 @@ module Array {
|
||||
preservesValue = true
|
||||
}
|
||||
|
||||
override predicate clearsContent(ParameterPosition pos, DataFlow::Content content) {
|
||||
override predicate clearsContent(ParameterPosition pos, DataFlow::ContentSet content) {
|
||||
pos.isSelf() and
|
||||
content instanceof DataFlow::Content::ArrayElementContent
|
||||
content.isAnyArrayElement()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1168,9 +1168,9 @@ module Array {
|
||||
)
|
||||
}
|
||||
|
||||
override predicate clearsContent(ParameterPosition pos, DataFlow::Content content) {
|
||||
override predicate clearsContent(ParameterPosition pos, DataFlow::ContentSet content) {
|
||||
pos.isSelf() and
|
||||
content instanceof DataFlow::Content::ArrayElementContent
|
||||
content.isAnyArrayElement()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1253,9 +1253,9 @@ module Array {
|
||||
|
||||
override MethodCall getACall() { result = mc }
|
||||
|
||||
override predicate clearsContent(ParameterPosition pos, DataFlow::Content content) {
|
||||
override predicate clearsContent(ParameterPosition pos, DataFlow::ContentSet content) {
|
||||
pos.isSelf() and
|
||||
content instanceof DataFlow::Content::ArrayElementContent
|
||||
content.isAnyArrayElement()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1314,9 +1314,9 @@ module Array {
|
||||
preservesValue = true
|
||||
}
|
||||
|
||||
override predicate clearsContent(ParameterPosition pos, DataFlow::Content content) {
|
||||
override predicate clearsContent(ParameterPosition pos, DataFlow::ContentSet content) {
|
||||
pos.isSelf() and
|
||||
content instanceof DataFlow::Content::ArrayElementContent
|
||||
content.isAnyArrayElement()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1328,9 +1328,9 @@ module Array {
|
||||
|
||||
override MethodCall getACall() { result = mc }
|
||||
|
||||
override predicate clearsContent(ParameterPosition pos, DataFlow::Content content) {
|
||||
override predicate clearsContent(ParameterPosition pos, DataFlow::ContentSet content) {
|
||||
pos.isSelf() and
|
||||
content instanceof DataFlow::Content::ArrayElementContent
|
||||
content.isAnyArrayElement()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1415,9 +1415,9 @@ module Array {
|
||||
bindingset[this]
|
||||
SliceBangSummary() { mc.getMethodName() = "slice!" }
|
||||
|
||||
override predicate clearsContent(ParameterPosition pos, DataFlow::Content content) {
|
||||
override predicate clearsContent(ParameterPosition pos, DataFlow::ContentSet content) {
|
||||
pos.isSelf() and
|
||||
content instanceof DataFlow::Content::ArrayElementContent
|
||||
content.isAnyArrayElement()
|
||||
}
|
||||
|
||||
override Call getACall() { result = mc }
|
||||
@@ -1564,9 +1564,9 @@ module Array {
|
||||
preservesValue = true
|
||||
}
|
||||
|
||||
override predicate clearsContent(ParameterPosition pos, DataFlow::Content content) {
|
||||
override predicate clearsContent(ParameterPosition pos, DataFlow::ContentSet content) {
|
||||
pos.isSelf() and
|
||||
content instanceof DataFlow::Content::KnownArrayElementContent
|
||||
content.isAnyArrayElement()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1583,9 +1583,9 @@ module Array {
|
||||
preservesValue = true
|
||||
}
|
||||
|
||||
override predicate clearsContent(ParameterPosition pos, DataFlow::Content content) {
|
||||
override predicate clearsContent(ParameterPosition pos, DataFlow::ContentSet content) {
|
||||
pos.isSelf() and
|
||||
content instanceof DataFlow::Content::KnownArrayElementContent
|
||||
content.isAnyArrayElement()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1619,9 +1619,9 @@ module Array {
|
||||
preservesValue = true
|
||||
}
|
||||
|
||||
override predicate clearsContent(ParameterPosition pos, DataFlow::Content content) {
|
||||
override predicate clearsContent(ParameterPosition pos, DataFlow::ContentSet content) {
|
||||
pos.isSelf() and
|
||||
content instanceof DataFlow::Content::KnownArrayElementContent
|
||||
content.isAnyArrayElement()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3401,18 +3401,12 @@ edges
|
||||
| array_flow.rb:1604:10:1604:10 | c [array element] : | array_flow.rb:1604:10:1604:13 | ...[...] |
|
||||
| array_flow.rb:1605:10:1605:10 | c [array element] : | array_flow.rb:1605:10:1605:13 | ...[...] |
|
||||
| array_flow.rb:1605:10:1605:10 | c [array element] : | array_flow.rb:1605:10:1605:13 | ...[...] |
|
||||
| array_flow.rb:1610:5:1610:5 | [post] a [array element 0, array element 0] : | array_flow.rb:1611:10:1611:10 | a [array element 0, array element 0] : |
|
||||
| array_flow.rb:1610:5:1610:5 | [post] a [array element 0, array element 0] : | array_flow.rb:1611:10:1611:10 | a [array element 0, array element 0] : |
|
||||
| array_flow.rb:1610:5:1610:5 | [post] a [array element, array element 0] : | array_flow.rb:1611:10:1611:10 | a [array element, array element 0] : |
|
||||
| array_flow.rb:1610:5:1610:5 | [post] a [array element, array element 0] : | array_flow.rb:1611:10:1611:10 | a [array element, array element 0] : |
|
||||
| array_flow.rb:1610:5:1610:8 | [post] ...[...] [array element 0] : | array_flow.rb:1610:5:1610:5 | [post] a [array element 0, array element 0] : |
|
||||
| array_flow.rb:1610:5:1610:8 | [post] ...[...] [array element 0] : | array_flow.rb:1610:5:1610:5 | [post] a [array element 0, array element 0] : |
|
||||
| array_flow.rb:1610:5:1610:8 | [post] ...[...] [array element 0] : | array_flow.rb:1610:5:1610:5 | [post] a [array element, array element 0] : |
|
||||
| array_flow.rb:1610:5:1610:8 | [post] ...[...] [array element 0] : | array_flow.rb:1610:5:1610:5 | [post] a [array element, array element 0] : |
|
||||
| array_flow.rb:1610:15:1610:27 | call to source : | array_flow.rb:1610:5:1610:8 | [post] ...[...] [array element 0] : |
|
||||
| array_flow.rb:1610:15:1610:27 | call to source : | array_flow.rb:1610:5:1610:8 | [post] ...[...] [array element 0] : |
|
||||
| array_flow.rb:1611:10:1611:10 | a [array element 0, array element 0] : | array_flow.rb:1611:10:1611:13 | ...[...] [array element 0] : |
|
||||
| array_flow.rb:1611:10:1611:10 | a [array element 0, array element 0] : | array_flow.rb:1611:10:1611:13 | ...[...] [array element 0] : |
|
||||
| array_flow.rb:1611:10:1611:10 | a [array element, array element 0] : | array_flow.rb:1611:10:1611:13 | ...[...] [array element 0] : |
|
||||
| array_flow.rb:1611:10:1611:10 | a [array element, array element 0] : | array_flow.rb:1611:10:1611:13 | ...[...] [array element 0] : |
|
||||
| array_flow.rb:1611:10:1611:13 | ...[...] [array element 0] : | array_flow.rb:1611:10:1611:16 | ...[...] |
|
||||
@@ -7065,16 +7059,12 @@ nodes
|
||||
| array_flow.rb:1605:10:1605:10 | c [array element] : | semmle.label | c [array element] : |
|
||||
| array_flow.rb:1605:10:1605:13 | ...[...] | semmle.label | ...[...] |
|
||||
| array_flow.rb:1605:10:1605:13 | ...[...] | semmle.label | ...[...] |
|
||||
| array_flow.rb:1610:5:1610:5 | [post] a [array element 0, array element 0] : | semmle.label | [post] a [array element 0, array element 0] : |
|
||||
| array_flow.rb:1610:5:1610:5 | [post] a [array element 0, array element 0] : | semmle.label | [post] a [array element 0, array element 0] : |
|
||||
| array_flow.rb:1610:5:1610:5 | [post] a [array element, array element 0] : | semmle.label | [post] a [array element, array element 0] : |
|
||||
| array_flow.rb:1610:5:1610:5 | [post] a [array element, array element 0] : | semmle.label | [post] a [array element, array element 0] : |
|
||||
| array_flow.rb:1610:5:1610:8 | [post] ...[...] [array element 0] : | semmle.label | [post] ...[...] [array element 0] : |
|
||||
| array_flow.rb:1610:5:1610:8 | [post] ...[...] [array element 0] : | semmle.label | [post] ...[...] [array element 0] : |
|
||||
| array_flow.rb:1610:15:1610:27 | call to source : | semmle.label | call to source : |
|
||||
| array_flow.rb:1610:15:1610:27 | call to source : | semmle.label | call to source : |
|
||||
| array_flow.rb:1611:10:1611:10 | a [array element 0, array element 0] : | semmle.label | a [array element 0, array element 0] : |
|
||||
| array_flow.rb:1611:10:1611:10 | a [array element 0, array element 0] : | semmle.label | a [array element 0, array element 0] : |
|
||||
| array_flow.rb:1611:10:1611:10 | a [array element, array element 0] : | semmle.label | a [array element, array element 0] : |
|
||||
| array_flow.rb:1611:10:1611:10 | a [array element, array element 0] : | semmle.label | a [array element, array element 0] : |
|
||||
| array_flow.rb:1611:10:1611:13 | ...[...] [array element 0] : | semmle.label | ...[...] [array element 0] : |
|
||||
|
||||
Reference in New Issue
Block a user