Merge branch 'main' into call-graph-code

This commit is contained in:
Rasmus Wriedt Larsen
2023-02-15 20:15:04 +01:00
607 changed files with 102060 additions and 11977 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

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Fixed module resolution so we properly recognize that in `from <pkg> import *`, where `<pkg>` is a package, the actual imports are made from the `<pkg>/__init__.py` file.

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
) {

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
) {

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
) {

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
) {

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

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
) {

View File

@@ -167,8 +167,22 @@ module ImportResolution {
)
}
/**
* Gets the (most likely) module for the name `name`, if any.
*
* Handles the fact that for the name `<pkg>` representing a package the actual module
* is `<pkg>.__init__`.
*
* See `isPreferredModuleForName` for more details on what "most likely" module means.
*/
pragma[inline]
private Module getModuleFromName(string name) {
isPreferredModuleForName(result.getFile(), name + ["", ".__init__"])
}
/** Gets the module from which attributes are imported by `i`. */
Module getModuleImportedByImportStar(ImportStar i) {
isPreferredModuleForName(result.getFile(), i.getImportedModuleName())
result = getModuleFromName(i.getImportedModuleName())
}
/**
@@ -223,7 +237,7 @@ module ImportResolution {
exists(string module_name | result = getReferenceToModuleName(module_name) |
// Depending on whether the referenced module is a package or not, we may need to add a
// trailing `.__init__` to the module name.
isPreferredModuleForName(m.getFile(), module_name + ["", ".__init__"])
m = getModuleFromName(module_name)
or
// Module defined via `sys.modules`
m = sys_modules_module_with_name(module_name)
@@ -234,7 +248,7 @@ module ImportResolution {
ar.accesses(getModuleReference(p), attr_name) and
result = ar
|
isPreferredModuleForName(m.getFile(), p.getPackageName() + "." + attr_name + ["", ".__init__"])
m = getModuleFromName(p.getPackageName() + "." + attr_name)
)
or
// This is also true for attributes that come from reexports.
@@ -248,8 +262,7 @@ module ImportResolution {
exists(string submodule, Module package |
SsaSource::init_module_submodule_defn(result.asVar().getSourceVariable(),
package.getEntryNode()) and
isPreferredModuleForName(m.getFile(),
package.getPackageName() + "." + submodule + ["", ".__init__"])
m = getModuleFromName(package.getPackageName() + "." + submodule)
)
}

View File

@@ -81,7 +81,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

@@ -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

@@ -84,6 +84,12 @@ from attr_clash import clashing_attr, non_clashing_submodule #$ imports=attr_cla
check("clashing_attr", clashing_attr, "clashing_attr", globals()) #$ prints=clashing_attr SPURIOUS: prints="<module attr_clash.clashing_attr>"
check("non_clashing_submodule", non_clashing_submodule, "<module attr_clash.non_clashing_submodule>", globals()) #$ prints="<module attr_clash.non_clashing_submodule>"
# check that import * from an __init__ file works
from package.subpackage2 import *
check("subpackage2_attr", subpackage2_attr, "subpackage2_attr", globals()) #$ prints=subpackage2_attr
exit(__file__)
print()
@@ -91,4 +97,4 @@ print()
if status() == 0:
print("PASS")
else:
print("FAIL")
sys.exit("FAIL")

View File

@@ -0,0 +1,6 @@
from trace import *
enter(__file__)
subpackage2_attr = "subpackage2_attr"
exit(__file__)