mirror of
https://github.com/github/codeql.git
synced 2025-12-24 04:36:35 +01:00
python: sync file
This commit is contained in:
@@ -26,6 +26,10 @@ module Public {
|
|||||||
string toString() {
|
string toString() {
|
||||||
exists(ContentSet c | this = TContentSummaryComponent(c) and result = c.toString())
|
exists(ContentSet c | this = TContentSummaryComponent(c) and result = c.toString())
|
||||||
or
|
or
|
||||||
|
exists(ContentSet c | this = TWithoutContentSummaryComponent(c) and result = "without " + c)
|
||||||
|
or
|
||||||
|
exists(ContentSet c | this = TWithContentSummaryComponent(c) and result = "with " + c)
|
||||||
|
or
|
||||||
exists(ArgumentPosition pos |
|
exists(ArgumentPosition pos |
|
||||||
this = TParameterSummaryComponent(pos) and result = "parameter " + pos
|
this = TParameterSummaryComponent(pos) and result = "parameter " + pos
|
||||||
)
|
)
|
||||||
@@ -43,6 +47,12 @@ module Public {
|
|||||||
/** Gets a summary component for content `c`. */
|
/** Gets a summary component for content `c`. */
|
||||||
SummaryComponent content(ContentSet c) { result = TContentSummaryComponent(c) }
|
SummaryComponent content(ContentSet c) { result = TContentSummaryComponent(c) }
|
||||||
|
|
||||||
|
/** Gets a summary component where data is not allowed to be stored in `c`. */
|
||||||
|
SummaryComponent withoutContent(ContentSet c) { result = TWithoutContentSummaryComponent(c) }
|
||||||
|
|
||||||
|
/** Gets a summary component where data must be stored in `c`. */
|
||||||
|
SummaryComponent withContent(ContentSet c) { result = TWithContentSummaryComponent(c) }
|
||||||
|
|
||||||
/** Gets a summary component for a parameter at position `pos`. */
|
/** Gets a summary component for a parameter at position `pos`. */
|
||||||
SummaryComponent parameter(ArgumentPosition pos) { result = TParameterSummaryComponent(pos) }
|
SummaryComponent parameter(ArgumentPosition pos) { result = TParameterSummaryComponent(pos) }
|
||||||
|
|
||||||
@@ -216,6 +226,8 @@ module Public {
|
|||||||
/**
|
/**
|
||||||
* Holds if values stored inside `content` are cleared on objects passed as
|
* Holds if values stored inside `content` are cleared on objects passed as
|
||||||
* arguments at position `pos` to this callable.
|
* arguments at position `pos` to this callable.
|
||||||
|
*
|
||||||
|
* TODO: Remove once all languages support `WithoutContent` tokens.
|
||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate clearsContent(ParameterPosition pos, ContentSet content) { none() }
|
predicate clearsContent(ParameterPosition pos, ContentSet content) { none() }
|
||||||
@@ -239,7 +251,9 @@ module Private {
|
|||||||
TContentSummaryComponent(ContentSet c) or
|
TContentSummaryComponent(ContentSet c) or
|
||||||
TParameterSummaryComponent(ArgumentPosition pos) or
|
TParameterSummaryComponent(ArgumentPosition pos) or
|
||||||
TArgumentSummaryComponent(ParameterPosition pos) or
|
TArgumentSummaryComponent(ParameterPosition pos) or
|
||||||
TReturnSummaryComponent(ReturnKind rk)
|
TReturnSummaryComponent(ReturnKind rk) or
|
||||||
|
TWithoutContentSummaryComponent(ContentSet c) or
|
||||||
|
TWithContentSummaryComponent(ContentSet c)
|
||||||
|
|
||||||
private TParameterSummaryComponent thisParam() {
|
private TParameterSummaryComponent thisParam() {
|
||||||
result = TParameterSummaryComponent(instanceParameterPosition())
|
result = TParameterSummaryComponent(instanceParameterPosition())
|
||||||
@@ -301,6 +315,23 @@ module Private {
|
|||||||
SummaryComponentStack::singleton(TArgumentSummaryComponent(_))) and
|
SummaryComponentStack::singleton(TArgumentSummaryComponent(_))) and
|
||||||
preservesValue = preservesValue1.booleanAnd(preservesValue2)
|
preservesValue = preservesValue1.booleanAnd(preservesValue2)
|
||||||
)
|
)
|
||||||
|
or
|
||||||
|
exists(ParameterPosition ppos, ContentSet cs |
|
||||||
|
c.clearsContent(ppos, cs) and
|
||||||
|
input = SummaryComponentStack::push(SummaryComponent::withoutContent(cs), output) and
|
||||||
|
output = SummaryComponentStack::argument(ppos) and
|
||||||
|
preservesValue = true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private class MkClearStack extends RequiredSummaryComponentStack {
|
||||||
|
override predicate required(SummaryComponent head, SummaryComponentStack tail) {
|
||||||
|
exists(SummarizedCallable sc, ParameterPosition ppos, ContentSet cs |
|
||||||
|
sc.clearsContent(ppos, cs) and
|
||||||
|
head = SummaryComponent::withoutContent(cs) and
|
||||||
|
tail = SummaryComponentStack::argument(ppos)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -383,10 +414,7 @@ module Private {
|
|||||||
|
|
||||||
private newtype TSummaryNodeState =
|
private newtype TSummaryNodeState =
|
||||||
TSummaryNodeInputState(SummaryComponentStack s) { inputState(_, s) } or
|
TSummaryNodeInputState(SummaryComponentStack s) { inputState(_, s) } or
|
||||||
TSummaryNodeOutputState(SummaryComponentStack s) { outputState(_, s) } or
|
TSummaryNodeOutputState(SummaryComponentStack s) { outputState(_, s) }
|
||||||
TSummaryNodeClearsContentState(ParameterPosition pos, boolean post) {
|
|
||||||
any(SummarizedCallable sc).clearsContent(pos, _) and post in [false, true]
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A state used to break up (complex) flow summaries into atomic flow steps.
|
* A state used to break up (complex) flow summaries into atomic flow steps.
|
||||||
@@ -433,12 +461,6 @@ module Private {
|
|||||||
this = TSummaryNodeOutputState(s) and
|
this = TSummaryNodeOutputState(s) and
|
||||||
result = "to write: " + s
|
result = "to write: " + s
|
||||||
)
|
)
|
||||||
or
|
|
||||||
exists(ParameterPosition pos, boolean post, string postStr |
|
|
||||||
this = TSummaryNodeClearsContentState(pos, post) and
|
|
||||||
(if post = true then postStr = " (post)" else postStr = "") and
|
|
||||||
result = "clear: " + pos + postStr
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -462,11 +484,6 @@ module Private {
|
|||||||
not parameterReadState(c, state, _)
|
not parameterReadState(c, state, _)
|
||||||
or
|
or
|
||||||
state.isOutputState(c, _)
|
state.isOutputState(c, _)
|
||||||
or
|
|
||||||
exists(ParameterPosition pos |
|
|
||||||
c.clearsContent(pos, _) and
|
|
||||||
state = TSummaryNodeClearsContentState(pos, _)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
@@ -502,8 +519,6 @@ module Private {
|
|||||||
parameterReadState(c, _, pos)
|
parameterReadState(c, _, pos)
|
||||||
or
|
or
|
||||||
isParameterPostUpdate(_, c, pos)
|
isParameterPostUpdate(_, c, pos)
|
||||||
or
|
|
||||||
c.clearsContent(pos, _)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private predicate callbackOutput(
|
private predicate callbackOutput(
|
||||||
@@ -511,7 +526,7 @@ module Private {
|
|||||||
) {
|
) {
|
||||||
any(SummaryNodeState state).isInputState(c, s) and
|
any(SummaryNodeState state).isInputState(c, s) and
|
||||||
s.head() = TReturnSummaryComponent(rk) and
|
s.head() = TReturnSummaryComponent(rk) and
|
||||||
receiver = summaryNodeInputState(c, s.drop(1))
|
receiver = summaryNodeInputState(c, s.tail())
|
||||||
}
|
}
|
||||||
|
|
||||||
private predicate callbackInput(
|
private predicate callbackInput(
|
||||||
@@ -519,7 +534,7 @@ module Private {
|
|||||||
) {
|
) {
|
||||||
any(SummaryNodeState state).isOutputState(c, s) and
|
any(SummaryNodeState state).isOutputState(c, s) and
|
||||||
s.head() = TParameterSummaryComponent(pos) and
|
s.head() = TParameterSummaryComponent(pos) and
|
||||||
receiver = summaryNodeInputState(c, s.drop(1))
|
receiver = summaryNodeInputState(c, s.tail())
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Holds if a call targeting `receiver` should be synthesized inside `c`. */
|
/** Holds if a call targeting `receiver` should be synthesized inside `c`. */
|
||||||
@@ -545,15 +560,21 @@ module Private {
|
|||||||
exists(SummarizedCallable c, SummaryComponentStack s, SummaryComponent head | head = s.head() |
|
exists(SummarizedCallable c, SummaryComponentStack s, SummaryComponent head | head = s.head() |
|
||||||
n = summaryNodeInputState(c, s) and
|
n = summaryNodeInputState(c, s) and
|
||||||
(
|
(
|
||||||
|
exists(ContentSet cont | result = getContentType(cont) |
|
||||||
|
head = TContentSummaryComponent(cont) or
|
||||||
|
head = TWithContentSummaryComponent(cont)
|
||||||
|
)
|
||||||
|
or
|
||||||
exists(ContentSet cont |
|
exists(ContentSet cont |
|
||||||
head = TContentSummaryComponent(cont) and result = getContentType(cont)
|
head = TWithoutContentSummaryComponent(cont) and
|
||||||
|
result = getNodeType(summaryNodeInputState(c, s.tail()))
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(ReturnKind rk |
|
exists(ReturnKind rk |
|
||||||
head = TReturnSummaryComponent(rk) and
|
head = TReturnSummaryComponent(rk) and
|
||||||
result =
|
result =
|
||||||
getCallbackReturnType(getNodeType(summaryNodeInputState(pragma[only_bind_out](c),
|
getCallbackReturnType(getNodeType(summaryNodeInputState(pragma[only_bind_out](c),
|
||||||
s.drop(1))), rk)
|
s.tail())), rk)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
@@ -572,16 +593,10 @@ module Private {
|
|||||||
exists(ArgumentPosition pos | head = TParameterSummaryComponent(pos) |
|
exists(ArgumentPosition pos | head = TParameterSummaryComponent(pos) |
|
||||||
result =
|
result =
|
||||||
getCallbackParameterType(getNodeType(summaryNodeInputState(pragma[only_bind_out](c),
|
getCallbackParameterType(getNodeType(summaryNodeInputState(pragma[only_bind_out](c),
|
||||||
s.drop(1))), pos)
|
s.tail())), pos)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
or
|
|
||||||
exists(SummarizedCallable c, ParameterPosition pos, ParamNode p |
|
|
||||||
n = summaryNode(c, TSummaryNodeClearsContentState(pos, false)) and
|
|
||||||
p.isParameterOf(c, pos) and
|
|
||||||
result = getNodeType(p)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Holds if summary node `out` contains output of kind `rk` from call `c`. */
|
/** Holds if summary node `out` contains output of kind `rk` from call `c`. */
|
||||||
@@ -607,9 +622,6 @@ module Private {
|
|||||||
exists(SummarizedCallable c, ParameterPosition pos |
|
exists(SummarizedCallable c, ParameterPosition pos |
|
||||||
isParameterPostUpdate(post, c, pos) and
|
isParameterPostUpdate(post, c, pos) and
|
||||||
pre.(ParamNode).isParameterOf(c, pos)
|
pre.(ParamNode).isParameterOf(c, pos)
|
||||||
or
|
|
||||||
pre = summaryNode(c, TSummaryNodeClearsContentState(pos, false)) and
|
|
||||||
post = summaryNode(c, TSummaryNodeClearsContentState(pos, true))
|
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(SummarizedCallable callable, SummaryComponentStack s |
|
exists(SummarizedCallable callable, SummaryComponentStack s |
|
||||||
@@ -633,8 +645,6 @@ module Private {
|
|||||||
*/
|
*/
|
||||||
predicate summaryAllowParameterReturnInSelf(ParamNode p) {
|
predicate summaryAllowParameterReturnInSelf(ParamNode p) {
|
||||||
exists(SummarizedCallable c, ParameterPosition ppos | p.isParameterOf(c, ppos) |
|
exists(SummarizedCallable c, ParameterPosition ppos | p.isParameterOf(c, ppos) |
|
||||||
c.clearsContent(ppos, _)
|
|
||||||
or
|
|
||||||
exists(SummaryComponentStack inputContents, SummaryComponentStack outputContents |
|
exists(SummaryComponentStack inputContents, SummaryComponentStack outputContents |
|
||||||
summary(c, inputContents, outputContents, _) and
|
summary(c, inputContents, outputContents, _) and
|
||||||
inputContents.bottom() = pragma[only_bind_into](TArgumentSummaryComponent(ppos)) and
|
inputContents.bottom() = pragma[only_bind_into](TArgumentSummaryComponent(ppos)) and
|
||||||
@@ -663,9 +673,10 @@ module Private {
|
|||||||
preservesValue = false and not summary(c, inputContents, outputContents, true)
|
preservesValue = false and not summary(c, inputContents, outputContents, true)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(SummarizedCallable c, ParameterPosition pos |
|
exists(SummarizedCallable c, SummaryComponentStack s |
|
||||||
pred.(ParamNode).isParameterOf(c, pos) and
|
pred = summaryNodeInputState(c, s.tail()) and
|
||||||
succ = summaryNode(c, TSummaryNodeClearsContentState(pos, _)) and
|
succ = summaryNodeInputState(c, s) and
|
||||||
|
s.head() = [SummaryComponent::withContent(_), SummaryComponent::withoutContent(_)] and
|
||||||
preservesValue = true
|
preservesValue = true
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -676,7 +687,7 @@ module Private {
|
|||||||
*/
|
*/
|
||||||
predicate summaryReadStep(Node pred, ContentSet c, Node succ) {
|
predicate summaryReadStep(Node pred, ContentSet c, Node succ) {
|
||||||
exists(SummarizedCallable sc, SummaryComponentStack s |
|
exists(SummarizedCallable sc, SummaryComponentStack s |
|
||||||
pred = summaryNodeInputState(sc, s.drop(1)) and
|
pred = summaryNodeInputState(sc, s.tail()) and
|
||||||
succ = summaryNodeInputState(sc, s) and
|
succ = summaryNodeInputState(sc, s) and
|
||||||
SummaryComponent::content(c) = s.head()
|
SummaryComponent::content(c) = s.head()
|
||||||
)
|
)
|
||||||
@@ -689,7 +700,7 @@ module Private {
|
|||||||
predicate summaryStoreStep(Node pred, ContentSet c, Node succ) {
|
predicate summaryStoreStep(Node pred, ContentSet c, Node succ) {
|
||||||
exists(SummarizedCallable sc, SummaryComponentStack s |
|
exists(SummarizedCallable sc, SummaryComponentStack s |
|
||||||
pred = summaryNodeOutputState(sc, s) and
|
pred = summaryNodeOutputState(sc, s) and
|
||||||
succ = summaryNodeOutputState(sc, s.drop(1)) and
|
succ = summaryNodeOutputState(sc, s.tail()) and
|
||||||
SummaryComponent::content(c) = s.head()
|
SummaryComponent::content(c) = s.head()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -714,9 +725,22 @@ module Private {
|
|||||||
* node where field `b` is cleared).
|
* node where field `b` is cleared).
|
||||||
*/
|
*/
|
||||||
predicate summaryClearsContent(Node n, ContentSet c) {
|
predicate summaryClearsContent(Node n, ContentSet c) {
|
||||||
exists(SummarizedCallable sc, ParameterPosition pos |
|
exists(SummarizedCallable sc, SummaryNodeState state, SummaryComponentStack stack |
|
||||||
n = summaryNode(sc, TSummaryNodeClearsContentState(pos, true)) and
|
n = summaryNode(sc, state) and
|
||||||
sc.clearsContent(pos, c)
|
state.isInputState(sc, stack) and
|
||||||
|
stack.head() = SummaryComponent::withoutContent(c)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if the value that is being tracked is expected to be stored inside
|
||||||
|
* content `c` at `n`.
|
||||||
|
*/
|
||||||
|
predicate summaryExpectsContent(Node n, ContentSet c) {
|
||||||
|
exists(SummarizedCallable sc, SummaryNodeState state, SummaryComponentStack stack |
|
||||||
|
n = summaryNode(sc, state) and
|
||||||
|
state.isInputState(sc, stack) and
|
||||||
|
stack.head() = SummaryComponent::withContent(c)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -728,22 +752,6 @@ module Private {
|
|||||||
sc = viableCallable(call)
|
sc = viableCallable(call)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if values stored inside content `c` are cleared inside a
|
|
||||||
* callable to which `arg` is an argument.
|
|
||||||
*
|
|
||||||
* In such cases, it is important to prevent use-use flow out of
|
|
||||||
* `arg` (see comment for `summaryClearsContent`).
|
|
||||||
*/
|
|
||||||
pragma[nomagic]
|
|
||||||
predicate summaryClearsContentArg(ArgNode arg, ContentSet c) {
|
|
||||||
exists(DataFlowCall call, SummarizedCallable sc, ParameterPosition ppos |
|
|
||||||
argumentPositionMatch(call, arg, ppos) and
|
|
||||||
viableParam(call, sc, ppos, _) and
|
|
||||||
sc.clearsContent(ppos, c)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private ParamNode summaryArgParam0(DataFlowCall call, ArgNode arg) {
|
private ParamNode summaryArgParam0(DataFlowCall call, ArgNode arg) {
|
||||||
exists(ParameterPosition ppos, SummarizedCallable sc |
|
exists(ParameterPosition ppos, SummarizedCallable sc |
|
||||||
@@ -752,6 +760,27 @@ module Private {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if use-use flow starting from `arg` should be prohibited.
|
||||||
|
*
|
||||||
|
* This is the case when `arg` is the argument of a call that targets a
|
||||||
|
* flow summary where the corresponding parameter either clears contents
|
||||||
|
* or expects contents.
|
||||||
|
*/
|
||||||
|
pragma[nomagic]
|
||||||
|
predicate prohibitsUseUseFlow(ArgNode arg) {
|
||||||
|
exists(ParamNode p, Node mid, ParameterPosition ppos, Node ret |
|
||||||
|
p = summaryArgParam0(_, arg) and
|
||||||
|
p.isParameterOf(_, ppos) and
|
||||||
|
summaryLocalStep(p, mid, true) and
|
||||||
|
summaryLocalStep(mid, ret, true) and
|
||||||
|
isParameterPostUpdate(ret, _, ppos)
|
||||||
|
|
|
||||||
|
summaryClearsContent(mid, _) or
|
||||||
|
summaryExpectsContent(mid, _)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private ParamNode summaryArgParam(ArgNode arg, ReturnKindExt rk, OutNodeExt out) {
|
private ParamNode summaryArgParam(ArgNode arg, ReturnKindExt rk, OutNodeExt out) {
|
||||||
exists(DataFlowCall call |
|
exists(DataFlowCall call |
|
||||||
@@ -1152,6 +1181,10 @@ module Private {
|
|||||||
Private::Steps::summaryClearsContent(a.asNode(), c) and
|
Private::Steps::summaryClearsContent(a.asNode(), c) and
|
||||||
b = a and
|
b = a and
|
||||||
value = "clear (" + c + ")"
|
value = "clear (" + c + ")"
|
||||||
|
or
|
||||||
|
Private::Steps::summaryExpectsContent(a.asNode(), c) and
|
||||||
|
b = a and
|
||||||
|
value = "expect (" + c + ")"
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
summaryPostUpdateNode(b.asNode(), a.asNode()) and
|
summaryPostUpdateNode(b.asNode(), a.asNode()) and
|
||||||
|
|||||||
Reference in New Issue
Block a user