Merge branch 'main' into js-use-shared-cryptography

This commit is contained in:
Alex Ford
2023-02-15 17:13:53 +00:00
committed by GitHub
774 changed files with 129170 additions and 17057 deletions

View File

@@ -0,0 +1,7 @@
---
category: breaking
---
- Python 2 is no longer supported for extracting databases using the CodeQL CLI. As a consequence,
the previously deprecated support for `pyxl` and `spitfire` templates has also been removed. When
extracting Python 2 code, having Python 2 installed is still recommended, as this ensures the
correct version of the Python standard library is extracted.

View File

@@ -3,32 +3,34 @@
import python
/** the Python major version number */
int major_version() {
explicit_major_version(result)
or
not explicit_major_version(_) and
/* If there is more than one version, prefer 2 for backwards compatibility */
(if py_flags_versioned("version.major", "2", "2") then result = 2 else result = 3)
}
int major_version() { full_python_analysis_version(result, _, _) }
/** the Python minor version number */
int minor_version() {
exists(string v | py_flags_versioned("version.minor", v, major_version().toString()) |
result = v.toInt()
)
}
int minor_version() { full_python_analysis_version(_, result, _) }
/** the Python micro version number */
int micro_version() {
exists(string v | py_flags_versioned("version.micro", v, major_version().toString()) |
result = v.toInt()
)
int micro_version() { full_python_analysis_version(_, _, result) }
/** Gets the latest supported minor version for the given major version. */
private int latest_supported_minor_version(int major) {
major = 2 and result = 7
or
major = 3 and result = 11
}
private predicate explicit_major_version(int v) {
exists(string version | py_flags_versioned("language.version", version, _) |
version.charAt(0) = "2" and v = 2
or
version.charAt(0) = "3" and v = 3
private predicate full_python_analysis_version(int major, int minor, int micro) {
exists(string version_string | py_flags_versioned("language.version", version_string, _) |
major = version_string.regexpFind("\\d+", 0, _).toInt() and
(
minor = version_string.regexpFind("\\d+", 1, _).toInt()
or
not exists(version_string.regexpFind("\\d+", 1, _)) and
minor = latest_supported_minor_version(major)
) and
(
micro = version_string.regexpFind("\\d+", 2, _).toInt()
or
not exists(version_string.regexpFind("\\d+", 2, _)) and micro = 0
)
)
}

View File

@@ -14,8 +14,20 @@
predicate isStrongHashingAlgorithm(string name) {
name =
[
// see https://cryptography.io/en/latest/hazmat/primitives/cryptographic-hashes/#blake2
// and https://www.blake2.net/
"BLAKE2", "BLAKE2B", "BLAKE2S",
// see https://github.com/BLAKE3-team/BLAKE3
"BLAKE3",
//
"DSA", "ED25519", "ES256", "ECDSA256", "ES384", "ECDSA384", "ES512", "ECDSA512", "SHA2",
"SHA224", "SHA256", "SHA384", "SHA512", "SHA3", "SHA3224", "SHA3256", "SHA3384", "SHA3512"
"SHA224", "SHA256", "SHA384", "SHA512", "SHA3", "SHA3224", "SHA3256", "SHA3384", "SHA3512",
// see https://cryptography.io/en/latest/hazmat/primitives/cryptographic-hashes/#cryptography.hazmat.primitives.hashes.SHAKE128
"SHAKE128", "SHAKE256",
// see https://cryptography.io/en/latest/hazmat/primitives/cryptographic-hashes/#sm3
"SM3",
// see https://security.stackexchange.com/a/216297
"WHIRLPOOL",
]
}

View File

@@ -667,23 +667,78 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true and
not fullBarrier(node, config)
)
fwdFlowIn(_, _, _, node, config) and
cc = true
or
// flow out of a callable
fwdFlowOut(_, node, false, config) and
cc = false
or
// flow through a callable
exists(DataFlowCall call |
fwdFlowOut(call, node, false, config) and
cc = false
or
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
}
// inline to reduce the number of iterations
pragma[inline]
private predicate fwdFlowIn(
DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config
) {
// call context cannot help reduce virtual dispatch
fwdFlow(arg, cc, config) and
viableParamArgEx(call, p, arg) and
not fullBarrier(p, config) and
(
cc = false
or
cc = true and
not reducedViableImplInCallContext(call, _, _)
)
or
// call context may help reduce virtual dispatch
exists(DataFlowCallable target |
fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and
target = viableImplInSomeFwdFlowCallContextExt(call, config) and
cc = true
)
}
/**
* Holds if an argument to `call` is reached in the flow covered by `fwdFlow`.
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
fwdFlowIn(call, _, cc, _, config)
}
pragma[nomagic]
private predicate fwdFlowInReducedViableImplInSomeCallContext(
DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config
) {
fwdFlow(arg, true, config) and
viableParamArgEx(call, p, arg) and
reducedViableImplInCallContext(call, _, _) and
target = p.getEnclosingCallable() and
not fullBarrier(p, config)
}
/**
* Gets a viable dispatch target of `call` in the context `ctx`. This is
* restricted to those `call`s for which a context might make a difference,
* and to `ctx`s that are reachable in `fwdFlow`.
*/
pragma[nomagic]
private DataFlowCallable viableImplInSomeFwdFlowCallContextExt(
DataFlowCall call, Configuration config
) {
exists(DataFlowCall ctx |
fwdFlowIsEntered(ctx, _, config) and
result = viableImplInCallContextExt(call, ctx)
)
}
private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) }
pragma[nomagic]
@@ -726,7 +781,8 @@ private module Stage1 implements StageSig {
)
}
pragma[nomagic]
// inline to reduce the number of iterations
pragma[inline]
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
@@ -740,17 +796,6 @@ private module Stage1 implements StageSig {
fwdFlowOut(call, out, true, config)
}
/**
* Holds if an argument to `call` is reached in the flow covered by `fwdFlow`.
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
exists(ArgNodeEx arg |
fwdFlow(arg, cc, config) and
viableParamArgEx(call, _, arg)
)
}
private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) {
exists(NodeEx node1 |
additionalLocalStateStep(node1, state1, _, state2, config) or
@@ -817,13 +862,8 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
exists(DataFlowCall call |
revFlowIn(call, node, false, config) and
toReturn = false
or
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
revFlowIn(_, node, false, config) and
toReturn = false
or
// flow out of a callable
exists(ReturnPosition pos |
@@ -831,6 +871,12 @@ private module Stage1 implements StageSig {
node.(RetNodeEx).getReturnPosition() = pos and
toReturn = true
)
or
// flow through a callable
exists(DataFlowCall call |
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
}
/**
@@ -886,11 +932,11 @@ private module Stage1 implements StageSig {
additional predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
) {
viableParamArgEx(call, p, arg) and
fwdFlow(arg, config)
fwdFlowIn(call, arg, _, p, config)
}
pragma[nomagic]
// inline to reduce the number of iterations
pragma[inline]
private predicate revFlowIn(
DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config
) {
@@ -1223,7 +1269,16 @@ private module MkStage<StageSig PrevStage> {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail);
Content getHeadContent(Ap ap);
/**
* An approximation of `Content` that corresponds to the precision level of
* `Ap`, such that the mappings from both `Ap` and `Content` to this type
* are functional.
*/
class ApHeadContent;
ApHeadContent getHeadContent(Ap ap);
ApHeadContent projectToHeadContent(Content c);
class ApOption;
@@ -1471,34 +1526,32 @@ private module MkStage<StageSig PrevStage> {
)
}
private class ApNonNil instanceof Ap {
pragma[nomagic]
ApNonNil() { not this instanceof ApNil }
string toString() { result = "" }
}
pragma[nomagic]
private predicate fwdFlowRead0(
NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap,
Configuration config
private predicate readStepCand(
NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config
) {
fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, _, _, config)
PrevStage::readStepCand(node1, c, node2, config) and
apc = projectToHeadContent(c)
}
bindingset[ap, c]
bindingset[node1, apc]
pragma[inline_late]
private predicate hasHeadContent(Ap ap, Content c) { getHeadContent(ap) = c }
private predicate readStepCand0(
NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config
) {
readStepCand(node1, apc, c, node2, config)
}
pragma[nomagic]
private predicate fwdFlowRead(
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
ParamNodeOption summaryCtx, ApOption argAp, Configuration config
) {
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, c, node2, config) and
hasHeadContent(ap, c)
exists(ApHeadContent apc |
fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and
apc = getHeadContent(ap) and
readStepCand0(node1, apc, c, node2, config)
)
}
pragma[nomagic]
@@ -2072,8 +2125,12 @@ private module Stage2Param implements MkStage<Stage1>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) }
class ApHeadContent = Unit;
pragma[inline]
Content getHeadContent(Ap ap) { exists(result) and ap = true }
ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true }
ApHeadContent projectToHeadContent(Content c) { any() }
class ApOption = BooleanOption;
@@ -2337,8 +2394,12 @@ private module Stage3Param implements MkStage<Stage2>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) }
class ApHeadContent = ContentApprox;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getAHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
predicate projectToHeadContent = getContentApprox/1;
class ApOption = ApproxAccessPathFrontOption;
@@ -2413,8 +2474,12 @@ private module Stage4Param implements MkStage<Stage3>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) }
class ApHeadContent = Content;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent projectToHeadContent(Content c) { result = c }
class ApOption = AccessPathFrontOption;
@@ -2743,8 +2808,12 @@ private module Stage5Param implements MkStage<Stage4>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) }
class ApHeadContent = Content;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent projectToHeadContent(Content c) { result = c }
class ApOption = AccessPathApproxOption;

View File

@@ -667,23 +667,78 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true and
not fullBarrier(node, config)
)
fwdFlowIn(_, _, _, node, config) and
cc = true
or
// flow out of a callable
fwdFlowOut(_, node, false, config) and
cc = false
or
// flow through a callable
exists(DataFlowCall call |
fwdFlowOut(call, node, false, config) and
cc = false
or
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
}
// inline to reduce the number of iterations
pragma[inline]
private predicate fwdFlowIn(
DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config
) {
// call context cannot help reduce virtual dispatch
fwdFlow(arg, cc, config) and
viableParamArgEx(call, p, arg) and
not fullBarrier(p, config) and
(
cc = false
or
cc = true and
not reducedViableImplInCallContext(call, _, _)
)
or
// call context may help reduce virtual dispatch
exists(DataFlowCallable target |
fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and
target = viableImplInSomeFwdFlowCallContextExt(call, config) and
cc = true
)
}
/**
* Holds if an argument to `call` is reached in the flow covered by `fwdFlow`.
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
fwdFlowIn(call, _, cc, _, config)
}
pragma[nomagic]
private predicate fwdFlowInReducedViableImplInSomeCallContext(
DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config
) {
fwdFlow(arg, true, config) and
viableParamArgEx(call, p, arg) and
reducedViableImplInCallContext(call, _, _) and
target = p.getEnclosingCallable() and
not fullBarrier(p, config)
}
/**
* Gets a viable dispatch target of `call` in the context `ctx`. This is
* restricted to those `call`s for which a context might make a difference,
* and to `ctx`s that are reachable in `fwdFlow`.
*/
pragma[nomagic]
private DataFlowCallable viableImplInSomeFwdFlowCallContextExt(
DataFlowCall call, Configuration config
) {
exists(DataFlowCall ctx |
fwdFlowIsEntered(ctx, _, config) and
result = viableImplInCallContextExt(call, ctx)
)
}
private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) }
pragma[nomagic]
@@ -726,7 +781,8 @@ private module Stage1 implements StageSig {
)
}
pragma[nomagic]
// inline to reduce the number of iterations
pragma[inline]
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
@@ -740,17 +796,6 @@ private module Stage1 implements StageSig {
fwdFlowOut(call, out, true, config)
}
/**
* Holds if an argument to `call` is reached in the flow covered by `fwdFlow`.
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
exists(ArgNodeEx arg |
fwdFlow(arg, cc, config) and
viableParamArgEx(call, _, arg)
)
}
private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) {
exists(NodeEx node1 |
additionalLocalStateStep(node1, state1, _, state2, config) or
@@ -817,13 +862,8 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
exists(DataFlowCall call |
revFlowIn(call, node, false, config) and
toReturn = false
or
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
revFlowIn(_, node, false, config) and
toReturn = false
or
// flow out of a callable
exists(ReturnPosition pos |
@@ -831,6 +871,12 @@ private module Stage1 implements StageSig {
node.(RetNodeEx).getReturnPosition() = pos and
toReturn = true
)
or
// flow through a callable
exists(DataFlowCall call |
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
}
/**
@@ -886,11 +932,11 @@ private module Stage1 implements StageSig {
additional predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
) {
viableParamArgEx(call, p, arg) and
fwdFlow(arg, config)
fwdFlowIn(call, arg, _, p, config)
}
pragma[nomagic]
// inline to reduce the number of iterations
pragma[inline]
private predicate revFlowIn(
DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config
) {
@@ -1223,7 +1269,16 @@ private module MkStage<StageSig PrevStage> {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail);
Content getHeadContent(Ap ap);
/**
* An approximation of `Content` that corresponds to the precision level of
* `Ap`, such that the mappings from both `Ap` and `Content` to this type
* are functional.
*/
class ApHeadContent;
ApHeadContent getHeadContent(Ap ap);
ApHeadContent projectToHeadContent(Content c);
class ApOption;
@@ -1471,34 +1526,32 @@ private module MkStage<StageSig PrevStage> {
)
}
private class ApNonNil instanceof Ap {
pragma[nomagic]
ApNonNil() { not this instanceof ApNil }
string toString() { result = "" }
}
pragma[nomagic]
private predicate fwdFlowRead0(
NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap,
Configuration config
private predicate readStepCand(
NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config
) {
fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, _, _, config)
PrevStage::readStepCand(node1, c, node2, config) and
apc = projectToHeadContent(c)
}
bindingset[ap, c]
bindingset[node1, apc]
pragma[inline_late]
private predicate hasHeadContent(Ap ap, Content c) { getHeadContent(ap) = c }
private predicate readStepCand0(
NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config
) {
readStepCand(node1, apc, c, node2, config)
}
pragma[nomagic]
private predicate fwdFlowRead(
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
ParamNodeOption summaryCtx, ApOption argAp, Configuration config
) {
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, c, node2, config) and
hasHeadContent(ap, c)
exists(ApHeadContent apc |
fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and
apc = getHeadContent(ap) and
readStepCand0(node1, apc, c, node2, config)
)
}
pragma[nomagic]
@@ -2072,8 +2125,12 @@ private module Stage2Param implements MkStage<Stage1>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) }
class ApHeadContent = Unit;
pragma[inline]
Content getHeadContent(Ap ap) { exists(result) and ap = true }
ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true }
ApHeadContent projectToHeadContent(Content c) { any() }
class ApOption = BooleanOption;
@@ -2337,8 +2394,12 @@ private module Stage3Param implements MkStage<Stage2>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) }
class ApHeadContent = ContentApprox;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getAHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
predicate projectToHeadContent = getContentApprox/1;
class ApOption = ApproxAccessPathFrontOption;
@@ -2413,8 +2474,12 @@ private module Stage4Param implements MkStage<Stage3>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) }
class ApHeadContent = Content;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent projectToHeadContent(Content c) { result = c }
class ApOption = AccessPathFrontOption;
@@ -2743,8 +2808,12 @@ private module Stage5Param implements MkStage<Stage4>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) }
class ApHeadContent = Content;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent projectToHeadContent(Content c) { result = c }
class ApOption = AccessPathApproxOption;

View File

@@ -667,23 +667,78 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true and
not fullBarrier(node, config)
)
fwdFlowIn(_, _, _, node, config) and
cc = true
or
// flow out of a callable
fwdFlowOut(_, node, false, config) and
cc = false
or
// flow through a callable
exists(DataFlowCall call |
fwdFlowOut(call, node, false, config) and
cc = false
or
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
}
// inline to reduce the number of iterations
pragma[inline]
private predicate fwdFlowIn(
DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config
) {
// call context cannot help reduce virtual dispatch
fwdFlow(arg, cc, config) and
viableParamArgEx(call, p, arg) and
not fullBarrier(p, config) and
(
cc = false
or
cc = true and
not reducedViableImplInCallContext(call, _, _)
)
or
// call context may help reduce virtual dispatch
exists(DataFlowCallable target |
fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and
target = viableImplInSomeFwdFlowCallContextExt(call, config) and
cc = true
)
}
/**
* Holds if an argument to `call` is reached in the flow covered by `fwdFlow`.
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
fwdFlowIn(call, _, cc, _, config)
}
pragma[nomagic]
private predicate fwdFlowInReducedViableImplInSomeCallContext(
DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config
) {
fwdFlow(arg, true, config) and
viableParamArgEx(call, p, arg) and
reducedViableImplInCallContext(call, _, _) and
target = p.getEnclosingCallable() and
not fullBarrier(p, config)
}
/**
* Gets a viable dispatch target of `call` in the context `ctx`. This is
* restricted to those `call`s for which a context might make a difference,
* and to `ctx`s that are reachable in `fwdFlow`.
*/
pragma[nomagic]
private DataFlowCallable viableImplInSomeFwdFlowCallContextExt(
DataFlowCall call, Configuration config
) {
exists(DataFlowCall ctx |
fwdFlowIsEntered(ctx, _, config) and
result = viableImplInCallContextExt(call, ctx)
)
}
private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) }
pragma[nomagic]
@@ -726,7 +781,8 @@ private module Stage1 implements StageSig {
)
}
pragma[nomagic]
// inline to reduce the number of iterations
pragma[inline]
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
@@ -740,17 +796,6 @@ private module Stage1 implements StageSig {
fwdFlowOut(call, out, true, config)
}
/**
* Holds if an argument to `call` is reached in the flow covered by `fwdFlow`.
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
exists(ArgNodeEx arg |
fwdFlow(arg, cc, config) and
viableParamArgEx(call, _, arg)
)
}
private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) {
exists(NodeEx node1 |
additionalLocalStateStep(node1, state1, _, state2, config) or
@@ -817,13 +862,8 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
exists(DataFlowCall call |
revFlowIn(call, node, false, config) and
toReturn = false
or
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
revFlowIn(_, node, false, config) and
toReturn = false
or
// flow out of a callable
exists(ReturnPosition pos |
@@ -831,6 +871,12 @@ private module Stage1 implements StageSig {
node.(RetNodeEx).getReturnPosition() = pos and
toReturn = true
)
or
// flow through a callable
exists(DataFlowCall call |
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
}
/**
@@ -886,11 +932,11 @@ private module Stage1 implements StageSig {
additional predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
) {
viableParamArgEx(call, p, arg) and
fwdFlow(arg, config)
fwdFlowIn(call, arg, _, p, config)
}
pragma[nomagic]
// inline to reduce the number of iterations
pragma[inline]
private predicate revFlowIn(
DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config
) {
@@ -1223,7 +1269,16 @@ private module MkStage<StageSig PrevStage> {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail);
Content getHeadContent(Ap ap);
/**
* An approximation of `Content` that corresponds to the precision level of
* `Ap`, such that the mappings from both `Ap` and `Content` to this type
* are functional.
*/
class ApHeadContent;
ApHeadContent getHeadContent(Ap ap);
ApHeadContent projectToHeadContent(Content c);
class ApOption;
@@ -1471,34 +1526,32 @@ private module MkStage<StageSig PrevStage> {
)
}
private class ApNonNil instanceof Ap {
pragma[nomagic]
ApNonNil() { not this instanceof ApNil }
string toString() { result = "" }
}
pragma[nomagic]
private predicate fwdFlowRead0(
NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap,
Configuration config
private predicate readStepCand(
NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config
) {
fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, _, _, config)
PrevStage::readStepCand(node1, c, node2, config) and
apc = projectToHeadContent(c)
}
bindingset[ap, c]
bindingset[node1, apc]
pragma[inline_late]
private predicate hasHeadContent(Ap ap, Content c) { getHeadContent(ap) = c }
private predicate readStepCand0(
NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config
) {
readStepCand(node1, apc, c, node2, config)
}
pragma[nomagic]
private predicate fwdFlowRead(
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
ParamNodeOption summaryCtx, ApOption argAp, Configuration config
) {
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, c, node2, config) and
hasHeadContent(ap, c)
exists(ApHeadContent apc |
fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and
apc = getHeadContent(ap) and
readStepCand0(node1, apc, c, node2, config)
)
}
pragma[nomagic]
@@ -2072,8 +2125,12 @@ private module Stage2Param implements MkStage<Stage1>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) }
class ApHeadContent = Unit;
pragma[inline]
Content getHeadContent(Ap ap) { exists(result) and ap = true }
ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true }
ApHeadContent projectToHeadContent(Content c) { any() }
class ApOption = BooleanOption;
@@ -2337,8 +2394,12 @@ private module Stage3Param implements MkStage<Stage2>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) }
class ApHeadContent = ContentApprox;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getAHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
predicate projectToHeadContent = getContentApprox/1;
class ApOption = ApproxAccessPathFrontOption;
@@ -2413,8 +2474,12 @@ private module Stage4Param implements MkStage<Stage3>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) }
class ApHeadContent = Content;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent projectToHeadContent(Content c) { result = c }
class ApOption = AccessPathFrontOption;
@@ -2743,8 +2808,12 @@ private module Stage5Param implements MkStage<Stage4>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) }
class ApHeadContent = Content;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent projectToHeadContent(Content c) { result = c }
class ApOption = AccessPathApproxOption;

View File

@@ -667,23 +667,78 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true and
not fullBarrier(node, config)
)
fwdFlowIn(_, _, _, node, config) and
cc = true
or
// flow out of a callable
fwdFlowOut(_, node, false, config) and
cc = false
or
// flow through a callable
exists(DataFlowCall call |
fwdFlowOut(call, node, false, config) and
cc = false
or
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
}
// inline to reduce the number of iterations
pragma[inline]
private predicate fwdFlowIn(
DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config
) {
// call context cannot help reduce virtual dispatch
fwdFlow(arg, cc, config) and
viableParamArgEx(call, p, arg) and
not fullBarrier(p, config) and
(
cc = false
or
cc = true and
not reducedViableImplInCallContext(call, _, _)
)
or
// call context may help reduce virtual dispatch
exists(DataFlowCallable target |
fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and
target = viableImplInSomeFwdFlowCallContextExt(call, config) and
cc = true
)
}
/**
* Holds if an argument to `call` is reached in the flow covered by `fwdFlow`.
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
fwdFlowIn(call, _, cc, _, config)
}
pragma[nomagic]
private predicate fwdFlowInReducedViableImplInSomeCallContext(
DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config
) {
fwdFlow(arg, true, config) and
viableParamArgEx(call, p, arg) and
reducedViableImplInCallContext(call, _, _) and
target = p.getEnclosingCallable() and
not fullBarrier(p, config)
}
/**
* Gets a viable dispatch target of `call` in the context `ctx`. This is
* restricted to those `call`s for which a context might make a difference,
* and to `ctx`s that are reachable in `fwdFlow`.
*/
pragma[nomagic]
private DataFlowCallable viableImplInSomeFwdFlowCallContextExt(
DataFlowCall call, Configuration config
) {
exists(DataFlowCall ctx |
fwdFlowIsEntered(ctx, _, config) and
result = viableImplInCallContextExt(call, ctx)
)
}
private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) }
pragma[nomagic]
@@ -726,7 +781,8 @@ private module Stage1 implements StageSig {
)
}
pragma[nomagic]
// inline to reduce the number of iterations
pragma[inline]
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
@@ -740,17 +796,6 @@ private module Stage1 implements StageSig {
fwdFlowOut(call, out, true, config)
}
/**
* Holds if an argument to `call` is reached in the flow covered by `fwdFlow`.
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
exists(ArgNodeEx arg |
fwdFlow(arg, cc, config) and
viableParamArgEx(call, _, arg)
)
}
private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) {
exists(NodeEx node1 |
additionalLocalStateStep(node1, state1, _, state2, config) or
@@ -817,13 +862,8 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
exists(DataFlowCall call |
revFlowIn(call, node, false, config) and
toReturn = false
or
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
revFlowIn(_, node, false, config) and
toReturn = false
or
// flow out of a callable
exists(ReturnPosition pos |
@@ -831,6 +871,12 @@ private module Stage1 implements StageSig {
node.(RetNodeEx).getReturnPosition() = pos and
toReturn = true
)
or
// flow through a callable
exists(DataFlowCall call |
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
}
/**
@@ -886,11 +932,11 @@ private module Stage1 implements StageSig {
additional predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
) {
viableParamArgEx(call, p, arg) and
fwdFlow(arg, config)
fwdFlowIn(call, arg, _, p, config)
}
pragma[nomagic]
// inline to reduce the number of iterations
pragma[inline]
private predicate revFlowIn(
DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config
) {
@@ -1223,7 +1269,16 @@ private module MkStage<StageSig PrevStage> {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail);
Content getHeadContent(Ap ap);
/**
* An approximation of `Content` that corresponds to the precision level of
* `Ap`, such that the mappings from both `Ap` and `Content` to this type
* are functional.
*/
class ApHeadContent;
ApHeadContent getHeadContent(Ap ap);
ApHeadContent projectToHeadContent(Content c);
class ApOption;
@@ -1471,34 +1526,32 @@ private module MkStage<StageSig PrevStage> {
)
}
private class ApNonNil instanceof Ap {
pragma[nomagic]
ApNonNil() { not this instanceof ApNil }
string toString() { result = "" }
}
pragma[nomagic]
private predicate fwdFlowRead0(
NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap,
Configuration config
private predicate readStepCand(
NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config
) {
fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, _, _, config)
PrevStage::readStepCand(node1, c, node2, config) and
apc = projectToHeadContent(c)
}
bindingset[ap, c]
bindingset[node1, apc]
pragma[inline_late]
private predicate hasHeadContent(Ap ap, Content c) { getHeadContent(ap) = c }
private predicate readStepCand0(
NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config
) {
readStepCand(node1, apc, c, node2, config)
}
pragma[nomagic]
private predicate fwdFlowRead(
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
ParamNodeOption summaryCtx, ApOption argAp, Configuration config
) {
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, c, node2, config) and
hasHeadContent(ap, c)
exists(ApHeadContent apc |
fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and
apc = getHeadContent(ap) and
readStepCand0(node1, apc, c, node2, config)
)
}
pragma[nomagic]
@@ -2072,8 +2125,12 @@ private module Stage2Param implements MkStage<Stage1>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) }
class ApHeadContent = Unit;
pragma[inline]
Content getHeadContent(Ap ap) { exists(result) and ap = true }
ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true }
ApHeadContent projectToHeadContent(Content c) { any() }
class ApOption = BooleanOption;
@@ -2337,8 +2394,12 @@ private module Stage3Param implements MkStage<Stage2>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) }
class ApHeadContent = ContentApprox;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getAHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
predicate projectToHeadContent = getContentApprox/1;
class ApOption = ApproxAccessPathFrontOption;
@@ -2413,8 +2474,12 @@ private module Stage4Param implements MkStage<Stage3>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) }
class ApHeadContent = Content;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent projectToHeadContent(Content c) { result = c }
class ApOption = AccessPathFrontOption;
@@ -2743,8 +2808,12 @@ private module Stage5Param implements MkStage<Stage4>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) }
class ApHeadContent = Content;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent projectToHeadContent(Content c) { result = c }
class ApOption = AccessPathApproxOption;

View File

@@ -707,8 +707,8 @@ private module Cached {
* Gets a viable dispatch target of `call` in the context `ctx`. This is
* restricted to those `call`s for which a context might make a difference.
*/
pragma[nomagic]
private DataFlowCallable viableImplInCallContextExt(DataFlowCall call, DataFlowCall ctx) {
cached
DataFlowCallable viableImplInCallContextExt(DataFlowCall call, DataFlowCall ctx) {
result = viableImplInCallContext(call, ctx) and
result = viableCallable(call)
or
@@ -1391,6 +1391,9 @@ class TypedContentApprox extends MkTypedContentApprox {
/** Gets a typed content approximated by this value. */
TypedContent getATypedContent() { result = getATypedContent(this) }
/** Gets the content. */
ContentApprox getContent() { result = c }
/** Gets the container type. */
DataFlowType getContainerType() { result = t }
@@ -1408,6 +1411,8 @@ abstract class ApproxAccessPathFront extends TApproxAccessPathFront {
abstract boolean toBoolNonEmpty();
TypedContentApprox getHead() { this = TApproxFrontHead(result) }
pragma[nomagic]
TypedContent getAHead() {
exists(TypedContentApprox cont |

View File

@@ -667,23 +667,78 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true and
not fullBarrier(node, config)
)
fwdFlowIn(_, _, _, node, config) and
cc = true
or
// flow out of a callable
fwdFlowOut(_, node, false, config) and
cc = false
or
// flow through a callable
exists(DataFlowCall call |
fwdFlowOut(call, node, false, config) and
cc = false
or
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
}
// inline to reduce the number of iterations
pragma[inline]
private predicate fwdFlowIn(
DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config
) {
// call context cannot help reduce virtual dispatch
fwdFlow(arg, cc, config) and
viableParamArgEx(call, p, arg) and
not fullBarrier(p, config) and
(
cc = false
or
cc = true and
not reducedViableImplInCallContext(call, _, _)
)
or
// call context may help reduce virtual dispatch
exists(DataFlowCallable target |
fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and
target = viableImplInSomeFwdFlowCallContextExt(call, config) and
cc = true
)
}
/**
* Holds if an argument to `call` is reached in the flow covered by `fwdFlow`.
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
fwdFlowIn(call, _, cc, _, config)
}
pragma[nomagic]
private predicate fwdFlowInReducedViableImplInSomeCallContext(
DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config
) {
fwdFlow(arg, true, config) and
viableParamArgEx(call, p, arg) and
reducedViableImplInCallContext(call, _, _) and
target = p.getEnclosingCallable() and
not fullBarrier(p, config)
}
/**
* Gets a viable dispatch target of `call` in the context `ctx`. This is
* restricted to those `call`s for which a context might make a difference,
* and to `ctx`s that are reachable in `fwdFlow`.
*/
pragma[nomagic]
private DataFlowCallable viableImplInSomeFwdFlowCallContextExt(
DataFlowCall call, Configuration config
) {
exists(DataFlowCall ctx |
fwdFlowIsEntered(ctx, _, config) and
result = viableImplInCallContextExt(call, ctx)
)
}
private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) }
pragma[nomagic]
@@ -726,7 +781,8 @@ private module Stage1 implements StageSig {
)
}
pragma[nomagic]
// inline to reduce the number of iterations
pragma[inline]
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
@@ -740,17 +796,6 @@ private module Stage1 implements StageSig {
fwdFlowOut(call, out, true, config)
}
/**
* Holds if an argument to `call` is reached in the flow covered by `fwdFlow`.
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
exists(ArgNodeEx arg |
fwdFlow(arg, cc, config) and
viableParamArgEx(call, _, arg)
)
}
private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) {
exists(NodeEx node1 |
additionalLocalStateStep(node1, state1, _, state2, config) or
@@ -817,13 +862,8 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
exists(DataFlowCall call |
revFlowIn(call, node, false, config) and
toReturn = false
or
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
revFlowIn(_, node, false, config) and
toReturn = false
or
// flow out of a callable
exists(ReturnPosition pos |
@@ -831,6 +871,12 @@ private module Stage1 implements StageSig {
node.(RetNodeEx).getReturnPosition() = pos and
toReturn = true
)
or
// flow through a callable
exists(DataFlowCall call |
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
}
/**
@@ -886,11 +932,11 @@ private module Stage1 implements StageSig {
additional predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
) {
viableParamArgEx(call, p, arg) and
fwdFlow(arg, config)
fwdFlowIn(call, arg, _, p, config)
}
pragma[nomagic]
// inline to reduce the number of iterations
pragma[inline]
private predicate revFlowIn(
DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config
) {
@@ -1223,7 +1269,16 @@ private module MkStage<StageSig PrevStage> {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail);
Content getHeadContent(Ap ap);
/**
* An approximation of `Content` that corresponds to the precision level of
* `Ap`, such that the mappings from both `Ap` and `Content` to this type
* are functional.
*/
class ApHeadContent;
ApHeadContent getHeadContent(Ap ap);
ApHeadContent projectToHeadContent(Content c);
class ApOption;
@@ -1471,34 +1526,32 @@ private module MkStage<StageSig PrevStage> {
)
}
private class ApNonNil instanceof Ap {
pragma[nomagic]
ApNonNil() { not this instanceof ApNil }
string toString() { result = "" }
}
pragma[nomagic]
private predicate fwdFlowRead0(
NodeEx node1, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, ApNonNil ap,
Configuration config
private predicate readStepCand(
NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config
) {
fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, _, _, config)
PrevStage::readStepCand(node1, c, node2, config) and
apc = projectToHeadContent(c)
}
bindingset[ap, c]
bindingset[node1, apc]
pragma[inline_late]
private predicate hasHeadContent(Ap ap, Content c) { getHeadContent(ap) = c }
private predicate readStepCand0(
NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config
) {
readStepCand(node1, apc, c, node2, config)
}
pragma[nomagic]
private predicate fwdFlowRead(
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
ParamNodeOption summaryCtx, ApOption argAp, Configuration config
) {
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, c, node2, config) and
hasHeadContent(ap, c)
exists(ApHeadContent apc |
fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and
apc = getHeadContent(ap) and
readStepCand0(node1, apc, c, node2, config)
)
}
pragma[nomagic]
@@ -2072,8 +2125,12 @@ private module Stage2Param implements MkStage<Stage1>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) }
class ApHeadContent = Unit;
pragma[inline]
Content getHeadContent(Ap ap) { exists(result) and ap = true }
ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true }
ApHeadContent projectToHeadContent(Content c) { any() }
class ApOption = BooleanOption;
@@ -2337,8 +2394,12 @@ private module Stage3Param implements MkStage<Stage2>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) }
class ApHeadContent = ContentApprox;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getAHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
predicate projectToHeadContent = getContentApprox/1;
class ApOption = ApproxAccessPathFrontOption;
@@ -2413,8 +2474,12 @@ private module Stage4Param implements MkStage<Stage3>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) }
class ApHeadContent = Content;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent projectToHeadContent(Content c) { result = c }
class ApOption = AccessPathFrontOption;
@@ -2743,8 +2808,12 @@ private module Stage5Param implements MkStage<Stage4>::StageParam {
bindingset[tc, tail]
Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) }
class ApHeadContent = Content;
pragma[noinline]
Content getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() }
ApHeadContent projectToHeadContent(Content c) { result = c }
class ApOption = AccessPathApproxOption;

View File

@@ -89,7 +89,14 @@ module Cryptography {
* data of arbitrary length using a block encryption algorithm.
*/
class BlockMode extends string {
BlockMode() { this = ["ECB", "CBC", "GCM", "CCM", "CFB", "OFB", "CTR", "OPENPGP"] }
BlockMode() {
this =
[
"ECB", "CBC", "GCM", "CCM", "CFB", "OFB", "CTR", "OPENPGP",
"XTS", // https://csrc.nist.gov/publications/detail/sp/800-38e/final
"EAX" // https://en.wikipedia.org/wiki/EAX_mode
]
}
/** Holds if this block mode is considered to be insecure. */
predicate isWeak() { this = "ECB" }

View File

@@ -85,6 +85,17 @@ predicate used_as_regex(Expr s, string mode) {
)
}
private import semmle.python.Concepts
private import semmle.python.RegexTreeView
/** Gets a parsed regular expression term that is executed at `exec`. */
RegExpTerm getTermForExecution(RegexExecution exec) {
exists(RegexTracking t, DataFlow::Node source | t.hasFlow(source, exec.getRegex()) |
result.getRegex() = source.asExpr() and
result.isRootTerm()
)
}
/**
* Gets the canonical name for the API graph node corresponding to the `re` flag `flag`. For flags
* that have multiple names, we pick the long-form name as a canonical representative.

View File

@@ -13,6 +13,7 @@ private import semmle.python.dataflow.new.RemoteFlowSources
private import semmle.python.dataflow.new.BarrierGuards
private import semmle.python.RegexTreeView::RegexTreeView as TreeView
private import semmle.python.ApiGraphs
private import semmle.python.regex
/**
* Provides default sources, sinks and sanitizers for detecting
@@ -66,7 +67,7 @@ module PolynomialReDoS {
RegexExecutionAsSink() {
exists(RegexExecution re |
re.getRegex().asExpr() = t.getRegex() and
t = getTermForExecution(re) and
this = re.getString()
) and
t.isRootTerm()

View File

@@ -111,11 +111,7 @@ class Builtin extends @py_cobject {
}
module Builtin {
Builtin builtinModule() {
py_special_objects(result, "builtin_module_2") and major_version() = 2
or
py_special_objects(result, "builtin_module_3") and major_version() = 3
}
Builtin builtinModule() { py_special_objects(result, "builtin_module") }
Builtin builtin(string name) { result = builtinModule().getMember(name) }

View File

@@ -6,4 +6,4 @@
| six.moves.urllib | Package six.moves.urllib |
| six.moves.urllib.parse | Module six.moves.urllib_parse |
| six.moves.urllib.parse.urlsplit | Function urlsplit |
| six.moves.zip | builtin-class itertools.izip |
| six.moves.zip | Builtin-function zip |

View File

@@ -1 +1 @@
| bad_encoding.py:11:19:11:19 | Encoding Error | 'utf8' codec can't decode byte 0x82 in position 82: invalid start byte |
| bad_encoding.py:11:19:11:19 | Encoding Error | 'utf-8' codec can't decode byte 0x82 in position 82: invalid start byte |

View File

@@ -1,2 +1,4 @@
| test.py:8:12:8:23 | Str | test.py:8:21:8:23 | \\s+ | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding \\s+$ |
| test.py:9:14:9:29 | Str | test.py:9:27:9:29 | \\d+ | Strings starting with '0.9' and with many repetitions of '99' can start matching anywhere after the start of the preceeding \\d+ |
| test.py:11:22:11:33 | Str | test.py:11:31:11:33 | \\s+ | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding \\s+$ |
| test.py:18:14:18:25 | Str | test.py:18:23:18:25 | \\s+ | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding \\s+$ |

View File

@@ -5,6 +5,10 @@ edges
| test.py:7:12:7:18 | ControlFlowNode for request | test.py:7:12:7:23 | ControlFlowNode for Attribute |
| test.py:7:12:7:23 | ControlFlowNode for Attribute | test.py:8:30:8:33 | ControlFlowNode for text |
| test.py:7:12:7:23 | ControlFlowNode for Attribute | test.py:9:32:9:35 | ControlFlowNode for text |
| test.py:7:12:7:23 | ControlFlowNode for Attribute | test.py:12:17:12:20 | ControlFlowNode for text |
| test.py:7:12:7:23 | ControlFlowNode for Attribute | test.py:18:28:18:31 | ControlFlowNode for text |
| test.py:14:33:14:39 | ControlFlowNode for my_text | test.py:16:24:16:30 | ControlFlowNode for my_text |
| test.py:18:28:18:31 | ControlFlowNode for text | test.py:14:33:14:39 | ControlFlowNode for my_text |
nodes
| test.py:0:0:0:0 | ModuleVariableNode for test.request | semmle.label | ModuleVariableNode for test.request |
| test.py:2:26:2:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember |
@@ -13,7 +17,13 @@ nodes
| test.py:7:12:7:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test.py:8:30:8:33 | ControlFlowNode for text | semmle.label | ControlFlowNode for text |
| test.py:9:32:9:35 | ControlFlowNode for text | semmle.label | ControlFlowNode for text |
| test.py:12:17:12:20 | ControlFlowNode for text | semmle.label | ControlFlowNode for text |
| test.py:14:33:14:39 | ControlFlowNode for my_text | semmle.label | ControlFlowNode for my_text |
| test.py:16:24:16:30 | ControlFlowNode for my_text | semmle.label | ControlFlowNode for my_text |
| test.py:18:28:18:31 | ControlFlowNode for text | semmle.label | ControlFlowNode for text |
subpaths
#select
| test.py:8:30:8:33 | ControlFlowNode for text | test.py:2:26:2:32 | ControlFlowNode for ImportMember | test.py:8:30:8:33 | ControlFlowNode for text | This $@ that depends on a $@ may run slow on strings with many repetitions of ' '. | test.py:8:21:8:23 | \\s+ | regular expression | test.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value |
| test.py:9:32:9:35 | ControlFlowNode for text | test.py:2:26:2:32 | ControlFlowNode for ImportMember | test.py:9:32:9:35 | ControlFlowNode for text | This $@ that depends on a $@ may run slow on strings starting with '0.9' and with many repetitions of '99'. | test.py:9:27:9:29 | \\d+ | regular expression | test.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value |
| test.py:12:17:12:20 | ControlFlowNode for text | test.py:2:26:2:32 | ControlFlowNode for ImportMember | test.py:12:17:12:20 | ControlFlowNode for text | This $@ that depends on a $@ may run slow on strings with many repetitions of ' '. | test.py:11:31:11:33 | \\s+ | regular expression | test.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value |
| test.py:16:24:16:30 | ControlFlowNode for my_text | test.py:2:26:2:32 | ControlFlowNode for ImportMember | test.py:16:24:16:30 | ControlFlowNode for my_text | This $@ that depends on a $@ may run slow on strings with many repetitions of ' '. | test.py:18:23:18:25 | \\s+ | regular expression | test.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value |

View File

@@ -7,3 +7,13 @@ def code_execution():
text = request.args.get("text")
re.sub(r"^\s+|\s+$", "", text) # NOT OK
re.match(r"^0\.\d+E?\d+$", text) # NOT OK
reg = re.compile(r"^\s+|\s+$")
reg.sub("", text) # NOT OK
def indirect(input_reg_str, my_text):
my_reg = re.compile(input_reg_str)
my_reg.sub("", my_text) # NOT OK
indirect(r"^\s+|\s+$", text)