Compare commits

..

1 Commits

Author SHA1 Message Date
Ian Lynagh
6260f95d5a XXX Experiment 2023-02-10 16:51:55 +00:00
2148 changed files with 22317 additions and 175492 deletions

View File

@@ -9,7 +9,7 @@ inputs:
outputs:
cache-dir:
description: "The directory where the cache was stored"
value: ${{ steps.output-compilation-dir.outputs.compdir }}
value: ${{ steps.fill-compilation-dir.outputs.compdir }}
runs:
using: composite
@@ -27,9 +27,7 @@ runs:
if: ${{ github.event_name == 'pull_request' }}
uses: actions/cache/restore@v3
with:
path: |
**/.cache
~/.codeql/compile-cache
path: '**/.cache'
key: codeql-compile-${{ inputs.key }}-pr-${{ github.sha }}
restore-keys: |
codeql-compile-${{ inputs.key }}-${{ github.base_ref }}-${{ env.merge_base }}
@@ -39,111 +37,18 @@ runs:
if: ${{ github.event_name != 'pull_request' }}
uses: actions/cache@v3
with:
path: |
**/.cache
~/.codeql/compile-cache
path: '**/.cache'
key: codeql-compile-${{ inputs.key }}-${{ github.ref_name }}-${{ github.sha }} # just fill on main
restore-keys: | # restore the latest cache if the exact cache is unavailable, to speed up compilation.
codeql-compile-${{ inputs.key }}-${{ github.ref_name }}-
codeql-compile-${{ inputs.key }}-main-
- name: Output-compilationdir
id: output-compilation-dir
- 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:
COMBINED_CACHE_DIR: ${{ runner.temp }}/compilation-dir
- name: Fill compilation cache directory
id: fill-compilation-dir
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");
const os = require("os");
// 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}`);
}
const globalCacheDir = path.join(os.homedir(), ".codeql", "compile-cache");
if (fs.existsSync(globalCacheDir)) {
console.log("Found global home dir: " + globalCacheDir);
cacheDirs.push(globalCacheDir);
}
if (cacheDirs.length === 0) {
console.log("No cache dirs found");
return;
}
// 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();

View File

@@ -0,0 +1,75 @@
// # 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();

View File

@@ -26,8 +26,9 @@ jobs:
shell: bash
run: |
EXIT_CODE=0
# TODO: remove the swift exception from the regex when we fix generated QLdoc
# TODO: remove the shared exception from the regex when coverage of qlpacks without dbschemes is supported
changed_lib_packs="$(git diff --name-only --diff-filter=ACMRT HEAD^ HEAD | { grep -Po '^(?!(shared))[a-z]*/ql/lib' || true; } | sort -u)"
changed_lib_packs="$(git diff --name-only --diff-filter=ACMRT HEAD^ HEAD | { grep -Po '^(?!(swift|shared))[a-z]*/ql/lib' || true; } | sort -u)"
for pack_dir in ${changed_lib_packs}; do
lang="${pack_dir%/ql/lib}"
codeql generate library-doc-coverage --output="${RUNNER_TEMP}/${lang}-current.txt" --dir="${pack_dir}"

View File

@@ -24,14 +24,14 @@ jobs:
with:
key: all-queries
- name: check formatting
run: find */ql -type f \( -name "*.qll" -o -name "*.ql" \) -print0 | xargs -0 -n 3000 -P 10 codeql query format -q --check-only
run: find */ql -type f \( -name "*.qll" -o -name "*.ql" \) -print0 | xargs -0 codeql query format --check-only
- name: compile queries - check-only
# run with --check-only if running in a PR (github.sha != main)
if : ${{ github.event_name == 'pull_request' }}
shell: bash
run: codeql query compile -q -j0 */ql/{src,examples} --keep-going --warnings=error --check-only --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}"
run: codeql query compile -j0 */ql/{src,examples} --keep-going --warnings=error --check-only --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}"
- name: compile queries - full
# do full compile if running on main - this populates the cache
if : ${{ github.event_name != 'pull_request' }}
shell: bash
run: codeql query compile -q -j0 */ql/{src,examples} --keep-going --warnings=error --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}"
run: codeql query compile -j0 */ql/{src,examples} --keep-going --warnings=error --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}"

View File

@@ -12,10 +12,10 @@ jobs:
name: Test MacOS
runs-on: macos-latest
steps:
- name: Set up Go 1.20
- name: Set up Go 1.19
uses: actions/setup-go@v3
with:
go-version: 1.20.0
go-version: 1.19
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.20
- name: Set up Go 1.19
uses: actions/setup-go@v3
with:
go-version: 1.20.0
go-version: 1.19
id: go
- name: Check out code

View File

@@ -20,10 +20,10 @@ jobs:
name: Test Linux (Ubuntu)
runs-on: ubuntu-latest-xl
steps:
- name: Set up Go 1.20
- name: Set up Go 1.19
uses: actions/setup-go@v3
with:
go-version: 1.20.0
go-version: 1.19
id: go
- name: Check out code

View File

@@ -5,6 +5,13 @@ 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
@@ -15,8 +22,6 @@ jobs:
steps:
### Build the queries ###
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Find codeql
id: find-codeql
uses: github/codeql-action/init@v2
@@ -29,9 +34,7 @@ jobs:
id: cache-extractor
uses: actions/cache@v3
with:
path: |
ql/extractor-pack/
ql/target/release/buramu
path: ql/extractor-pack/
key: ${{ runner.os }}-${{ steps.os_version.outputs.version }}-extractor-${{ hashFiles('ql/**/Cargo.lock') }}-${{ hashFiles('ql/**/*.rs') }}
- name: Cache cargo
if: steps.cache-extractor.outputs.cache-hit != 'true'
@@ -54,7 +57,6 @@ jobs:
key: run-ql-for-ql
- name: Make database and analyze
run: |
./ql/target/release/buramu | tee deprecated.blame # Add a blame file for the extractor to parse.
${CODEQL} database create -l=ql --search-path ql/extractor-pack ${DB}
${CODEQL} database analyze -j0 --format=sarif-latest --output=ql-for-ql.sarif ${DB} ql/ql/src/codeql-suites/ql-code-scanning.qls --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}"
env:
@@ -63,7 +65,6 @@ jobs:
LGTM_INDEX_FILTERS: |
exclude:ql/ql/test
exclude:*/ql/lib/upgrades/
exclude:java/ql/integration-tests
- name: Upload sarif to code-scanning
uses: github/codeql-action/upload-sarif@v2
with:

View File

@@ -5,7 +5,6 @@ on:
paths:
- "swift/**"
- "misc/bazel/**"
- "misc/codegen/**"
- "*.bazel*"
- .github/workflows/swift.yml
- .github/actions/**
@@ -20,7 +19,6 @@ on:
paths:
- "swift/**"
- "misc/bazel/**"
- "misc/codegen/**"
- "*.bazel*"
- .github/workflows/swift.yml
- .github/actions/**

View File

@@ -53,5 +53,5 @@ repos:
name: Run Swift code generation unit tests
files: ^swift/codegen/.*\.py$
language: system
entry: bazel test //misc/codegen/test
entry: bazel test //swift/codegen/test
pass_filenames: false

View File

@@ -2,11 +2,10 @@
/csharp/ @github/codeql-csharp
/go/ @github/codeql-go
/java/ @github/codeql-java
/javascript/ @github/codeql-dynamic
/python/ @github/codeql-dynamic
/ruby/ @github/codeql-dynamic
/javascript/ @github/codeql-javascript
/python/ @github/codeql-python
/ruby/ @github/codeql-ruby
/swift/ @github/codeql-swift
/misc/codegen/ @github/codeql-swift
/java/kotlin-extractor/ @github/codeql-kotlin
/java/kotlin-explorer/ @github/codeql-kotlin

View File

@@ -131,14 +131,6 @@ 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)));

View File

@@ -1,11 +1,3 @@
## 0.5.4
No user-facing changes.
## 0.5.3
No user-facing changes.
## 0.5.2
No user-facing changes.

View File

@@ -1,3 +0,0 @@
## 0.5.3
No user-facing changes.

View File

@@ -1,3 +0,0 @@
## 0.5.4
No user-facing changes.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.5.4
lastReleaseVersion: 0.5.2

View File

@@ -667,75 +667,20 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
fwdFlowIn(_, _, _, node, config) and
cc = true
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true and
not fullBarrier(node, config)
)
or
// flow out of a callable
fwdFlowOut(_, node, false, config) and
cc = false
or
// flow through a callable
exists(DataFlowCall call |
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
(
fwdFlowOut(call, node, false, 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)
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
}
@@ -781,8 +726,7 @@ private module Stage1 implements StageSig {
)
}
// inline to reduce the number of iterations
pragma[inline]
pragma[nomagic]
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
@@ -796,6 +740,17 @@ 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
@@ -862,8 +817,13 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
revFlowIn(_, node, false, config) and
toReturn = false
exists(DataFlowCall call |
revFlowIn(call, node, false, config) and
toReturn = false
or
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
or
// flow out of a callable
exists(ReturnPosition pos |
@@ -871,12 +831,6 @@ 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)
)
}
/**
@@ -932,11 +886,11 @@ private module Stage1 implements StageSig {
additional predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
) {
fwdFlowIn(call, arg, _, p, config)
viableParamArgEx(call, p, arg) and
fwdFlow(arg, config)
}
// inline to reduce the number of iterations
pragma[inline]
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config
) {

View File

@@ -667,75 +667,20 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
fwdFlowIn(_, _, _, node, config) and
cc = true
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true and
not fullBarrier(node, config)
)
or
// flow out of a callable
fwdFlowOut(_, node, false, config) and
cc = false
or
// flow through a callable
exists(DataFlowCall call |
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
(
fwdFlowOut(call, node, false, 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)
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
}
@@ -781,8 +726,7 @@ private module Stage1 implements StageSig {
)
}
// inline to reduce the number of iterations
pragma[inline]
pragma[nomagic]
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
@@ -796,6 +740,17 @@ 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
@@ -862,8 +817,13 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
revFlowIn(_, node, false, config) and
toReturn = false
exists(DataFlowCall call |
revFlowIn(call, node, false, config) and
toReturn = false
or
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
or
// flow out of a callable
exists(ReturnPosition pos |
@@ -871,12 +831,6 @@ 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)
)
}
/**
@@ -932,11 +886,11 @@ private module Stage1 implements StageSig {
additional predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
) {
fwdFlowIn(call, arg, _, p, config)
viableParamArgEx(call, p, arg) and
fwdFlow(arg, config)
}
// inline to reduce the number of iterations
pragma[inline]
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config
) {

View File

@@ -667,75 +667,20 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
fwdFlowIn(_, _, _, node, config) and
cc = true
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true and
not fullBarrier(node, config)
)
or
// flow out of a callable
fwdFlowOut(_, node, false, config) and
cc = false
or
// flow through a callable
exists(DataFlowCall call |
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
(
fwdFlowOut(call, node, false, 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)
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
}
@@ -781,8 +726,7 @@ private module Stage1 implements StageSig {
)
}
// inline to reduce the number of iterations
pragma[inline]
pragma[nomagic]
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
@@ -796,6 +740,17 @@ 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
@@ -862,8 +817,13 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
revFlowIn(_, node, false, config) and
toReturn = false
exists(DataFlowCall call |
revFlowIn(call, node, false, config) and
toReturn = false
or
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
or
// flow out of a callable
exists(ReturnPosition pos |
@@ -871,12 +831,6 @@ 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)
)
}
/**
@@ -932,11 +886,11 @@ private module Stage1 implements StageSig {
additional predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
) {
fwdFlowIn(call, arg, _, p, config)
viableParamArgEx(call, p, arg) and
fwdFlow(arg, config)
}
// inline to reduce the number of iterations
pragma[inline]
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config
) {

View File

@@ -667,75 +667,20 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
fwdFlowIn(_, _, _, node, config) and
cc = true
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true and
not fullBarrier(node, config)
)
or
// flow out of a callable
fwdFlowOut(_, node, false, config) and
cc = false
or
// flow through a callable
exists(DataFlowCall call |
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
(
fwdFlowOut(call, node, false, 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)
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
}
@@ -781,8 +726,7 @@ private module Stage1 implements StageSig {
)
}
// inline to reduce the number of iterations
pragma[inline]
pragma[nomagic]
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
@@ -796,6 +740,17 @@ 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
@@ -862,8 +817,13 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
revFlowIn(_, node, false, config) and
toReturn = false
exists(DataFlowCall call |
revFlowIn(call, node, false, config) and
toReturn = false
or
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
or
// flow out of a callable
exists(ReturnPosition pos |
@@ -871,12 +831,6 @@ 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)
)
}
/**
@@ -932,11 +886,11 @@ private module Stage1 implements StageSig {
additional predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
) {
fwdFlowIn(call, arg, _, p, config)
viableParamArgEx(call, p, arg) and
fwdFlow(arg, config)
}
// inline to reduce the number of iterations
pragma[inline]
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config
) {

View File

@@ -707,8 +707,8 @@ private module Cached {
* Gets a viable dispatch target of `call` in the context `ctx`. This is
* restricted to those `call`s for which a context might make a difference.
*/
cached
DataFlowCallable viableImplInCallContextExt(DataFlowCall call, DataFlowCall ctx) {
pragma[nomagic]
private DataFlowCallable viableImplInCallContextExt(DataFlowCall call, DataFlowCall ctx) {
result = viableImplInCallContext(call, ctx) and
result = viableCallable(call)
or

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-all
version: 0.5.4
version: 0.5.3-dev
groups: cpp
dbscheme: semmlecode.cpp.dbscheme
extractor: cpp

View File

@@ -667,75 +667,20 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
fwdFlowIn(_, _, _, node, config) and
cc = true
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true and
not fullBarrier(node, config)
)
or
// flow out of a callable
fwdFlowOut(_, node, false, config) and
cc = false
or
// flow through a callable
exists(DataFlowCall call |
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
(
fwdFlowOut(call, node, false, 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)
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
}
@@ -781,8 +726,7 @@ private module Stage1 implements StageSig {
)
}
// inline to reduce the number of iterations
pragma[inline]
pragma[nomagic]
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
@@ -796,6 +740,17 @@ 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
@@ -862,8 +817,13 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
revFlowIn(_, node, false, config) and
toReturn = false
exists(DataFlowCall call |
revFlowIn(call, node, false, config) and
toReturn = false
or
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
or
// flow out of a callable
exists(ReturnPosition pos |
@@ -871,12 +831,6 @@ 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)
)
}
/**
@@ -932,11 +886,11 @@ private module Stage1 implements StageSig {
additional predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
) {
fwdFlowIn(call, arg, _, p, config)
viableParamArgEx(call, p, arg) and
fwdFlow(arg, config)
}
// inline to reduce the number of iterations
pragma[inline]
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config
) {

View File

@@ -667,75 +667,20 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
fwdFlowIn(_, _, _, node, config) and
cc = true
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true and
not fullBarrier(node, config)
)
or
// flow out of a callable
fwdFlowOut(_, node, false, config) and
cc = false
or
// flow through a callable
exists(DataFlowCall call |
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
(
fwdFlowOut(call, node, false, 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)
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
}
@@ -781,8 +726,7 @@ private module Stage1 implements StageSig {
)
}
// inline to reduce the number of iterations
pragma[inline]
pragma[nomagic]
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
@@ -796,6 +740,17 @@ 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
@@ -862,8 +817,13 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
revFlowIn(_, node, false, config) and
toReturn = false
exists(DataFlowCall call |
revFlowIn(call, node, false, config) and
toReturn = false
or
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
or
// flow out of a callable
exists(ReturnPosition pos |
@@ -871,12 +831,6 @@ 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)
)
}
/**
@@ -932,11 +886,11 @@ private module Stage1 implements StageSig {
additional predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
) {
fwdFlowIn(call, arg, _, p, config)
viableParamArgEx(call, p, arg) and
fwdFlow(arg, config)
}
// inline to reduce the number of iterations
pragma[inline]
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config
) {

View File

@@ -667,75 +667,20 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
fwdFlowIn(_, _, _, node, config) and
cc = true
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true and
not fullBarrier(node, config)
)
or
// flow out of a callable
fwdFlowOut(_, node, false, config) and
cc = false
or
// flow through a callable
exists(DataFlowCall call |
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
(
fwdFlowOut(call, node, false, 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)
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
}
@@ -781,8 +726,7 @@ private module Stage1 implements StageSig {
)
}
// inline to reduce the number of iterations
pragma[inline]
pragma[nomagic]
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
@@ -796,6 +740,17 @@ 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
@@ -862,8 +817,13 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
revFlowIn(_, node, false, config) and
toReturn = false
exists(DataFlowCall call |
revFlowIn(call, node, false, config) and
toReturn = false
or
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
or
// flow out of a callable
exists(ReturnPosition pos |
@@ -871,12 +831,6 @@ 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)
)
}
/**
@@ -932,11 +886,11 @@ private module Stage1 implements StageSig {
additional predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
) {
fwdFlowIn(call, arg, _, p, config)
viableParamArgEx(call, p, arg) and
fwdFlow(arg, config)
}
// inline to reduce the number of iterations
pragma[inline]
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config
) {

View File

@@ -667,75 +667,20 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
fwdFlowIn(_, _, _, node, config) and
cc = true
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true and
not fullBarrier(node, config)
)
or
// flow out of a callable
fwdFlowOut(_, node, false, config) and
cc = false
or
// flow through a callable
exists(DataFlowCall call |
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
(
fwdFlowOut(call, node, false, 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)
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
}
@@ -781,8 +726,7 @@ private module Stage1 implements StageSig {
)
}
// inline to reduce the number of iterations
pragma[inline]
pragma[nomagic]
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
@@ -796,6 +740,17 @@ 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
@@ -862,8 +817,13 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
revFlowIn(_, node, false, config) and
toReturn = false
exists(DataFlowCall call |
revFlowIn(call, node, false, config) and
toReturn = false
or
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
or
// flow out of a callable
exists(ReturnPosition pos |
@@ -871,12 +831,6 @@ 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)
)
}
/**
@@ -932,11 +886,11 @@ private module Stage1 implements StageSig {
additional predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
) {
fwdFlowIn(call, arg, _, p, config)
viableParamArgEx(call, p, arg) and
fwdFlow(arg, config)
}
// inline to reduce the number of iterations
pragma[inline]
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config
) {

View File

@@ -707,8 +707,8 @@ private module Cached {
* Gets a viable dispatch target of `call` in the context `ctx`. This is
* restricted to those `call`s for which a context might make a difference.
*/
cached
DataFlowCallable viableImplInCallContextExt(DataFlowCall call, DataFlowCall ctx) {
pragma[nomagic]
private DataFlowCallable viableImplInCallContextExt(DataFlowCall call, DataFlowCall ctx) {
result = viableImplInCallContext(call, ctx) and
result = viableCallable(call)
or

View File

@@ -667,75 +667,20 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
fwdFlowIn(_, _, _, node, config) and
cc = true
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true and
not fullBarrier(node, config)
)
or
// flow out of a callable
fwdFlowOut(_, node, false, config) and
cc = false
or
// flow through a callable
exists(DataFlowCall call |
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
(
fwdFlowOut(call, node, false, 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)
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
}
@@ -781,8 +726,7 @@ private module Stage1 implements StageSig {
)
}
// inline to reduce the number of iterations
pragma[inline]
pragma[nomagic]
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
@@ -796,6 +740,17 @@ 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
@@ -862,8 +817,13 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
revFlowIn(_, node, false, config) and
toReturn = false
exists(DataFlowCall call |
revFlowIn(call, node, false, config) and
toReturn = false
or
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
or
// flow out of a callable
exists(ReturnPosition pos |
@@ -871,12 +831,6 @@ 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)
)
}
/**
@@ -932,11 +886,11 @@ private module Stage1 implements StageSig {
additional predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
) {
fwdFlowIn(call, arg, _, p, config)
viableParamArgEx(call, p, arg) and
fwdFlow(arg, config)
}
// inline to reduce the number of iterations
pragma[inline]
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config
) {

View File

@@ -667,75 +667,20 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
fwdFlowIn(_, _, _, node, config) and
cc = true
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true and
not fullBarrier(node, config)
)
or
// flow out of a callable
fwdFlowOut(_, node, false, config) and
cc = false
or
// flow through a callable
exists(DataFlowCall call |
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
(
fwdFlowOut(call, node, false, 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)
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
}
@@ -781,8 +726,7 @@ private module Stage1 implements StageSig {
)
}
// inline to reduce the number of iterations
pragma[inline]
pragma[nomagic]
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
@@ -796,6 +740,17 @@ 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
@@ -862,8 +817,13 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
revFlowIn(_, node, false, config) and
toReturn = false
exists(DataFlowCall call |
revFlowIn(call, node, false, config) and
toReturn = false
or
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
or
// flow out of a callable
exists(ReturnPosition pos |
@@ -871,12 +831,6 @@ 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)
)
}
/**
@@ -932,11 +886,11 @@ private module Stage1 implements StageSig {
additional predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
) {
fwdFlowIn(call, arg, _, p, config)
viableParamArgEx(call, p, arg) and
fwdFlow(arg, config)
}
// inline to reduce the number of iterations
pragma[inline]
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config
) {

View File

@@ -667,75 +667,20 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
fwdFlowIn(_, _, _, node, config) and
cc = true
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true and
not fullBarrier(node, config)
)
or
// flow out of a callable
fwdFlowOut(_, node, false, config) and
cc = false
or
// flow through a callable
exists(DataFlowCall call |
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
(
fwdFlowOut(call, node, false, 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)
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
}
@@ -781,8 +726,7 @@ private module Stage1 implements StageSig {
)
}
// inline to reduce the number of iterations
pragma[inline]
pragma[nomagic]
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
@@ -796,6 +740,17 @@ 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
@@ -862,8 +817,13 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
revFlowIn(_, node, false, config) and
toReturn = false
exists(DataFlowCall call |
revFlowIn(call, node, false, config) and
toReturn = false
or
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
or
// flow out of a callable
exists(ReturnPosition pos |
@@ -871,12 +831,6 @@ 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)
)
}
/**
@@ -932,11 +886,11 @@ private module Stage1 implements StageSig {
additional predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
) {
fwdFlowIn(call, arg, _, p, config)
viableParamArgEx(call, p, arg) and
fwdFlow(arg, config)
}
// inline to reduce the number of iterations
pragma[inline]
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config
) {

View File

@@ -667,75 +667,20 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
fwdFlowIn(_, _, _, node, config) and
cc = true
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true and
not fullBarrier(node, config)
)
or
// flow out of a callable
fwdFlowOut(_, node, false, config) and
cc = false
or
// flow through a callable
exists(DataFlowCall call |
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
(
fwdFlowOut(call, node, false, 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)
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
}
@@ -781,8 +726,7 @@ private module Stage1 implements StageSig {
)
}
// inline to reduce the number of iterations
pragma[inline]
pragma[nomagic]
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
@@ -796,6 +740,17 @@ 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
@@ -862,8 +817,13 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
revFlowIn(_, node, false, config) and
toReturn = false
exists(DataFlowCall call |
revFlowIn(call, node, false, config) and
toReturn = false
or
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
or
// flow out of a callable
exists(ReturnPosition pos |
@@ -871,12 +831,6 @@ 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)
)
}
/**
@@ -932,11 +886,11 @@ private module Stage1 implements StageSig {
additional predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
) {
fwdFlowIn(call, arg, _, p, config)
viableParamArgEx(call, p, arg) and
fwdFlow(arg, config)
}
// inline to reduce the number of iterations
pragma[inline]
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config
) {

View File

@@ -667,75 +667,20 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
fwdFlowIn(_, _, _, node, config) and
cc = true
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true and
not fullBarrier(node, config)
)
or
// flow out of a callable
fwdFlowOut(_, node, false, config) and
cc = false
or
// flow through a callable
exists(DataFlowCall call |
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
(
fwdFlowOut(call, node, false, 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)
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
}
@@ -781,8 +726,7 @@ private module Stage1 implements StageSig {
)
}
// inline to reduce the number of iterations
pragma[inline]
pragma[nomagic]
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
@@ -796,6 +740,17 @@ 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
@@ -862,8 +817,13 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
revFlowIn(_, node, false, config) and
toReturn = false
exists(DataFlowCall call |
revFlowIn(call, node, false, config) and
toReturn = false
or
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
or
// flow out of a callable
exists(ReturnPosition pos |
@@ -871,12 +831,6 @@ 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)
)
}
/**
@@ -932,11 +886,11 @@ private module Stage1 implements StageSig {
additional predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
) {
fwdFlowIn(call, arg, _, p, config)
viableParamArgEx(call, p, arg) and
fwdFlow(arg, config)
}
// inline to reduce the number of iterations
pragma[inline]
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config
) {

View File

@@ -707,8 +707,8 @@ private module Cached {
* Gets a viable dispatch target of `call` in the context `ctx`. This is
* restricted to those `call`s for which a context might make a difference.
*/
cached
DataFlowCallable viableImplInCallContextExt(DataFlowCall call, DataFlowCall ctx) {
pragma[nomagic]
private DataFlowCallable viableImplInCallContextExt(DataFlowCall call, DataFlowCall ctx) {
result = viableImplInCallContext(call, ctx) and
result = viableCallable(call)
or

View File

@@ -1,11 +1,3 @@
## 0.5.4
No user-facing changes.
## 0.5.3
No user-facing changes.
## 0.5.2
No user-facing changes.

View File

@@ -1,3 +0,0 @@
## 0.5.3
No user-facing changes.

View File

@@ -1,3 +0,0 @@
## 0.5.4
No user-facing changes.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.5.4
lastReleaseVersion: 0.5.2

View File

@@ -1,7 +0,0 @@
...
a = getc(f);
if (a < 123) ret = 123/a; // BAD
...
if (a != 0) ret = 123/a; // GOOD
...

View File

@@ -1,23 +0,0 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p> Possible cases of division by zero when using the return value from functions.</p>
</overview>
<example>
<p>The following example shows the use of a function with an error when using the return value and without an error.</p>
<sample src="DivideByZeroUsingReturnValue.cpp" />
</example>
<references>
<li>
CERT Coding Standard:
<a href="https://wiki.sei.cmu.edu/confluence/display/c/INT33-C.+Ensure+that+division+and+remainder+operations+do+not+result+in+divide-by-zero+errors">INT33-C. Ensure that division and remainder operations do not result in divide-by-zero errors - SEI CERT C Coding Standard - Confluence</a>.
</li>
</references>
</qhelp>

View File

@@ -1,274 +0,0 @@
/**
* @name Divide by zero using return value
* @description Possible cases of division by zero when using the return value from functions.
* @kind problem
* @id cpp/divide-by-zero-using-return-value
* @problem.severity warning
* @precision medium
* @tags correctness
* security
* external/cwe/cwe-369
*/
import cpp
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
import semmle.code.cpp.controlflow.Guards
/** Holds if function `fn` can return a value equal to value `val` */
predicate mayBeReturnValue(Function fn, float val) {
exists(Expr tmpExp, ReturnStmt rs |
tmpExp.getValue().toFloat() = val and
rs.getEnclosingFunction() = fn and
(
globalValueNumber(rs.getExpr()) = globalValueNumber(tmpExp)
or
exists(AssignExpr ae |
ae.getLValue().(VariableAccess).getTarget() =
globalValueNumber(rs.getExpr()).getAnExpr().(VariableAccess).getTarget() and
globalValueNumber(ae.getRValue()) = globalValueNumber(tmpExp)
)
or
exists(Initializer it |
globalValueNumber(it.getExpr()) = globalValueNumber(tmpExp) and
it.getDeclaration().(Variable).getAnAccess().getTarget() =
globalValueNumber(rs.getExpr()).getAnExpr().(VariableAccess).getTarget()
)
)
)
}
/** Holds if function `fn` can return a value equal zero */
predicate mayBeReturnZero(Function fn) {
mayBeReturnValue(fn, 0)
or
fn.hasName([
"iswalpha", "iswlower", "iswprint", "iswspace", "iswblank", "iswupper", "iswcntrl",
"iswctype", "iswalnum", "iswgraph", "iswxdigit", "iswdigit", "iswpunct", "isblank", "isupper",
"isgraph", "isalnum", "ispunct", "islower", "isspace", "isprint", "isxdigit", "iscntrl",
"isdigit", "isalpha", "timespec_get", "feof", "atomic_is_lock_free",
"atomic_compare_exchange", "thrd_equal", "isfinite", "islessequal", "isnan", "isgreater",
"signbit", "isinf", "islessgreater", "isnormal", "isless", "isgreaterequal", "isunordered",
"ferror"
])
or
fn.hasName([
"thrd_sleep", "feenv", "feholdexcept", "feclearexcept", "feexceptflag", "feupdateenv",
"remove", "fflush", "setvbuf", "fgetpos", "fsetpos", "fclose", "rename", "fseek", "raise"
])
or
fn.hasName(["tss_get", "gets"])
or
fn.hasName(["getc", "atoi"])
}
/** Gets the Guard which compares the expression `bound` */
pragma[inline]
GuardCondition checkByValue(Expr bound, Expr val) {
exists(GuardCondition gc |
(
gc.ensuresEq(bound, val, _, _, _) or
gc.ensuresEq(val, bound, _, _, _) or
gc.ensuresLt(bound, val, _, _, _) or
gc.ensuresLt(val, bound, _, _, _) or
gc = globalValueNumber(bound).getAnExpr()
) and
result = gc
)
}
/** Holds if there are no comparisons between the value returned by possible function calls `compArg` and the value `valArg`, or when these comparisons do not exclude equality to the value `valArg`. */
pragma[inline]
predicate compareFunctionWithValue(Expr guardExp, Function compArg, Expr valArg) {
not exists(Expr exp |
exp.getAChild*() = globalValueNumber(compArg.getACallToThisFunction()).getAnExpr() and
checkByValue(exp, valArg).controls(guardExp.getBasicBlock(), _)
)
or
exists(GuardCondition gc |
(
gc.ensuresEq(globalValueNumber(compArg.getACallToThisFunction()).getAnExpr(), valArg, 0,
guardExp.getBasicBlock(), true)
or
gc.ensuresEq(valArg, globalValueNumber(compArg.getACallToThisFunction()).getAnExpr(), 0,
guardExp.getBasicBlock(), true)
or
gc.ensuresLt(globalValueNumber(compArg.getACallToThisFunction()).getAnExpr(), valArg, 0,
guardExp.getBasicBlock(), false)
or
gc.ensuresLt(valArg, globalValueNumber(compArg.getACallToThisFunction()).getAnExpr(), 0,
guardExp.getBasicBlock(), false)
)
or
exists(Expr exp |
exp.getValue().toFloat() > valArg.getValue().toFloat() and
gc.ensuresLt(globalValueNumber(compArg.getACallToThisFunction()).getAnExpr(), exp, 0,
guardExp.getBasicBlock(), true)
or
exp.getValue().toFloat() < valArg.getValue().toFloat() and
gc.ensuresLt(exp, globalValueNumber(compArg.getACallToThisFunction()).getAnExpr(), 0,
guardExp.getBasicBlock(), true)
)
)
or
valArg.getValue().toFloat() = 0 and
exists(NotExpr ne, IfStmt ifne |
ne.getOperand() = globalValueNumber(compArg.getACallToThisFunction()).getAnExpr() and
ifne.getCondition() = ne and
ifne.getThen().getAChild*() = guardExp
)
}
/** Wraping predicate for call `compareFunctionWithValue`. */
pragma[inline]
predicate checkConditions1(Expr div, Function fn, float changeInt) {
exists(Expr val |
val.getEnclosingFunction() = fn and
val.getValue().toFloat() = changeInt and
compareFunctionWithValue(div, fn, val)
)
}
/** Holds if there are no comparisons between the value `compArg` and the value `valArg`, or when these comparisons do not exclude equality to the value `valArg`. */
pragma[inline]
predicate compareExprWithValue(Expr guardExp, Expr compArg, Expr valArg) {
not exists(Expr exp |
exp.getAChild*() = globalValueNumber(compArg).getAnExpr() and
checkByValue(exp, valArg).controls(guardExp.getBasicBlock(), _)
)
or
exists(GuardCondition gc |
(
gc.ensuresEq(globalValueNumber(compArg).getAnExpr(), valArg, 0, guardExp.getBasicBlock(), true)
or
gc.ensuresEq(valArg, globalValueNumber(compArg).getAnExpr(), 0, guardExp.getBasicBlock(), true)
or
gc.ensuresLt(globalValueNumber(compArg).getAnExpr(), valArg, 0, guardExp.getBasicBlock(),
false)
or
gc.ensuresLt(valArg, globalValueNumber(compArg).getAnExpr(), 0, guardExp.getBasicBlock(),
false)
)
or
exists(Expr exp |
exp.getValue().toFloat() > valArg.getValue().toFloat() and
gc.ensuresLt(globalValueNumber(compArg).getAnExpr(), exp, 0, guardExp.getBasicBlock(), true)
or
exp.getValue().toFloat() < valArg.getValue().toFloat() and
gc.ensuresLt(exp, globalValueNumber(compArg).getAnExpr(), 0, guardExp.getBasicBlock(), true)
)
)
or
valArg.getValue().toFloat() = 0 and
exists(NotExpr ne, IfStmt ifne |
ne.getOperand() = globalValueNumber(compArg).getAnExpr() and
ifne.getCondition() = ne and
ifne.getThen().getAChild*() = guardExp
)
}
/** Wraping predicate for call `compareExprWithValue`. */
pragma[inline]
predicate checkConditions2(Expr div, Expr divVal, float changeInt2) {
exists(Expr val |
(
val.getEnclosingFunction() =
div.getEnclosingFunction().getACallToThisFunction().getEnclosingFunction() or
val.getEnclosingFunction() = div.getEnclosingFunction()
) and
val.getValue().toFloat() = changeInt2 and
compareExprWithValue(div, divVal, val)
)
}
/** Gets the value of the difference or summand from the expression `src`. */
float getValueOperand(Expr src, Expr e1, Expr e2) {
src.(SubExpr).hasOperands(e1, e2) and
result = e2.getValue().toFloat()
or
src.(AddExpr).hasOperands(e1, e2) and
result = -e2.getValue().toFloat()
}
/** Function the return of the expression `e1` and the multiplication operands, or the left operand of division if `e1` contains a multiplication or division, respectively. */
Expr getMulDivOperand(Expr e1) {
result = e1 or
result = e1.(MulExpr).getAnOperand() or
result = e1.(DivExpr).getLeftOperand()
}
/** The class that defines possible variants of the division expression or the search for the remainder. */
class MyDiv extends Expr {
MyDiv() {
this instanceof DivExpr or
this instanceof RemExpr or
this instanceof AssignDivExpr or
this instanceof AssignRemExpr
}
Expr getRV() {
result = this.(AssignArithmeticOperation).getRValue() or
result = this.(BinaryArithmeticOperation).getRightOperand()
}
}
from Expr exp, string msg, Function fn, GVN findVal, float changeInt, MyDiv div
where
findVal = globalValueNumber(fn.getACallToThisFunction()) and
(
// Look for divide-by-zero operations possible due to the return value of the function `fn`.
checkConditions1(div, fn, changeInt) and
(
// Function return value can be zero.
mayBeReturnZero(fn) and
getMulDivOperand(globalValueNumber(div.getRV()).getAnExpr()) = findVal.getAnExpr() and
changeInt = 0
or
// Denominator can be sum or difference.
changeInt = getValueOperand(div.getRV(), findVal.getAnExpr(), _) and
mayBeReturnValue(fn, changeInt)
) and
exp = div and
msg =
"Can lead to division by 0, since the function " + fn.getName() + " can return a value " +
changeInt.toString() + "."
or
// Search for situations where division by zero is possible inside the `divFn` function if the passed argument can be equal to a certain value.
exists(int posArg, Expr divVal, FunctionCall divFc, float changeInt2 |
// Division is associated with the function argument.
exists(Function divFn |
divFn.getParameter(posArg).getAnAccess() = divVal and
divVal.getEnclosingStmt() = div.getEnclosingStmt() and
divFc = divFn.getACallToThisFunction()
) and
(
divVal = div.getRV() and
divFc.getArgument(posArg) != findVal.getAnExpr() and
(
// Function return value can be zero.
mayBeReturnZero(fn) and
getMulDivOperand(globalValueNumber(divFc.getArgument(posArg)).getAnExpr()) =
findVal.getAnExpr() and
changeInt = 0 and
changeInt2 = 0
or
// Denominator can be sum or difference.
changeInt = getValueOperand(divFc.getArgument(posArg), findVal.getAnExpr(), _) and
mayBeReturnValue(fn, changeInt) and
changeInt2 = 0
)
or
// Look for a situation where the difference or subtraction is considered as an argument, and it can be used in the same way.
changeInt = getValueOperand(div.getRV(), divVal, _) and
changeInt2 = changeInt and
mayBeReturnValue(fn, changeInt) and
divFc.getArgument(posArg) = findVal.getAnExpr()
) and
checkConditions2(div, divVal, changeInt2) and
checkConditions1(divFc, fn, changeInt) and
exp = divFc and
msg =
"Can lead to division by 0, since the function " + fn.getName() + " can return a value " +
changeInt.toString() + "."
)
)
select exp, msg

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-queries
version: 0.5.4
version: 0.5.3-dev
groups:
- cpp
- queries

View File

@@ -1,27 +0,0 @@
| test.cpp:47:24:47:31 | ... / ... | Can lead to division by 0, since the function getSize can return a value 0. |
| test.cpp:48:15:48:34 | ... / ... | Can lead to division by 0, since the function getSize2 can return a value 0. |
| test.cpp:53:10:53:17 | ... / ... | Can lead to division by 0, since the function getSize can return a value 0. |
| test.cpp:65:15:65:22 | ... / ... | Can lead to division by 0, since the function getSize can return a value 0. |
| test.cpp:68:15:68:22 | ... / ... | Can lead to division by 0, since the function getSize can return a value 0. |
| test.cpp:71:9:71:16 | ... / ... | Can lead to division by 0, since the function getSize can return a value 0. |
| test.cpp:74:9:74:16 | ... / ... | Can lead to division by 0, since the function getSize can return a value 0. |
| test.cpp:77:21:77:28 | ... / ... | Can lead to division by 0, since the function getSize can return a value 0. |
| test.cpp:79:25:79:32 | ... / ... | Can lead to division by 0, since the function getSize can return a value 0. |
| test.cpp:81:24:81:31 | ... / ... | Can lead to division by 0, since the function getSize can return a value 0. |
| test.cpp:128:10:128:16 | ... / ... | Can lead to division by 0, since the function getSize can return a value 0. |
| test.cpp:135:10:135:16 | ... / ... | Can lead to division by 0, since the function getSize can return a value 0. |
| test.cpp:141:10:141:23 | ... / ... | Can lead to division by 0, since the function getSize can return a value 0. |
| test.cpp:153:12:153:19 | ... / ... | Can lead to division by 0, since the function getSize can return a value 0. |
| test.cpp:172:3:172:12 | ... /= ... | Can lead to division by 0, since the function getSize can return a value 0. |
| test.cpp:173:3:173:12 | ... %= ... | Can lead to division by 0, since the function getSize can return a value 0. |
| test.cpp:187:10:187:17 | ... / ... | Can lead to division by 0, since the function getSizeFloat can return a value 0. |
| test.cpp:199:12:199:25 | ... / ... | Can lead to division by 0, since the function getSize can return a value -1. |
| test.cpp:202:12:202:25 | ... / ... | Can lead to division by 0, since the function getSize can return a value 1. |
| test.cpp:205:10:205:23 | ... / ... | Can lead to division by 0, since the function getSize can return a value 1. |
| test.cpp:210:10:210:23 | ... / ... | Can lead to division by 0, since the function getSize can return a value 3. |
| test.cpp:258:3:258:10 | call to badMyDiv | Can lead to division by 0, since the function getSize can return a value 0. |
| test.cpp:259:3:259:10 | call to badMyDiv | Can lead to division by 0, since the function getSize can return a value 2. |
| test.cpp:260:3:260:13 | call to badMySubDiv | Can lead to division by 0, since the function getSize can return a value 3. |
| test.cpp:263:5:263:15 | call to badMySubDiv | Can lead to division by 0, since the function getSize can return a value 3. |
| test.cpp:273:5:273:12 | call to badMyDiv | Can lead to division by 0, since the function getSize can return a value 3. |
| test.cpp:275:5:275:12 | call to badMyDiv | Can lead to division by 0, since the function getSize can return a value -1. |

View File

@@ -1 +0,0 @@
experimental/Security/CWE/CWE-369/DivideByZeroUsingReturnValue.ql

View File

@@ -1,278 +0,0 @@
typedef struct {}
FILE;
int getc(FILE * stream);
int getSize(int type) {
int st;
switch (type) {
case 1:
st = 1;
break;
case 2:
st = 2;
break;
case 3:
st = 3;
break;
case 4:
st = -1;
break;
default:
st = 0;
break;
}
return st;
}
int getSize2(int type) {
int st = 0;
switch (type) {
case 1:
st = 1;
break;
case 2:
st = 2;
break;
case 3:
st = 3;
break;
case 4:
st = -1;
break;
}
return st;
}
int badTestf1(int type, int met) {
int is = getSize(type);
if (met == 1) return 123 / is; // BAD
else return 123 / getSize2(type); // BAD
}
int badTestf2(int type) {
int is;
is = getSize(type);
return 123 / is; // BAD
}
int badTestf3(int type, int met) {
int is;
is = getSize(type);
switch (met) {
case 1:
if (is >= 0) return 123 / is; // BAD [NOT DETECTED]
case 2:
if (0 == is) return 123 / is; // BAD [NOT DETECTED]
case 3:
if (!is & 123 / is) // BAD
return 123;
case 4:
if (!is | 123 / is) // BAD
return 123;
case 5:
if (123 / is || !is) // BAD
return 123;
case 6:
if (123 / is && !is) // BAD
return 123;
case 7:
if (!is) return 123 / is; // BAD
case 8:
if (is > -1) return 123 / is; // BAD
case 9:
if (is < 2) return 123 / is; // BAD
}
if (is != 0) return -1;
if (is == 0) type += 1;
return 123 / is; // BAD [NOT DETECTED]
}
int goodTestf3(int type, int met) {
int is = getSize(type);
if (is == 0) return -1;
switch (met) {
case 1:
if (is < 0) return 123 / is; // GOOD
case 2:
if (!is && 123 / is) // GOOD
return 123;
case 3:
if (!is || 123 / is) // GOOD
return 123;
case 8:
if (is < -1) return 123 / is; // GOOD
case 9:
if (is > 2) return 123 / is; // GOOD
}
return 123 / is;
}
int goodTestf3a(int type, int met) {
int is = getSize(type);
switch (met) {
case 1:
if (is < 0)
return 123 / is; // GOOD
case 2:
if (!is && 123 / is) // GOOD
return 123;
case 3:
if (!is || 123 / is) // GOOD
return 123;
}
return 1;
}
int badTestf4(int type) {
int is = getSize(type);
int d;
d = type * is;
return 123 / d; // BAD
}
int badTestf5(int type) {
int is = getSize(type);
int d;
d = is / type;
return 123 / d; // BAD
}
int badTestf6(int type) {
int is = getSize(type);
int d;
d = is / type;
return type * 123 / d; // BAD
}
int badTestf7(int type, int met) {
int is = getSize(type);
if (is == 0) goto quit;
switch (met) {
case 1:
if (is < 0)
return 123 / is; // GOOD
}
quit:
return 123 / is; // BAD
}
int goodTestf7(int type, int met) {
int is = getSize(type);
if (is == 0) goto quit2;
if (is == 0.) return -1;
switch (met) {
case 1:
if (is < 0.)
return 123 / is; // GOOD
}
return 123 / is; // GOOD
quit2:
return -1;
}
int badTestf8(int type) {
int is = getSize(type);
type /= is; // BAD
type %= is; // BAD
return type;
}
float getSizeFloat(float type) {
float st;
if (type)
st = 1.0;
else
st = 0.0;
return st;
}
float badTestf9(float type) {
float is = getSizeFloat(type);
return 123 / is; // BAD
}
float goodTestf9(float type) {
float is = getSizeFloat(type);
if (is == 0.0) return -1;
return 123 / is; // GOOD
}
int badTestf10(int type) {
int out = type;
int is = getSize(type);
if (is > -2) {
out /= 123 / (is + 1); // BAD
}
if (is > 0) {
return 123 / (is - 1); // BAD
}
if (is <= 0) return 0;
return 123 / (is - 1); // BAD
return 0;
}
int badTestf11(int type) {
int is = getSize(type);
return 123 / (is - 3); // BAD
}
int goodTestf11(int type) {
int is = getSize(type);
if (is > 1) {
return 123 / (is - 1); // GOOD
} else {
return 0;
}
}
int badTestf12(FILE * f) {
int a;
int ret = -1;
a = getc(f);
if (a == 0) ret = 123 / a; // BAD [NOT DETECTED]
return ret;
}
int goodTestf12(FILE * f) {
int a;
int ret = -1;
a = getc(f);
if (a != 0) ret = 123 / a; // GOOD
return ret;
}
int badMyDiv(int type, int is) {
type /= is;
type %= is;
return type;
}
int goodMyDiv(int type, int is) {
if (is == 0) return -1;
type /= is;
type %= is;
return type;
}
int badMySubDiv(int type, int is) {
type /= (is - 3);
type %= (is + 1);
return type;
}
void badTestf13(int type) {
int is = getSize(type);
badMyDiv(type, is); // BAD
badMyDiv(type, is - 2); // BAD
badMySubDiv(type, is); // BAD
goodMyDiv(type, is); // GOOD
if (is < 5)
badMySubDiv(type, is); // BAD
if (is < 0)
badMySubDiv(type, is); // BAD [NOT DETECTED]
if (is > 5)
badMySubDiv(type, is); // GOOD
if (is == 0)
badMyDiv(type, is); // BAD
if (is > 0)
badMyDiv(type, is); // GOOD
if (is < 5)
badMyDiv(type, is - 3); // BAD
if (is < 0)
badMyDiv(type, is + 1); // BAD
if (is > 5)
badMyDiv(type, is - 3); // GOOD
}

View File

@@ -145,14 +145,6 @@ 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)));

View File

@@ -7,7 +7,6 @@ using System.Xml;
using System.Net.Http;
using System.Diagnostics.CodeAnalysis;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
namespace Semmle.Autobuild.Shared
{
@@ -99,18 +98,6 @@ 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>
@@ -216,12 +203,6 @@ 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);

View File

@@ -1,36 +1,18 @@
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())
@@ -75,7 +57,7 @@ namespace Semmle.Autobuild.Shared
Script;
var nugetRestore = GetNugetRestoreScript();
var msbuildRestoreCommand = new CommandBuilder(builder.Actions).
MsBuildCommand(builder).
RunCommand(msBuild).
Argument("/t:restore").
QuoteArgument(projectOrSolution.FullPath);
@@ -113,7 +95,7 @@ namespace Semmle.Autobuild.Shared
command.RunCommand("set Platform=&& type NUL", quoteExe: false);
}
command.MsBuildCommand(builder);
command.RunCommand(msBuild);
command.QuoteArgument(projectOrSolution.FullPath);
var target = builder.Options.MsBuildTarget ?? "rebuild";

View File

@@ -1,3 +0,0 @@
description: Remove a relation for scoped annotations.
compatibility: backwards
scoped_annotation.rel: delete

View File

@@ -106,6 +106,36 @@ namespace Semmle.BuildAnalyser
return result;
}
// Attempt to load the reference from the GAC.
try
{
var loadedAssembly = System.Reflection.Assembly.ReflectionOnlyLoad(id);
if (loadedAssembly is not null)
{
// The assembly was somewhere we haven't indexed before.
// Add this assembly to our index so that subsequent lookups are faster.
result = AssemblyInfo.MakeFromAssembly(loadedAssembly);
assemblyInfoById[id] = result;
assemblyInfoByFileName[loadedAssembly.Location] = result;
return result;
}
}
catch (FileNotFoundException)
{
// A suitable assembly could not be found
}
catch (FileLoadException)
{
// The assembly cannot be loaded for some reason
// e.g. The name is malformed.
}
catch (PlatformNotSupportedException)
{
// .NET Core does not have a GAC.
}
// Fallback position - locate the assembly by its lower-case name only.
var asmName = assemblyName.ToLowerInvariant();

View File

@@ -59,19 +59,6 @@ namespace Semmle.Extraction.CSharp.Entities
}
}
protected void PopulateScopedKind(TextWriter trapFile, ScopedKind kind)
{
switch (kind)
{
case ScopedKind.ScopedRef:
trapFile.scoped_annotation(this, Kinds.ScopedAnnotation.ScopedRef);
break;
case ScopedKind.ScopedValue:
trapFile.scoped_annotation(this, Kinds.ScopedAnnotation.ScopedValue);
break;
}
}
protected void ExtractCompilerGenerated(TextWriter trapFile)
{
if (Symbol.IsImplicitlyDeclared)

View File

@@ -10,8 +10,6 @@ namespace Semmle.Extraction.CSharp.Entities
private Conversion(Context cx, IMethodSymbol init)
: base(cx, init) { }
protected override MethodKind ExplicitlyImplementsKind => MethodKind.Conversion;
public static new Conversion Create(Context cx, IMethodSymbol symbol) =>
ConversionFactory.Instance.CreateEntityFromSymbol(cx, symbol);

View File

@@ -33,8 +33,7 @@ namespace Semmle.Extraction.CSharp.Entities
PopulateRefKind(trapFile, Symbol.RefKind);
var unboundFieldKey = Field.Create(Context, Symbol.OriginalDefinition);
var kind = Symbol.IsConst ? VariableKind.Const : VariableKind.None;
trapFile.fields(this, kind, Symbol.Name, ContainingType, Type.TypeRef, unboundFieldKey);
trapFile.fields(this, (Symbol.IsConst ? 2 : 1), Symbol.Name, ContainingType, Type.TypeRef, unboundFieldKey);
PopulateModifiers(trapFile);

View File

@@ -23,23 +23,17 @@ namespace Semmle.Extraction.CSharp.Entities
public void PopulateManual(Expression parent, bool isVar)
{
var trapFile = Context.TrapWriter.Writer;
var @var = isVar ? 1 : 0;
var (kind, type) = Symbol is ILocalSymbol l
? (l.IsRef ? 3 : l.IsConst ? 2 : 1, l.GetAnnotatedType())
: (1, parent.Type);
trapFile.localvars(this, kind, Symbol.Name, isVar ? 1 : 0, Type.Create(Context, type).TypeRef, parent);
if (Symbol is ILocalSymbol local)
{
var kind = local.IsRef ? Kinds.VariableKind.Ref : local.IsConst ? Kinds.VariableKind.Const : Kinds.VariableKind.None;
var type = local.GetAnnotatedType();
trapFile.localvars(this, kind, Symbol.Name, @var, Type.Create(Context, type).TypeRef, parent);
PopulateNullability(trapFile, local.GetAnnotatedType());
PopulateScopedKind(trapFile, local.ScopedKind);
if (local.IsRef)
trapFile.type_annotation(this, Kinds.TypeAnnotation.Ref);
}
else
{
trapFile.localvars(this, Kinds.VariableKind.None, Symbol.Name, @var, Type.Create(Context, parent.Type).TypeRef, parent);
}
trapFile.localvar_location(this, Location);

View File

@@ -83,12 +83,10 @@ namespace Semmle.Extraction.CSharp.Entities
}
}
protected virtual MethodKind ExplicitlyImplementsKind => MethodKind.Ordinary;
public void Overrides(TextWriter trapFile)
{
foreach (var explicitInterface in Symbol.ExplicitInterfaceImplementations
.Where(sym => sym.MethodKind == ExplicitlyImplementsKind)
.Where(sym => sym.MethodKind == MethodKind.Ordinary)
.Select(impl => Type.Create(Context, impl.ContainingType)))
{
trapFile.explicitly_implements(this, explicitInterface.TypeRef);

View File

@@ -65,15 +65,6 @@ 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)
@@ -85,9 +76,6 @@ namespace Semmle.Extraction.CSharp.Entities
if (nt.IsRecord)
HasModifier(cx, trapFile, key, Modifiers.Record);
if (nt.IsFileLocal)
HasModifier(cx, trapFile, key, Modifiers.File);
if (nt.TypeKind == TypeKind.Struct)
{
if (nt.IsReadOnly)
@@ -100,11 +88,7 @@ namespace Semmle.Extraction.CSharp.Entities
public static void ExtractModifiers(Context cx, TextWriter trapFile, IEntity key, ISymbol symbol)
{
// A file scoped type has declared accessibility `internal` which we shouldn't extract.
// The file modifier is extracted as a source level modifier.
if (symbol.Kind != SymbolKind.NamedType || !((INamedTypeSymbol)symbol).IsFileLocal)
HasAccessibility(cx, trapFile, key, symbol.DeclaredAccessibility);
HasAccessibility(cx, trapFile, key, symbol.DeclaredAccessibility);
if (symbol.Kind == SymbolKind.ErrorType)
trapFile.has_modifiers(key, Modifier.Create(cx, Accessibility.Public));
@@ -122,11 +106,8 @@ namespace Semmle.Extraction.CSharp.Entities
if (symbol.IsVirtual)
HasModifier(cx, trapFile, key, Modifiers.Virtual);
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.Kind == SymbolKind.Field && ((IFieldSymbol)symbol).IsReadOnly)
HasModifier(cx, trapFile, key, Modifiers.Readonly);
if (symbol.IsOverride)
HasModifier(cx, trapFile, key, Modifiers.Override);

View File

@@ -4,7 +4,6 @@ internal static class Modifiers
public const string Async = "async";
public const string Const = "const";
public const string Extern = "extern";
public const string File = "file";
public const string Internal = "internal";
public const string New = "new";
public const string Override = "override";
@@ -14,7 +13,6 @@ 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";

View File

@@ -100,7 +100,6 @@ namespace Semmle.Extraction.CSharp.Entities
PopulateAttributes();
PopulateNullability(trapFile, Symbol.GetAnnotatedType());
PopulateRefKind(trapFile, Symbol.RefKind);
PopulateScopedKind(trapFile, Symbol.ScopedKind);
if (Symbol.Name != Original.Symbol.Name)
Context.ModelError(Symbol, "Inconsistent parameter declaration");

View File

@@ -11,8 +11,6 @@ namespace Semmle.Extraction.CSharp.Entities
protected UserOperator(Context cx, IMethodSymbol init)
: base(cx, init) { }
protected override MethodKind ExplicitlyImplementsKind => MethodKind.UserDefinedOperator;
public override void Populate(TextWriter trapFile)
{
PopulateMethod(trapFile);
@@ -39,7 +37,6 @@ namespace Semmle.Extraction.CSharp.Entities
}
ContainingType.PopulateGenerics();
Overrides(trapFile);
}
public override bool NeedsPopulation => Context.Defines(Symbol) || IsImplicitOperator(out _);

View File

@@ -1,8 +0,0 @@
namespace Semmle.Extraction.Kinds;
public enum ScopedAnnotation
{
None = 0,
ScopedRef = 1,
ScopedValue = 2
}

View File

@@ -1,8 +0,0 @@
namespace Semmle.Extraction.Kinds;
public enum VariableKind
{
None = 1,
Const = 2,
Ref = 3
}

View File

@@ -77,8 +77,12 @@ namespace Semmle.Extraction.CSharp
/// <summary>
/// Gets the source-level modifiers belonging to this symbol, if any.
/// </summary>
public static IEnumerable<string> GetSourceLevelModifiers(this ISymbol symbol) =>
symbol.GetModifiers<Microsoft.CodeAnalysis.CSharp.Syntax.MemberDeclarationSyntax>(md => md.Modifiers).Select(m => m.Text);
public static IEnumerable<string> GetSourceLevelModifiers(this ISymbol symbol)
{
var methodModifiers = symbol.GetModifiers<Microsoft.CodeAnalysis.CSharp.Syntax.BaseMethodDeclarationSyntax>(md => md.Modifiers);
var typeModifiers = symbol.GetModifiers<Microsoft.CodeAnalysis.CSharp.Syntax.TypeDeclarationSyntax>(cd => cd.Modifiers);
return methodModifiers.Concat(typeModifiers).Select(m => m.Text);
}
/// <summary>
/// Holds if the ID generated for `dependant` will contain a reference to
@@ -282,60 +286,54 @@ namespace Semmle.Extraction.CSharp
public static IEnumerable<IFieldSymbol?> GetTupleElementsMaybeNull(this INamedTypeSymbol type) =>
type.TupleElements;
private static void BuildQualifierAndName(INamedTypeSymbol named, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined)
{
if (named.ContainingType is not null)
{
named.ContainingType.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType: false);
trapFile.Write('.');
}
else if (named.ContainingNamespace is not null)
{
if (cx.ShouldAddAssemblyTrapPrefix && named.ContainingAssembly is not null)
BuildAssembly(named.ContainingAssembly, trapFile);
named.ContainingNamespace.BuildNamespace(cx, trapFile);
}
var name = named.IsFileLocal ? named.MetadataName : named.Name;
trapFile.Write(name);
}
private static void BuildTupleId(INamedTypeSymbol named, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined)
{
trapFile.Write('(');
trapFile.BuildList(",", named.GetTupleElementsMaybeNull(),
(i, f) =>
{
if (f is null)
{
trapFile.Write($"null({i})");
}
else
{
trapFile.Write((f.CorrespondingTupleField ?? f).Name);
trapFile.Write(":");
f.Type.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType: false);
}
}
);
trapFile.Write(")");
}
private static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined, bool constructUnderlyingTupleType)
{
if (!constructUnderlyingTupleType && named.IsTupleType)
{
BuildTupleId(named, cx, trapFile, symbolBeingDefined);
trapFile.Write('(');
trapFile.BuildList(",", named.GetTupleElementsMaybeNull(),
(i, f) =>
{
if (f is null)
{
trapFile.Write($"null({i})");
}
else
{
trapFile.Write((f.CorrespondingTupleField ?? f).Name);
trapFile.Write(":");
f.Type.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType: false);
}
}
);
trapFile.Write(")");
return;
}
void AddContaining()
{
if (named.ContainingType is not null)
{
named.ContainingType.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType: false);
trapFile.Write('.');
}
else if (named.ContainingNamespace is not null)
{
if (cx.ShouldAddAssemblyTrapPrefix && named.ContainingAssembly is not null)
BuildAssembly(named.ContainingAssembly, trapFile);
named.ContainingNamespace.BuildNamespace(cx, trapFile);
}
}
if (named.TypeParameters.IsEmpty)
{
BuildQualifierAndName(named, cx, trapFile, symbolBeingDefined);
AddContaining();
trapFile.Write(named.Name);
}
else if (named.IsReallyUnbound())
{
BuildQualifierAndName(named, cx, trapFile, symbolBeingDefined);
AddContaining();
trapFile.Write(named.Name);
trapFile.Write("`");
trapFile.Write(named.TypeParameters.Length);
}

View File

@@ -191,8 +191,8 @@ namespace Semmle.Extraction.CSharp
internal static void field_location(this TextWriter trapFile, Field field, Location location) =>
trapFile.WriteTuple("field_location", field, location);
internal static void fields(this TextWriter trapFile, Field field, VariableKind kind, string name, Type declaringType, Type fieldType, Field unboundKey) =>
trapFile.WriteTuple("fields", field, (int)kind, name, declaringType, fieldType, unboundKey);
internal static void fields(this TextWriter trapFile, Field field, int @const, string name, Type declaringType, Type fieldType, Field unboundKey) =>
trapFile.WriteTuple("fields", field, @const, name, declaringType, fieldType, unboundKey);
internal static void general_type_parameter_constraints(this TextWriter trapFile, TypeParameterConstraints constraints, int hasKind) =>
trapFile.WriteTuple("general_type_parameter_constraints", constraints, hasKind);
@@ -227,8 +227,8 @@ namespace Semmle.Extraction.CSharp
internal static void localvar_location(this TextWriter trapFile, LocalVariable var, Location location) =>
trapFile.WriteTuple("localvar_location", var, location);
internal static void localvars(this TextWriter trapFile, LocalVariable key, VariableKind kind, string name, int @var, Type type, Expression expr) =>
trapFile.WriteTuple("localvars", key, (int)kind, name, @var, type, expr);
internal static void localvars(this TextWriter trapFile, LocalVariable key, int @const, string name, int @var, Type type, Expression expr) =>
trapFile.WriteTuple("localvars", key, @const, name, @var, type, expr);
public static void metadata_handle(this TextWriter trapFile, IEntity entity, Location assembly, int handleValue) =>
trapFile.WriteTuple("metadata_handle", entity, assembly, handleValue);
@@ -462,8 +462,5 @@ namespace Semmle.Extraction.CSharp
internal static void file_extraction_mode(this System.IO.TextWriter trapFile, Entities.File file, ExtractorMode mode) =>
trapFile.WriteTuple("file_extraction_mode", file, mode);
internal static void scoped_annotation(this TextWriter trapFile, IEntity element, ScopedAnnotation @scoped) =>
trapFile.WriteTuple("scoped_annotation", element, (int)@scoped);
}
}

View File

@@ -1,11 +1,3 @@
## 1.4.4
No user-facing changes.
## 1.4.3
No user-facing changes.
## 1.4.2
No user-facing changes.

View File

@@ -1,3 +0,0 @@
## 1.4.3
No user-facing changes.

View File

@@ -1,3 +0,0 @@
## 1.4.4
No user-facing changes.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.4.4
lastReleaseVersion: 1.4.2

View File

@@ -1,5 +1,5 @@
name: codeql/csharp-solorigate-all
version: 1.4.4
version: 1.4.3-dev
groups:
- csharp
- solorigate

View File

@@ -1,11 +1,3 @@
## 1.4.4
No user-facing changes.
## 1.4.3
No user-facing changes.
## 1.4.2
No user-facing changes.

View File

@@ -1,3 +0,0 @@
## 1.4.3
No user-facing changes.

View File

@@ -1,3 +0,0 @@
## 1.4.4
No user-facing changes.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.4.4
lastReleaseVersion: 1.4.2

View File

@@ -1,5 +1,5 @@
name: codeql/csharp-solorigate-queries
version: 1.4.4
version: 1.4.3-dev
groups:
- csharp
- solorigate

View File

@@ -1,13 +0,0 @@
using System;
namespace Test
{
public class Program
{
public static int Main(string[] args)
{
Console.WriteLine("Hello world!");
return 0;
}
}
}

View File

@@ -1,7 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net4.0</TargetFramework>
</PropertyGroup>
</Project>

View File

@@ -1,4 +0,0 @@
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' })

View File

@@ -1,20 +1,3 @@
## 0.5.4
### Minor Analysis Improvements
* The query `cs/static-field-written-by-instance` is updated to handle properties.
* C# 11: Support for explicit interface member implementation of operators.
* The extraction of member modifiers has been generalized, which could lead to the extraction of more modifiers.
* C# 11: Added extractor and library support for `file` scoped types.
* C# 11: Added extractor support for `required` fields and properties.
* C# 11: Added library support for `checked` operators.
## 0.5.3
### Minor Analysis Improvements
* C# 11: Added extractor support for the `scoped` modifier annotation on parameters and local variables.
## 0.5.2
### Major Analysis Improvements

View File

@@ -1,5 +0,0 @@
## 0.5.3
### Minor Analysis Improvements
* C# 11: Added extractor support for the `scoped` modifier annotation on parameters and local variables.

View File

@@ -1,10 +0,0 @@
## 0.5.4
### Minor Analysis Improvements
* The query `cs/static-field-written-by-instance` is updated to handle properties.
* C# 11: Support for explicit interface member implementation of operators.
* The extraction of member modifiers has been generalized, which could lead to the extraction of more modifiers.
* C# 11: Added extractor and library support for `file` scoped types.
* C# 11: Added extractor support for `required` fields and properties.
* C# 11: Added library support for `checked` operators.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.5.4
lastReleaseVersion: 0.5.2

View File

@@ -1,5 +1,5 @@
name: codeql/csharp-all
version: 0.5.4
version: 0.5.3-dev
groups: csharp
dbscheme: semmlecode.csharp.dbscheme
extractor: csharp
@@ -8,7 +8,6 @@ upgrades: upgrades
dependencies:
codeql/ssa: ${workspace}
codeql/tutorial: ${workspace}
codeql/util: ${workspace}
dataExtensions:
- ext/*.model.yml
- ext/generated/*.model.yml

View File

@@ -434,13 +434,9 @@ class Destructor extends DotNet::Destructor, Callable, Member, Attributable, @de
* Either a unary operator (`UnaryOperator`), a binary operator
* (`BinaryOperator`), or a conversion operator (`ConversionOperator`).
*/
class Operator extends Callable, Member, Attributable, Overridable, @operator {
/**
* DEPRECATED: use `getFunctionName()` instead.
*
* Gets the assembly name of this operator.
*/
deprecated string getAssemblyName() { result = this.getFunctionName() }
class Operator extends Callable, Member, Attributable, @operator {
/** Gets the assembly name of this operator. */
string getAssemblyName() { operators(this, result, _, _, _, _) }
override string getName() { operators(this, _, result, _, _, _) }
@@ -449,7 +445,7 @@ class Operator extends Callable, Member, Attributable, Overridable, @operator {
/**
* Gets the metadata name of the operator, such as `op_implicit` or `op_RightShift`.
*/
string getFunctionName() { operators(this, result, _, _, _, _) }
string getFunctionName() { none() }
override ValueOrRefType getDeclaringType() { operators(this, _, _, result, _, _) }
@@ -485,11 +481,10 @@ class RecordCloneMethod extends Method, DotNet::RecordCloneCallable {
* A user-defined unary operator - an operator taking one operand.
*
* Either a plus operator (`PlusOperator`), minus operator (`MinusOperator`),
* 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`).
* not operator (`NotOperator`), complement operator (`ComplementOperator`),
* true operator (`TrueOperator`), false operator (`FalseOperator`),
* increment operator (`IncrementOperator`), or decrement operator
* (`DecrementOperator`).
*/
class UnaryOperator extends Operator {
UnaryOperator() {
@@ -510,6 +505,8 @@ class UnaryOperator extends Operator {
class PlusOperator extends UnaryOperator {
PlusOperator() { this.getName() = "+" }
override string getFunctionName() { result = "op_UnaryPlus" }
override string getAPrimaryQlClass() { result = "PlusOperator" }
}
@@ -525,24 +522,11 @@ 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
*
@@ -555,6 +539,8 @@ class CheckedMinusOperator extends UnaryOperator {
class NotOperator extends UnaryOperator {
NotOperator() { this.getName() = "!" }
override string getFunctionName() { result = "op_LogicalNot" }
override string getAPrimaryQlClass() { result = "NotOperator" }
}
@@ -570,6 +556,8 @@ class NotOperator extends UnaryOperator {
class ComplementOperator extends UnaryOperator {
ComplementOperator() { this.getName() = "~" }
override string getFunctionName() { result = "op_OnesComplement" }
override string getAPrimaryQlClass() { result = "ComplementOperator" }
}
@@ -585,24 +573,11 @@ 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
*
@@ -615,24 +590,11 @@ class CheckedIncrementOperator 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
*
@@ -645,6 +607,8 @@ class CheckedDecrementOperator extends UnaryOperator {
class FalseOperator extends UnaryOperator {
FalseOperator() { this.getName() = "false" }
override string getFunctionName() { result = "op_False" }
override string getAPrimaryQlClass() { result = "FalseOperator" }
}
@@ -660,18 +624,17 @@ 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 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
* Either an addition operator (`AddOperator`), a subtraction operator
* (`SubOperator`), a multiplication operator (`MulOperator`), a division
* operator (`DivOperator`), 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
@@ -696,24 +659,11 @@ 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
*
@@ -726,24 +676,11 @@ class CheckedAddOperator 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
*
@@ -756,24 +693,11 @@ class CheckedSubOperator 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
*
@@ -786,24 +710,11 @@ class CheckedMulOperator 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
*
@@ -816,6 +727,8 @@ class CheckedDivOperator extends BinaryOperator {
class RemOperator extends BinaryOperator {
RemOperator() { this.getName() = "%" }
override string getFunctionName() { result = "op_Modulus" }
override string getAPrimaryQlClass() { result = "RemOperator" }
}
@@ -831,6 +744,8 @@ class RemOperator extends BinaryOperator {
class AndOperator extends BinaryOperator {
AndOperator() { this.getName() = "&" }
override string getFunctionName() { result = "op_BitwiseAnd" }
override string getAPrimaryQlClass() { result = "AndOperator" }
}
@@ -846,6 +761,8 @@ class AndOperator extends BinaryOperator {
class OrOperator extends BinaryOperator {
OrOperator() { this.getName() = "|" }
override string getFunctionName() { result = "op_BitwiseOr" }
override string getAPrimaryQlClass() { result = "OrOperator" }
}
@@ -861,6 +778,8 @@ class OrOperator extends BinaryOperator {
class XorOperator extends BinaryOperator {
XorOperator() { this.getName() = "^" }
override string getFunctionName() { result = "op_ExclusiveOr" }
override string getAPrimaryQlClass() { result = "XorOperator" }
}
@@ -876,6 +795,8 @@ class XorOperator extends BinaryOperator {
class LeftShiftOperator extends BinaryOperator {
LeftShiftOperator() { this.getName() = "<<" }
override string getFunctionName() { result = "op_LeftShift" }
override string getAPrimaryQlClass() { result = "LeftShiftOperator" }
}
@@ -894,6 +815,8 @@ deprecated class LShiftOperator = LeftShiftOperator;
class RightShiftOperator extends BinaryOperator {
RightShiftOperator() { this.getName() = ">>" }
override string getFunctionName() { result = "op_RightShift" }
override string getAPrimaryQlClass() { result = "RightShiftOperator" }
}
@@ -912,6 +835,8 @@ deprecated class RShiftOperator = RightShiftOperator;
class UnsignedRightShiftOperator extends BinaryOperator {
UnsignedRightShiftOperator() { this.getName() = ">>>" }
override string getFunctionName() { result = "op_UnsignedRightShift" }
override string getAPrimaryQlClass() { result = "UnsignedRightShiftOperator" }
}
@@ -927,6 +852,8 @@ class UnsignedRightShiftOperator extends BinaryOperator {
class EQOperator extends BinaryOperator {
EQOperator() { this.getName() = "==" }
override string getFunctionName() { result = "op_Equality" }
override string getAPrimaryQlClass() { result = "EQOperator" }
}
@@ -942,6 +869,8 @@ class EQOperator extends BinaryOperator {
class NEOperator extends BinaryOperator {
NEOperator() { this.getName() = "!=" }
override string getFunctionName() { result = "op_Inequality" }
override string getAPrimaryQlClass() { result = "NEOperator" }
}
@@ -957,6 +886,8 @@ class NEOperator extends BinaryOperator {
class LTOperator extends BinaryOperator {
LTOperator() { this.getName() = "<" }
override string getFunctionName() { result = "op_LessThan" }
override string getAPrimaryQlClass() { result = "LTOperator" }
}
@@ -972,6 +903,8 @@ class LTOperator extends BinaryOperator {
class GTOperator extends BinaryOperator {
GTOperator() { this.getName() = ">" }
override string getFunctionName() { result = "op_GreaterThan" }
override string getAPrimaryQlClass() { result = "GTOperator" }
}
@@ -987,6 +920,8 @@ class GTOperator extends BinaryOperator {
class LEOperator extends BinaryOperator {
LEOperator() { this.getName() = "<=" }
override string getFunctionName() { result = "op_LessThanOrEqual" }
override string getAPrimaryQlClass() { result = "LEOperator" }
}
@@ -1002,6 +937,8 @@ class LEOperator extends BinaryOperator {
class GEOperator extends BinaryOperator {
GEOperator() { this.getName() = ">=" }
override string getFunctionName() { result = "op_GreaterThanOrEqual" }
override string getAPrimaryQlClass() { result = "GEOperator" }
}
@@ -1017,8 +954,7 @@ class GEOperator extends BinaryOperator {
class ConversionOperator extends Operator {
ConversionOperator() {
this.getName() = "implicit conversion" or
this.getName() = "explicit conversion" or
this.getName() = "checked explicit conversion"
this.getName() = "explicit conversion"
}
/** Gets the source type of the conversion. */
@@ -1040,6 +976,8 @@ class ConversionOperator extends Operator {
class ImplicitConversionOperator extends ConversionOperator {
ImplicitConversionOperator() { this.getName() = "implicit conversion" }
override string getFunctionName() { result = "op_Implicit" }
override string getAPrimaryQlClass() { result = "ImplicitConversionOperator" }
}
@@ -1055,24 +993,11 @@ 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

View File

@@ -3,34 +3,184 @@
*/
private import Comments
private import codeql.util.FileSystem
private module Input implements InputSig {
abstract class ContainerBase extends @container {
abstract string getAbsolutePath();
/** A file or folder. */
class Container extends @container {
/**
* Gets the absolute, canonical path of this container, using forward slashes
* as path separator.
*
* The path starts with a _root prefix_ followed by zero or more _path
* segments_ separated by forward slashes.
*
* The root prefix is of one of the following forms:
*
* 1. A single forward slash `/` (Unix-style)
* 2. An upper-case drive letter followed by a colon and a forward slash,
* such as `C:/` (Windows-style)
* 3. Two forward slashes, a computer name, and then another forward slash,
* such as `//FileServer/` (UNC-style)
*
* Path segments are never empty (that is, absolute paths never contain two
* contiguous slashes, except as part of a UNC-style root prefix). Also, path
* segments never contain forward slashes, and no path segment is of the
* form `.` (one dot) or `..` (two dots).
*
* Note that an absolute path never ends with a forward slash, except if it is
* a bare root prefix, that is, the path has no path segments. A container
* whose absolute path has no segments is always a `Folder`, not a `File`.
*/
string getAbsolutePath() { none() }
ContainerBase getParentContainer() { containerparent(result, this) }
/**
* Gets a URL representing the location of this container.
*
* For more information see [Providing URLs](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/#providing-urls).
*/
string getURL() { none() }
string toString() { result = this.getAbsolutePath() }
/**
* Gets the relative path of this file or folder from the root folder of the
* analyzed source location. The relative path of the root folder itself is
* the empty string.
*
* This has no result if the container is outside the source root, that is,
* if the root folder is not a reflexive, transitive parent of this container.
*/
string getRelativePath() {
exists(string absPath, string pref |
absPath = this.getAbsolutePath() and sourceLocationPrefix(pref)
|
absPath = pref and result = ""
or
absPath = pref.regexpReplaceAll("/$", "") + "/" + result and
not result.matches("/%")
)
}
class FolderBase extends ContainerBase, @folder {
override string getAbsolutePath() { folders(this, result) }
/**
* Gets the base name of this container including extension, that is, the last
* segment of its absolute path, or the empty string if it has no segments.
*
* Here are some examples of absolute paths and the corresponding base names
* (surrounded with quotes to avoid ambiguity):
*
* <table border="1">
* <tr><th>Absolute path</th><th>Base name</th></tr>
* <tr><td>"/tmp/tst.cs"</td><td>"tst.cs"</td></tr>
* <tr><td>"C:/Program Files (x86)"</td><td>"Program Files (x86)"</td></tr>
* <tr><td>"/"</td><td>""</td></tr>
* <tr><td>"C:/"</td><td>""</td></tr>
* <tr><td>"D:/"</td><td>""</td></tr>
* <tr><td>"//FileServer/"</td><td>""</td></tr>
* </table>
*/
string getBaseName() {
result = this.getAbsolutePath().regexpCapture(".*/(([^/]*?)(?:\\.([^.]*))?)", 1)
}
class FileBase extends ContainerBase, @file {
override string getAbsolutePath() { files(this, result) }
/**
* Gets the extension of this container, that is, the suffix of its base name
* after the last dot character, if any.
*
* In particular,
*
* - if the name does not include a dot, there is no extension, so this
* predicate has no result;
* - if the name ends in a dot, the extension is the empty string;
* - if the name contains multiple dots, the extension follows the last dot.
*
* Here are some examples of absolute paths and the corresponding extensions
* (surrounded with quotes to avoid ambiguity):
*
* <table border="1">
* <tr><th>Absolute path</th><th>Extension</th></tr>
* <tr><td>"/tmp/tst.cs"</td><td>"cs"</td></tr>
* <tr><td>"/tmp/.classpath"</td><td>"classpath"</td></tr>
* <tr><td>"/bin/bash"</td><td>not defined</td></tr>
* <tr><td>"/tmp/tst2."</td><td>""</td></tr>
* <tr><td>"/tmp/x.tar.gz"</td><td>"gz"</td></tr>
* </table>
*/
string getExtension() {
result = this.getAbsolutePath().regexpCapture(".*/([^/]*?)(\\.([^.]*))?", 3)
}
predicate hasSourceLocationPrefix = sourceLocationPrefix/1;
/**
* Gets the stem of this container, that is, the prefix of its base name up to
* (but not including) the last dot character if there is one, or the entire
* base name if there is not.
*
* Here are some examples of absolute paths and the corresponding stems
* (surrounded with quotes to avoid ambiguity):
*
* <table border="1">
* <tr><th>Absolute path</th><th>Stem</th></tr>
* <tr><td>"/tmp/tst.cs"</td><td>"tst"</td></tr>
* <tr><td>"/tmp/.classpath"</td><td>""</td></tr>
* <tr><td>"/bin/bash"</td><td>"bash"</td></tr>
* <tr><td>"/tmp/tst2."</td><td>"tst2"</td></tr>
* <tr><td>"/tmp/x.tar.gz"</td><td>"x.tar"</td></tr>
* </table>
*/
string getStem() {
result = this.getAbsolutePath().regexpCapture(".*/([^/]*?)(?:\\.([^.]*))?", 1)
}
/** Gets the parent container of this file or folder, if any. */
Container getParentContainer() { containerparent(result, this) }
/** Gets a file or sub-folder in this container. */
Container getAChildContainer() { this = result.getParentContainer() }
/** Gets a file in this container. */
File getAFile() { result = this.getAChildContainer() }
/** Gets the file in this container that has the given `baseName`, if any. */
File getFile(string baseName) {
result = this.getAFile() and
result.getBaseName() = baseName
}
/** Gets a sub-folder in this container. */
Folder getAFolder() { result = this.getAChildContainer() }
/** Gets the sub-folder in this container that has the given `baseName`, if any. */
Folder getFolder(string baseName) {
result = this.getAFolder() and
result.getBaseName() = baseName
}
/** Gets the file or sub-folder in this container that has the given `name`, if any. */
Container getChildContainer(string name) {
result = this.getAChildContainer() and
result.getBaseName() = name
}
/** Gets the file in this container that has the given `stem` and `extension`, if any. */
File getFile(string stem, string extension) {
result = this.getAChildContainer() and
result.getStem() = stem and
result.getExtension() = extension
}
/** Gets a sub-folder contained in this container. */
Folder getASubFolder() { result = this.getAChildContainer() }
/**
* Gets a textual representation of the path of this container.
*
* This is the absolute path of the container.
*/
string toString() { result = this.getAbsolutePath() }
}
private module Impl = Make<Input>;
class Container = Impl::Container;
/** A folder. */
class Folder extends Container, Impl::Folder { }
class Folder extends Container, @folder {
override string getAbsolutePath() { folders(this, result) }
override string getURL() { result = "folder://" + this.getAbsolutePath() }
}
bindingset[flag]
private predicate fileHasExtractionFlag(File f, int flag) {
@@ -41,7 +191,9 @@ private predicate fileHasExtractionFlag(File f, int flag) {
}
/** A file. */
class File extends Container, Impl::File {
class File extends Container, @file {
override string getAbsolutePath() { files(this, result) }
/** Gets the number of lines in this file. */
int getNumberOfLines() { numlines(this, result, _, _) }

View File

@@ -90,12 +90,6 @@ 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 `file` local. */
predicate isFile() { this.hasModifier("file") }
/** Holds if this declaration is `unsafe`. */
predicate isUnsafe() {
this.hasModifier("unsafe") or
@@ -184,10 +178,6 @@ 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() }
override predicate isFile() { Modifiable.super.isFile() }
}
private class TOverridable = @virtualizable or @callable_accessor;

View File

@@ -71,11 +71,6 @@ class LocalScopeVariable extends Variable, @local_scope_variable {
*/
predicate isRef() { none() }
/**
* Holds if this local variable or parameter is `scoped`.
*/
predicate isScoped() { scoped_annotation(this, _) }
override predicate hasQualifiedName(string qualifier, string name) { none() }
}

View File

@@ -137,8 +137,6 @@ private class RecordConstructorFlow extends SummarizedCallable {
preservesValue = true
)
}
override predicate hasProvenance(string provenance) { provenance = "manual" }
}
class RequiredSummaryComponentStack = Impl::Public::RequiredSummaryComponentStack;

View File

@@ -667,75 +667,20 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
fwdFlowIn(_, _, _, node, config) and
cc = true
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true and
not fullBarrier(node, config)
)
or
// flow out of a callable
fwdFlowOut(_, node, false, config) and
cc = false
or
// flow through a callable
exists(DataFlowCall call |
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
(
fwdFlowOut(call, node, false, 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)
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
}
@@ -781,8 +726,7 @@ private module Stage1 implements StageSig {
)
}
// inline to reduce the number of iterations
pragma[inline]
pragma[nomagic]
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
@@ -796,6 +740,17 @@ 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
@@ -862,8 +817,13 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
revFlowIn(_, node, false, config) and
toReturn = false
exists(DataFlowCall call |
revFlowIn(call, node, false, config) and
toReturn = false
or
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
or
// flow out of a callable
exists(ReturnPosition pos |
@@ -871,12 +831,6 @@ 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)
)
}
/**
@@ -932,11 +886,11 @@ private module Stage1 implements StageSig {
additional predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
) {
fwdFlowIn(call, arg, _, p, config)
viableParamArgEx(call, p, arg) and
fwdFlow(arg, config)
}
// inline to reduce the number of iterations
pragma[inline]
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config
) {

View File

@@ -667,75 +667,20 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
fwdFlowIn(_, _, _, node, config) and
cc = true
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true and
not fullBarrier(node, config)
)
or
// flow out of a callable
fwdFlowOut(_, node, false, config) and
cc = false
or
// flow through a callable
exists(DataFlowCall call |
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
(
fwdFlowOut(call, node, false, 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)
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
}
@@ -781,8 +726,7 @@ private module Stage1 implements StageSig {
)
}
// inline to reduce the number of iterations
pragma[inline]
pragma[nomagic]
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
@@ -796,6 +740,17 @@ 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
@@ -862,8 +817,13 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
revFlowIn(_, node, false, config) and
toReturn = false
exists(DataFlowCall call |
revFlowIn(call, node, false, config) and
toReturn = false
or
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
or
// flow out of a callable
exists(ReturnPosition pos |
@@ -871,12 +831,6 @@ 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)
)
}
/**
@@ -932,11 +886,11 @@ private module Stage1 implements StageSig {
additional predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
) {
fwdFlowIn(call, arg, _, p, config)
viableParamArgEx(call, p, arg) and
fwdFlow(arg, config)
}
// inline to reduce the number of iterations
pragma[inline]
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config
) {

View File

@@ -667,75 +667,20 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
fwdFlowIn(_, _, _, node, config) and
cc = true
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true and
not fullBarrier(node, config)
)
or
// flow out of a callable
fwdFlowOut(_, node, false, config) and
cc = false
or
// flow through a callable
exists(DataFlowCall call |
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
(
fwdFlowOut(call, node, false, 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)
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
}
@@ -781,8 +726,7 @@ private module Stage1 implements StageSig {
)
}
// inline to reduce the number of iterations
pragma[inline]
pragma[nomagic]
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
@@ -796,6 +740,17 @@ 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
@@ -862,8 +817,13 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
revFlowIn(_, node, false, config) and
toReturn = false
exists(DataFlowCall call |
revFlowIn(call, node, false, config) and
toReturn = false
or
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
or
// flow out of a callable
exists(ReturnPosition pos |
@@ -871,12 +831,6 @@ 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)
)
}
/**
@@ -932,11 +886,11 @@ private module Stage1 implements StageSig {
additional predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
) {
fwdFlowIn(call, arg, _, p, config)
viableParamArgEx(call, p, arg) and
fwdFlow(arg, config)
}
// inline to reduce the number of iterations
pragma[inline]
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config
) {

View File

@@ -667,75 +667,20 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
fwdFlowIn(_, _, _, node, config) and
cc = true
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true and
not fullBarrier(node, config)
)
or
// flow out of a callable
fwdFlowOut(_, node, false, config) and
cc = false
or
// flow through a callable
exists(DataFlowCall call |
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
(
fwdFlowOut(call, node, false, 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)
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
}
@@ -781,8 +726,7 @@ private module Stage1 implements StageSig {
)
}
// inline to reduce the number of iterations
pragma[inline]
pragma[nomagic]
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
@@ -796,6 +740,17 @@ 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
@@ -862,8 +817,13 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
revFlowIn(_, node, false, config) and
toReturn = false
exists(DataFlowCall call |
revFlowIn(call, node, false, config) and
toReturn = false
or
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
or
// flow out of a callable
exists(ReturnPosition pos |
@@ -871,12 +831,6 @@ 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)
)
}
/**
@@ -932,11 +886,11 @@ private module Stage1 implements StageSig {
additional predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
) {
fwdFlowIn(call, arg, _, p, config)
viableParamArgEx(call, p, arg) and
fwdFlow(arg, config)
}
// inline to reduce the number of iterations
pragma[inline]
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config
) {

View File

@@ -667,75 +667,20 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
fwdFlowIn(_, _, _, node, config) and
cc = true
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true and
not fullBarrier(node, config)
)
or
// flow out of a callable
fwdFlowOut(_, node, false, config) and
cc = false
or
// flow through a callable
exists(DataFlowCall call |
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
(
fwdFlowOut(call, node, false, 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)
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
}
@@ -781,8 +726,7 @@ private module Stage1 implements StageSig {
)
}
// inline to reduce the number of iterations
pragma[inline]
pragma[nomagic]
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
@@ -796,6 +740,17 @@ 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
@@ -862,8 +817,13 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
revFlowIn(_, node, false, config) and
toReturn = false
exists(DataFlowCall call |
revFlowIn(call, node, false, config) and
toReturn = false
or
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
or
// flow out of a callable
exists(ReturnPosition pos |
@@ -871,12 +831,6 @@ 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)
)
}
/**
@@ -932,11 +886,11 @@ private module Stage1 implements StageSig {
additional predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
) {
fwdFlowIn(call, arg, _, p, config)
viableParamArgEx(call, p, arg) and
fwdFlow(arg, config)
}
// inline to reduce the number of iterations
pragma[inline]
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config
) {

View File

@@ -707,8 +707,8 @@ private module Cached {
* Gets a viable dispatch target of `call` in the context `ctx`. This is
* restricted to those `call`s for which a context might make a difference.
*/
cached
DataFlowCallable viableImplInCallContextExt(DataFlowCall call, DataFlowCall ctx) {
pragma[nomagic]
private DataFlowCallable viableImplInCallContextExt(DataFlowCall call, DataFlowCall ctx) {
result = viableImplInCallContext(call, ctx) and
result = viableCallable(call)
or

View File

@@ -667,75 +667,20 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
fwdFlowIn(_, _, _, node, config) and
cc = true
exists(NodeEx arg |
fwdFlow(arg, _, config) and
viableParamArgEx(_, node, arg) and
cc = true and
not fullBarrier(node, config)
)
or
// flow out of a callable
fwdFlowOut(_, node, false, config) and
cc = false
or
// flow through a callable
exists(DataFlowCall call |
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
(
fwdFlowOut(call, node, false, 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)
fwdFlowOutFromArg(call, node, config) and
fwdFlowIsEntered(call, cc, config)
)
}
@@ -781,8 +726,7 @@ private module Stage1 implements StageSig {
)
}
// inline to reduce the number of iterations
pragma[inline]
pragma[nomagic]
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
@@ -796,6 +740,17 @@ 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
@@ -862,8 +817,13 @@ private module Stage1 implements StageSig {
)
or
// flow into a callable
revFlowIn(_, node, false, config) and
toReturn = false
exists(DataFlowCall call |
revFlowIn(call, node, false, config) and
toReturn = false
or
revFlowInToReturn(call, node, config) and
revFlowIsReturned(call, toReturn, config)
)
or
// flow out of a callable
exists(ReturnPosition pos |
@@ -871,12 +831,6 @@ 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)
)
}
/**
@@ -932,11 +886,11 @@ private module Stage1 implements StageSig {
additional predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
) {
fwdFlowIn(call, arg, _, p, config)
viableParamArgEx(call, p, arg) and
fwdFlow(arg, config)
}
// inline to reduce the number of iterations
pragma[inline]
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config
) {

View File

@@ -248,9 +248,7 @@ module Public {
/**
* Holds if all the summaries that apply to `this` are auto generated and not manually created.
*/
final predicate isAutoGenerated() {
this.hasProvenance(["generated", "ai-generated"]) and not this.isManual()
}
final predicate isAutoGenerated() { this.hasProvenance("generated") and not this.isManual() }
/**
* Holds if there exists a manual summary that applies to `this`.
@@ -270,7 +268,7 @@ module Public {
/**
* Holds if the neutral is auto generated.
*/
predicate isAutoGenerated() { neutralElement(this, ["generated", "ai-generated"]) }
predicate isAutoGenerated() { neutralElement(this, "generated") }
/**
* Holds if there exists a manual neutral that applies to `this`.
@@ -1204,11 +1202,11 @@ module Private {
}
private string renderProvenance(SummarizedCallable c) {
if c.isManual() then result = "manual" else c.hasProvenance(result)
if c.isAutoGenerated() then result = "generated" else result = "manual"
}
private string renderProvenanceNeutral(NeutralCallable c) {
if c.isManual() then result = "manual" else c.hasProvenance(result)
if c.isAutoGenerated() then result = "generated" else result = "manual"
}
/**

View File

@@ -86,8 +86,6 @@ module EntityFramework {
abstract class EFSummarizedCallable extends SummarizedCallable {
bindingset[this]
EFSummarizedCallable() { any() }
override predicate hasProvenance(string provenance) { provenance = "manual" }
}
private class DbSetAddOrUpdateRequiredSummaryComponentStack extends RequiredSummaryComponentStack {

View File

@@ -80,12 +80,6 @@ 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 is declared `file` local. */
predicate isFile() { none() }
/**
* Holds if this member has name `name` and is defined in type `type`
* with namespace `namespace`.

View File

@@ -878,13 +878,6 @@ param_location(
int id: @parameter ref,
int loc: @location ref);
@has_scoped_annotation = @local_scope_variable
scoped_annotation(
int id: @has_scoped_annotation ref,
int kind: int ref // scoped ref = 1, scoped value = 2
);
/** STATEMENTS **/
@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent;

View File

@@ -26228,59 +26228,6 @@
</dep>
</dependencies>
</relation>
<relation>
<name>scoped_annotation</name>
<cardinality>43498</cardinality>
<columnsizes>
<e>
<k>id</k>
<v>43498</v>
</e>
<e>
<k>kind</k>
<v>18</v>
</e>
</columnsizes>
<dependencies>
<dep>
<src>id</src>
<trg>kind</trg>
<val>
<hist>
<budget>12</budget>
<bs>
<b>
<a>1</a>
<b>2</b>
<v>43498</v>
</b>
</bs>
</hist>
</val>
</dep>
<dep>
<src>kind</src>
<trg>id</trg>
<val>
<hist>
<budget>12</budget>
<bs>
<b>
<a>11</a>
<b>12</b>
<v>9</v>
</b>
<b>
<a>4599</a>
<b>4600</b>
<v>9</v>
</b>
</bs>
</hist>
</val>
</dep>
</dependencies>
</relation>
<relation>
<name>statements</name>
<cardinality>2458000</cardinality>

Some files were not shown because too many files have changed in this diff Show More