mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Merge branch 'main' into js-use-shared-cryptography
This commit is contained in:
@@ -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.
|
||||
@@ -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
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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" }
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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) }
|
||||
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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+$ |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user