mirror of
https://github.com/github/codeql.git
synced 2026-05-03 04:39:29 +02:00
C#: Sync files
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
private import FlowSummaryImplSpecific
|
||||
private import DataFlowImplSpecific::Private
|
||||
private import DataFlowImplSpecific::Public
|
||||
private import DataFlowImplCommon as DataFlowImplCommon
|
||||
|
||||
/** Provides classes and predicates for defining flow summaries. */
|
||||
module Public {
|
||||
@@ -178,7 +179,6 @@ module Public {
|
||||
*/
|
||||
module Private {
|
||||
private import Public
|
||||
private import DataFlowImplCommon as DataFlowImplCommon
|
||||
|
||||
newtype TSummaryComponent =
|
||||
TContentSummaryComponent(Content c) or
|
||||
@@ -580,6 +580,14 @@ module Private {
|
||||
* summaries into a `SummarizedCallable`s.
|
||||
*/
|
||||
module External {
|
||||
/** Holds if `spec` is a relevant external specification. */
|
||||
private predicate relevantSpec(string spec) {
|
||||
summaryElement(_, spec, _, _) or
|
||||
summaryElement(_, _, spec, _) or
|
||||
sourceElement(_, spec, _) or
|
||||
sinkElement(_, spec, _)
|
||||
}
|
||||
|
||||
/** Holds if the `n`th component of specification `s` is `c`. */
|
||||
predicate specSplit(string s, string c, int n) { relevantSpec(s) and s.splitAt(" of ", n) = c }
|
||||
|
||||
@@ -629,6 +637,8 @@ module Private {
|
||||
or
|
||||
exists(int pos | parseParam(c, pos) and result = SummaryComponent::parameter(pos))
|
||||
or
|
||||
c = "ReturnValue" and result = SummaryComponent::return(getReturnValueKind())
|
||||
or
|
||||
result = interpretComponentSpecific(c)
|
||||
)
|
||||
}
|
||||
@@ -664,13 +674,13 @@ module Private {
|
||||
}
|
||||
|
||||
private class SummarizedCallableExternal extends SummarizedCallable {
|
||||
SummarizedCallableExternal() { externalSummary(this, _, _, _) }
|
||||
SummarizedCallableExternal() { summaryElement(this, _, _, _) }
|
||||
|
||||
override predicate propagatesFlow(
|
||||
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue
|
||||
) {
|
||||
exists(string inSpec, string outSpec, string kind |
|
||||
externalSummary(this, inSpec, outSpec, kind) and
|
||||
summaryElement(this, inSpec, outSpec, kind) and
|
||||
interpretSpec(inSpec, 0, input) and
|
||||
interpretSpec(outSpec, 0, output)
|
||||
|
|
||||
@@ -686,6 +696,111 @@ module Private {
|
||||
specSplit(spec, c, _) and
|
||||
not exists(interpretComponent(c))
|
||||
}
|
||||
|
||||
private predicate inputNeedsReference(string c) {
|
||||
c = "Argument" or
|
||||
parseArg(c, _)
|
||||
}
|
||||
|
||||
private predicate outputNeedsReference(string c) {
|
||||
c = "Argument" or
|
||||
parseArg(c, _) or
|
||||
c = "ReturnValue"
|
||||
}
|
||||
|
||||
private predicate sourceElementRef(InterpretNode ref, string output, string kind) {
|
||||
exists(SourceOrSinkElement e |
|
||||
sourceElement(e, output, kind) and
|
||||
if outputNeedsReference(specLast(output))
|
||||
then viableCallable(ref.asCall()) = any(InterpretNode n | n.asElement() = e).asCallable()
|
||||
else ref.asElement() = e
|
||||
)
|
||||
}
|
||||
|
||||
private predicate sinkElementRef(InterpretNode ref, string input, string kind) {
|
||||
exists(SourceOrSinkElement e |
|
||||
sinkElement(e, input, kind) and
|
||||
if inputNeedsReference(specLast(input))
|
||||
then viableCallable(ref.asCall()) = any(InterpretNode n | n.asElement() = e).asCallable()
|
||||
else ref.asElement() = e
|
||||
)
|
||||
}
|
||||
|
||||
private predicate interpretOutput(string output, int idx, InterpretNode ref, InterpretNode node) {
|
||||
sourceElementRef(ref, output, _) and
|
||||
specLength(output, idx) and
|
||||
node = ref
|
||||
or
|
||||
exists(InterpretNode mid, string c |
|
||||
interpretOutput(output, idx + 1, ref, mid) and
|
||||
specSplit(output, c, idx)
|
||||
|
|
||||
exists(int pos |
|
||||
node.asNode()
|
||||
.(PostUpdateNode)
|
||||
.getPreUpdateNode()
|
||||
.(ArgumentNode)
|
||||
.argumentOf(mid.asCall(), pos)
|
||||
|
|
||||
c = "Argument" or parseArg(c, pos)
|
||||
)
|
||||
or
|
||||
exists(int pos | node.asNode().(ParameterNode).isParameterOf(mid.asCallable(), pos) |
|
||||
c = "Parameter" or parseParam(c, pos)
|
||||
)
|
||||
or
|
||||
c = "ReturnValue" and
|
||||
node.asNode() = getAnOutNode(mid.asCall(), getReturnValueKind())
|
||||
or
|
||||
interpretOutputSpecific(c, mid, node)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate interpretInput(string input, int idx, InterpretNode ref, InterpretNode node) {
|
||||
sinkElementRef(ref, input, _) and
|
||||
specLength(input, idx) and
|
||||
node = ref
|
||||
or
|
||||
exists(InterpretNode mid, string c |
|
||||
interpretInput(input, idx + 1, ref, mid) and
|
||||
specSplit(input, c, idx)
|
||||
|
|
||||
exists(int pos | node.asNode().(ArgumentNode).argumentOf(mid.asCall(), pos) |
|
||||
c = "Argument" or parseArg(c, pos)
|
||||
)
|
||||
or
|
||||
exists(ReturnNode ret |
|
||||
c = "ReturnValue" and
|
||||
ret = node.asNode() and
|
||||
ret.getKind() = getReturnValueKind() and
|
||||
mid.asCallable() = DataFlowImplCommon::getNodeEnclosingCallable(ret)
|
||||
)
|
||||
or
|
||||
interpretInputSpecific(c, mid, node)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` is specified as a source with the given kind in a CSV flow
|
||||
* model.
|
||||
*/
|
||||
predicate isSourceNode(InterpretNode node, string kind) {
|
||||
exists(InterpretNode ref, string output |
|
||||
sourceElementRef(ref, output, kind) and
|
||||
interpretOutput(output, 0, ref, node)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` is specified as a sink with the given kind in a CSV flow
|
||||
* model.
|
||||
*/
|
||||
predicate isSinkNode(InterpretNode node, string kind) {
|
||||
exists(InterpretNode ref, string input |
|
||||
sinkElementRef(ref, input, kind) and
|
||||
interpretInput(input, 0, ref, node)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** Provides a query predicate for outputting a set of relevant flow summaries. */
|
||||
|
||||
@@ -78,20 +78,15 @@ DataFlowType getCallbackReturnType(DataFlowType t, ReturnKind rk) {
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `spec` is a relevant external specification. */
|
||||
predicate relevantSpec(string spec) { none() }
|
||||
|
||||
/**
|
||||
* Holds if an external flow summary exists for `c` with input specification
|
||||
* `input`, output specification `output`, and kind `kind`.
|
||||
*/
|
||||
predicate externalSummary(DataFlowCallable c, string input, string output, string kind) { none() }
|
||||
predicate summaryElement(DataFlowCallable c, string input, string output, string kind) { none() }
|
||||
|
||||
/** Gets the summary component for specification component `c`, if any. */
|
||||
bindingset[c]
|
||||
SummaryComponent interpretComponentSpecific(string c) {
|
||||
c = "ReturnValue" and result = SummaryComponent::return(any(NormalReturnKind nrk))
|
||||
or
|
||||
c = "Element" and result = SummaryComponent::content(any(ElementContent ec))
|
||||
or
|
||||
exists(Field f |
|
||||
@@ -104,3 +99,78 @@ SummaryComponent interpretComponentSpecific(string c) {
|
||||
result = SummaryComponent::content(any(PropertyContent pc | pc.getProperty() = p))
|
||||
)
|
||||
}
|
||||
|
||||
class SourceOrSinkElement = Element;
|
||||
|
||||
/**
|
||||
* Holds if an external source specification exists for `e` with output specification
|
||||
* `output` and kind `kind`.
|
||||
*/
|
||||
predicate sourceElement(Element e, string output, string kind) { none() }
|
||||
|
||||
/**
|
||||
* Holds if an external sink specification exists for `n` with input specification
|
||||
* `input` and kind `kind`.
|
||||
*/
|
||||
predicate sinkElement(Element e, string input, string kind) { none() }
|
||||
|
||||
/** Gets the return kind corresponding to specification `"ReturnValue"`. */
|
||||
NormalReturnKind getReturnValueKind() { any() }
|
||||
|
||||
private newtype TInterpretNode =
|
||||
TElement_(Element n) or
|
||||
TNode_(Node n) or
|
||||
TDataFlowCall_(DataFlowCall c)
|
||||
|
||||
/** An entity used to interpret a source/sink specification. */
|
||||
class InterpretNode extends TInterpretNode {
|
||||
/** Gets the element that this node corresponds to, if any. */
|
||||
SourceOrSinkElement asElement() { this = TElement_(result) }
|
||||
|
||||
/** Gets the data-flow node that this node corresponds to, if any. */
|
||||
Node asNode() { this = TNode_(result) }
|
||||
|
||||
/** Gets the call that this node corresponds to, if any. */
|
||||
DataFlowCall asCall() { this = TDataFlowCall_(result) }
|
||||
|
||||
/** Gets the callable that this node corresponds to, if any. */
|
||||
DataFlowCallable asCallable() { result = this.asElement() }
|
||||
|
||||
/** Gets a textual representation of this node. */
|
||||
string toString() {
|
||||
result = this.asElement().toString()
|
||||
or
|
||||
result = this.asNode().toString()
|
||||
or
|
||||
result = this.asCall().toString()
|
||||
}
|
||||
|
||||
/** Gets the location of this node. */
|
||||
Location getLocation() {
|
||||
result = this.asElement().getLocation()
|
||||
or
|
||||
result = this.asNode().getLocation()
|
||||
or
|
||||
result = this.asCall().getLocation()
|
||||
}
|
||||
}
|
||||
|
||||
/** Provides additional sink specification logic required for attributes. */
|
||||
predicate interpretOutputSpecific(string c, InterpretNode mid, InterpretNode node) {
|
||||
exists(Node n | n = node.asNode() |
|
||||
(c = "Parameter" or c = "") and
|
||||
n.asParameter() = mid.asElement()
|
||||
or
|
||||
c = "" and
|
||||
n.asExpr().(AssignableRead).getTarget().getUnboundDeclaration() = mid.asElement()
|
||||
)
|
||||
}
|
||||
|
||||
/** Provides additional sink specification logic required for attributes. */
|
||||
predicate interpretInputSpecific(string c, InterpretNode mid, InterpretNode n) {
|
||||
c = "" and
|
||||
exists(Assignable a |
|
||||
n.asNode().asExpr() = a.getAnAssignedValue() and
|
||||
a.getUnboundDeclaration() = mid.asElement()
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user