Skip to content

Commit 23a518f

Browse files
committed
Ruby: Approximate FieldContent in data flow.
1 parent a2b6c1f commit 23a518f

1 file changed

Lines changed: 33 additions & 17 deletions

File tree

ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -676,26 +676,28 @@ private module Cached {
676676
)
677677
}
678678

679+
private predicate fieldName(string name) {
680+
name = any(InstanceVariable v).getName()
681+
or
682+
name = "@" + any(SetterMethodCall c).getTargetName()
683+
or
684+
// The following equation unfortunately leads to a non-monotonic recursion error:
685+
// name = any(AccessPathToken a).getAnArgument("Field")
686+
// Therefore, we use the following instead to extract the field names from the
687+
// external model data. This, unfortunately, does not included any field names used
688+
// in models defined in QL code.
689+
exists(string input, string output |
690+
ModelOutput::relevantSummaryModel(_, _, input, output, _, _)
691+
|
692+
name = [input, output].regexpFind("(?<=(^|\\.)Field\\[)[^\\]]+(?=\\])", _, _).trim()
693+
)
694+
}
695+
679696
cached
680697
newtype TContent =
681698
TKnownElementContent(ConstantValue cv) { trackKnownValue(cv) } or
682699
TUnknownElementContent() or
683-
TFieldContent(string name) {
684-
name = any(InstanceVariable v).getName()
685-
or
686-
name = "@" + any(SetterMethodCall c).getTargetName()
687-
or
688-
// The following equation unfortunately leads to a non-monotonic recursion error:
689-
// name = any(AccessPathToken a).getAnArgument("Field")
690-
// Therefore, we use the following instead to extract the field names from the
691-
// external model data. This, unfortunately, does not included any field names used
692-
// in models defined in QL code.
693-
exists(string input, string output |
694-
ModelOutput::relevantSummaryModel(_, _, input, output, _, _)
695-
|
696-
name = [input, output].regexpFind("(?<=(^|\\.)Field\\[)[^\\]]+(?=\\])", _, _).trim()
697-
)
698-
} or
700+
TFieldContent(string name) { fieldName(name) } or
699701
deprecated TSplatContent(int i, Boolean shifted) { i in [0 .. 10] } or
700702
deprecated THashSplatContent(ConstantValue::ConstantSymbolValue cv) or
701703
TCapturedVariableContent(VariableCapture::CapturedVariable v) or
@@ -716,12 +718,20 @@ private module Cached {
716718
)
717719
}
718720

721+
cached
722+
int fieldNameBucket(string name) {
723+
exists(int r | name = rank[r](string n | fieldName(n)) and result = r % 30)
724+
}
725+
719726
cached
720727
newtype TContentApprox =
721728
TUnknownElementContentApprox() or
722729
TKnownIntegerElementContentApprox() or
723730
TKnownElementContentApprox(string approx) { approx = approxKnownElementIndex(_) } or
724-
TNonElementContentApprox(Content c) { not c instanceof Content::ElementContent } or
731+
TFieldContentApprox(int bucket) { bucket = fieldNameBucket(_) } or
732+
TNonElementContentApprox(Content c) {
733+
not c instanceof Content::ElementContent and not c instanceof Content::FieldContent
734+
} or
725735
TCapturedVariableContentApprox(VariableCapture::CapturedVariable v)
726736

727737
cached
@@ -2268,6 +2278,10 @@ class ContentApprox extends TContentApprox {
22682278
result = "approximated element " + approx
22692279
)
22702280
or
2281+
exists(int bucket |
2282+
this = TFieldContentApprox(bucket) and result = "field bucket " + bucket.toString()
2283+
)
2284+
or
22712285
exists(Content c |
22722286
this = TNonElementContentApprox(c) and
22732287
result = c.toString()
@@ -2307,6 +2321,8 @@ ContentApprox getContentApprox(Content c) {
23072321
result =
23082322
TKnownElementContentApprox(approxKnownElementIndex(c.(Content::KnownElementContent).getIndex()))
23092323
or
2324+
result = TFieldContentApprox(fieldNameBucket(c.(Content::FieldContent).getName()))
2325+
or
23102326
result = TNonElementContentApprox(c)
23112327
}
23122328

0 commit comments

Comments
 (0)