mirror of
https://github.com/github/codeql.git
synced 2026-04-27 09:45:15 +02:00
Merge branch 'main' into nsstring
This commit is contained in:
@@ -43,12 +43,83 @@ runs:
|
||||
codeql-compile-${{ inputs.key }}-${{ github.ref_name }}-
|
||||
codeql-compile-${{ inputs.key }}-main-
|
||||
- name: Fill compilation cache directory
|
||||
id: fill-compilation-dir
|
||||
shell: bash
|
||||
run: |
|
||||
# Move all the existing cache into another folder, so we only preserve the cache for the current queries.
|
||||
node $GITHUB_WORKSPACE/.github/actions/cache-query-compilation/move-caches.js ${COMBINED_CACHE_DIR}
|
||||
|
||||
echo "compdir=${COMBINED_CACHE_DIR}" >> $GITHUB_OUTPUT
|
||||
env:
|
||||
uses: actions/github-script@v6
|
||||
env:
|
||||
COMBINED_CACHE_DIR: ${{ runner.temp }}/compilation-dir
|
||||
with:
|
||||
script: |
|
||||
// # Move all the existing cache into another folder, so we only preserve the cache for the current queries.
|
||||
// mkdir -p ${COMBINED_CACHE_DIR}
|
||||
// rm -f **/.cache/{lock,size} # -f to avoid errors if the cache is empty.
|
||||
// # copy the contents of the .cache folders into the combined cache folder.
|
||||
// cp -r **/.cache/* ${COMBINED_CACHE_DIR}/ || : # ignore missing files
|
||||
// # clean up the .cache folders
|
||||
// rm -rf **/.cache/*
|
||||
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
// the first argv is the cache folder to create.
|
||||
const COMBINED_CACHE_DIR = process.env.COMBINED_CACHE_DIR;
|
||||
|
||||
function* walkCaches(dir) {
|
||||
const files = fs.readdirSync(dir, { withFileTypes: true });
|
||||
for (const file of files) {
|
||||
if (file.isDirectory()) {
|
||||
const filePath = path.join(dir, file.name);
|
||||
yield* walkCaches(filePath);
|
||||
if (file.name === ".cache") {
|
||||
yield filePath;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function copyDir(src, dest) {
|
||||
for await (const file of await fs.promises.readdir(src, { withFileTypes: true })) {
|
||||
const srcPath = path.join(src, file.name);
|
||||
const destPath = path.join(dest, file.name);
|
||||
if (file.isDirectory()) {
|
||||
if (!fs.existsSync(destPath)) {
|
||||
fs.mkdirSync(destPath);
|
||||
}
|
||||
await copyDir(srcPath, destPath);
|
||||
} else {
|
||||
await fs.promises.copyFile(srcPath, destPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const cacheDirs = [...walkCaches(".")];
|
||||
|
||||
for (const dir of cacheDirs) {
|
||||
console.log(`Found .cache dir at ${dir}`);
|
||||
}
|
||||
|
||||
// mkdir -p ${COMBINED_CACHE_DIR}
|
||||
fs.mkdirSync(COMBINED_CACHE_DIR, { recursive: true });
|
||||
|
||||
// rm -f **/.cache/{lock,size} # -f to avoid errors if the cache is empty.
|
||||
await Promise.all(
|
||||
cacheDirs.map((cacheDir) =>
|
||||
(async function () {
|
||||
await fs.promises.rm(path.join(cacheDir, "lock"), { force: true });
|
||||
await fs.promises.rm(path.join(cacheDir, "size"), { force: true });
|
||||
})()
|
||||
)
|
||||
);
|
||||
|
||||
// # copy the contents of the .cache folders into the combined cache folder.
|
||||
// cp -r **/.cache/* ${COMBINED_CACHE_DIR}/ || : # ignore missing files
|
||||
await Promise.all(
|
||||
cacheDirs.map((cacheDir) => copyDir(cacheDir, COMBINED_CACHE_DIR))
|
||||
);
|
||||
|
||||
// # clean up the .cache folders
|
||||
// rm -rf **/.cache/*
|
||||
await Promise.all(
|
||||
cacheDirs.map((cacheDir) => fs.promises.rm(cacheDir, { recursive: true }))
|
||||
);
|
||||
}
|
||||
main();
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
// # Move all the existing cache into another folder, so we only preserve the cache for the current queries.
|
||||
// mkdir -p ${COMBINED_CACHE_DIR}
|
||||
// rm -f **/.cache/{lock,size} # -f to avoid errors if the cache is empty.
|
||||
// # copy the contents of the .cache folders into the combined cache folder.
|
||||
// cp -r **/.cache/* ${COMBINED_CACHE_DIR}/ || : # ignore missing files
|
||||
// # clean up the .cache folders
|
||||
// rm -rf **/.cache/*
|
||||
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
// the first argv is the cache folder to create.
|
||||
const COMBINED_CACHE_DIR = process.argv[2];
|
||||
|
||||
function* walkCaches(dir) {
|
||||
const files = fs.readdirSync(dir, { withFileTypes: true });
|
||||
for (const file of files) {
|
||||
if (file.isDirectory()) {
|
||||
const filePath = path.join(dir, file.name);
|
||||
yield* walkCaches(filePath);
|
||||
if (file.name === ".cache") {
|
||||
yield filePath;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function copyDir(src, dest) {
|
||||
for await (const file of await fs.promises.readdir(src, { withFileTypes: true })) {
|
||||
const srcPath = path.join(src, file.name);
|
||||
const destPath = path.join(dest, file.name);
|
||||
if (file.isDirectory()) {
|
||||
if (!fs.existsSync(destPath)) {
|
||||
fs.mkdirSync(destPath);
|
||||
}
|
||||
await copyDir(srcPath, destPath);
|
||||
} else {
|
||||
await fs.promises.copyFile(srcPath, destPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const cacheDirs = [...walkCaches(".")];
|
||||
|
||||
for (const dir of cacheDirs) {
|
||||
console.log(`Found .cache dir at ${dir}`);
|
||||
}
|
||||
|
||||
// mkdir -p ${COMBINED_CACHE_DIR}
|
||||
fs.mkdirSync(COMBINED_CACHE_DIR, { recursive: true });
|
||||
|
||||
// rm -f **/.cache/{lock,size} # -f to avoid errors if the cache is empty.
|
||||
await Promise.all(
|
||||
cacheDirs.map((cacheDir) =>
|
||||
(async function () {
|
||||
await fs.promises.rm(path.join(cacheDir, "lock"), { force: true });
|
||||
await fs.promises.rm(path.join(cacheDir, "size"), { force: true });
|
||||
})()
|
||||
)
|
||||
);
|
||||
|
||||
// # copy the contents of the .cache folders into the combined cache folder.
|
||||
// cp -r **/.cache/* ${COMBINED_CACHE_DIR}/ || : # ignore missing files
|
||||
await Promise.all(
|
||||
cacheDirs.map((cacheDir) => copyDir(cacheDir, COMBINED_CACHE_DIR))
|
||||
);
|
||||
|
||||
// # clean up the .cache folders
|
||||
// rm -rf **/.cache/*
|
||||
await Promise.all(
|
||||
cacheDirs.map((cacheDir) => fs.promises.rm(cacheDir, { recursive: true }))
|
||||
);
|
||||
}
|
||||
main();
|
||||
8
.github/workflows/go-tests-other-os.yml
vendored
8
.github/workflows/go-tests-other-os.yml
vendored
@@ -12,10 +12,10 @@ jobs:
|
||||
name: Test MacOS
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- name: Set up Go 1.19
|
||||
- name: Set up Go 1.20
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.19
|
||||
go-version: 1.20.0
|
||||
id: go
|
||||
|
||||
- name: Check out code
|
||||
@@ -47,10 +47,10 @@ jobs:
|
||||
name: Test Windows
|
||||
runs-on: windows-latest-xl
|
||||
steps:
|
||||
- name: Set up Go 1.19
|
||||
- name: Set up Go 1.20
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.19
|
||||
go-version: 1.20.0
|
||||
id: go
|
||||
|
||||
- name: Check out code
|
||||
|
||||
4
.github/workflows/go-tests.yml
vendored
4
.github/workflows/go-tests.yml
vendored
@@ -20,10 +20,10 @@ jobs:
|
||||
name: Test Linux (Ubuntu)
|
||||
runs-on: ubuntu-latest-xl
|
||||
steps:
|
||||
- name: Set up Go 1.19
|
||||
- name: Set up Go 1.20
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.19
|
||||
go-version: 1.20.0
|
||||
id: go
|
||||
|
||||
- name: Check out code
|
||||
|
||||
7
.github/workflows/ql-for-ql-build.yml
vendored
7
.github/workflows/ql-for-ql-build.yml
vendored
@@ -5,13 +5,6 @@ on:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
paths:
|
||||
- "ql/**"
|
||||
- "**.qll"
|
||||
- "**.ql"
|
||||
- "**.dbscheme"
|
||||
- "**/qlpack.yml"
|
||||
- ".github/workflows/ql-for-ql-build.yml"
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
@@ -131,6 +131,14 @@ namespace Semmle.Autobuild.Cpp.Tests
|
||||
|
||||
bool IBuildActions.IsWindows() => IsWindows;
|
||||
|
||||
public bool IsMacOs { get; set; }
|
||||
|
||||
bool IBuildActions.IsMacOs() => IsMacOs;
|
||||
|
||||
public bool IsArm { get; set; }
|
||||
|
||||
bool IBuildActions.IsArm() => IsArm;
|
||||
|
||||
string IBuildActions.PathCombine(params string[] parts)
|
||||
{
|
||||
return string.Join(IsWindows ? '\\' : '/', parts.Where(p => !string.IsNullOrWhiteSpace(p)));
|
||||
|
||||
@@ -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
|
||||
) {
|
||||
|
||||
@@ -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
|
||||
) {
|
||||
|
||||
@@ -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
|
||||
) {
|
||||
|
||||
@@ -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
|
||||
) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
) {
|
||||
|
||||
@@ -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
|
||||
) {
|
||||
|
||||
@@ -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
|
||||
) {
|
||||
|
||||
@@ -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
|
||||
) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
) {
|
||||
|
||||
@@ -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
|
||||
) {
|
||||
|
||||
@@ -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
|
||||
) {
|
||||
|
||||
@@ -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
|
||||
) {
|
||||
|
||||
@@ -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
|
||||
) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -145,6 +145,14 @@ namespace Semmle.Autobuild.CSharp.Tests
|
||||
|
||||
bool IBuildActions.IsWindows() => IsWindows;
|
||||
|
||||
public bool IsMacOs { get; set; }
|
||||
|
||||
bool IBuildActions.IsMacOs() => IsMacOs;
|
||||
|
||||
public bool IsArm { get; set; }
|
||||
|
||||
bool IBuildActions.IsArm() => IsArm;
|
||||
|
||||
public string PathCombine(params string[] parts)
|
||||
{
|
||||
return string.Join(IsWindows ? '\\' : '/', parts.Where(p => !string.IsNullOrWhiteSpace(p)));
|
||||
|
||||
@@ -7,6 +7,7 @@ using System.Xml;
|
||||
using System.Net.Http;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Threading.Tasks;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Semmle.Autobuild.Shared
|
||||
{
|
||||
@@ -98,6 +99,18 @@ namespace Semmle.Autobuild.Shared
|
||||
/// </summary>
|
||||
bool IsWindows();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether we are running on macOS.
|
||||
/// </summary>
|
||||
/// <returns>True if we are running on macOS.</returns>
|
||||
bool IsMacOs();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether we are running on arm.
|
||||
/// </summary>
|
||||
/// <returns>True if we are running on arm.</returns>
|
||||
bool IsArm();
|
||||
|
||||
/// <summary>
|
||||
/// Combine path segments, Path.Combine().
|
||||
/// </summary>
|
||||
@@ -203,6 +216,12 @@ namespace Semmle.Autobuild.Shared
|
||||
|
||||
bool IBuildActions.IsWindows() => Win32.IsWindows();
|
||||
|
||||
bool IBuildActions.IsMacOs() => RuntimeInformation.IsOSPlatform(OSPlatform.OSX);
|
||||
|
||||
bool IBuildActions.IsArm() =>
|
||||
RuntimeInformation.ProcessArchitecture == Architecture.Arm64 ||
|
||||
RuntimeInformation.ProcessArchitecture == Architecture.Arm;
|
||||
|
||||
string IBuildActions.PathCombine(params string[] parts) => Path.Combine(parts);
|
||||
|
||||
void IBuildActions.WriteAllText(string filename, string contents) => File.WriteAllText(filename, contents);
|
||||
|
||||
@@ -1,18 +1,36 @@
|
||||
using Semmle.Util.Logging;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Semmle.Autobuild.Shared
|
||||
{
|
||||
internal static class MsBuildCommandExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Appends a call to msbuild.
|
||||
/// </summary>
|
||||
/// <param name="cmdBuilder"></param>
|
||||
/// <param name="builder"></param>
|
||||
/// <returns></returns>
|
||||
public static CommandBuilder MsBuildCommand(this CommandBuilder cmdBuilder, IAutobuilder<AutobuildOptionsShared> builder)
|
||||
{
|
||||
var isArmMac = builder.Actions.IsMacOs() && builder.Actions.IsArm();
|
||||
|
||||
// mono doesn't ship with `msbuild` on Arm-based Macs, but we can fall back to
|
||||
// msbuild that ships with `dotnet` which can be invoked with `dotnet msbuild`
|
||||
// perhaps we should do this on all platforms?
|
||||
return isArmMac ?
|
||||
cmdBuilder.RunCommand("dotnet").Argument("msbuild") :
|
||||
cmdBuilder.RunCommand("msbuild");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A build rule using msbuild.
|
||||
/// </summary>
|
||||
public class MsBuildRule : IBuildRule<AutobuildOptionsShared>
|
||||
{
|
||||
/// <summary>
|
||||
/// The name of the msbuild command.
|
||||
/// </summary>
|
||||
private const string msBuild = "msbuild";
|
||||
|
||||
public BuildScript Analyse(IAutobuilder<AutobuildOptionsShared> builder, bool auto)
|
||||
{
|
||||
if (!builder.ProjectsOrSolutionsToBuild.Any())
|
||||
@@ -57,7 +75,7 @@ namespace Semmle.Autobuild.Shared
|
||||
Script;
|
||||
var nugetRestore = GetNugetRestoreScript();
|
||||
var msbuildRestoreCommand = new CommandBuilder(builder.Actions).
|
||||
RunCommand(msBuild).
|
||||
MsBuildCommand(builder).
|
||||
Argument("/t:restore").
|
||||
QuoteArgument(projectOrSolution.FullPath);
|
||||
|
||||
@@ -95,7 +113,7 @@ namespace Semmle.Autobuild.Shared
|
||||
command.RunCommand("set Platform=&& type NUL", quoteExe: false);
|
||||
}
|
||||
|
||||
command.RunCommand(msBuild);
|
||||
command.MsBuildCommand(builder);
|
||||
command.QuoteArgument(projectOrSolution.FullPath);
|
||||
|
||||
var target = builder.Options.MsBuildTarget ?? "rebuild";
|
||||
|
||||
@@ -65,6 +65,15 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
trapFile.has_modifiers(target, Modifier.Create(cx, modifier));
|
||||
}
|
||||
|
||||
private static void ExtractFieldModifiers(Context cx, TextWriter trapFile, IEntity key, IFieldSymbol symbol)
|
||||
{
|
||||
if (symbol.IsReadOnly)
|
||||
HasModifier(cx, trapFile, key, Modifiers.Readonly);
|
||||
|
||||
if (symbol.IsRequired)
|
||||
HasModifier(cx, trapFile, key, Modifiers.Required);
|
||||
}
|
||||
|
||||
private static void ExtractNamedTypeModifiers(Context cx, TextWriter trapFile, IEntity key, ISymbol symbol)
|
||||
{
|
||||
if (symbol.Kind != SymbolKind.NamedType)
|
||||
@@ -106,8 +115,11 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
if (symbol.IsVirtual)
|
||||
HasModifier(cx, trapFile, key, Modifiers.Virtual);
|
||||
|
||||
if (symbol.Kind == SymbolKind.Field && ((IFieldSymbol)symbol).IsReadOnly)
|
||||
HasModifier(cx, trapFile, key, Modifiers.Readonly);
|
||||
if (symbol is IFieldSymbol field)
|
||||
ExtractFieldModifiers(cx, trapFile, key, field);
|
||||
|
||||
if (symbol.Kind == SymbolKind.Property && ((IPropertySymbol)symbol).IsRequired)
|
||||
HasModifier(cx, trapFile, key, Modifiers.Required);
|
||||
|
||||
if (symbol.IsOverride)
|
||||
HasModifier(cx, trapFile, key, Modifiers.Override);
|
||||
|
||||
@@ -13,6 +13,7 @@ internal static class Modifiers
|
||||
public const string Public = "public";
|
||||
public const string Readonly = "readonly";
|
||||
public const string Record = "record";
|
||||
public const string Required = "required";
|
||||
public const string Ref = "ref";
|
||||
public const string Sealed = "sealed";
|
||||
public const string Static = "static";
|
||||
|
||||
13
csharp/ql/integration-tests/all-platforms/msbuild/Program.cs
Normal file
13
csharp/ql/integration-tests/all-platforms/msbuild/Program.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
|
||||
namespace Test
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static int Main(string[] args)
|
||||
{
|
||||
Console.WriteLine("Hello world!");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net4.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,4 @@
|
||||
from create_database_utils import *
|
||||
|
||||
# force CodeQL to use MSBuild by setting `LGTM_INDEX_MSBUILD_TARGET`
|
||||
run_codeql_database_create([], test_db="default-db", db=None, lang="csharp", extra_env={ 'LGTM_INDEX_MSBUILD_TARGET': 'Build' })
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* C# 11: Added library support for `checked` operators.
|
||||
4
csharp/ql/lib/change-notes/2023-02-16-requiredmembers.md
Normal file
4
csharp/ql/lib/change-notes/2023-02-16-requiredmembers.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* C# 11: Added extractor support for `required` fields and properties.
|
||||
@@ -435,8 +435,12 @@ class Destructor extends DotNet::Destructor, Callable, Member, Attributable, @de
|
||||
* (`BinaryOperator`), or a conversion operator (`ConversionOperator`).
|
||||
*/
|
||||
class Operator extends Callable, Member, Attributable, @operator {
|
||||
/** Gets the assembly name of this operator. */
|
||||
string getAssemblyName() { operators(this, result, _, _, _, _) }
|
||||
/**
|
||||
* DEPRECATED: use `getFunctionName()` instead.
|
||||
*
|
||||
* Gets the assembly name of this operator.
|
||||
*/
|
||||
deprecated string getAssemblyName() { result = this.getFunctionName() }
|
||||
|
||||
override string getName() { operators(this, _, result, _, _, _) }
|
||||
|
||||
@@ -445,7 +449,7 @@ class Operator extends Callable, Member, Attributable, @operator {
|
||||
/**
|
||||
* Gets the metadata name of the operator, such as `op_implicit` or `op_RightShift`.
|
||||
*/
|
||||
string getFunctionName() { none() }
|
||||
string getFunctionName() { operators(this, result, _, _, _, _) }
|
||||
|
||||
override ValueOrRefType getDeclaringType() { operators(this, _, _, result, _, _) }
|
||||
|
||||
@@ -481,10 +485,11 @@ class RecordCloneMethod extends Method, DotNet::RecordCloneCallable {
|
||||
* A user-defined unary operator - an operator taking one operand.
|
||||
*
|
||||
* Either a plus operator (`PlusOperator`), minus operator (`MinusOperator`),
|
||||
* not operator (`NotOperator`), complement operator (`ComplementOperator`),
|
||||
* true operator (`TrueOperator`), false operator (`FalseOperator`),
|
||||
* increment operator (`IncrementOperator`), or decrement operator
|
||||
* (`DecrementOperator`).
|
||||
* checked minus operator (`CheckedMinusOperator`), not operator (`NotOperator`),
|
||||
* complement operator (`ComplementOperator`), true operator (`TrueOperator`),
|
||||
* false operator (`FalseOperator`), increment operator (`IncrementOperator`),
|
||||
* checked increment operator (`CheckedIncrementOperator`), decrement operator
|
||||
* (`DecrementOperator`) or checked decrement operator (`CheckedDecrementOperator`).
|
||||
*/
|
||||
class UnaryOperator extends Operator {
|
||||
UnaryOperator() {
|
||||
@@ -505,8 +510,6 @@ class UnaryOperator extends Operator {
|
||||
class PlusOperator extends UnaryOperator {
|
||||
PlusOperator() { this.getName() = "+" }
|
||||
|
||||
override string getFunctionName() { result = "op_UnaryPlus" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "PlusOperator" }
|
||||
}
|
||||
|
||||
@@ -522,11 +525,24 @@ class PlusOperator extends UnaryOperator {
|
||||
class MinusOperator extends UnaryOperator {
|
||||
MinusOperator() { this.getName() = "-" }
|
||||
|
||||
override string getFunctionName() { result = "op_UnaryNegation" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "MinusOperator" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A user-defined checked minus operator (`-`), for example
|
||||
*
|
||||
* ```csharp
|
||||
* public static Widget operator checked -(Widget w) {
|
||||
* ...
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class CheckedMinusOperator extends UnaryOperator {
|
||||
CheckedMinusOperator() { this.getName() = "checked -" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "CheckedMinusOperator" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A user-defined not operator (`!`), for example
|
||||
*
|
||||
@@ -539,8 +555,6 @@ class MinusOperator extends UnaryOperator {
|
||||
class NotOperator extends UnaryOperator {
|
||||
NotOperator() { this.getName() = "!" }
|
||||
|
||||
override string getFunctionName() { result = "op_LogicalNot" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "NotOperator" }
|
||||
}
|
||||
|
||||
@@ -556,8 +570,6 @@ class NotOperator extends UnaryOperator {
|
||||
class ComplementOperator extends UnaryOperator {
|
||||
ComplementOperator() { this.getName() = "~" }
|
||||
|
||||
override string getFunctionName() { result = "op_OnesComplement" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "ComplementOperator" }
|
||||
}
|
||||
|
||||
@@ -573,11 +585,24 @@ class ComplementOperator extends UnaryOperator {
|
||||
class IncrementOperator extends UnaryOperator {
|
||||
IncrementOperator() { this.getName() = "++" }
|
||||
|
||||
override string getFunctionName() { result = "op_Increment" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "IncrementOperator" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A user-defined checked increment operator (`++`), for example
|
||||
*
|
||||
* ```csharp
|
||||
* public static Widget operator checked ++(Widget w) {
|
||||
* ...
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class CheckedIncrementOperator extends UnaryOperator {
|
||||
CheckedIncrementOperator() { this.getName() = "checked ++" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "CheckedIncrementOperator" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A user-defined decrement operator (`--`), for example
|
||||
*
|
||||
@@ -590,11 +615,24 @@ class IncrementOperator extends UnaryOperator {
|
||||
class DecrementOperator extends UnaryOperator {
|
||||
DecrementOperator() { this.getName() = "--" }
|
||||
|
||||
override string getFunctionName() { result = "op_Decrement" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "DecrementOperator" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A user-defined checked decrement operator (`--`), for example
|
||||
*
|
||||
* ```csharp
|
||||
* public static Widget operator checked --(Widget w) {
|
||||
* ...
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class CheckedDecrementOperator extends UnaryOperator {
|
||||
CheckedDecrementOperator() { this.getName() = "checked --" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "CheckedDecrementOperator" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A user-defined false operator (`false`), for example
|
||||
*
|
||||
@@ -607,8 +645,6 @@ class DecrementOperator extends UnaryOperator {
|
||||
class FalseOperator extends UnaryOperator {
|
||||
FalseOperator() { this.getName() = "false" }
|
||||
|
||||
override string getFunctionName() { result = "op_False" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "FalseOperator" }
|
||||
}
|
||||
|
||||
@@ -624,17 +660,18 @@ class FalseOperator extends UnaryOperator {
|
||||
class TrueOperator extends UnaryOperator {
|
||||
TrueOperator() { this.getName() = "true" }
|
||||
|
||||
override string getFunctionName() { result = "op_True" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "TrueOperator" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A user-defined binary operator.
|
||||
*
|
||||
* Either an addition operator (`AddOperator`), a subtraction operator
|
||||
* (`SubOperator`), a multiplication operator (`MulOperator`), a division
|
||||
* operator (`DivOperator`), a remainder operator (`RemOperator`), an and
|
||||
* Either an addition operator (`AddOperator`), a checked addition operator
|
||||
* (`CheckedAddOperator`) a subtraction operator (`SubOperator`), a checked
|
||||
* substraction operator (`CheckedSubOperator`), a multiplication operator
|
||||
* (`MulOperator`), a checked multiplication operator (`CheckedMulOperator`),
|
||||
* a division operator (`DivOperator`), a checked division operator
|
||||
* (`CheckedDivOperator`), a remainder operator (`RemOperator`), an and
|
||||
* operator (`AndOperator`), an or operator (`OrOperator`), an xor
|
||||
* operator (`XorOperator`), a left shift operator (`LeftShiftOperator`),
|
||||
* a right shift operator (`RightShiftOperator`), an unsigned right shift
|
||||
@@ -659,11 +696,24 @@ class BinaryOperator extends Operator {
|
||||
class AddOperator extends BinaryOperator {
|
||||
AddOperator() { this.getName() = "+" }
|
||||
|
||||
override string getFunctionName() { result = "op_Addition" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "AddOperator" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A user-defined checked addition operator (`+`), for example
|
||||
*
|
||||
* ```csharp
|
||||
* public static Widget operator checked +(Widget lhs, Widget rhs) {
|
||||
* ...
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class CheckedAddOperator extends BinaryOperator {
|
||||
CheckedAddOperator() { this.getName() = "checked +" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "CheckedAddOperator" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A user-defined subtraction operator (`-`), for example
|
||||
*
|
||||
@@ -676,11 +726,24 @@ class AddOperator extends BinaryOperator {
|
||||
class SubOperator extends BinaryOperator {
|
||||
SubOperator() { this.getName() = "-" }
|
||||
|
||||
override string getFunctionName() { result = "op_Subtraction" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "SubOperator" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A user-defined checked subtraction operator (`-`), for example
|
||||
*
|
||||
* ```csharp
|
||||
* public static Widget operator checked -(Widget lhs, Widget rhs) {
|
||||
* ...
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class CheckedSubOperator extends BinaryOperator {
|
||||
CheckedSubOperator() { this.getName() = "checked -" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "CheckedSubOperator" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A user-defined multiplication operator (`*`), for example
|
||||
*
|
||||
@@ -693,11 +756,24 @@ class SubOperator extends BinaryOperator {
|
||||
class MulOperator extends BinaryOperator {
|
||||
MulOperator() { this.getName() = "*" }
|
||||
|
||||
override string getFunctionName() { result = "op_Multiply" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "MulOperator" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A user-defined checked multiplication operator (`*`), for example
|
||||
*
|
||||
* ```csharp
|
||||
* public static Widget operator checked *(Widget lhs, Widget rhs) {
|
||||
* ...
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class CheckedMulOperator extends BinaryOperator {
|
||||
CheckedMulOperator() { this.getName() = "checked *" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "CheckedMulOperator" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A user-defined division operator (`/`), for example
|
||||
*
|
||||
@@ -710,11 +786,24 @@ class MulOperator extends BinaryOperator {
|
||||
class DivOperator extends BinaryOperator {
|
||||
DivOperator() { this.getName() = "/" }
|
||||
|
||||
override string getFunctionName() { result = "op_Division" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "DivOperator" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A user-defined checked division operator (`/`), for example
|
||||
*
|
||||
* ```csharp
|
||||
* public static Widget operator checked /(Widget lhs, Widget rhs) {
|
||||
* ...
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class CheckedDivOperator extends BinaryOperator {
|
||||
CheckedDivOperator() { this.getName() = "checked /" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "CheckedDivOperator" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A user-defined remainder operator (`%`), for example
|
||||
*
|
||||
@@ -727,8 +816,6 @@ class DivOperator extends BinaryOperator {
|
||||
class RemOperator extends BinaryOperator {
|
||||
RemOperator() { this.getName() = "%" }
|
||||
|
||||
override string getFunctionName() { result = "op_Modulus" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "RemOperator" }
|
||||
}
|
||||
|
||||
@@ -744,8 +831,6 @@ class RemOperator extends BinaryOperator {
|
||||
class AndOperator extends BinaryOperator {
|
||||
AndOperator() { this.getName() = "&" }
|
||||
|
||||
override string getFunctionName() { result = "op_BitwiseAnd" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "AndOperator" }
|
||||
}
|
||||
|
||||
@@ -761,8 +846,6 @@ class AndOperator extends BinaryOperator {
|
||||
class OrOperator extends BinaryOperator {
|
||||
OrOperator() { this.getName() = "|" }
|
||||
|
||||
override string getFunctionName() { result = "op_BitwiseOr" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "OrOperator" }
|
||||
}
|
||||
|
||||
@@ -778,8 +861,6 @@ class OrOperator extends BinaryOperator {
|
||||
class XorOperator extends BinaryOperator {
|
||||
XorOperator() { this.getName() = "^" }
|
||||
|
||||
override string getFunctionName() { result = "op_ExclusiveOr" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "XorOperator" }
|
||||
}
|
||||
|
||||
@@ -795,8 +876,6 @@ class XorOperator extends BinaryOperator {
|
||||
class LeftShiftOperator extends BinaryOperator {
|
||||
LeftShiftOperator() { this.getName() = "<<" }
|
||||
|
||||
override string getFunctionName() { result = "op_LeftShift" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "LeftShiftOperator" }
|
||||
}
|
||||
|
||||
@@ -815,8 +894,6 @@ deprecated class LShiftOperator = LeftShiftOperator;
|
||||
class RightShiftOperator extends BinaryOperator {
|
||||
RightShiftOperator() { this.getName() = ">>" }
|
||||
|
||||
override string getFunctionName() { result = "op_RightShift" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "RightShiftOperator" }
|
||||
}
|
||||
|
||||
@@ -835,8 +912,6 @@ deprecated class RShiftOperator = RightShiftOperator;
|
||||
class UnsignedRightShiftOperator extends BinaryOperator {
|
||||
UnsignedRightShiftOperator() { this.getName() = ">>>" }
|
||||
|
||||
override string getFunctionName() { result = "op_UnsignedRightShift" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "UnsignedRightShiftOperator" }
|
||||
}
|
||||
|
||||
@@ -852,8 +927,6 @@ class UnsignedRightShiftOperator extends BinaryOperator {
|
||||
class EQOperator extends BinaryOperator {
|
||||
EQOperator() { this.getName() = "==" }
|
||||
|
||||
override string getFunctionName() { result = "op_Equality" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "EQOperator" }
|
||||
}
|
||||
|
||||
@@ -869,8 +942,6 @@ class EQOperator extends BinaryOperator {
|
||||
class NEOperator extends BinaryOperator {
|
||||
NEOperator() { this.getName() = "!=" }
|
||||
|
||||
override string getFunctionName() { result = "op_Inequality" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "NEOperator" }
|
||||
}
|
||||
|
||||
@@ -886,8 +957,6 @@ class NEOperator extends BinaryOperator {
|
||||
class LTOperator extends BinaryOperator {
|
||||
LTOperator() { this.getName() = "<" }
|
||||
|
||||
override string getFunctionName() { result = "op_LessThan" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "LTOperator" }
|
||||
}
|
||||
|
||||
@@ -903,8 +972,6 @@ class LTOperator extends BinaryOperator {
|
||||
class GTOperator extends BinaryOperator {
|
||||
GTOperator() { this.getName() = ">" }
|
||||
|
||||
override string getFunctionName() { result = "op_GreaterThan" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "GTOperator" }
|
||||
}
|
||||
|
||||
@@ -920,8 +987,6 @@ class GTOperator extends BinaryOperator {
|
||||
class LEOperator extends BinaryOperator {
|
||||
LEOperator() { this.getName() = "<=" }
|
||||
|
||||
override string getFunctionName() { result = "op_LessThanOrEqual" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "LEOperator" }
|
||||
}
|
||||
|
||||
@@ -937,8 +1002,6 @@ class LEOperator extends BinaryOperator {
|
||||
class GEOperator extends BinaryOperator {
|
||||
GEOperator() { this.getName() = ">=" }
|
||||
|
||||
override string getFunctionName() { result = "op_GreaterThanOrEqual" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "GEOperator" }
|
||||
}
|
||||
|
||||
@@ -954,7 +1017,8 @@ class GEOperator extends BinaryOperator {
|
||||
class ConversionOperator extends Operator {
|
||||
ConversionOperator() {
|
||||
this.getName() = "implicit conversion" or
|
||||
this.getName() = "explicit conversion"
|
||||
this.getName() = "explicit conversion" or
|
||||
this.getName() = "checked explicit conversion"
|
||||
}
|
||||
|
||||
/** Gets the source type of the conversion. */
|
||||
@@ -976,8 +1040,6 @@ class ConversionOperator extends Operator {
|
||||
class ImplicitConversionOperator extends ConversionOperator {
|
||||
ImplicitConversionOperator() { this.getName() = "implicit conversion" }
|
||||
|
||||
override string getFunctionName() { result = "op_Implicit" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "ImplicitConversionOperator" }
|
||||
}
|
||||
|
||||
@@ -993,11 +1055,24 @@ class ImplicitConversionOperator extends ConversionOperator {
|
||||
class ExplicitConversionOperator extends ConversionOperator {
|
||||
ExplicitConversionOperator() { this.getName() = "explicit conversion" }
|
||||
|
||||
override string getFunctionName() { result = "op_Explicit" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "ExplicitConversionOperator" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A user-defined checked explicit conversion operator, for example
|
||||
*
|
||||
* ```csharp
|
||||
* public static explicit operator checked int(BigInteger i) {
|
||||
* ...
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class CheckedExplicitConversionOperator extends ConversionOperator {
|
||||
CheckedExplicitConversionOperator() { this.getName() = "checked explicit conversion" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "CheckedExplicitConversionOperator" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A local function, defined within the scope of another callable.
|
||||
* For example, `Fac` on lines 2--4 in
|
||||
|
||||
@@ -90,6 +90,9 @@ class Modifiable extends Declaration, @modifiable {
|
||||
/** Holds if this declaration is `const`. */
|
||||
predicate isConst() { this.hasModifier("const") }
|
||||
|
||||
/** Holds if this declaration has the modifier `required`. */
|
||||
predicate isRequired() { this.hasModifier("required") }
|
||||
|
||||
/** Holds if this declaration is `unsafe`. */
|
||||
predicate isUnsafe() {
|
||||
this.hasModifier("unsafe") or
|
||||
@@ -178,6 +181,8 @@ class Member extends DotNet::Member, Modifiable, @member {
|
||||
override predicate isAbstract() { Modifiable.super.isAbstract() }
|
||||
|
||||
override predicate isStatic() { Modifiable.super.isStatic() }
|
||||
|
||||
override predicate isRequired() { Modifiable.super.isRequired() }
|
||||
}
|
||||
|
||||
private class TOverridable = @virtualizable or @callable_accessor;
|
||||
|
||||
@@ -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
|
||||
) {
|
||||
|
||||
@@ -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
|
||||
) {
|
||||
|
||||
@@ -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
|
||||
) {
|
||||
|
||||
@@ -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
|
||||
) {
|
||||
|
||||
@@ -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
|
||||
) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
) {
|
||||
|
||||
@@ -80,6 +80,9 @@ class Member extends Declaration, @dotnet_member {
|
||||
/** Holds if this member is `static`. */
|
||||
predicate isStatic() { none() }
|
||||
|
||||
/** Holds if this member is declared `required`. */
|
||||
predicate isRequired() { none() }
|
||||
|
||||
/**
|
||||
* Holds if this member has name `name` and is defined in type `type`
|
||||
* with namespace `namespace`.
|
||||
|
||||
56
csharp/ql/test/library-tests/csharp11/CheckedOperators.cs
Normal file
56
csharp/ql/test/library-tests/csharp11/CheckedOperators.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
namespace CheckedOperators;
|
||||
|
||||
public class Number
|
||||
{
|
||||
public int Value { get; }
|
||||
|
||||
public Number(int n) => this.Value = n;
|
||||
|
||||
public static Number operator checked +(Number n1, Number n2) =>
|
||||
new Number(checked(n1.Value + n2.Value));
|
||||
|
||||
public static Number operator +(Number n1, Number n2) =>
|
||||
new Number(n1.Value + n2.Value);
|
||||
|
||||
public static Number operator checked -(Number n1, Number n2) =>
|
||||
new Number(checked(n1.Value - n2.Value));
|
||||
|
||||
public static Number operator -(Number n1, Number n2) =>
|
||||
new Number(n1.Value - n2.Value);
|
||||
|
||||
public static Number operator checked *(Number n1, Number n2) =>
|
||||
new Number(checked(n1.Value * n2.Value));
|
||||
|
||||
public static Number operator *(Number n1, Number n2) =>
|
||||
new Number(n1.Value * n2.Value);
|
||||
|
||||
public static Number operator checked /(Number n1, Number n2) =>
|
||||
new Number(checked(n1.Value / n2.Value));
|
||||
|
||||
public static Number operator /(Number n1, Number n2) =>
|
||||
new Number(n1.Value / n2.Value);
|
||||
|
||||
public static Number operator checked -(Number n) =>
|
||||
new Number(checked(-n.Value));
|
||||
|
||||
public static Number operator -(Number n) =>
|
||||
new Number(-n.Value);
|
||||
|
||||
public static Number operator checked ++(Number n) =>
|
||||
new Number(checked(n.Value + 1));
|
||||
|
||||
public static Number operator ++(Number n) =>
|
||||
new Number(n.Value + 1);
|
||||
|
||||
public static Number operator checked --(Number n) =>
|
||||
new Number(checked(n.Value - 1));
|
||||
|
||||
public static Number operator --(Number n) =>
|
||||
new Number(n.Value - 1);
|
||||
|
||||
public static explicit operator short(Number n) =>
|
||||
(short)n.Value;
|
||||
|
||||
public static explicit operator checked short(Number n) =>
|
||||
checked((short)n.Value);
|
||||
}
|
||||
@@ -1,3 +1,221 @@
|
||||
CheckedOperators.cs:
|
||||
# 1| [NamespaceDeclaration] namespace ... { ... }
|
||||
# 3| 1: [Class] Number
|
||||
# 5| 4: [Property] Value
|
||||
# 5| -1: [TypeMention] int
|
||||
# 5| 3: [Getter] get_Value
|
||||
# 7| 5: [InstanceConstructor] Number
|
||||
#-----| 2: (Parameters)
|
||||
# 7| 0: [Parameter] n
|
||||
# 7| -1: [TypeMention] int
|
||||
# 7| 4: [AssignExpr] ... = ...
|
||||
# 7| 0: [PropertyCall] access to property Value
|
||||
# 7| -1: [ThisAccess] this access
|
||||
# 7| 1: [ParameterAccess] access to parameter n
|
||||
# 9| 6: [CheckedAddOperator] checked +
|
||||
# 9| -1: [TypeMention] Number
|
||||
#-----| 2: (Parameters)
|
||||
# 9| 0: [Parameter] n1
|
||||
# 9| -1: [TypeMention] Number
|
||||
# 9| 1: [Parameter] n2
|
||||
# 9| -1: [TypeMention] Number
|
||||
# 10| 4: [ObjectCreation] object creation of type Number
|
||||
# 10| -1: [TypeMention] Number
|
||||
# 10| 0: [CheckedExpr] checked (...)
|
||||
# 10| 0: [AddExpr] ... + ...
|
||||
# 10| 0: [PropertyCall] access to property Value
|
||||
# 10| -1: [ParameterAccess] access to parameter n1
|
||||
# 10| 1: [PropertyCall] access to property Value
|
||||
# 10| -1: [ParameterAccess] access to parameter n2
|
||||
# 12| 7: [AddOperator] +
|
||||
# 12| -1: [TypeMention] Number
|
||||
#-----| 2: (Parameters)
|
||||
# 12| 0: [Parameter] n1
|
||||
# 12| -1: [TypeMention] Number
|
||||
# 12| 1: [Parameter] n2
|
||||
# 12| -1: [TypeMention] Number
|
||||
# 13| 4: [ObjectCreation] object creation of type Number
|
||||
# 13| -1: [TypeMention] Number
|
||||
# 13| 0: [AddExpr] ... + ...
|
||||
# 13| 0: [PropertyCall] access to property Value
|
||||
# 13| -1: [ParameterAccess] access to parameter n1
|
||||
# 13| 1: [PropertyCall] access to property Value
|
||||
# 13| -1: [ParameterAccess] access to parameter n2
|
||||
# 15| 8: [CheckedSubOperator] checked -
|
||||
# 15| -1: [TypeMention] Number
|
||||
#-----| 2: (Parameters)
|
||||
# 15| 0: [Parameter] n1
|
||||
# 15| -1: [TypeMention] Number
|
||||
# 15| 1: [Parameter] n2
|
||||
# 15| -1: [TypeMention] Number
|
||||
# 16| 4: [ObjectCreation] object creation of type Number
|
||||
# 16| -1: [TypeMention] Number
|
||||
# 16| 0: [CheckedExpr] checked (...)
|
||||
# 16| 0: [SubExpr] ... - ...
|
||||
# 16| 0: [PropertyCall] access to property Value
|
||||
# 16| -1: [ParameterAccess] access to parameter n1
|
||||
# 16| 1: [PropertyCall] access to property Value
|
||||
# 16| -1: [ParameterAccess] access to parameter n2
|
||||
# 18| 9: [SubOperator] -
|
||||
# 18| -1: [TypeMention] Number
|
||||
#-----| 2: (Parameters)
|
||||
# 18| 0: [Parameter] n1
|
||||
# 18| -1: [TypeMention] Number
|
||||
# 18| 1: [Parameter] n2
|
||||
# 18| -1: [TypeMention] Number
|
||||
# 19| 4: [ObjectCreation] object creation of type Number
|
||||
# 19| -1: [TypeMention] Number
|
||||
# 19| 0: [SubExpr] ... - ...
|
||||
# 19| 0: [PropertyCall] access to property Value
|
||||
# 19| -1: [ParameterAccess] access to parameter n1
|
||||
# 19| 1: [PropertyCall] access to property Value
|
||||
# 19| -1: [ParameterAccess] access to parameter n2
|
||||
# 21| 10: [CheckedMulOperator] checked *
|
||||
# 21| -1: [TypeMention] Number
|
||||
#-----| 2: (Parameters)
|
||||
# 21| 0: [Parameter] n1
|
||||
# 21| -1: [TypeMention] Number
|
||||
# 21| 1: [Parameter] n2
|
||||
# 21| -1: [TypeMention] Number
|
||||
# 22| 4: [ObjectCreation] object creation of type Number
|
||||
# 22| -1: [TypeMention] Number
|
||||
# 22| 0: [CheckedExpr] checked (...)
|
||||
# 22| 0: [MulExpr] ... * ...
|
||||
# 22| 0: [PropertyCall] access to property Value
|
||||
# 22| -1: [ParameterAccess] access to parameter n1
|
||||
# 22| 1: [PropertyCall] access to property Value
|
||||
# 22| -1: [ParameterAccess] access to parameter n2
|
||||
# 24| 11: [MulOperator] *
|
||||
# 24| -1: [TypeMention] Number
|
||||
#-----| 2: (Parameters)
|
||||
# 24| 0: [Parameter] n1
|
||||
# 24| -1: [TypeMention] Number
|
||||
# 24| 1: [Parameter] n2
|
||||
# 24| -1: [TypeMention] Number
|
||||
# 25| 4: [ObjectCreation] object creation of type Number
|
||||
# 25| -1: [TypeMention] Number
|
||||
# 25| 0: [MulExpr] ... * ...
|
||||
# 25| 0: [PropertyCall] access to property Value
|
||||
# 25| -1: [ParameterAccess] access to parameter n1
|
||||
# 25| 1: [PropertyCall] access to property Value
|
||||
# 25| -1: [ParameterAccess] access to parameter n2
|
||||
# 27| 12: [CheckedDivOperator] checked /
|
||||
# 27| -1: [TypeMention] Number
|
||||
#-----| 2: (Parameters)
|
||||
# 27| 0: [Parameter] n1
|
||||
# 27| -1: [TypeMention] Number
|
||||
# 27| 1: [Parameter] n2
|
||||
# 27| -1: [TypeMention] Number
|
||||
# 28| 4: [ObjectCreation] object creation of type Number
|
||||
# 28| -1: [TypeMention] Number
|
||||
# 28| 0: [CheckedExpr] checked (...)
|
||||
# 28| 0: [DivExpr] ... / ...
|
||||
# 28| 0: [PropertyCall] access to property Value
|
||||
# 28| -1: [ParameterAccess] access to parameter n1
|
||||
# 28| 1: [PropertyCall] access to property Value
|
||||
# 28| -1: [ParameterAccess] access to parameter n2
|
||||
# 30| 13: [DivOperator] /
|
||||
# 30| -1: [TypeMention] Number
|
||||
#-----| 2: (Parameters)
|
||||
# 30| 0: [Parameter] n1
|
||||
# 30| -1: [TypeMention] Number
|
||||
# 30| 1: [Parameter] n2
|
||||
# 30| -1: [TypeMention] Number
|
||||
# 31| 4: [ObjectCreation] object creation of type Number
|
||||
# 31| -1: [TypeMention] Number
|
||||
# 31| 0: [DivExpr] ... / ...
|
||||
# 31| 0: [PropertyCall] access to property Value
|
||||
# 31| -1: [ParameterAccess] access to parameter n1
|
||||
# 31| 1: [PropertyCall] access to property Value
|
||||
# 31| -1: [ParameterAccess] access to parameter n2
|
||||
# 33| 14: [CheckedMinusOperator] checked -
|
||||
# 33| -1: [TypeMention] Number
|
||||
#-----| 2: (Parameters)
|
||||
# 33| 0: [Parameter] n
|
||||
# 33| -1: [TypeMention] Number
|
||||
# 34| 4: [ObjectCreation] object creation of type Number
|
||||
# 34| -1: [TypeMention] Number
|
||||
# 34| 0: [CheckedExpr] checked (...)
|
||||
# 34| 0: [UnaryMinusExpr] -...
|
||||
# 34| 0: [PropertyCall] access to property Value
|
||||
# 34| -1: [ParameterAccess] access to parameter n
|
||||
# 36| 15: [MinusOperator] -
|
||||
# 36| -1: [TypeMention] Number
|
||||
#-----| 2: (Parameters)
|
||||
# 36| 0: [Parameter] n
|
||||
# 36| -1: [TypeMention] Number
|
||||
# 37| 4: [ObjectCreation] object creation of type Number
|
||||
# 37| -1: [TypeMention] Number
|
||||
# 37| 0: [UnaryMinusExpr] -...
|
||||
# 37| 0: [PropertyCall] access to property Value
|
||||
# 37| -1: [ParameterAccess] access to parameter n
|
||||
# 39| 16: [CheckedIncrementOperator] checked ++
|
||||
# 39| -1: [TypeMention] Number
|
||||
#-----| 2: (Parameters)
|
||||
# 39| 0: [Parameter] n
|
||||
# 39| -1: [TypeMention] Number
|
||||
# 40| 4: [ObjectCreation] object creation of type Number
|
||||
# 40| -1: [TypeMention] Number
|
||||
# 40| 0: [CheckedExpr] checked (...)
|
||||
# 40| 0: [AddExpr] ... + ...
|
||||
# 40| 0: [PropertyCall] access to property Value
|
||||
# 40| -1: [ParameterAccess] access to parameter n
|
||||
# 40| 1: [IntLiteral] 1
|
||||
# 42| 17: [IncrementOperator] ++
|
||||
# 42| -1: [TypeMention] Number
|
||||
#-----| 2: (Parameters)
|
||||
# 42| 0: [Parameter] n
|
||||
# 42| -1: [TypeMention] Number
|
||||
# 43| 4: [ObjectCreation] object creation of type Number
|
||||
# 43| -1: [TypeMention] Number
|
||||
# 43| 0: [AddExpr] ... + ...
|
||||
# 43| 0: [PropertyCall] access to property Value
|
||||
# 43| -1: [ParameterAccess] access to parameter n
|
||||
# 43| 1: [IntLiteral] 1
|
||||
# 45| 18: [CheckedDecrementOperator] checked --
|
||||
# 45| -1: [TypeMention] Number
|
||||
#-----| 2: (Parameters)
|
||||
# 45| 0: [Parameter] n
|
||||
# 45| -1: [TypeMention] Number
|
||||
# 46| 4: [ObjectCreation] object creation of type Number
|
||||
# 46| -1: [TypeMention] Number
|
||||
# 46| 0: [CheckedExpr] checked (...)
|
||||
# 46| 0: [SubExpr] ... - ...
|
||||
# 46| 0: [PropertyCall] access to property Value
|
||||
# 46| -1: [ParameterAccess] access to parameter n
|
||||
# 46| 1: [IntLiteral] 1
|
||||
# 48| 19: [DecrementOperator] --
|
||||
# 48| -1: [TypeMention] Number
|
||||
#-----| 2: (Parameters)
|
||||
# 48| 0: [Parameter] n
|
||||
# 48| -1: [TypeMention] Number
|
||||
# 49| 4: [ObjectCreation] object creation of type Number
|
||||
# 49| -1: [TypeMention] Number
|
||||
# 49| 0: [SubExpr] ... - ...
|
||||
# 49| 0: [PropertyCall] access to property Value
|
||||
# 49| -1: [ParameterAccess] access to parameter n
|
||||
# 49| 1: [IntLiteral] 1
|
||||
# 51| 20: [ExplicitConversionOperator] explicit conversion
|
||||
# 51| -1: [TypeMention] short
|
||||
#-----| 2: (Parameters)
|
||||
# 51| 0: [Parameter] n
|
||||
# 51| -1: [TypeMention] Number
|
||||
# 52| 4: [CastExpr] (...) ...
|
||||
# 52| 0: [TypeAccess] access to type Int16
|
||||
# 52| 0: [TypeMention] short
|
||||
# 52| 1: [PropertyCall] access to property Value
|
||||
# 52| -1: [ParameterAccess] access to parameter n
|
||||
# 54| 21: [CheckedExplicitConversionOperator] checked explicit conversion
|
||||
# 54| -1: [TypeMention] short
|
||||
#-----| 2: (Parameters)
|
||||
# 54| 0: [Parameter] n
|
||||
# 54| -1: [TypeMention] Number
|
||||
# 55| 4: [CheckedExpr] checked (...)
|
||||
# 55| 0: [CastExpr] (...) ...
|
||||
# 55| 0: [TypeAccess] access to type Int16
|
||||
# 55| 0: [TypeMention] short
|
||||
# 55| 1: [PropertyCall] access to property Value
|
||||
# 55| -1: [ParameterAccess] access to parameter n
|
||||
GenericAttribute.cs:
|
||||
# 3| [GenericAssemblyAttribute] [assembly: MyGeneric<Int32>(...)]
|
||||
# 3| 0: [TypeMention] MyGenericAttribute<int>
|
||||
@@ -343,6 +561,193 @@ PatternMatchSpan.cs:
|
||||
# 16| 2: [DefaultCase] default:
|
||||
# 16| 3: [BlockStmt] {...}
|
||||
# 16| 0: [BreakStmt] break;
|
||||
RelaxedShift.cs:
|
||||
# 1| [Interface] IShiftOperators<,,>
|
||||
#-----| 1: (Type parameters)
|
||||
# 1| 0: [TypeParameter] TSelf
|
||||
# 1| 1: [TypeParameter] TOther
|
||||
# 1| 2: [TypeParameter] TReturn
|
||||
# 3| 4: [LeftShiftOperator] <<
|
||||
# 3| -1: [TypeMention] TReturn
|
||||
#-----| 2: (Parameters)
|
||||
# 3| 0: [Parameter] value
|
||||
# 3| -1: [TypeMention] TSelf
|
||||
# 3| 1: [Parameter] shiftAmount
|
||||
# 3| -1: [TypeMention] TOther
|
||||
# 5| 5: [RightShiftOperator] >>
|
||||
# 5| -1: [TypeMention] TReturn
|
||||
#-----| 2: (Parameters)
|
||||
# 5| 0: [Parameter] value
|
||||
# 5| -1: [TypeMention] TSelf
|
||||
# 5| 1: [Parameter] shiftAmount
|
||||
# 5| -1: [TypeMention] TOther
|
||||
# 7| 6: [UnsignedRightShiftOperator] >>>
|
||||
# 7| -1: [TypeMention] TReturn
|
||||
#-----| 2: (Parameters)
|
||||
# 7| 0: [Parameter] value
|
||||
# 7| -1: [TypeMention] TSelf
|
||||
# 7| 1: [Parameter] shiftAmount
|
||||
# 7| -1: [TypeMention] TOther
|
||||
# 10| [Class] Number
|
||||
#-----| 3: (Base types)
|
||||
# 12| 5: [LeftShiftOperator] <<
|
||||
# 12| -1: [TypeMention] Number
|
||||
#-----| 2: (Parameters)
|
||||
# 12| 0: [Parameter] value
|
||||
# 12| -1: [TypeMention] Number
|
||||
# 12| 1: [Parameter] shiftAmount
|
||||
# 12| -1: [TypeMention] string
|
||||
# 12| 4: [ParameterAccess] access to parameter value
|
||||
# 14| 6: [RightShiftOperator] >>
|
||||
# 14| -1: [TypeMention] Number
|
||||
#-----| 2: (Parameters)
|
||||
# 14| 0: [Parameter] value
|
||||
# 14| -1: [TypeMention] Number
|
||||
# 14| 1: [Parameter] shiftAmount
|
||||
# 14| -1: [TypeMention] string
|
||||
# 14| 4: [ParameterAccess] access to parameter value
|
||||
# 16| 7: [UnsignedRightShiftOperator] >>>
|
||||
# 16| -1: [TypeMention] Number
|
||||
#-----| 2: (Parameters)
|
||||
# 16| 0: [Parameter] value
|
||||
# 16| -1: [TypeMention] Number
|
||||
# 16| 1: [Parameter] shiftAmount
|
||||
# 16| -1: [TypeMention] string
|
||||
# 16| 4: [ParameterAccess] access to parameter value
|
||||
# 19| [Class] TestRelaxedShift
|
||||
# 21| 5: [Method] M1
|
||||
# 21| -1: [TypeMention] Void
|
||||
# 22| 4: [BlockStmt] {...}
|
||||
# 23| 0: [LocalVariableDeclStmt] ... ...;
|
||||
# 23| 0: [LocalVariableDeclAndInitExpr] Number n11 = ...
|
||||
# 23| -1: [TypeMention] Number
|
||||
# 23| 0: [LocalVariableAccess] access to local variable n11
|
||||
# 23| 1: [ObjectCreation] object creation of type Number
|
||||
# 23| 0: [TypeMention] Number
|
||||
# 24| 1: [LocalVariableDeclStmt] ... ...;
|
||||
# 24| 0: [LocalVariableDeclAndInitExpr] Number n12 = ...
|
||||
# 24| -1: [TypeMention] Number
|
||||
# 24| 0: [LocalVariableAccess] access to local variable n12
|
||||
# 24| 1: [OperatorCall] call to operator <<
|
||||
# 24| 0: [LocalVariableAccess] access to local variable n11
|
||||
# 24| 1: [StringLiteralUtf16] "1"
|
||||
# 26| 2: [LocalVariableDeclStmt] ... ...;
|
||||
# 26| 0: [LocalVariableDeclAndInitExpr] Number n21 = ...
|
||||
# 26| -1: [TypeMention] Number
|
||||
# 26| 0: [LocalVariableAccess] access to local variable n21
|
||||
# 26| 1: [ObjectCreation] object creation of type Number
|
||||
# 26| 0: [TypeMention] Number
|
||||
# 27| 3: [LocalVariableDeclStmt] ... ...;
|
||||
# 27| 0: [LocalVariableDeclAndInitExpr] Number n22 = ...
|
||||
# 27| -1: [TypeMention] Number
|
||||
# 27| 0: [LocalVariableAccess] access to local variable n22
|
||||
# 27| 1: [OperatorCall] call to operator >>
|
||||
# 27| 0: [LocalVariableAccess] access to local variable n21
|
||||
# 27| 1: [StringLiteralUtf16] "2"
|
||||
# 29| 4: [LocalVariableDeclStmt] ... ...;
|
||||
# 29| 0: [LocalVariableDeclAndInitExpr] Number n31 = ...
|
||||
# 29| -1: [TypeMention] Number
|
||||
# 29| 0: [LocalVariableAccess] access to local variable n31
|
||||
# 29| 1: [ObjectCreation] object creation of type Number
|
||||
# 29| 0: [TypeMention] Number
|
||||
# 30| 5: [LocalVariableDeclStmt] ... ...;
|
||||
# 30| 0: [LocalVariableDeclAndInitExpr] Number n32 = ...
|
||||
# 30| -1: [TypeMention] Number
|
||||
# 30| 0: [LocalVariableAccess] access to local variable n32
|
||||
# 30| 1: [OperatorCall] call to operator >>>
|
||||
# 30| 0: [LocalVariableAccess] access to local variable n31
|
||||
# 30| 1: [StringLiteralUtf16] "3"
|
||||
RequiredMembers.cs:
|
||||
# 4| [Class] ClassRequiredMembers
|
||||
# 6| 4: [Field] RequiredField
|
||||
# 6| -1: [TypeMention] object
|
||||
# 7| 5: [Property] RequiredProperty
|
||||
# 7| -1: [TypeMention] string
|
||||
# 7| 3: [Getter] get_RequiredProperty
|
||||
# 7| 4: [Setter] set_RequiredProperty
|
||||
#-----| 2: (Parameters)
|
||||
# 7| 0: [Parameter] value
|
||||
# 8| 6: [Property] VirtualProperty
|
||||
# 8| -1: [TypeMention] object
|
||||
# 8| 3: [Getter] get_VirtualProperty
|
||||
# 8| 4: [Setter] set_VirtualProperty
|
||||
#-----| 2: (Parameters)
|
||||
# 8| 0: [Parameter] value
|
||||
# 10| 7: [InstanceConstructor] ClassRequiredMembers
|
||||
# 10| 4: [BlockStmt] {...}
|
||||
# 13| 8: [InstanceConstructor] ClassRequiredMembers
|
||||
#-----| 0: (Attributes)
|
||||
# 12| 1: [DefaultAttribute] [SetsRequiredMembers(...)]
|
||||
# 12| 0: [TypeMention] SetsRequiredMembersAttribute
|
||||
#-----| 2: (Parameters)
|
||||
# 13| 0: [Parameter] requiredField
|
||||
# 13| -1: [TypeMention] object
|
||||
# 13| 1: [Parameter] requiredProperty
|
||||
# 13| -1: [TypeMention] string
|
||||
# 14| 4: [BlockStmt] {...}
|
||||
# 15| 0: [ExprStmt] ...;
|
||||
# 15| 0: [AssignExpr] ... = ...
|
||||
# 15| 0: [FieldAccess] access to field RequiredField
|
||||
# 15| 1: [ParameterAccess] access to parameter requiredField
|
||||
# 16| 1: [ExprStmt] ...;
|
||||
# 16| 0: [AssignExpr] ... = ...
|
||||
# 16| 0: [PropertyCall] access to property RequiredProperty
|
||||
# 16| 1: [ParameterAccess] access to parameter requiredProperty
|
||||
# 20| [Class] ClassRequiredMembersSub
|
||||
#-----| 3: (Base types)
|
||||
# 20| 0: [TypeMention] ClassRequiredMembers
|
||||
# 22| 4: [Property] VirtualProperty
|
||||
# 22| -1: [TypeMention] object
|
||||
# 22| 3: [Getter] get_VirtualProperty
|
||||
# 22| 4: [Setter] set_VirtualProperty
|
||||
#-----| 2: (Parameters)
|
||||
# 22| 0: [Parameter] value
|
||||
# 24| 5: [InstanceConstructor] ClassRequiredMembersSub
|
||||
# 24| 3: [ConstructorInitializer] call to constructor ClassRequiredMembers
|
||||
# 24| 4: [BlockStmt] {...}
|
||||
# 27| 6: [InstanceConstructor] ClassRequiredMembersSub
|
||||
#-----| 0: (Attributes)
|
||||
# 26| 1: [DefaultAttribute] [SetsRequiredMembers(...)]
|
||||
# 26| 0: [TypeMention] SetsRequiredMembersAttribute
|
||||
#-----| 2: (Parameters)
|
||||
# 27| 0: [Parameter] requiredField
|
||||
# 27| -1: [TypeMention] object
|
||||
# 27| 1: [Parameter] requiredProperty
|
||||
# 27| -1: [TypeMention] string
|
||||
# 27| 2: [Parameter] virtualProperty
|
||||
# 27| -1: [TypeMention] object
|
||||
# 27| 3: [ConstructorInitializer] call to constructor ClassRequiredMembers
|
||||
# 27| 0: [ParameterAccess] access to parameter requiredField
|
||||
# 27| 1: [ParameterAccess] access to parameter requiredProperty
|
||||
# 28| 4: [BlockStmt] {...}
|
||||
# 29| 0: [ExprStmt] ...;
|
||||
# 29| 0: [AssignExpr] ... = ...
|
||||
# 29| 0: [PropertyCall] access to property VirtualProperty
|
||||
# 29| 1: [ParameterAccess] access to parameter virtualProperty
|
||||
# 33| [RecordClass] RecordRequiredMembers
|
||||
# 33| 12: [NEOperator] !=
|
||||
#-----| 2: (Parameters)
|
||||
# 33| 0: [Parameter] left
|
||||
# 33| 1: [Parameter] right
|
||||
# 33| 13: [EQOperator] ==
|
||||
#-----| 2: (Parameters)
|
||||
# 33| 0: [Parameter] left
|
||||
# 33| 1: [Parameter] right
|
||||
# 33| 14: [Property] EqualityContract
|
||||
# 33| 3: [Getter] get_EqualityContract
|
||||
# 35| 15: [Property] X
|
||||
# 35| -1: [TypeMention] object
|
||||
# 35| 3: [Getter] get_X
|
||||
# 35| 4: [Setter] set_X
|
||||
#-----| 2: (Parameters)
|
||||
# 35| 0: [Parameter] value
|
||||
# 38| [Struct] StructRequiredMembers
|
||||
# 40| 5: [Property] Y
|
||||
# 40| -1: [TypeMention] string
|
||||
# 40| 3: [Getter] get_Y
|
||||
# 40| 4: [Setter] set_Y
|
||||
#-----| 2: (Parameters)
|
||||
# 40| 0: [Parameter] value
|
||||
Scoped.cs:
|
||||
# 1| [Struct] S1
|
||||
# 2| [Struct] S2
|
||||
|
||||
32
csharp/ql/test/library-tests/csharp11/RelaxedShift.cs
Normal file
32
csharp/ql/test/library-tests/csharp11/RelaxedShift.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
public interface IShiftOperators<TSelf, TOther, TReturn> where TSelf : IShiftOperators<TSelf, TOther, TReturn>
|
||||
{
|
||||
public static abstract TReturn operator <<(TSelf value, TOther shiftAmount);
|
||||
|
||||
public static abstract TReturn operator >>(TSelf value, TOther shiftAmount);
|
||||
|
||||
public static abstract TReturn operator >>>(TSelf value, TOther shiftAmount);
|
||||
}
|
||||
|
||||
public class Number : IShiftOperators<Number, string, Number>
|
||||
{
|
||||
public static Number operator <<(Number value, string shiftAmount) => value;
|
||||
|
||||
public static Number operator >>(Number value, string shiftAmount) => value;
|
||||
|
||||
public static Number operator >>>(Number value, string shiftAmount) => value;
|
||||
}
|
||||
|
||||
public class TestRelaxedShift
|
||||
{
|
||||
public void M1()
|
||||
{
|
||||
var n11 = new Number();
|
||||
var n12 = n11 << "1";
|
||||
|
||||
var n21 = new Number();
|
||||
var n22 = n21 >> "2";
|
||||
|
||||
var n31 = new Number();
|
||||
var n32 = n31 >>> "3";
|
||||
}
|
||||
}
|
||||
42
csharp/ql/test/library-tests/csharp11/RequiredMembers.cs
Normal file
42
csharp/ql/test/library-tests/csharp11/RequiredMembers.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
public class ClassRequiredMembers
|
||||
{
|
||||
public required object? RequiredField;
|
||||
public required string? RequiredProperty { get; init; }
|
||||
public virtual object? VirtualProperty { get; init; }
|
||||
|
||||
public ClassRequiredMembers() { }
|
||||
|
||||
[SetsRequiredMembers]
|
||||
public ClassRequiredMembers(object requiredField, string requiredProperty)
|
||||
{
|
||||
RequiredField = requiredField;
|
||||
RequiredProperty = requiredProperty;
|
||||
}
|
||||
}
|
||||
|
||||
public class ClassRequiredMembersSub : ClassRequiredMembers
|
||||
{
|
||||
public override required object? VirtualProperty { get; init; }
|
||||
|
||||
public ClassRequiredMembersSub() : base() { }
|
||||
|
||||
[SetsRequiredMembers]
|
||||
public ClassRequiredMembersSub(object requiredField, string requiredProperty, object virtualProperty) : base(requiredField, requiredProperty)
|
||||
{
|
||||
VirtualProperty = virtualProperty;
|
||||
}
|
||||
}
|
||||
|
||||
public record RecordRequiredMembers
|
||||
{
|
||||
public required object? X { get; init; }
|
||||
}
|
||||
|
||||
public struct StructRequiredMembers
|
||||
{
|
||||
public required string? Y { get; init; }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
| CheckedOperators.cs:9:43:9:43 | checked + | op_CheckedAddition | CheckedAddOperator |
|
||||
| CheckedOperators.cs:12:35:12:35 | + | op_Addition | AddOperator |
|
||||
| CheckedOperators.cs:15:43:15:43 | checked - | op_CheckedSubtraction | CheckedSubOperator |
|
||||
| CheckedOperators.cs:18:35:18:35 | - | op_Subtraction | SubOperator |
|
||||
| CheckedOperators.cs:21:43:21:43 | checked * | op_CheckedMultiply | CheckedMulOperator |
|
||||
| CheckedOperators.cs:24:35:24:35 | * | op_Multiply | MulOperator |
|
||||
| CheckedOperators.cs:27:43:27:43 | checked / | op_CheckedDivision | CheckedDivOperator |
|
||||
| CheckedOperators.cs:30:35:30:35 | / | op_Division | DivOperator |
|
||||
| CheckedOperators.cs:33:43:33:43 | checked - | op_CheckedUnaryNegation | CheckedMinusOperator |
|
||||
| CheckedOperators.cs:36:35:36:35 | - | op_UnaryNegation | MinusOperator |
|
||||
| CheckedOperators.cs:39:43:39:44 | checked ++ | op_CheckedIncrement | CheckedIncrementOperator |
|
||||
| CheckedOperators.cs:42:35:42:36 | ++ | op_Increment | IncrementOperator |
|
||||
| CheckedOperators.cs:45:43:45:44 | checked -- | op_CheckedDecrement | CheckedDecrementOperator |
|
||||
| CheckedOperators.cs:48:35:48:36 | -- | op_Decrement | DecrementOperator |
|
||||
| CheckedOperators.cs:51:28:51:35 | explicit conversion | op_Explicit | ExplicitConversionOperator |
|
||||
| CheckedOperators.cs:54:28:54:35 | checked explicit conversion | op_CheckedExplicit | CheckedExplicitConversionOperator |
|
||||
@@ -0,0 +1,5 @@
|
||||
import csharp
|
||||
|
||||
from Operator o
|
||||
where o.getFile().getStem() = "CheckedOperators"
|
||||
select o, o.getFunctionName(), o.getAPrimaryQlClass()
|
||||
@@ -0,0 +1,8 @@
|
||||
userdefinedoperators
|
||||
| RelaxedShift.cs:3:45:3:46 | << | LeftShiftOperator | RelaxedShift.cs:1:18:1:56 | IShiftOperators<Number,String,Number> |
|
||||
| RelaxedShift.cs:5:45:5:46 | >> | RightShiftOperator | RelaxedShift.cs:1:18:1:56 | IShiftOperators<Number,String,Number> |
|
||||
| RelaxedShift.cs:7:45:7:47 | >>> | UnsignedRightShiftOperator | RelaxedShift.cs:1:18:1:56 | IShiftOperators<Number,String,Number> |
|
||||
binaryoperatorcalls
|
||||
| RelaxedShift.cs:24:19:24:28 | call to operator << | RelaxedShift.cs:12:35:12:36 | << | RelaxedShift.cs:24:19:24:21 | access to local variable n11 | RelaxedShift.cs:24:26:24:28 | "1" |
|
||||
| RelaxedShift.cs:27:19:27:28 | call to operator >> | RelaxedShift.cs:14:35:14:36 | >> | RelaxedShift.cs:27:19:27:21 | access to local variable n21 | RelaxedShift.cs:27:26:27:28 | "2" |
|
||||
| RelaxedShift.cs:30:19:30:29 | call to operator >>> | RelaxedShift.cs:16:35:16:37 | >>> | RelaxedShift.cs:30:19:30:21 | access to local variable n31 | RelaxedShift.cs:30:27:30:29 | "3" |
|
||||
15
csharp/ql/test/library-tests/csharp11/relaxedShift.ql
Normal file
15
csharp/ql/test/library-tests/csharp11/relaxedShift.ql
Normal file
@@ -0,0 +1,15 @@
|
||||
import csharp
|
||||
|
||||
query predicate userdefinedoperators(BinaryOperator op, string qlclass, Type t) {
|
||||
op.getFile().getStem() = "RelaxedShift" and
|
||||
qlclass = op.getAPrimaryQlClass() and
|
||||
t = op.getDeclaringType() and
|
||||
op != op.getUnboundDeclaration()
|
||||
}
|
||||
|
||||
query predicate binaryoperatorcalls(OperatorCall oc, BinaryOperator o, Expr left, Expr right) {
|
||||
oc.getFile().getStem() = "RelaxedShift" and
|
||||
o = oc.getTarget() and
|
||||
left = oc.getArgument(0) and
|
||||
right = oc.getArgument(1)
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
| RequiredMembers.cs:6:29:6:41 | RequiredField | ClassRequiredMembers | Field |
|
||||
| RequiredMembers.cs:7:29:7:44 | RequiredProperty | ClassRequiredMembers | Property |
|
||||
| RequiredMembers.cs:22:38:22:52 | VirtualProperty | ClassRequiredMembersSub | Property |
|
||||
| RequiredMembers.cs:35:29:35:29 | X | RecordRequiredMembers | Property |
|
||||
| RequiredMembers.cs:40:29:40:29 | Y | StructRequiredMembers | Property |
|
||||
8
csharp/ql/test/library-tests/csharp11/requiredMembers.ql
Normal file
8
csharp/ql/test/library-tests/csharp11/requiredMembers.ql
Normal file
@@ -0,0 +1,8 @@
|
||||
import csharp
|
||||
|
||||
query predicate requiredmembers(Member m, string type, string qlclass) {
|
||||
m.getFile().getStem() = "RequiredMembers" and
|
||||
m.isRequired() and
|
||||
type = m.getDeclaringType().getName() and
|
||||
qlclass = m.getAPrimaryQlClass()
|
||||
}
|
||||
@@ -238,3 +238,7 @@
|
||||
| ViableCallable.cs:458:10:458:14 | M5<> | ViableCallable.cs:444:23:444:27 | M2<> |
|
||||
| ViableCallable.cs:475:10:475:12 | Run | ViableCallable.cs:468:10:468:11 | M2 |
|
||||
| ViableCallable.cs:475:10:475:12 | Run | ViableCallable.cs:473:17:473:18 | M1 |
|
||||
| ViableCallable.cs:492:10:492:12 | Run | ViableCallable.cs:487:32:487:32 | + |
|
||||
| ViableCallable.cs:492:10:492:12 | Run | ViableCallable.cs:488:40:488:40 | checked + |
|
||||
| ViableCallable.cs:492:10:492:12 | Run | ViableCallable.cs:489:28:489:35 | explicit conversion |
|
||||
| ViableCallable.cs:492:10:492:12 | Run | ViableCallable.cs:490:28:490:35 | checked explicit conversion |
|
||||
|
||||
@@ -471,3 +471,7 @@
|
||||
| ViableCallable.cs:461:9:461:30 | call to method M2<T> | C17.M2<T>(Func<T>) |
|
||||
| ViableCallable.cs:478:9:478:14 | call to method M1 | C18.M1() |
|
||||
| ViableCallable.cs:481:9:481:14 | call to method M2 | I2.M2() |
|
||||
| ViableCallable.cs:495:18:495:22 | call to operator + | C19.+(C19, C19) |
|
||||
| ViableCallable.cs:498:26:498:30 | call to operator checked + | C19.checked +(C19, C19) |
|
||||
| ViableCallable.cs:501:18:501:23 | call to operator explicit conversion | C19.explicit conversion(C19) |
|
||||
| ViableCallable.cs:504:26:504:31 | call to operator checked explicit conversion | C19.checked explicit conversion(C19) |
|
||||
|
||||
@@ -480,4 +480,27 @@ class C18 : I2
|
||||
// Viable callables: I2.M2()
|
||||
i.M2();
|
||||
}
|
||||
}
|
||||
|
||||
class C19
|
||||
{
|
||||
public static C19 operator +(C19 x, C19 y) => throw null;
|
||||
public static C19 operator checked +(C19 x, C19 y) => throw null;
|
||||
public static explicit operator int(C19 x) => throw null;
|
||||
public static explicit operator checked int(C19 x) => throw null;
|
||||
|
||||
void Run(C19 c)
|
||||
{
|
||||
// Viable callables: C19.op_Addition()
|
||||
var c1 = c + c;
|
||||
|
||||
// Viable callables: C19.op_CheckedAddition()
|
||||
var c2 = checked(c + c);
|
||||
|
||||
// Viable callables: C19.op_Explicit()
|
||||
var n1 = (int)c;
|
||||
|
||||
// Viable callables: C19.op_CheckedExplicit()
|
||||
var n2 = checked((int)c);
|
||||
}
|
||||
}
|
||||
@@ -268,3 +268,7 @@
|
||||
| ViableCallable.cs:423:9:423:21 | call to method M<String> | M<> | A5 |
|
||||
| ViableCallable.cs:478:9:478:14 | call to method M1 | M1 | C18 |
|
||||
| ViableCallable.cs:481:9:481:14 | call to method M2 | M2 | I2 |
|
||||
| ViableCallable.cs:495:18:495:22 | call to operator + | + | C19 |
|
||||
| ViableCallable.cs:498:26:498:30 | call to operator checked + | checked + | C19 |
|
||||
| ViableCallable.cs:501:18:501:23 | call to operator explicit conversion | explicit conversion | C19 |
|
||||
| ViableCallable.cs:504:26:504:31 | call to operator checked explicit conversion | checked explicit conversion | C19 |
|
||||
|
||||
@@ -6,7 +6,11 @@ if [[ "$OSTYPE" == "linux-gnu"* ]]; then
|
||||
dotnet_platform="linux-x64"
|
||||
elif [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
platform="osx64"
|
||||
dotnet_platform="osx-x64"
|
||||
if [[ $(uname -m) == 'arm64' ]]; then
|
||||
dotnet_platform="osx-arm64"
|
||||
else
|
||||
dotnet_platform="osx-x64"
|
||||
fi
|
||||
else
|
||||
echo "Unknown OS"
|
||||
exit 1
|
||||
|
||||
@@ -289,6 +289,39 @@ into the places where it is called. This can be useful when a predicate body is
|
||||
compute entirely, as it ensures that the predicate is evaluated with the other contextual information
|
||||
at the places where it is called.
|
||||
|
||||
``pragma[inline_late]``
|
||||
-----------------------
|
||||
|
||||
**Available for**: |non-member predicates|
|
||||
|
||||
The ``pragma[inline_late]`` annotation must be used in conjunction with a
|
||||
``bindingset[...]`` pragma. Together, they tell the QL optimiser to use the
|
||||
specified binding set for assessing join orders both in the body of the
|
||||
annotated predicate and at call sites and to inline the body into call sites
|
||||
after join ordering. This can be useful to prevent the optimiser from choosing
|
||||
a sub-optimal join order.
|
||||
|
||||
For instance, in the example below, the ``pragma[inline_late]`` and
|
||||
``bindingset[x]`` annotations specifiy that calls to ``p`` should be join ordered
|
||||
in a context where ``x`` is already bound. This forces the join orderer to
|
||||
order ``q(x)`` before ``p(x)``, which is more computationally efficient
|
||||
than ordering ``p(x)`` before ``q(x)``.
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
bindingset[x]
|
||||
pragma[inline_late]
|
||||
predicate p(int x) { x in [0..100000000] }
|
||||
|
||||
predicate q(int x) { x in [0..10000] }
|
||||
|
||||
from int x
|
||||
where p(x) and q(x)
|
||||
select x
|
||||
|
||||
..
|
||||
|
||||
|
||||
``pragma[noinline]``
|
||||
--------------------
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
.NET Core up to 3.1
|
||||
|
||||
.NET 5, .NET 6","``.sln``, ``.csproj``, ``.cs``, ``.cshtml``, ``.xaml``"
|
||||
Go (aka Golang), "Go up to 1.19", "Go 1.11 or more recent", ``.go``
|
||||
Go (aka Golang), "Go up to 1.20", "Go 1.11 or more recent", ``.go``
|
||||
Java,"Java 7 to 19 [4]_","javac (OpenJDK and Oracle JDK),
|
||||
|
||||
Eclipse compiler for Java (ECJ) [5]_",``.java``
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
module github.com/github/codeql-go
|
||||
|
||||
go 1.18
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4
|
||||
golang.org/x/tools v0.1.12
|
||||
golang.org/x/mod v0.8.0
|
||||
golang.org/x/tools v0.6.0
|
||||
)
|
||||
|
||||
require (
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect
|
||||
golang.org/x/sys v0.5.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||
)
|
||||
|
||||
@@ -6,6 +6,8 @@ golang.org/x/mod v0.5.0 h1:UG21uOlmZabA4fW5i7ZX6bjw1xELEGg/ZLgZq9auk/Q=
|
||||
golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
@@ -19,6 +21,8 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0v
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
@@ -28,6 +32,8 @@ golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA=
|
||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
htmlFiles
|
||||
extractionErrors
|
||||
#select
|
||||
| test.go:0:0:0:0 | test.go |
|
||||
@@ -0,0 +1,12 @@
|
||||
package makesample
|
||||
|
||||
import (
|
||||
"golang.org/x/net/ipv4"
|
||||
)
|
||||
|
||||
func test() {
|
||||
|
||||
header := ipv4.Header{}
|
||||
header.Version = 4
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import sys
|
||||
|
||||
from create_database_utils import *
|
||||
|
||||
run_codeql_database_create([], lang="go")
|
||||
@@ -0,0 +1,9 @@
|
||||
import go
|
||||
import semmle.go.DiagnosticsReporting
|
||||
|
||||
from GoFile f
|
||||
select f
|
||||
|
||||
query predicate htmlFiles(HtmlFile x) { any() }
|
||||
|
||||
query predicate extractionErrors(string msg, int sev) { reportableDiagnostics(_, msg, sev) }
|
||||
@@ -0,0 +1,2 @@
|
||||
all:
|
||||
go get
|
||||
@@ -0,0 +1,7 @@
|
||||
go 1.14
|
||||
|
||||
require (
|
||||
golang.org/x/net v0.0.0-20200505041828-1ed23360d12c
|
||||
)
|
||||
|
||||
module makesample
|
||||
@@ -0,0 +1,7 @@
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/net v0.0.0-20200505041828-1ed23360d12c h1:zJ0mtu4jCalhKg6Oaukv6iIkb+cOvDrajDH9DH46Q4M=
|
||||
golang.org/x/net v0.0.0-20200505041828-1ed23360d12c/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@@ -0,0 +1,4 @@
|
||||
htmlFiles
|
||||
extractionErrors
|
||||
#select
|
||||
| test.go:0:0:0:0 | test.go |
|
||||
@@ -0,0 +1,12 @@
|
||||
package makesample
|
||||
|
||||
import (
|
||||
"golang.org/x/net/ipv4"
|
||||
)
|
||||
|
||||
func test() {
|
||||
|
||||
header := ipv4.Header{}
|
||||
header.Version = 4
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import sys
|
||||
|
||||
from create_database_utils import *
|
||||
|
||||
run_codeql_database_create([], lang="go")
|
||||
@@ -0,0 +1,9 @@
|
||||
import go
|
||||
import semmle.go.DiagnosticsReporting
|
||||
|
||||
from GoFile f
|
||||
select f
|
||||
|
||||
query predicate htmlFiles(HtmlFile x) { any() }
|
||||
|
||||
query predicate extractionErrors(string msg, int sev) { reportableDiagnostics(_, msg, sev) }
|
||||
@@ -0,0 +1,4 @@
|
||||
all:
|
||||
# If the Makefile isn't used, then todel.go will be seen and fail the build.
|
||||
rm todel.go
|
||||
go get
|
||||
@@ -0,0 +1,7 @@
|
||||
go 1.14
|
||||
|
||||
require (
|
||||
golang.org/x/net v0.0.0-20200505041828-1ed23360d12c
|
||||
)
|
||||
|
||||
module makesample
|
||||
@@ -0,0 +1,7 @@
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/net v0.0.0-20200505041828-1ed23360d12c h1:zJ0mtu4jCalhKg6Oaukv6iIkb+cOvDrajDH9DH46Q4M=
|
||||
golang.org/x/net v0.0.0-20200505041828-1ed23360d12c/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@@ -0,0 +1,4 @@
|
||||
htmlFiles
|
||||
extractionErrors
|
||||
#select
|
||||
| test.go:0:0:0:0 | test.go |
|
||||
12
go/ql/integration-tests/all-platforms/go/make-sample/test.go
Normal file
12
go/ql/integration-tests/all-platforms/go/make-sample/test.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package makesample
|
||||
|
||||
import (
|
||||
"golang.org/x/net/ipv4"
|
||||
)
|
||||
|
||||
func test() {
|
||||
|
||||
header := ipv4.Header{}
|
||||
header.Version = 4
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import sys
|
||||
|
||||
from create_database_utils import *
|
||||
|
||||
run_codeql_database_create([], lang="go")
|
||||
@@ -0,0 +1,9 @@
|
||||
import go
|
||||
import semmle.go.DiagnosticsReporting
|
||||
|
||||
from GoFile f
|
||||
select f
|
||||
|
||||
query predicate htmlFiles(HtmlFile x) { any() }
|
||||
|
||||
query predicate extractionErrors(string msg, int sev) { reportableDiagnostics(_, msg, sev) }
|
||||
@@ -0,0 +1,12 @@
|
||||
package makesample
|
||||
|
||||
import (
|
||||
"golang.org/x/net/ipv4"
|
||||
)
|
||||
|
||||
func test() {
|
||||
|
||||
header := ipv4.Header{}
|
||||
header.Version = 4
|
||||
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
# ninja log v5
|
||||
0 1209 0 all 616b4577059039b7
|
||||
@@ -0,0 +1,5 @@
|
||||
rule get
|
||||
command = rm todel.go && go get
|
||||
# If the build.ninja file isn't used, then todel.go will be seen and fail the build.
|
||||
|
||||
build all: get test.go
|
||||
@@ -0,0 +1,7 @@
|
||||
go 1.14
|
||||
|
||||
require (
|
||||
golang.org/x/net v0.0.0-20200505041828-1ed23360d12c
|
||||
)
|
||||
|
||||
module makesample
|
||||
@@ -0,0 +1,7 @@
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/net v0.0.0-20200505041828-1ed23360d12c h1:zJ0mtu4jCalhKg6Oaukv6iIkb+cOvDrajDH9DH46Q4M=
|
||||
golang.org/x/net v0.0.0-20200505041828-1ed23360d12c/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@@ -0,0 +1,4 @@
|
||||
htmlFiles
|
||||
extractionErrors
|
||||
#select
|
||||
| test.go:0:0:0:0 | test.go |
|
||||
@@ -0,0 +1,12 @@
|
||||
package makesample
|
||||
|
||||
import (
|
||||
"golang.org/x/net/ipv4"
|
||||
)
|
||||
|
||||
func test() {
|
||||
|
||||
header := ipv4.Header{}
|
||||
header.Version = 4
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import sys
|
||||
|
||||
from create_database_utils import *
|
||||
|
||||
run_codeql_database_create([], lang="go")
|
||||
@@ -0,0 +1,9 @@
|
||||
import go
|
||||
import semmle.go.DiagnosticsReporting
|
||||
|
||||
from GoFile f
|
||||
select f
|
||||
|
||||
query predicate htmlFiles(HtmlFile x) { any() }
|
||||
|
||||
query predicate extractionErrors(string msg, int sev) { reportableDiagnostics(_, msg, sev) }
|
||||
@@ -0,0 +1,12 @@
|
||||
package makesample
|
||||
|
||||
import (
|
||||
"golang.org/x/net/ipv4"
|
||||
)
|
||||
|
||||
func test() {
|
||||
|
||||
header := ipv4.Header{}
|
||||
header.Version = 4
|
||||
|
||||
}
|
||||
4
go/ql/integration-tests/all-platforms/go/qlpack.yml
Normal file
4
go/ql/integration-tests/all-platforms/go/qlpack.yml
Normal file
@@ -0,0 +1,4 @@
|
||||
dependencies:
|
||||
codeql/go-all: '*'
|
||||
codeql/go-tests: '*'
|
||||
codeql/go-queries: '*'
|
||||
@@ -0,0 +1,4 @@
|
||||
htmlFiles
|
||||
extractionErrors
|
||||
#select
|
||||
| work/test.go:0:0:0:0 | work/test.go |
|
||||
7
go/ql/integration-tests/linux-only/go/dep-sample/test.py
Normal file
7
go/ql/integration-tests/linux-only/go/dep-sample/test.py
Normal file
@@ -0,0 +1,7 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
from create_database_utils import *
|
||||
|
||||
os.environ['LGTM_INDEX_IMPORT_PATH'] = "deptest"
|
||||
run_codeql_database_create([], lang="go", source="work")
|
||||
9
go/ql/integration-tests/linux-only/go/dep-sample/test.ql
Normal file
9
go/ql/integration-tests/linux-only/go/dep-sample/test.ql
Normal file
@@ -0,0 +1,9 @@
|
||||
import go
|
||||
import semmle.go.DiagnosticsReporting
|
||||
|
||||
from GoFile f
|
||||
select f
|
||||
|
||||
query predicate htmlFiles(HtmlFile x) { any() }
|
||||
|
||||
query predicate extractionErrors(string msg, int sev) { reportableDiagnostics(_, msg, sev) }
|
||||
17
go/ql/integration-tests/linux-only/go/dep-sample/work/Gopkg.lock
generated
Normal file
17
go/ql/integration-tests/linux-only/go/dep-sample/work/Gopkg.lock
generated
Normal file
@@ -0,0 +1,17 @@
|
||||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:9a12483c63e8328a477280cd6855689af0f584eb580b66c0d113a1f5fe7791b0"
|
||||
name = "golang.org/x/time"
|
||||
packages = ["rate"]
|
||||
pruneopts = "UT"
|
||||
revision = "3af7569d3a1e776fc2a3c1cec133b43105ea9c2e"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
input-imports = ["golang.org/x/time/rate"]
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
@@ -0,0 +1,31 @@
|
||||
# Gopkg.toml example
|
||||
#
|
||||
# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html
|
||||
# for detailed Gopkg.toml documentation.
|
||||
#
|
||||
# required = ["github.com/user/thing/cmd/thing"]
|
||||
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project"
|
||||
# version = "1.0.0"
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project2"
|
||||
# branch = "dev"
|
||||
# source = "github.com/myfork/project2"
|
||||
#
|
||||
# [[override]]
|
||||
# name = "github.com/x/y"
|
||||
# version = "2.4.0"
|
||||
#
|
||||
# [prune]
|
||||
# non-go = false
|
||||
# go-tests = true
|
||||
# unused-packages = true
|
||||
|
||||
|
||||
[prune]
|
||||
go-tests = true
|
||||
unused-packages = true
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package deptest
|
||||
|
||||
import (
|
||||
"golang.org/x/time/rate"
|
||||
)
|
||||
|
||||
func test() {
|
||||
|
||||
r := rate.Limit(1)
|
||||
_ = r
|
||||
|
||||
}
|
||||
3
go/ql/integration-tests/linux-only/go/dep-sample/work/vendor/golang.org/x/time/AUTHORS
generated
vendored
Normal file
3
go/ql/integration-tests/linux-only/go/dep-sample/work/vendor/golang.org/x/time/AUTHORS
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# This source code refers to The Go Authors for copyright purposes.
|
||||
# The master list of authors is in the main Go distribution,
|
||||
# visible at http://tip.golang.org/AUTHORS.
|
||||
3
go/ql/integration-tests/linux-only/go/dep-sample/work/vendor/golang.org/x/time/CONTRIBUTORS
generated
vendored
Normal file
3
go/ql/integration-tests/linux-only/go/dep-sample/work/vendor/golang.org/x/time/CONTRIBUTORS
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# This source code was written by the Go contributors.
|
||||
# The master list of contributors is in the main Go distribution,
|
||||
# visible at http://tip.golang.org/CONTRIBUTORS.
|
||||
27
go/ql/integration-tests/linux-only/go/dep-sample/work/vendor/golang.org/x/time/LICENSE
generated
vendored
Normal file
27
go/ql/integration-tests/linux-only/go/dep-sample/work/vendor/golang.org/x/time/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
22
go/ql/integration-tests/linux-only/go/dep-sample/work/vendor/golang.org/x/time/PATENTS
generated
vendored
Normal file
22
go/ql/integration-tests/linux-only/go/dep-sample/work/vendor/golang.org/x/time/PATENTS
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
Additional IP Rights Grant (Patents)
|
||||
|
||||
"This implementation" means the copyrightable works distributed by
|
||||
Google as part of the Go project.
|
||||
|
||||
Google hereby grants to You a perpetual, worldwide, non-exclusive,
|
||||
no-charge, royalty-free, irrevocable (except as stated in this section)
|
||||
patent license to make, have made, use, offer to sell, sell, import,
|
||||
transfer and otherwise run, modify and propagate the contents of this
|
||||
implementation of Go, where such license applies only to those patent
|
||||
claims, both currently owned or controlled by Google and acquired in
|
||||
the future, licensable by Google that are necessarily infringed by this
|
||||
implementation of Go. This grant does not include claims that would be
|
||||
infringed only as a consequence of further modification of this
|
||||
implementation. If you or your agent or exclusive licensee institute or
|
||||
order or agree to the institution of patent litigation against any
|
||||
entity (including a cross-claim or counterclaim in a lawsuit) alleging
|
||||
that this implementation of Go or any code incorporated within this
|
||||
implementation of Go constitutes direct or contributory patent
|
||||
infringement, or inducement of patent infringement, then any patent
|
||||
rights granted to you under this License for this implementation of Go
|
||||
shall terminate as of the date such litigation is filed.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user