C++: Add support for 'Element' content in dataflow.

This commit is contained in:
Mathias Vorreiter Pedersen
2024-06-19 13:39:39 +01:00
parent c158f8054e
commit 013ee9c15e
3 changed files with 44 additions and 3 deletions

View File

@@ -1325,7 +1325,7 @@ import IsUnreachableInCall
* 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 ElementContent }
/** Holds if `n` should be hidden from path explanations. */
predicate nodeIsHidden(Node n) {
@@ -1396,7 +1396,8 @@ private predicate unionHasApproxName(Cpp::Union u, string s) { s = u.getName().c
cached
private newtype TContentApprox =
TFieldApproxContent(string s) { fieldHasApproxName(_, s) } or
TUnionApproxContent(string s) { unionHasApproxName(_, s) }
TUnionApproxContent(string s) { unionHasApproxName(_, s) } or
TElementApproxContent()
/** An approximated `Content`. */
class ContentApprox extends TContentApprox {
@@ -1427,6 +1428,10 @@ private class UnionApproxContent extends ContentApprox, TUnionApproxContent {
final override string toString() { result = s }
}
private class ElementApproxContent extends ContentApprox, TElementApproxContent {
final override string toString() { result = "ElementApprox" }
}
/** Gets an approximated value for content `c`. */
pragma[inline]
ContentApprox getContentApprox(Content c) {
@@ -1441,6 +1446,9 @@ ContentApprox getContentApprox(Content c) {
u = c.(UnionContent).getUnion() and
unionHasApproxName(u, prefix)
)
or
c instanceof ElementContent and
result instanceof ElementApproxContent
}
/**
@@ -1700,6 +1708,14 @@ class DataFlowSecondLevelScope extends TDataFlowSecondLevelScope {
/** Gets the second-level scope containing the node `n`, if any. */
DataFlowSecondLevelScope getSecondLevelScope(Node n) { result.getANode() = n }
/**
* Gets the maximum number of indirections to use for `ElementContent`.
*
* This should be equal to the largest number of stars (i.e., `*`s) in any
* `Element` content across all of our MaD summaries, sources, and sinks.
*/
int getMaxElementContentIndirectionIndex() { result = 5 }
/**
* Module that defines flow through iterators.
* For example,

View File

@@ -2083,6 +2083,9 @@ private newtype TContent =
indirectionIndex =
[1 .. max(Ssa::getMaxIndirectionsForType(getAFieldWithSize(u, bytes).getUnspecifiedType()))]
)
} or
TElementContent(int indirectionIndex) {
indirectionIndex = [1 .. getMaxElementContentIndirectionIndex()]
}
/**
@@ -2193,6 +2196,25 @@ class UnionContent extends Content, TUnionContent {
}
}
/**
* A `Content` that represents one of the elements of a
* container (e.g., `std::vector`).
*/
class ElementContent extends Content, TElementContent {
int indirectionIndex;
ElementContent() { this = TElementContent(indirectionIndex) }
pragma[inline]
override int getIndirectionIndex() {
pragma[only_bind_into](result) = pragma[only_bind_out](indirectionIndex)
}
override predicate impliesClearOf(Content c) { none() }
override string toString() { result = contentStars(this) + "element" }
}
/**
* An entity that represents a set of `Content`s.
*

View File

@@ -147,7 +147,10 @@ predicate defaultAdditionalTaintStep(DataFlow::Node src, DataFlow::Node sink, st
* of `c` at sinks and inputs to additional taint steps.
*/
bindingset[node]
predicate defaultImplicitTaintRead(DataFlow::Node node, DataFlow::ContentSet c) { none() }
predicate defaultImplicitTaintRead(DataFlow::Node node, DataFlow::ContentSet c) {
node instanceof ArgumentNode and
c.isSingleton(any(ElementContent ec))
}
/**
* Holds if `node` should be a sanitizer in all global taint flow configurations