Compare commits

..

4 Commits

Author SHA1 Message Date
Nick Rolfe
afad46c6bc NPE reproduction 2022-05-26 11:22:28 +01:00
Nick Rolfe
a93b11e044 Merge remote-tracking branch 'origin/main' into nickrolfe/callgraph_mixins 2022-05-25 12:36:34 +01:00
Nick Rolfe
d1db83cae5 Merge remote-tracking branch 'origin/main' into nickrolfe/callgraph_mixins 2022-05-20 11:45:56 +01:00
Nick Rolfe
42dfa4e8b5 Ruby: add test showing callgraph bug 2022-05-09 12:17:47 +01:00
2587 changed files with 67056 additions and 142448 deletions

30
.codeqlmanifest.json Normal file
View File

@@ -0,0 +1,30 @@
{
"provide": [
"*/ql/src/qlpack.yml",
"*/ql/lib/qlpack.yml",
"*/ql/test/qlpack.yml",
"*/ql/examples/qlpack.yml",
"*/ql/consistency-queries/qlpack.yml",
"cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/qlpack.yml",
"go/ql/config/legacy-support/qlpack.yml",
"go/build/codeql-extractor-go/codeql-extractor.yml",
"javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml",
"javascript/ql/experimental/adaptivethreatmodeling/modelbuilding/qlpack.yml",
"javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml",
"csharp/ql/campaigns/Solorigate/lib/qlpack.yml",
"csharp/ql/campaigns/Solorigate/src/qlpack.yml",
"csharp/ql/campaigns/Solorigate/test/qlpack.yml",
"misc/legacy-support/*/qlpack.yml",
"misc/suite-helpers/qlpack.yml",
"ruby/extractor-pack/codeql-extractor.yml",
"swift/extractor-pack/codeql-extractor.yml",
"ql/extractor-pack/codeql-extractor.yml"
],
"versionPolicies": {
"default": {
"requireChangeNotes": true,
"committedPrereleaseSuffix": "dev",
"committedVersion": "nextPatchRelease"
}
}
}

View File

@@ -1,9 +0,0 @@
# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.236.0/containers/cpp/.devcontainer/base.Dockerfile
# [Choice] Debian / Ubuntu version (use Debian 11, Ubuntu 18.04/22.04 on local arm64/Apple Silicon): debian-11, debian-10, ubuntu-22.04, ubuntu-20.04, ubuntu-18.04
FROM mcr.microsoft.com/vscode/devcontainers/cpp:0-ubuntu-22.04
USER root
ADD root.sh /tmp/root.sh
ADD update-codeql.sh /usr/local/bin/update-codeql
RUN bash /tmp/root.sh && rm /tmp/root.sh

View File

@@ -1,25 +0,0 @@
{
"extensions": [
"github.vscode-codeql",
"hbenl.vscode-test-explorer",
"ms-vscode.test-adapter-converter",
"slevesque.vscode-zipexplorer",
"ms-vscode.cpptools"
],
"settings": {
"files.watcherExclude": {
"**/target/**": true
},
"codeQL.runningQueries.memory": 2048
},
"build": {
"dockerfile": "Dockerfile",
},
"runArgs": [
"--cap-add=SYS_PTRACE",
"--security-opt",
"seccomp=unconfined"
],
"remoteUser": "vscode",
"onCreateCommand": ".devcontainer/swift/user.sh"
}

View File

@@ -1,22 +0,0 @@
set -xe
BAZELISK_VERSION=v1.12.0
BAZELISK_DOWNLOAD_SHA=6b0bcb2ea15bca16fffabe6fda75803440375354c085480fe361d2cbf32501db
apt-get update
export DEBIAN_FRONTEND=noninteractive
apt-get -y install --no-install-recommends \
zlib1g-dev \
uuid-dev \
python3-distutils \
python3-pip \
bash-completion
# Install Bazel
curl -fSsL -o /usr/local/bin/bazelisk https://github.com/bazelbuild/bazelisk/releases/download/${BAZELISK_VERSION}/bazelisk-linux-amd64
echo "${BAZELISK_DOWNLOAD_SHA} */usr/local/bin/bazelisk" | sha256sum --check -
chmod 0755 /usr/local/bin/bazelisk
ln -s bazelisk /usr/local/bin/bazel
# install latest codeql
update-codeql

View File

@@ -1,20 +0,0 @@
#!/bin/bash -e
URL=https://github.com/github/codeql-cli-binaries/releases
LATEST_VERSION=$(curl -L -s -H 'Accept: application/json' $URL/latest | sed -e 's/.*"tag_name":"\([^"]*\)".*/\1/')
CURRENT_VERSION=v$(codeql version 2>/dev/null | sed -ne 's/.*release \([0-9.]*\)\./\1/p')
if [[ $CURRENT_VERSION != $LATEST_VERSION ]]; then
if [[ $UID != 0 ]]; then
echo "update required, please run this script with sudo:"
echo " sudo $0"
exit 1
fi
ZIP=$(mktemp codeql.XXXX.zip)
curl -fSqL -o $ZIP $URL/download/$LATEST_VERSION/codeql-linux64.zip
unzip -q $ZIP -d /opt
rm $ZIP
ln -sf /opt/codeql/codeql /usr/local/bin/codeql
echo installed version $LATEST_VERSION
else
echo current version $CURRENT_VERSION is up-to-date
fi

View File

@@ -1,13 +0,0 @@
set -xe
# add the workspace to the codeql search path
mkdir -p /home/vscode/.config/codeql
echo "--search-path /workspaces/codeql" > /home/vscode/.config/codeql/config
# create a swift extractor pack with the current state
cd /workspaces/codeql
bazel run swift/create-extractor-pack
#install and set up pre-commit
python3 -m pip install pre-commit --no-warn-script-location
$HOME/.local/bin/pre-commit install

View File

@@ -13,11 +13,6 @@ runs:
shell: bash
run: echo "GA_CODEQL_CLI_PLATFORM=osx64" >> $GITHUB_ENV
- name: Select platform - Windows
if: runner.os == 'Windows'
shell: bash
run: echo "GA_CODEQL_CLI_PLATFORM=win64" >> $GITHUB_ENV
- name: Fetch CodeQL
shell: bash
run: |

15
.github/labeler.yml vendored
View File

@@ -6,23 +6,14 @@
- csharp/**/*
- change-notes/**/*csharp*
Go:
- go/**/*
- change-notes/**/*go.*
Java:
- any: [ 'java/**/*', '!java/kotlin-extractor/**/*', '!java/kotlin-explorer/**/*', '!java/ql/test/kotlin/**/*' ]
- java/**/*
- change-notes/**/*java.*
JS:
- any: [ 'javascript/**/*', '!javascript/ql/experimental/adaptivethreatmodeling/**/*' ]
- change-notes/**/*javascript*
Kotlin:
- java/kotlin-extractor/**/*
- java/kotlin-explorer/**/*
- java/ql/test/kotlin/**/*
Python:
- python/**/*
- change-notes/**/*python*
@@ -30,7 +21,7 @@ Python:
Ruby:
- ruby/**/*
- change-notes/**/*ruby*
Swift:
- swift/**/*
- change-notes/**/*swift*
@@ -40,5 +31,5 @@ documentation:
- "**/*.md"
- docs/**/*
"QL-for-QL":
"QL-for-QL":
- ql/**/*

View File

@@ -10,7 +10,6 @@ on:
- "*/ql/lib/**/*.qll"
- "!**/experimental/**"
- "!ql/**"
- "!swift/**"
- ".github/workflows/check-change-note.yml"
jobs:

View File

@@ -41,7 +41,7 @@ jobs:
git log -1 --format='%H'
working-directory: base
- name: Set up Python 3.8
uses: actions/setup-python@v4
uses: actions/setup-python@v3
with:
python-version: 3.8
- name: Download CodeQL CLI

View File

@@ -22,7 +22,7 @@ jobs:
- name: Clone self (github/codeql)
uses: actions/checkout@v3
- name: Set up Python 3.8
uses: actions/setup-python@v4
uses: actions/setup-python@v3
with:
python-version: 3.8

View File

@@ -19,7 +19,7 @@ jobs:
path: codeqlModels
fetch-depth: 0
- name: Set up Python 3.8
uses: actions/setup-python@v4
uses: actions/setup-python@v3
with:
python-version: 3.8
- name: Download CodeQL CLI

View File

@@ -22,7 +22,7 @@ jobs:
path: ql
fetch-depth: 0
- name: Set up Python 3.8
uses: actions/setup-python@v4
uses: actions/setup-python@v3
with:
python-version: 3.8
- name: Download CodeQL CLI

View File

@@ -23,7 +23,7 @@ jobs:
path: codeqlModels
ref: ${{ github.event.inputs.qlModelShaOverride || github.ref }}
- name: Set up Python 3.8
uses: actions/setup-python@v4
uses: actions/setup-python@v3
with:
python-version: 3.8
- name: Download CodeQL CLI

View File

@@ -4,7 +4,6 @@ on:
paths:
- "go/**"
- .github/workflows/go-tests.yml
- codeql-workspace.yml
jobs:
test-linux:

View File

@@ -5,7 +5,6 @@ on:
paths:
- "javascript/ql/experimental/adaptivethreatmodeling/**"
- .github/workflows/js-ml-tests.yml
- codeql-workspace.yml
branches:
- main
- "rc/*"
@@ -13,8 +12,6 @@ on:
paths:
- "javascript/ql/experimental/adaptivethreatmodeling/**"
- .github/workflows/js-ml-tests.yml
- codeql-workspace.yml
workflow_dispatch:
defaults:
run:

View File

@@ -4,9 +4,6 @@ on:
jobs:
triage:
permissions:
contents: read
pull-requests: write
runs-on: ubuntu-latest
steps:
- uses: actions/labeler@v4

View File

@@ -61,7 +61,7 @@ jobs:
DATABASE=$2
cd codeql-$QL_VARIANT
SHORTNAME=`basename $DATABASE`
python java/ql/src/utils/model-generator/GenerateFlowModel.py --with-summaries --with-sinks $DATABASE $MODELS/${SHORTNAME}.qll
python java/ql/src/utils/model-generator/GenerateFlowModel.py $DATABASE $MODELS/${SHORTNAME}.qll
mv $MODELS/${SHORTNAME}.qll $MODELS/${SHORTNAME}Generated_${QL_VARIANT}.qll
cd ..
}

View File

@@ -20,7 +20,7 @@ jobs:
ref: ["placeholder"]
include:
- slug: "apache/commons-io"
ref: "13258ce2d07aa0e764bbaa8020af4dcd3a02a620"
ref: "8985de8fe74f6622a419b37a6eed0dbc484dc128"
exclude:
- slug: "placeholder"
ref: "placeholder"

View File

@@ -10,16 +10,16 @@ env:
CARGO_TERM_COLOR: always
jobs:
analyze:
runs-on: ubuntu-latest-xl
queries:
runs-on: ubuntu-latest
steps:
### Build the queries ###
- uses: actions/checkout@v3
- name: Find codeql
id: find-codeql
uses: github/codeql-action/init@aa93aea877e5fb8841bcb1193f672abf6e9f2980
with:
languages: javascript # does not matter
tools: latest
- name: Get CodeQL version
id: get-codeql-version
run: |
@@ -49,7 +49,14 @@ jobs:
name: query-pack-zip
path: ${{ runner.temp }}/query-pack.zip
### Build the extractor ###
extractors:
strategy:
fail-fast: false
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Cache entire extractor
id: cache-extractor
uses: actions/cache@v3
@@ -93,8 +100,15 @@ jobs:
ql/target/release/ql-extractor
ql/target/release/ql-extractor.exe
retention-days: 1
package:
runs-on: ubuntu-latest
### Package the queries and extractor ###
needs:
- extractors
- queries
steps:
- uses: actions/checkout@v3
- uses: actions/download-artifact@v3
with:
name: query-pack-zip
@@ -122,8 +136,16 @@ jobs:
name: codeql-ql-pack
path: codeql-ql.zip
retention-days: 1
analyze:
runs-on: ubuntu-latest
strategy:
matrix:
folder: [cpp, csharp, java, javascript, python, ql, ruby, swift, go]
### Run the analysis ###
needs:
- package
steps:
- name: Download pack
uses: actions/download-artifact@v3
with:
@@ -143,11 +165,14 @@ jobs:
env:
PACK: ${{ runner.temp }}/pack
- name: Checkout repository
uses: actions/checkout@v3
- name: Create CodeQL config file
run: |
echo "paths:" > ${CONF}
echo " - ${FOLDER}" >> ${CONF}
echo "paths-ignore:" >> ${CONF}
echo " - ql/ql/test" >> ${CONF}
echo " - \"*/ql/lib/upgrades/\"" >> ${CONF}
echo "disable-default-queries: true" >> ${CONF}
echo "packs:" >> ${CONF}
echo " - codeql/ql" >> ${CONF}
@@ -155,34 +180,24 @@ jobs:
cat ${CONF}
env:
CONF: ./ql-for-ql-config.yml
FOLDER: ${{ matrix.folder }}
- name: Initialize CodeQL
uses: github/codeql-action/init@aa93aea877e5fb8841bcb1193f672abf6e9f2980
with:
languages: ql
db-location: ${{ runner.temp }}/db
config-file: ./ql-for-ql-config.yml
tools: latest
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@aa93aea877e5fb8841bcb1193f672abf6e9f2980
with:
category: "ql-for-ql"
category: "ql-for-ql-${{ matrix.folder }}"
- name: Copy sarif file to CWD
run: cp ../results/ql.sarif ./ql-for-ql.sarif
- name: Fixup the $scema in sarif # Until https://github.com/microsoft/sarif-vscode-extension/pull/436/ is part in a stable release
run: |
sed -i 's/\$schema.*/\$schema": "https:\/\/raw.githubusercontent.com\/oasis-tcs\/sarif-spec\/master\/Schemata\/sarif-schema-2.1.0",/' ql-for-ql.sarif
run: cp ../results/ql.sarif ./${{ matrix.folder }}.sarif
- name: Sarif as artifact
uses: actions/upload-artifact@v3
with:
name: ql-for-ql.sarif
path: ql-for-ql.sarif
- name: Split out the sarif file into langs
run: |
mkdir split-sarif
node ./ql/scripts/split-sarif.js ql-for-ql.sarif split-sarif
- name: Upload langs as artifacts
uses: actions/upload-artifact@v3
with:
name: ql-for-ql-langs
path: split-sarif
retention-days: 1
name: ${{ matrix.folder }}.sarif
path: ${{ matrix.folder }}.sarif

View File

@@ -36,7 +36,7 @@ jobs:
ql/target
key: ${{ runner.os }}-qltest-cargo-${{ hashFiles('ql/**/Cargo.lock') }}
- name: Build Extractor
run: cd ql; env "PATH=$PATH:`dirname ${CODEQL}`" ./scripts/create-extractor-pack.sh
run: cd ql; env "PATH=$PATH:`dirname ${CODEQL}`" ./create-extractor-pack.sh
env:
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
- name: Checkout ${{ matrix.repo }}

View File

@@ -5,12 +5,10 @@ on:
branches: [main]
paths:
- "ql/**"
- codeql-workspace.yml
pull_request:
branches: [main]
paths:
- "ql/**"
- codeql-workspace.yml
env:
CARGO_TERM_COLOR: always
@@ -36,7 +34,7 @@ jobs:
run: |
cd ql;
codeqlpath=$(dirname ${{ steps.find-codeql.outputs.codeql-path }});
env "PATH=$PATH:$codeqlpath" ./scripts/create-extractor-pack.sh
env "PATH=$PATH:$codeqlpath" ./create-extractor-pack.sh
- name: Run QL tests
run: |
"${CODEQL}" test run --check-databases --check-unused-labels --check-repeated-labels --check-redefined-labels --check-use-before-definition --search-path "${{ github.workspace }}/ql/extractor-pack" --consistency-queries ql/ql/consistency-queries ql/ql/test

View File

@@ -5,8 +5,6 @@ on:
branches:
- main
- 'rc/**'
tags:
- 'codeql-cli/*'
pull_request:
paths:
- '.github/workflows/query-list.yml'
@@ -23,7 +21,7 @@ jobs:
with:
path: codeql
- name: Set up Python 3.8
uses: actions/setup-python@v4
uses: actions/setup-python@v3
with:
python-version: 3.8
- name: Download CodeQL CLI

View File

@@ -5,7 +5,6 @@ on:
paths:
- "ruby/**"
- .github/workflows/ruby-build.yml
- codeql-workspace.yml
branches:
- main
- "rc/*"
@@ -13,7 +12,6 @@ on:
paths:
- "ruby/**"
- .github/workflows/ruby-build.yml
- codeql-workspace.yml
branches:
- main
- "rc/*"

View File

@@ -5,7 +5,6 @@ on:
paths:
- "ruby/**"
- .github/workflows/ruby-qltest.yml
- codeql-workspace.yml
branches:
- main
- "rc/*"
@@ -13,7 +12,6 @@ on:
paths:
- "ruby/**"
- .github/workflows/ruby-qltest.yml
- codeql-workspace.yml
branches:
- main
- "rc/*"

View File

@@ -15,22 +15,18 @@ jobs:
- uses: actions/checkout@v3
- uses: ./.github/actions/fetch-codeql
- uses: bazelbuild/setup-bazelisk@v2
- uses: actions/setup-python@v3
- uses: pre-commit/action@v3.0.0
name: Check that python code is properly formatted
with:
extra_args: autopep8 --all-files
- name: Run unit tests
run: |
bazel test //swift/codegen/test --test_output=errors
- uses: pre-commit/action@v3.0.0
name: Check that QL generated code was checked in
with:
extra_args: swift-codegen --all-files
- name: Check that QL generated code was checked in
run: |
bazel run //swift/codegen
git add swift
git diff --exit-code --stat HEAD
- name: Generate C++ files
run: |
bazel run //swift/codegen:codegen -- --generate=trap,cpp --cpp-output=$PWD/swift-generated-cpp-files
bazel run //swift/codegen:cppcodegen -- --cpp-output=$PWD/swift-generated-headers
- uses: actions/upload-artifact@v3
with:
name: swift-generated-cpp-files
path: swift-generated-cpp-files/**
name: swift-generated-headers
path: swift-generated-headers/*.h

View File

@@ -1,34 +0,0 @@
name: "Swift: Run Integration Tests"
on:
pull_request:
paths:
- "swift/**"
- .github/workflows/swift-integration-tests.yml
- codeql-workspace.yml
branches:
- main
defaults:
run:
working-directory: swift
jobs:
integration-tests:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- ubuntu-20.04
# - macos-latest TODO
steps:
- uses: actions/checkout@v3
- uses: ./.github/actions/fetch-codeql
- uses: bazelbuild/setup-bazelisk@v2
- uses: actions/setup-python@v3
- name: Build Swift extractor
run: |
bazel run //swift:create-extractor-pack
- name: Run integration tests
run: |
python integration-tests/runner.py

View File

@@ -5,7 +5,6 @@ on:
paths:
- "swift/**"
- .github/workflows/swift-qltest.yml
- codeql-workspace.yml
branches:
- main
defaults:

6
.gitignore vendored
View File

@@ -55,9 +55,3 @@ go/tools/win64
go/tools/tokenizer.jar
go/main
# node_modules folders except in the JS test suite
node_modules/
!/javascript/ql/test/**/node_modules/
# Temporary folders for working with generated models
.model-temp

View File

@@ -15,12 +15,6 @@ repos:
- id: clang-format
files: ^swift/.*\.(h|c|cpp)$
- repo: https://github.com/pre-commit/mirrors-autopep8
rev: v1.6.0
hooks:
- id: autopep8
files: ^swift/codegen/.*\.py
- repo: local
hooks:
- id: codeql-format
@@ -31,7 +25,7 @@ repos:
- id: sync-files
name: Fix files required to be identical
files: \.(qll?|qhelp|swift)$
files: \.(qll?|qhelp)$
language: system
entry: python3 config/sync-files.py --latest
pass_filenames: false
@@ -46,7 +40,7 @@ repos:
name: Run Swift checked in code generation
files: ^swift/(codegen/|.*/generated/|ql/lib/(swift\.dbscheme$|codeql/swift/elements))
language: system
entry: bazel run //swift/codegen -- --quiet
entry: bazel run //swift/codegen
pass_filenames: false
- id: swift-codegen-unit-tests

View File

@@ -28,8 +28,8 @@
# QL for QL reviewers
/ql/ @github/codeql-ql-for-ql-reviewers
# Bazel (excluding BUILD.bazel files)
WORKSPACE.bazel @github/codeql-ci-reviewers
# Bazel
**/*.bazel @github/codeql-ci-reviewers
**/*.bzl @github/codeql-ci-reviewers
# Documentation etc
@@ -42,4 +42,3 @@ WORKSPACE.bazel @github/codeql-ci-reviewers
/.github/workflows/js-ml-tests.yml @github/codeql-ml-powered-queries-reviewers
/.github/workflows/ql-for-ql-* @github/codeql-ql-for-ql-reviewers
/.github/workflows/ruby-* @github/codeql-ruby
/.github/workflows/swift-* @github/codeql-c

View File

@@ -1,32 +0,0 @@
provide:
- "*/ql/src/qlpack.yml"
- "*/ql/lib/qlpack.yml"
- "*/ql/test/qlpack.yml"
- "*/ql/examples/qlpack.yml"
- "*/ql/consistency-queries/qlpack.yml"
- "cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/qlpack.yml"
- "go/ql/config/legacy-support/qlpack.yml"
- "go/build/codeql-extractor-go/codeql-extractor.yml"
- "javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml"
# This pack is explicitly excluded from the workspace since most users
# will want to use a version of this pack from the package cache. Internal
# users can uncomment the following line and place a custom ML model
# in the corresponding pack to test a custom ML model within their local
# checkout.
# - "javascript/ql/experimental/adaptivethreatmodeling/model/qlpack.yml"
- "javascript/ql/experimental/adaptivethreatmodeling/modelbuilding/qlpack.yml"
- "javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml"
- "csharp/ql/campaigns/Solorigate/lib/qlpack.yml"
- "csharp/ql/campaigns/Solorigate/src/qlpack.yml"
- "csharp/ql/campaigns/Solorigate/test/qlpack.yml"
- "misc/legacy-support/*/qlpack.yml"
- "misc/suite-helpers/qlpack.yml"
- "ruby/extractor-pack/codeql-extractor.yml"
- "swift/extractor-pack/codeql-extractor.yml"
- "ql/extractor-pack/codeql-extractor.ym"
versionPolicies:
default:
requireChangeNotes: true
committedPrereleaseSuffix: dev
committedVersion: nextPatchRelease

View File

@@ -75,8 +75,7 @@
"DataFlow Java/C# Flow Summaries": [
"java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll",
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll",
"ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImpl.qll",
"swift/ql/lib/codeql/swift/dataflow/internal/FlowSummaryImpl.qll"
"ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImpl.qll"
],
"SsaReadPosition Java/C#": [
"java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/SsaReadPositionCommon.qll",
@@ -391,8 +390,7 @@
"java/ql/test/TestUtilities/InlineExpectationsTest.qll",
"python/ql/test/TestUtilities/InlineExpectationsTest.qll",
"ruby/ql/test/TestUtilities/InlineExpectationsTest.qll",
"ql/ql/test/TestUtilities/InlineExpectationsTest.qll",
"go/ql/test/TestUtilities/InlineExpectationsTest.qll"
"ql/ql/test/TestUtilities/InlineExpectationsTest.qll"
],
"C++ ExternalAPIs": [
"cpp/ql/src/Security/CWE/CWE-020/ExternalAPIs.qll",
@@ -453,11 +451,11 @@
"python/ql/src/Lexical/CommentedOutCodeReferences.inc.qhelp"
],
"IDE Contextual Queries": [
"cpp/ql/lib/IDEContextual.qll",
"csharp/ql/lib/IDEContextual.qll",
"java/ql/lib/IDEContextual.qll",
"javascript/ql/lib/IDEContextual.qll",
"python/ql/lib/analysis/IDEContextual.qll"
"cpp/ql/src/IDEContextual.qll",
"csharp/ql/src/IDEContextual.qll",
"java/ql/src/IDEContextual.qll",
"javascript/ql/src/IDEContextual.qll",
"python/ql/src/analysis/IDEContextual.qll"
],
"SSA C#": [
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/SsaImplCommon.qll",
@@ -527,9 +525,7 @@
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/AccessPathSyntax.qll",
"java/ql/lib/semmle/code/java/dataflow/internal/AccessPathSyntax.qll",
"javascript/ql/lib/semmle/javascript/frameworks/data/internal/AccessPathSyntax.qll",
"ruby/ql/lib/codeql/ruby/dataflow/internal/AccessPathSyntax.qll",
"python/ql/lib/semmle/python/frameworks/data/internal/AccessPathSyntax.qll",
"swift/ql/lib/codeql/swift/dataflow/internal/AccessPathSyntax.qll"
"ruby/ql/lib/codeql/ruby/dataflow/internal/AccessPathSyntax.qll"
],
"IncompleteUrlSubstringSanitization": [
"javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.qll",
@@ -547,8 +543,7 @@
],
"ApiGraphModels": [
"javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModels.qll",
"ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModels.qll",
"python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModels.qll"
"ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModels.qll"
],
"TaintedFormatStringQuery Ruby/JS": [
"javascript/ql/lib/semmle/javascript/security/dataflow/TaintedFormatStringQuery.qll",
@@ -569,21 +564,5 @@
"Typo database": [
"javascript/ql/src/Expressions/TypoDatabase.qll",
"ql/ql/src/codeql_ql/style/TypoDatabase.qll"
],
"Swift declarations test file": [
"swift/ql/test/extractor-tests/declarations/declarations.swift",
"swift/ql/test/library-tests/parent/declarations.swift"
],
"Swift statements test file": [
"swift/ql/test/extractor-tests/statements/statements.swift",
"swift/ql/test/library-tests/parent/statements.swift"
],
"Swift expressions test file": [
"swift/ql/test/extractor-tests/expressions/expressions.swift",
"swift/ql/test/library-tests/parent/expressions.swift"
],
"Swift patterns test file": [
"swift/ql/test/extractor-tests/patterns/patterns.swift",
"swift/ql/test/library-tests/parent/patterns.swift"
]
}
}

View File

@@ -1,3 +0,0 @@
description: Add relation for tracking C++ braced initializers
compatibility: full
braced_initialisers.rel: delete

View File

@@ -1,17 +0,0 @@
class Expr extends @expr {
string toString() { none() }
}
class Location extends @location_expr {
string toString() { none() }
}
predicate isExprWithNewBuiltin(Expr expr) {
exists(int kind | exprs(expr, kind, _) | 330 <= kind and kind <= 334)
}
from Expr expr, int kind, int kind_new, Location location
where
exprs(expr, kind, location) and
if isExprWithNewBuiltin(expr) then kind_new = 0 else kind_new = kind
select expr, kind_new, location

View File

@@ -1,3 +0,0 @@
description: Add new builtin operations
compatibility: partial
exprs.rel: run exprs.qlo

View File

@@ -1,35 +1,3 @@
## 0.3.1
### Minor Analysis Improvements
* `AnalysedExpr::isNullCheck` and `AnalysedExpr::isValidCheck` have been updated to handle variable accesses on the left-hand side of the C++ logical "and", and variable declarations in conditions.
## 0.3.0
### Deprecated APIs
* The `BarrierGuard` class has been deprecated. Such barriers and sanitizers can now instead be created using the new `BarrierGuard` parameterized module.
### Bug Fixes
* `UserType.getADeclarationEntry()` now yields all forward declarations when the user type is a `class`, `struct`, or `union`.
## 0.2.3
### New Features
* An `isBraced` predicate was added to the `Initializer` class which holds when a C++ braced initializer was used in the initialization.
## 0.2.2
### Deprecated APIs
* The `AnalysedString` class in the `StringAnalysis` module has been replaced with `AnalyzedString`, to follow our style guide. The old name still exists as a deprecated alias.
### New Features
* A `getInitialization` predicate was added to the `ConstexprIfStmt`, `IfStmt`, and `SwitchStmt` classes that yields the C++17-style initializer of the `if` or `switch` statement when it exists.
## 0.2.1
## 0.2.0

View File

@@ -0,0 +1,4 @@
---
category: feature
---
* A `getInitialization` predicate was added to the `ConstexprIfStmt`, `IfStmt`, and `SwitchStmt` classes that yields the C++17-style initializer of the `if` or `switch` statement when it exists.

View File

@@ -0,0 +1,4 @@
---
category: deprecated
---
* The `AnalysedString` class in the `StringAnalysis` module has been replaced with `AnalyzedString`, to follow our style guide. The old name still exists as a deprecated alias.

View File

@@ -1,4 +0,0 @@
---
category: fix
---
* Under certain circumstances a variable declaration that is not also a definition could be associated with a `Variable` that did not have the definition as a `VariableDeclarationEntry`. This is now fixed, and a unique `Variable` will exist that has both the declaration and the definition as a `VariableDeclarationEntry`.

View File

@@ -1,4 +0,0 @@
---
category: feature
---
* Added subclasses of `BuiltInOperations` for `__builtin_bit_cast`, `__builtin_shuffle`, `__has_unique_object_representations`, `__is_aggregate`, and `__is_assignable`.

View File

@@ -1,9 +0,0 @@
## 0.2.2
### Deprecated APIs
* The `AnalysedString` class in the `StringAnalysis` module has been replaced with `AnalyzedString`, to follow our style guide. The old name still exists as a deprecated alias.
### New Features
* A `getInitialization` predicate was added to the `ConstexprIfStmt`, `IfStmt`, and `SwitchStmt` classes that yields the C++17-style initializer of the `if` or `switch` statement when it exists.

View File

@@ -1,5 +0,0 @@
## 0.2.3
### New Features
* An `isBraced` predicate was added to the `Initializer` class which holds when a C++ braced initializer was used in the initialization.

View File

@@ -1,9 +0,0 @@
## 0.3.0
### Deprecated APIs
* The `BarrierGuard` class has been deprecated. Such barriers and sanitizers can now instead be created using the new `BarrierGuard` parameterized module.
### Bug Fixes
* `UserType.getADeclarationEntry()` now yields all forward declarations when the user type is a `class`, `struct`, or `union`.

View File

@@ -1,5 +0,0 @@
## 0.3.1
### Minor Analysis Improvements
* `AnalysedExpr::isNullCheck` and `AnalysedExpr::isValidCheck` have been updated to handle variable accesses on the left-hand side of the C++ logical "and", and variable declarations in conditions.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.3.1
lastReleaseVersion: 0.2.1

View File

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

View File

@@ -6,7 +6,6 @@
import semmle.code.cpp.Location
private import semmle.code.cpp.Enclosing
private import semmle.code.cpp.internal.ResolveClass
private import semmle.code.cpp.internal.ResolveGlobalVariable
/**
* Get the `Element` that represents this `@element`.
@@ -29,12 +28,9 @@ Element mkElement(@element e) { unresolveElement(result) = e }
pragma[inline]
@element unresolveElement(Element e) {
not result instanceof @usertype and
not result instanceof @variable and
result = e
or
e = resolveClass(result)
or
e = resolveGlobalVariable(result)
}
/**

View File

@@ -51,7 +51,4 @@ class Initializer extends ControlFlowNode, @initialiser {
override Function getControlFlowScope() { result = this.getExpr().getEnclosingFunction() }
override Stmt getEnclosingStmt() { result = this.getExpr().getEnclosingStmt() }
/** Holds if the initializer used the C++ braced initializer notation. */
predicate isBraced() { braced_initialisers(underlyingElement(this)) }
}

View File

@@ -48,8 +48,8 @@ class UserType extends Type, Declaration, NameQualifyingElement, AccessHolder, @
}
override TypeDeclarationEntry getADeclarationEntry() {
if type_decls(_, unresolveElement(this), _)
then type_decls(underlyingElement(result), unresolveElement(this), _)
if type_decls(_, underlyingElement(this), _)
then type_decls(unresolveElement(result), underlyingElement(this), _)
else exists(Class t | this.(Class).isConstructedFrom(t) and result = t.getADeclarationEntry())
}

View File

@@ -6,7 +6,6 @@ import semmle.code.cpp.Element
import semmle.code.cpp.exprs.Access
import semmle.code.cpp.Initializer
private import semmle.code.cpp.internal.ResolveClass
private import semmle.code.cpp.internal.ResolveGlobalVariable
/**
* A C/C++ variable. For example, in the following code there are four
@@ -33,8 +32,6 @@ private import semmle.code.cpp.internal.ResolveGlobalVariable
* can have multiple declarations.
*/
class Variable extends Declaration, @variable {
Variable() { isVariable(underlyingElement(this)) }
override string getAPrimaryQlClass() { result = "Variable" }
/** Gets the initializer of this variable, if any. */

View File

@@ -168,7 +168,7 @@ private predicate callsVariadicFormatter(
) {
// calls a variadic formatter with `formatParamIndex`, `outputParamIndex` linked
exists(FunctionCall fc, int format, int output |
variadicFormatter(pragma[only_bind_into](fc.getTarget()), type, format, output) and
variadicFormatter(fc.getTarget(), type, format, output) and
fc.getEnclosingFunction() = f and
fc.getArgument(format) = f.getParameter(formatParamIndex).getAnAccess() and
fc.getArgument(output) = f.getParameter(outputParamIndex).getAnAccess()
@@ -176,7 +176,7 @@ private predicate callsVariadicFormatter(
or
// calls a variadic formatter with only `formatParamIndex` linked
exists(FunctionCall fc, string calledType, int format, int output |
variadicFormatter(pragma[only_bind_into](fc.getTarget()), calledType, format, output) and
variadicFormatter(fc.getTarget(), calledType, format, output) and
fc.getEnclosingFunction() = f and
fc.getArgument(format) = f.getParameter(formatParamIndex).getAnAccess() and
not fc.getArgument(output) = f.getParameter(_).getAnAccess() and

View File

@@ -46,7 +46,7 @@ predicate nullCheckExpr(Expr checkExpr, Variable var) {
or
exists(LogicalAndExpr op, AnalysedExpr child |
expr = op and
op.getAnOperand() = child and
op.getRightOperand() = child and
nullCheckExpr(child, v)
)
or
@@ -99,7 +99,7 @@ predicate validCheckExpr(Expr checkExpr, Variable var) {
or
exists(LogicalAndExpr op, AnalysedExpr child |
expr = op and
op.getAnOperand() = child and
op.getRightOperand() = child and
validCheckExpr(child, v)
)
or
@@ -169,10 +169,7 @@ class AnalysedExpr extends Expr {
*/
predicate isDef(LocalScopeVariable v) {
this.inCondition() and
(
this.(Assignment).getLValue() = v.getAnAccess() or
this.(ConditionDeclExpr).getVariableAccess() = v.getAnAccess()
)
this.(Assignment).getLValue() = v.getAnAccess()
}
/**

View File

@@ -90,20 +90,14 @@ abstract class Configuration extends string {
/** Holds if data flow out of `node` is prohibited. */
predicate isBarrierOut(Node node) { none() }
/**
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited.
*/
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
predicate isBarrierGuard(BarrierGuard guard) { none() }
/**
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited when
* the flow state is `state`
*/
deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
/**
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
@@ -341,29 +335,6 @@ private predicate outBarrier(NodeEx node, Configuration config) {
)
}
/** A bridge class to access the deprecated `isBarrierGuard`. */
private class BarrierGuardGuardedNodeBridge extends Unit {
abstract predicate guardedNode(Node n, Configuration config);
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
}
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
deprecated override predicate guardedNode(Node n, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
}
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
}
}
pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n |
@@ -377,7 +348,10 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
not config.isSink(n) and
not config.isSink(n, _)
or
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config)
exists(BarrierGuard g |
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
)
}
@@ -386,7 +360,10 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
exists(Node n | node.asNode() = n |
config.isBarrier(n, state)
or
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config)
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
)
}
@@ -428,7 +405,7 @@ private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
simpleLocalFlowStepExt(n1, n2) and
stepFilter(node1, node2, config)
)
or
@@ -447,7 +424,7 @@ private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configurat
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
config.isAdditionalFlowStep(n1, n2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config)
)
@@ -466,7 +443,7 @@ private predicate additionalLocalStateStep(
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and
not stateBarrier(node1, s1, config) and
@@ -481,7 +458,7 @@ private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
jumpStepCached(n1, n2) and
stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
)
@@ -494,7 +471,7 @@ private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration c
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
config.isAdditionalFlowStep(n1, n2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -507,7 +484,7 @@ private predicate additionalJumpStateStep(
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and
not stateBarrier(node1, s1, config) and
@@ -518,7 +495,7 @@ private predicate additionalJumpStateStep(
pragma[nomagic]
private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) {
readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and
readSet(node1.asNode(), c, node2.asNode()) and
stepFilter(node1, node2, config)
or
exists(Node n |
@@ -562,8 +539,7 @@ pragma[nomagic]
private predicate store(
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
) {
store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()),
contentType) and
store(node1.asNode(), tc, node2.asNode(), contentType) and
read(_, tc.getContent(), _, config) and
stepFilter(node1, node2, config)
}
@@ -3878,11 +3854,16 @@ class PathNode extends TPathNode {
/** Gets the associated configuration. */
Configuration getConfiguration() { none() }
private PathNode getASuccessorIfHidden() {
this.(PathNodeImpl).isHidden() and
result = this.(PathNodeImpl).getASuccessorImpl()
}
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() {
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
reach(this) and
reach(result)
result = this.(PathNodeImpl).getASuccessorImpl().getASuccessorIfHidden*() and
not this.(PathNodeImpl).isHidden() and
not result.(PathNodeImpl).isHidden()
}
/** Holds if this node is a source. */
@@ -3890,18 +3871,7 @@ class PathNode extends TPathNode {
}
abstract private class PathNodeImpl extends PathNode {
abstract PathNodeImpl getASuccessorImpl();
private PathNodeImpl getASuccessorIfHidden() {
this.isHidden() and
result = this.getASuccessorImpl()
}
final PathNodeImpl getANonHiddenSuccessor() {
result = this.getASuccessorImpl().getASuccessorIfHidden*() and
not this.isHidden() and
not result.isHidden()
}
abstract PathNode getASuccessorImpl();
abstract NodeEx getNodeEx();
@@ -3944,17 +3914,15 @@ abstract private class PathNodeImpl extends PathNode {
}
/** Holds if `n` can reach a sink. */
private predicate directReach(PathNodeImpl n) {
n instanceof PathNodeSink or directReach(n.getANonHiddenSuccessor())
private predicate directReach(PathNode n) {
n instanceof PathNodeSink or directReach(n.getASuccessor())
}
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
}
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and directReach(n2) }
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
@@ -3963,7 +3931,7 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
*/
module PathGraph {
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b }
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b and reach(a) and reach(b) }
/** Holds if `n` is a node in the graph of data flow path explanations. */
query predicate nodes(PathNode n, string key, string val) {
@@ -4081,7 +4049,7 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink {
override Configuration getConfiguration() { result = config }
override PathNodeImpl getASuccessorImpl() { none() }
override PathNode getASuccessorImpl() { none() }
override predicate isSource() { sourceNode(node, state, config) }
}
@@ -4397,8 +4365,8 @@ private module Subpaths {
}
pragma[nomagic]
private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getANonHiddenSuccessor() and
private predicate hasSuccessor(PathNode pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getASuccessor() and
succNode = succ.getNodeEx()
}
@@ -4407,9 +4375,9 @@ private module Subpaths {
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
* `ret -> out` is summarized as the edge `arg -> out`.
*/
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
pragma[only_bind_into](arg).getASuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
hasSuccessor(pragma[only_bind_into](arg), par, p) and
not ret.isHidden() and
@@ -4422,12 +4390,12 @@ private module Subpaths {
/**
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
*/
predicate retReach(PathNodeImpl n) {
predicate retReach(PathNode n) {
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
or
exists(PathNodeImpl mid |
exists(PathNode mid |
retReach(mid) and
n.getANonHiddenSuccessor() = mid and
n.getASuccessor() = mid and
not subpaths(_, mid, _, _)
)
}

View File

@@ -90,20 +90,14 @@ abstract class Configuration extends string {
/** Holds if data flow out of `node` is prohibited. */
predicate isBarrierOut(Node node) { none() }
/**
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited.
*/
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
predicate isBarrierGuard(BarrierGuard guard) { none() }
/**
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited when
* the flow state is `state`
*/
deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
/**
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
@@ -341,29 +335,6 @@ private predicate outBarrier(NodeEx node, Configuration config) {
)
}
/** A bridge class to access the deprecated `isBarrierGuard`. */
private class BarrierGuardGuardedNodeBridge extends Unit {
abstract predicate guardedNode(Node n, Configuration config);
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
}
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
deprecated override predicate guardedNode(Node n, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
}
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
}
}
pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n |
@@ -377,7 +348,10 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
not config.isSink(n) and
not config.isSink(n, _)
or
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config)
exists(BarrierGuard g |
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
)
}
@@ -386,7 +360,10 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
exists(Node n | node.asNode() = n |
config.isBarrier(n, state)
or
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config)
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
)
}
@@ -428,7 +405,7 @@ private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
simpleLocalFlowStepExt(n1, n2) and
stepFilter(node1, node2, config)
)
or
@@ -447,7 +424,7 @@ private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configurat
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
config.isAdditionalFlowStep(n1, n2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config)
)
@@ -466,7 +443,7 @@ private predicate additionalLocalStateStep(
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and
not stateBarrier(node1, s1, config) and
@@ -481,7 +458,7 @@ private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
jumpStepCached(n1, n2) and
stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
)
@@ -494,7 +471,7 @@ private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration c
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
config.isAdditionalFlowStep(n1, n2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -507,7 +484,7 @@ private predicate additionalJumpStateStep(
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and
not stateBarrier(node1, s1, config) and
@@ -518,7 +495,7 @@ private predicate additionalJumpStateStep(
pragma[nomagic]
private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) {
readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and
readSet(node1.asNode(), c, node2.asNode()) and
stepFilter(node1, node2, config)
or
exists(Node n |
@@ -562,8 +539,7 @@ pragma[nomagic]
private predicate store(
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
) {
store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()),
contentType) and
store(node1.asNode(), tc, node2.asNode(), contentType) and
read(_, tc.getContent(), _, config) and
stepFilter(node1, node2, config)
}
@@ -3878,11 +3854,16 @@ class PathNode extends TPathNode {
/** Gets the associated configuration. */
Configuration getConfiguration() { none() }
private PathNode getASuccessorIfHidden() {
this.(PathNodeImpl).isHidden() and
result = this.(PathNodeImpl).getASuccessorImpl()
}
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() {
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
reach(this) and
reach(result)
result = this.(PathNodeImpl).getASuccessorImpl().getASuccessorIfHidden*() and
not this.(PathNodeImpl).isHidden() and
not result.(PathNodeImpl).isHidden()
}
/** Holds if this node is a source. */
@@ -3890,18 +3871,7 @@ class PathNode extends TPathNode {
}
abstract private class PathNodeImpl extends PathNode {
abstract PathNodeImpl getASuccessorImpl();
private PathNodeImpl getASuccessorIfHidden() {
this.isHidden() and
result = this.getASuccessorImpl()
}
final PathNodeImpl getANonHiddenSuccessor() {
result = this.getASuccessorImpl().getASuccessorIfHidden*() and
not this.isHidden() and
not result.isHidden()
}
abstract PathNode getASuccessorImpl();
abstract NodeEx getNodeEx();
@@ -3944,17 +3914,15 @@ abstract private class PathNodeImpl extends PathNode {
}
/** Holds if `n` can reach a sink. */
private predicate directReach(PathNodeImpl n) {
n instanceof PathNodeSink or directReach(n.getANonHiddenSuccessor())
private predicate directReach(PathNode n) {
n instanceof PathNodeSink or directReach(n.getASuccessor())
}
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
}
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and directReach(n2) }
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
@@ -3963,7 +3931,7 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
*/
module PathGraph {
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b }
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b and reach(a) and reach(b) }
/** Holds if `n` is a node in the graph of data flow path explanations. */
query predicate nodes(PathNode n, string key, string val) {
@@ -4081,7 +4049,7 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink {
override Configuration getConfiguration() { result = config }
override PathNodeImpl getASuccessorImpl() { none() }
override PathNode getASuccessorImpl() { none() }
override predicate isSource() { sourceNode(node, state, config) }
}
@@ -4397,8 +4365,8 @@ private module Subpaths {
}
pragma[nomagic]
private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getANonHiddenSuccessor() and
private predicate hasSuccessor(PathNode pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getASuccessor() and
succNode = succ.getNodeEx()
}
@@ -4407,9 +4375,9 @@ private module Subpaths {
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
* `ret -> out` is summarized as the edge `arg -> out`.
*/
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
pragma[only_bind_into](arg).getASuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
hasSuccessor(pragma[only_bind_into](arg), par, p) and
not ret.isHidden() and
@@ -4422,12 +4390,12 @@ private module Subpaths {
/**
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
*/
predicate retReach(PathNodeImpl n) {
predicate retReach(PathNode n) {
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
or
exists(PathNodeImpl mid |
exists(PathNode mid |
retReach(mid) and
n.getANonHiddenSuccessor() = mid and
n.getASuccessor() = mid and
not subpaths(_, mid, _, _)
)
}

View File

@@ -90,20 +90,14 @@ abstract class Configuration extends string {
/** Holds if data flow out of `node` is prohibited. */
predicate isBarrierOut(Node node) { none() }
/**
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited.
*/
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
predicate isBarrierGuard(BarrierGuard guard) { none() }
/**
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited when
* the flow state is `state`
*/
deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
/**
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
@@ -341,29 +335,6 @@ private predicate outBarrier(NodeEx node, Configuration config) {
)
}
/** A bridge class to access the deprecated `isBarrierGuard`. */
private class BarrierGuardGuardedNodeBridge extends Unit {
abstract predicate guardedNode(Node n, Configuration config);
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
}
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
deprecated override predicate guardedNode(Node n, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
}
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
}
}
pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n |
@@ -377,7 +348,10 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
not config.isSink(n) and
not config.isSink(n, _)
or
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config)
exists(BarrierGuard g |
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
)
}
@@ -386,7 +360,10 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
exists(Node n | node.asNode() = n |
config.isBarrier(n, state)
or
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config)
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
)
}
@@ -428,7 +405,7 @@ private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
simpleLocalFlowStepExt(n1, n2) and
stepFilter(node1, node2, config)
)
or
@@ -447,7 +424,7 @@ private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configurat
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
config.isAdditionalFlowStep(n1, n2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config)
)
@@ -466,7 +443,7 @@ private predicate additionalLocalStateStep(
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and
not stateBarrier(node1, s1, config) and
@@ -481,7 +458,7 @@ private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
jumpStepCached(n1, n2) and
stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
)
@@ -494,7 +471,7 @@ private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration c
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
config.isAdditionalFlowStep(n1, n2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -507,7 +484,7 @@ private predicate additionalJumpStateStep(
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and
not stateBarrier(node1, s1, config) and
@@ -518,7 +495,7 @@ private predicate additionalJumpStateStep(
pragma[nomagic]
private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) {
readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and
readSet(node1.asNode(), c, node2.asNode()) and
stepFilter(node1, node2, config)
or
exists(Node n |
@@ -562,8 +539,7 @@ pragma[nomagic]
private predicate store(
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
) {
store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()),
contentType) and
store(node1.asNode(), tc, node2.asNode(), contentType) and
read(_, tc.getContent(), _, config) and
stepFilter(node1, node2, config)
}
@@ -3878,11 +3854,16 @@ class PathNode extends TPathNode {
/** Gets the associated configuration. */
Configuration getConfiguration() { none() }
private PathNode getASuccessorIfHidden() {
this.(PathNodeImpl).isHidden() and
result = this.(PathNodeImpl).getASuccessorImpl()
}
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() {
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
reach(this) and
reach(result)
result = this.(PathNodeImpl).getASuccessorImpl().getASuccessorIfHidden*() and
not this.(PathNodeImpl).isHidden() and
not result.(PathNodeImpl).isHidden()
}
/** Holds if this node is a source. */
@@ -3890,18 +3871,7 @@ class PathNode extends TPathNode {
}
abstract private class PathNodeImpl extends PathNode {
abstract PathNodeImpl getASuccessorImpl();
private PathNodeImpl getASuccessorIfHidden() {
this.isHidden() and
result = this.getASuccessorImpl()
}
final PathNodeImpl getANonHiddenSuccessor() {
result = this.getASuccessorImpl().getASuccessorIfHidden*() and
not this.isHidden() and
not result.isHidden()
}
abstract PathNode getASuccessorImpl();
abstract NodeEx getNodeEx();
@@ -3944,17 +3914,15 @@ abstract private class PathNodeImpl extends PathNode {
}
/** Holds if `n` can reach a sink. */
private predicate directReach(PathNodeImpl n) {
n instanceof PathNodeSink or directReach(n.getANonHiddenSuccessor())
private predicate directReach(PathNode n) {
n instanceof PathNodeSink or directReach(n.getASuccessor())
}
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
}
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and directReach(n2) }
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
@@ -3963,7 +3931,7 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
*/
module PathGraph {
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b }
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b and reach(a) and reach(b) }
/** Holds if `n` is a node in the graph of data flow path explanations. */
query predicate nodes(PathNode n, string key, string val) {
@@ -4081,7 +4049,7 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink {
override Configuration getConfiguration() { result = config }
override PathNodeImpl getASuccessorImpl() { none() }
override PathNode getASuccessorImpl() { none() }
override predicate isSource() { sourceNode(node, state, config) }
}
@@ -4397,8 +4365,8 @@ private module Subpaths {
}
pragma[nomagic]
private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getANonHiddenSuccessor() and
private predicate hasSuccessor(PathNode pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getASuccessor() and
succNode = succ.getNodeEx()
}
@@ -4407,9 +4375,9 @@ private module Subpaths {
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
* `ret -> out` is summarized as the edge `arg -> out`.
*/
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
pragma[only_bind_into](arg).getASuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
hasSuccessor(pragma[only_bind_into](arg), par, p) and
not ret.isHidden() and
@@ -4422,12 +4390,12 @@ private module Subpaths {
/**
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
*/
predicate retReach(PathNodeImpl n) {
predicate retReach(PathNode n) {
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
or
exists(PathNodeImpl mid |
exists(PathNode mid |
retReach(mid) and
n.getANonHiddenSuccessor() = mid and
n.getASuccessor() = mid and
not subpaths(_, mid, _, _)
)
}

View File

@@ -90,20 +90,14 @@ abstract class Configuration extends string {
/** Holds if data flow out of `node` is prohibited. */
predicate isBarrierOut(Node node) { none() }
/**
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited.
*/
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
predicate isBarrierGuard(BarrierGuard guard) { none() }
/**
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited when
* the flow state is `state`
*/
deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
/**
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
@@ -341,29 +335,6 @@ private predicate outBarrier(NodeEx node, Configuration config) {
)
}
/** A bridge class to access the deprecated `isBarrierGuard`. */
private class BarrierGuardGuardedNodeBridge extends Unit {
abstract predicate guardedNode(Node n, Configuration config);
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
}
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
deprecated override predicate guardedNode(Node n, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
}
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
}
}
pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n |
@@ -377,7 +348,10 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
not config.isSink(n) and
not config.isSink(n, _)
or
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config)
exists(BarrierGuard g |
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
)
}
@@ -386,7 +360,10 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
exists(Node n | node.asNode() = n |
config.isBarrier(n, state)
or
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config)
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
)
}
@@ -428,7 +405,7 @@ private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
simpleLocalFlowStepExt(n1, n2) and
stepFilter(node1, node2, config)
)
or
@@ -447,7 +424,7 @@ private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configurat
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
config.isAdditionalFlowStep(n1, n2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config)
)
@@ -466,7 +443,7 @@ private predicate additionalLocalStateStep(
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and
not stateBarrier(node1, s1, config) and
@@ -481,7 +458,7 @@ private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
jumpStepCached(n1, n2) and
stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
)
@@ -494,7 +471,7 @@ private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration c
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
config.isAdditionalFlowStep(n1, n2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -507,7 +484,7 @@ private predicate additionalJumpStateStep(
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and
not stateBarrier(node1, s1, config) and
@@ -518,7 +495,7 @@ private predicate additionalJumpStateStep(
pragma[nomagic]
private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) {
readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and
readSet(node1.asNode(), c, node2.asNode()) and
stepFilter(node1, node2, config)
or
exists(Node n |
@@ -562,8 +539,7 @@ pragma[nomagic]
private predicate store(
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
) {
store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()),
contentType) and
store(node1.asNode(), tc, node2.asNode(), contentType) and
read(_, tc.getContent(), _, config) and
stepFilter(node1, node2, config)
}
@@ -3878,11 +3854,16 @@ class PathNode extends TPathNode {
/** Gets the associated configuration. */
Configuration getConfiguration() { none() }
private PathNode getASuccessorIfHidden() {
this.(PathNodeImpl).isHidden() and
result = this.(PathNodeImpl).getASuccessorImpl()
}
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() {
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
reach(this) and
reach(result)
result = this.(PathNodeImpl).getASuccessorImpl().getASuccessorIfHidden*() and
not this.(PathNodeImpl).isHidden() and
not result.(PathNodeImpl).isHidden()
}
/** Holds if this node is a source. */
@@ -3890,18 +3871,7 @@ class PathNode extends TPathNode {
}
abstract private class PathNodeImpl extends PathNode {
abstract PathNodeImpl getASuccessorImpl();
private PathNodeImpl getASuccessorIfHidden() {
this.isHidden() and
result = this.getASuccessorImpl()
}
final PathNodeImpl getANonHiddenSuccessor() {
result = this.getASuccessorImpl().getASuccessorIfHidden*() and
not this.isHidden() and
not result.isHidden()
}
abstract PathNode getASuccessorImpl();
abstract NodeEx getNodeEx();
@@ -3944,17 +3914,15 @@ abstract private class PathNodeImpl extends PathNode {
}
/** Holds if `n` can reach a sink. */
private predicate directReach(PathNodeImpl n) {
n instanceof PathNodeSink or directReach(n.getANonHiddenSuccessor())
private predicate directReach(PathNode n) {
n instanceof PathNodeSink or directReach(n.getASuccessor())
}
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
}
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and directReach(n2) }
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
@@ -3963,7 +3931,7 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
*/
module PathGraph {
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b }
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b and reach(a) and reach(b) }
/** Holds if `n` is a node in the graph of data flow path explanations. */
query predicate nodes(PathNode n, string key, string val) {
@@ -4081,7 +4049,7 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink {
override Configuration getConfiguration() { result = config }
override PathNodeImpl getASuccessorImpl() { none() }
override PathNode getASuccessorImpl() { none() }
override predicate isSource() { sourceNode(node, state, config) }
}
@@ -4397,8 +4365,8 @@ private module Subpaths {
}
pragma[nomagic]
private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getANonHiddenSuccessor() and
private predicate hasSuccessor(PathNode pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getASuccessor() and
succNode = succ.getNodeEx()
}
@@ -4407,9 +4375,9 @@ private module Subpaths {
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
* `ret -> out` is summarized as the edge `arg -> out`.
*/
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
pragma[only_bind_into](arg).getASuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
hasSuccessor(pragma[only_bind_into](arg), par, p) and
not ret.isHidden() and
@@ -4422,12 +4390,12 @@ private module Subpaths {
/**
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
*/
predicate retReach(PathNodeImpl n) {
predicate retReach(PathNode n) {
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
or
exists(PathNodeImpl mid |
exists(PathNode mid |
retReach(mid) and
n.getANonHiddenSuccessor() = mid and
n.getASuccessor() = mid and
not subpaths(_, mid, _, _)
)
}

View File

@@ -90,20 +90,14 @@ abstract class Configuration extends string {
/** Holds if data flow out of `node` is prohibited. */
predicate isBarrierOut(Node node) { none() }
/**
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited.
*/
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
predicate isBarrierGuard(BarrierGuard guard) { none() }
/**
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited when
* the flow state is `state`
*/
deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
/**
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
@@ -341,29 +335,6 @@ private predicate outBarrier(NodeEx node, Configuration config) {
)
}
/** A bridge class to access the deprecated `isBarrierGuard`. */
private class BarrierGuardGuardedNodeBridge extends Unit {
abstract predicate guardedNode(Node n, Configuration config);
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
}
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
deprecated override predicate guardedNode(Node n, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
}
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
}
}
pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n |
@@ -377,7 +348,10 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
not config.isSink(n) and
not config.isSink(n, _)
or
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config)
exists(BarrierGuard g |
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
)
}
@@ -386,7 +360,10 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
exists(Node n | node.asNode() = n |
config.isBarrier(n, state)
or
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config)
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
)
}
@@ -428,7 +405,7 @@ private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
simpleLocalFlowStepExt(n1, n2) and
stepFilter(node1, node2, config)
)
or
@@ -447,7 +424,7 @@ private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configurat
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
config.isAdditionalFlowStep(n1, n2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config)
)
@@ -466,7 +443,7 @@ private predicate additionalLocalStateStep(
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and
not stateBarrier(node1, s1, config) and
@@ -481,7 +458,7 @@ private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
jumpStepCached(n1, n2) and
stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
)
@@ -494,7 +471,7 @@ private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration c
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
config.isAdditionalFlowStep(n1, n2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -507,7 +484,7 @@ private predicate additionalJumpStateStep(
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and
not stateBarrier(node1, s1, config) and
@@ -518,7 +495,7 @@ private predicate additionalJumpStateStep(
pragma[nomagic]
private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) {
readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and
readSet(node1.asNode(), c, node2.asNode()) and
stepFilter(node1, node2, config)
or
exists(Node n |
@@ -562,8 +539,7 @@ pragma[nomagic]
private predicate store(
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
) {
store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()),
contentType) and
store(node1.asNode(), tc, node2.asNode(), contentType) and
read(_, tc.getContent(), _, config) and
stepFilter(node1, node2, config)
}
@@ -3878,11 +3854,16 @@ class PathNode extends TPathNode {
/** Gets the associated configuration. */
Configuration getConfiguration() { none() }
private PathNode getASuccessorIfHidden() {
this.(PathNodeImpl).isHidden() and
result = this.(PathNodeImpl).getASuccessorImpl()
}
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() {
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
reach(this) and
reach(result)
result = this.(PathNodeImpl).getASuccessorImpl().getASuccessorIfHidden*() and
not this.(PathNodeImpl).isHidden() and
not result.(PathNodeImpl).isHidden()
}
/** Holds if this node is a source. */
@@ -3890,18 +3871,7 @@ class PathNode extends TPathNode {
}
abstract private class PathNodeImpl extends PathNode {
abstract PathNodeImpl getASuccessorImpl();
private PathNodeImpl getASuccessorIfHidden() {
this.isHidden() and
result = this.getASuccessorImpl()
}
final PathNodeImpl getANonHiddenSuccessor() {
result = this.getASuccessorImpl().getASuccessorIfHidden*() and
not this.isHidden() and
not result.isHidden()
}
abstract PathNode getASuccessorImpl();
abstract NodeEx getNodeEx();
@@ -3944,17 +3914,15 @@ abstract private class PathNodeImpl extends PathNode {
}
/** Holds if `n` can reach a sink. */
private predicate directReach(PathNodeImpl n) {
n instanceof PathNodeSink or directReach(n.getANonHiddenSuccessor())
private predicate directReach(PathNode n) {
n instanceof PathNodeSink or directReach(n.getASuccessor())
}
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
}
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and directReach(n2) }
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
@@ -3963,7 +3931,7 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
*/
module PathGraph {
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b }
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b and reach(a) and reach(b) }
/** Holds if `n` is a node in the graph of data flow path explanations. */
query predicate nodes(PathNode n, string key, string val) {
@@ -4081,7 +4049,7 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink {
override Configuration getConfiguration() { result = config }
override PathNodeImpl getASuccessorImpl() { none() }
override PathNode getASuccessorImpl() { none() }
override predicate isSource() { sourceNode(node, state, config) }
}
@@ -4397,8 +4365,8 @@ private module Subpaths {
}
pragma[nomagic]
private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getANonHiddenSuccessor() and
private predicate hasSuccessor(PathNode pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getASuccessor() and
succNode = succ.getNodeEx()
}
@@ -4407,9 +4375,9 @@ private module Subpaths {
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
* `ret -> out` is summarized as the edge `arg -> out`.
*/
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
pragma[only_bind_into](arg).getASuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
hasSuccessor(pragma[only_bind_into](arg), par, p) and
not ret.isHidden() and
@@ -4422,12 +4390,12 @@ private module Subpaths {
/**
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
*/
predicate retReach(PathNodeImpl n) {
predicate retReach(PathNode n) {
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
or
exists(PathNodeImpl mid |
exists(PathNode mid |
retReach(mid) and
n.getANonHiddenSuccessor() = mid and
n.getASuccessor() = mid and
not subpaths(_, mid, _, _)
)
}

View File

@@ -850,34 +850,6 @@ class ContentSet instanceof Content {
}
/**
* Holds if the guard `g` validates the expression `e` upon evaluating to `branch`.
*
* The expression `e` is expected to be a syntactic part of the guard `g`.
* For example, the guard `g` might be a call `isSafe(x)` and the expression `e`
* the argument `x`.
*/
signature predicate guardChecksSig(GuardCondition g, Expr e, boolean branch);
/**
* Provides a set of barrier nodes for a guard that validates an expression.
*
* This is expected to be used in `isBarrier`/`isSanitizer` definitions
* in data flow and taint tracking.
*/
module BarrierGuard<guardChecksSig/3 guardChecks> {
/** Gets a node that is safely guarded by the given guard check. */
ExprNode getABarrierNode() {
exists(GuardCondition g, SsaDefinition def, Variable v, boolean branch |
result.getExpr() = def.getAUse(v) and
guardChecks(g, def.getAUse(v), branch) and
g.controls(result.getExpr().getBasicBlock(), branch)
)
}
}
/**
* DEPRECATED: Use `BarrierGuard` module instead.
*
* A guard that validates some expression.
*
* To use this in a configuration, extend the class and provide a
@@ -886,7 +858,7 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
*
* It is important that all extending classes in scope are disjoint.
*/
deprecated class BarrierGuard extends GuardCondition {
class BarrierGuard extends GuardCondition {
/** Override this predicate to hold if this guard validates `e` upon evaluating to `b`. */
abstract predicate checks(Expr e, boolean b);

View File

@@ -47,6 +47,12 @@ predicate defaultImplicitTaintRead(DataFlow::Node node, DataFlow::Content c) { n
*/
predicate defaultTaintSanitizer(DataFlow::Node node) { none() }
/**
* Holds if `guard` should be a sanitizer guard in all global taint flow configurations
* but not in local taint.
*/
predicate defaultTaintSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
/**
* Holds if taint can flow in one local step from `nodeFrom` to `nodeTo` excluding
* local data flow steps. That is, `nodeFrom` and `nodeTo` are likely to represent

View File

@@ -116,30 +116,20 @@ abstract class Configuration extends DataFlow::Configuration {
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
/**
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
*
* Holds if taint propagation through nodes guarded by `guard` is prohibited.
*/
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
deprecated final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
this.isSanitizerGuard(guard)
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
this.isSanitizerGuard(guard) or defaultTaintSanitizerGuard(guard)
}
/**
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
*
* Holds if taint propagation through nodes guarded by `guard` is prohibited
* when the flow state is `state`.
*/
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
none()
}
predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { none() }
deprecated final override predicate isBarrierGuard(
DataFlow::BarrierGuard guard, DataFlow::FlowState state
) {
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
this.isSanitizerGuard(guard, state)
}

View File

@@ -116,30 +116,20 @@ abstract class Configuration extends DataFlow::Configuration {
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
/**
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
*
* Holds if taint propagation through nodes guarded by `guard` is prohibited.
*/
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
deprecated final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
this.isSanitizerGuard(guard)
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
this.isSanitizerGuard(guard) or defaultTaintSanitizerGuard(guard)
}
/**
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
*
* Holds if taint propagation through nodes guarded by `guard` is prohibited
* when the flow state is `state`.
*/
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
none()
}
predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { none() }
deprecated final override predicate isBarrierGuard(
DataFlow::BarrierGuard guard, DataFlow::FlowState state
) {
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
this.isSanitizerGuard(guard, state)
}

View File

@@ -1,5 +1,5 @@
/**
* Provides classes for modeling built-in operations. Built-in operations are
* Provides classes for modeling built-in operations. Built-in operations are
* typically compiler specific and are used by libraries and generated code.
*/
@@ -120,8 +120,8 @@ class BuiltInNoOp extends BuiltInOperation, @noopexpr {
/**
* A C/C++ `__builtin_offsetof` built-in operation (used by some implementations
* of `offsetof`). The operation retains its semantics even in the presence
* of an overloaded `operator &`). This is a gcc/clang extension.
* of `offsetof`). The operation retains its semantics even in the presence
* of an overloaded `operator &`). This is a GNU/Clang extension.
* ```
* struct S {
* int a, b;
@@ -137,8 +137,8 @@ class BuiltInOperationBuiltInOffsetOf extends BuiltInOperation, @offsetofexpr {
/**
* A C/C++ `__INTADDR__` built-in operation (used by some implementations
* of `offsetof`). The operation retains its semantics even in the presence
* of an overloaded `operator &`). This is an EDG extension.
* of `offsetof`). The operation retains its semantics even in the presence
* of an overloaded `operator &`). This is an EDG extension.
* ```
* struct S {
* int a, b;
@@ -173,7 +173,7 @@ class BuiltInOperationHasAssign extends BuiltInOperation, @hasassignexpr {
*
* Returns `true` if the type has a copy constructor.
* ```
* std::integral_constant<bool, __has_copy(_Tp)> hc;
* std::integral_constant< bool, __has_copy(_Tp)> hc;
* ```
*/
class BuiltInOperationHasCopy extends BuiltInOperation, @hascopyexpr {
@@ -189,7 +189,7 @@ class BuiltInOperationHasCopy extends BuiltInOperation, @hascopyexpr {
* Returns `true` if a copy assignment operator has an empty exception
* specification.
* ```
* std::integral_constant<bool, __has_nothrow_assign(_Tp)> hnta;
* std::integral_constant< bool, __has_nothrow_assign(_Tp)> hnta;
* ```
*/
class BuiltInOperationHasNoThrowAssign extends BuiltInOperation, @hasnothrowassign {
@@ -220,7 +220,7 @@ class BuiltInOperationHasNoThrowConstructor extends BuiltInOperation, @hasnothro
*
* Returns `true` if the copy constructor has an empty exception specification.
* ```
* std::integral_constant<bool, __has_nothrow_copy(MyType) >;
* std::integral_constant< bool, __has_nothrow_copy(MyType) >;
* ```
*/
class BuiltInOperationHasNoThrowCopy extends BuiltInOperation, @hasnothrowcopy {
@@ -266,7 +266,7 @@ class BuiltInOperationHasTrivialConstructor extends BuiltInOperation, @hastrivia
*
* Returns true if the type has a trivial copy constructor.
* ```
* std::integral_constant<bool, __has_trivial_copy(MyType)> htc;
* std::integral_constant< bool, __has_trivial_copy(MyType) > htc;
* ```
*/
class BuiltInOperationHasTrivialCopy extends BuiltInOperation, @hastrivialcopy {
@@ -468,7 +468,7 @@ class BuiltInOperationIsUnion extends BuiltInOperation, @isunionexpr {
* ```
* template<typename _Tp1, typename _Tp2>
* struct types_compatible
* : public integral_constant<bool, __builtin_types_compatible_p(_Tp1, _Tp2)>
* : public integral_constant<bool, __builtin_types_compatible_p(_Tp1, _Tp2) >
* { };
* ```
*/
@@ -479,7 +479,8 @@ class BuiltInOperationBuiltInTypesCompatibleP extends BuiltInOperation, @typesco
/**
* A clang `__builtin_shufflevector` expression.
*
* It outputs a permutation of elements from one or two input vectors. See
* It outputs a permutation of elements from one or two input vectors.
* Please see
* https://releases.llvm.org/3.7.0/tools/clang/docs/LanguageExtensions.html#langext-builtin-shufflevector
* for more information.
* ```
@@ -493,29 +494,11 @@ class BuiltInOperationBuiltInShuffleVector extends BuiltInOperation, @builtinshu
override string getAPrimaryQlClass() { result = "BuiltInOperationBuiltInShuffleVector" }
}
/**
* A gcc `__builtin_shuffle` expression.
*
* It outputs a permutation of elements from one or two input vectors.
* See https://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html
* for more information.
* ```
* // Concatenate every other element of 4-element vectors V1 and V2.
* M = {0, 2, 4, 6};
* V3 = __builtin_shuffle(V1, V2, M);
* ```
*/
class BuiltInOperationBuiltInShuffle extends BuiltInOperation, @builtinshuffle {
override string toString() { result = "__builtin_shuffle" }
override string getAPrimaryQlClass() { result = "BuiltInOperationBuiltInShuffle" }
}
/**
* A clang `__builtin_convertvector` expression.
*
* Allows for conversion of vectors of equal element count and compatible
* element types. See
* element types. Please see
* https://releases.llvm.org/3.7.0/tools/clang/docs/LanguageExtensions.html#builtin-convertvector
* for more information.
* ```
@@ -564,7 +547,7 @@ class BuiltInOperationBuiltInAddressOf extends UnaryOperation, BuiltInOperation,
* ```
* template<typename T, typename... Args>
* struct is_trivially_constructible
* : public integral_constant<bool, __is_trivially_constructible(T, Args...)>
* : public integral_constant<bool, __is_trivially_constructible(T, Args...) >
* { };
* ```
*/
@@ -629,10 +612,13 @@ class BuiltInOperationIsTriviallyDestructible extends BuiltInOperation, @istrivi
* The `__is_trivially_assignable` built-in operation (used by some
* implementations of the `<type_traits>` header).
*
* Returns `true` if the assignment operator `C::operator =(const D& d)` is
* trivial (i.e., it will not call any operation that is non-trivial).
* Returns `true` if the assignment operator `C::operator =(const C& c)` is
* trivial.
* ```
* bool v = __is_trivially_assignable(MyType1, MyType2);
* template<typename T>
* struct is_trivially_assignable
* : public integral_constant<bool, __is_trivially_assignable(T) >
* { };
* ```
*/
class BuiltInOperationIsTriviallyAssignable extends BuiltInOperation, @istriviallyassignableexpr {
@@ -645,10 +631,10 @@ class BuiltInOperationIsTriviallyAssignable extends BuiltInOperation, @istrivial
* The `__is_nothrow_assignable` built-in operation (used by some
* implementations of the `<type_traits>` header).
*
* Returns true if there exists a `C::operator =(const D& d) nothrow`
* Returns true if there exists a `C::operator =(const C& c) nothrow`
* assignment operator (i.e, with an empty exception specification).
* ```
* bool v = __is_nothrow_assignable(MyType1, MyType2);
* bool v = __is_nothrow_assignable(MyType);
* ```
*/
class BuiltInOperationIsNothrowAssignable extends BuiltInOperation, @isnothrowassignableexpr {
@@ -657,30 +643,15 @@ class BuiltInOperationIsNothrowAssignable extends BuiltInOperation, @isnothrowas
override string getAPrimaryQlClass() { result = "BuiltInOperationIsNothrowAssignable" }
}
/**
* The `__is_assignable` built-in operation (used by some implementations
* of the `<type_traits>` header).
*
* Returns true if there exists a `C::operator =(const D& d)` assignment
* operator.
* ```
* bool v = __is_assignable(MyType1, MyType2);
* ```
*/
class BuiltInOperationIsAssignable extends BuiltInOperation, @isassignable {
override string toString() { result = "__is_assignable" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsAssignable" }
}
/**
* The `__is_standard_layout` built-in operation (used by some implementations
* of the `<type_traits>` header).
*
* Returns `true` if the type is a primitive type, or a `class`, `struct` or
* `union` without (1) virtual functions or base classes, (2) reference member
* variable, or (3) multiple occurrences of base `class` objects, among other
* restrictions. See https://en.cppreference.com/w/cpp/named_req/StandardLayoutType
* `union` WITHOUT (1) virtual functions or base classes, (2) reference member
* variable or (3) multiple occurrences of base `class` objects, among other
* restrictions. Please see
* https://en.cppreference.com/w/cpp/named_req/StandardLayoutType
* for more information.
* ```
* bool v = __is_standard_layout(MyType);
@@ -697,7 +668,7 @@ class BuiltInOperationIsStandardLayout extends BuiltInOperation, @isstandardlayo
* implementations of the `<type_traits>` header).
*
* Returns `true` if instances of this type can be copied by trivial
* means. The copying is done in a manner similar to the `memcpy`
* means. The copying is done in a manner similar to the `memcpy`
* function.
*/
class BuiltInOperationIsTriviallyCopyable extends BuiltInOperation, @istriviallycopyableexpr {
@@ -711,13 +682,13 @@ class BuiltInOperationIsTriviallyCopyable extends BuiltInOperation, @istrivially
* the `<type_traits>` header).
*
* Returns `true` if the type is a scalar type, a reference type or an array of
* literal types, among others. See
* literal types, among others. Please see
* https://en.cppreference.com/w/cpp/named_req/LiteralType
* for more information.
*
* ```
* template <typename _Tp>
* std::integral_constant<bool, __is_literal_type(_Tp)> ilt;
* std::integral_constant< bool, __is_literal_type(_Tp)> ilt;
* ```
*/
class BuiltInOperationIsLiteralType extends BuiltInOperation, @isliteraltypeexpr {
@@ -734,7 +705,7 @@ class BuiltInOperationIsLiteralType extends BuiltInOperation, @isliteraltypeexpr
* compiler, with semantics of the `memcpy` operation.
* ```
* template <typename _Tp>
* std::integral_constant<bool, __has_trivial_move_constructor(_Tp)> htmc;
* std::integral_constant< bool, __has_trivial_move_constructor(_Tp)> htmc;
* ```
*/
class BuiltInOperationHasTrivialMoveConstructor extends BuiltInOperation,
@@ -752,7 +723,7 @@ class BuiltInOperationHasTrivialMoveConstructor extends BuiltInOperation,
* ```
* template<typename T>
* struct has_trivial_move_assign
* : public integral_constant<bool, __has_trivial_move_assign(T)>
* : public integral_constant<bool, __has_trivial_move_assign(T) >
* { };
* ```
*/
@@ -787,7 +758,7 @@ class BuiltInOperationHasNothrowMoveAssign extends BuiltInOperation, @hasnothrow
* ```
* template<typename T, typename... Args>
* struct is_constructible
* : public integral_constant<bool, __is_constructible(T, Args...)>
* : public integral_constant<bool, __is_constructible(T, Args...) >
* { };
* ```
*/
@@ -814,7 +785,7 @@ class BuiltInOperationIsNothrowConstructible extends BuiltInOperation, @isnothro
}
/**
* The `__has_finalizer` built-in operation. This is a Microsoft extension.
* The `__has_finalizer` built-in operation. This is a Microsoft extension.
*
* Returns `true` if the type defines a _finalizer_ `C::!C(void)`, to be called
* from either the regular destructor or the garbage collector.
@@ -829,10 +800,10 @@ class BuiltInOperationHasFinalizer extends BuiltInOperation, @hasfinalizerexpr {
}
/**
* The `__is_delegate` built-in operation. This is a Microsoft extension.
* The `__is_delegate` built-in operation. This is a Microsoft extension.
*
* Returns `true` if the function has been declared as a `delegate`, used in
* message forwarding. See
* message forwarding. Please see
* https://docs.microsoft.com/en-us/cpp/extensions/delegate-cpp-component-extensions
* for more information.
*/
@@ -843,9 +814,9 @@ class BuiltInOperationIsDelegate extends BuiltInOperation, @isdelegateexpr {
}
/**
* The `__is_interface_class` built-in operation. This is a Microsoft extension.
* The `__is_interface_class` built-in operation. This is a Microsoft extension.
*
* Returns `true` if the type has been declared as an `interface`. See
* Returns `true` if the type has been declared as an `interface`. Please see
* https://docs.microsoft.com/en-us/cpp/extensions/interface-class-cpp-component-extensions
* for more information.
*/
@@ -856,9 +827,9 @@ class BuiltInOperationIsInterfaceClass extends BuiltInOperation, @isinterfacecla
}
/**
* The `__is_ref_array` built-in operation. This is a Microsoft extension.
* The `__is_ref_array` built-in operation. This is a Microsoft extension.
*
* Returns `true` if the object passed in is a _platform array_. See
* Returns `true` if the object passed in is a _platform array_. Please see
* https://docs.microsoft.com/en-us/cpp/extensions/arrays-cpp-component-extensions
* for more information.
* ```
@@ -873,9 +844,9 @@ class BuiltInOperationIsRefArray extends BuiltInOperation, @isrefarrayexpr {
}
/**
* The `__is_ref_class` built-in operation. This is a Microsoft extension.
* The `__is_ref_class` built-in operation. This is a Microsoft extension.
*
* Returns `true` if the type is a _reference class_. See
* Returns `true` if the type is a _reference class_. Please see
* https://docs.microsoft.com/en-us/cpp/extensions/classes-and-structs-cpp-component-extensions
* for more information.
* ```
@@ -890,10 +861,10 @@ class BuiltInOperationIsRefClass extends BuiltInOperation, @isrefclassexpr {
}
/**
* The `__is_sealed` built-in operation. This is a Microsoft extension.
* The `__is_sealed` built-in operation. This is a Microsoft extension.
*
* Returns `true` if a given class or virtual function is marked as `sealed`,
* meaning that it cannot be extended or overridden. The `sealed` keyword
* meaning that it cannot be extended or overridden. The `sealed` keyword
* is similar to the C++11 `final` keyword.
* ```
* ref class X sealed {
@@ -908,7 +879,7 @@ class BuiltInOperationIsSealed extends BuiltInOperation, @issealedexpr {
}
/**
* The `__is_simple_value_class` built-in operation. This is a Microsoft extension.
* The `__is_simple_value_class` built-in operation. This is a Microsoft extension.
*
* Returns `true` if passed a value type that contains no references to the
* garbage-collected heap.
@@ -927,9 +898,9 @@ class BuiltInOperationIsSimpleValueClass extends BuiltInOperation, @issimplevalu
}
/**
* The `__is_value_class` built-in operation. This is a Microsoft extension.
* The `__is_value_class` built-in operation. This is a Microsoft extension.
*
* Returns `true` if passed a value type. See
* Returns `true` if passed a value type. Please see
* https://docs.microsoft.com/en-us/cpp/extensions/classes-and-structs-cpp-component-extensions
* For more information.
* ```
@@ -951,7 +922,7 @@ class BuiltInOperationIsValueClass extends BuiltInOperation, @isvalueclassexpr {
* ```
* template<typename T>
* struct is_final
* : public integral_constant<bool, __is_final(T)>
* : public integral_constant<bool, __is_final(T) >
* { };
* ```
*/
@@ -962,7 +933,7 @@ class BuiltInOperationIsFinal extends BuiltInOperation, @isfinalexpr {
}
/**
* The `__builtin_choose_expr` expression. This is a gcc/clang extension.
* The `__builtin_choose_expr` expression. This is a GNU/Clang extension.
*
* The expression functions similarly to the ternary `?:` operator, except
* that it is evaluated at compile-time.
@@ -1007,50 +978,3 @@ class BuiltInComplexOperation extends BuiltInOperation, @builtincomplex {
/** Gets the operand corresponding to the imaginary part of the complex number. */
Expr getImaginaryOperand() { this.hasChild(result, 1) }
}
/**
* A C++ `__is_aggregate` built-in operation (used by some implementations of the
* `<type_traits>` header).
*
* Returns `true` if the type has is an aggregate type.
* ```
* std::integral_constant<bool, __is_aggregate(_Tp)> ia;
* ```
*/
class BuiltInOperationIsAggregate extends BuiltInOperation, @isaggregate {
override string toString() { result = "__is_aggregate" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsAggregate" }
}
/**
* A C++ `__has_unique_object_representations` built-in operation (used by some
* implementations of the `<type_traits>` header).
*
* Returns `true` if the type is trivially copyable and if the object representation
* is unique for two objects with the same value.
* ```
* bool v = __has_unique_object_representations(MyType);
* ```
*/
class BuiltInOperationHasUniqueObjectRepresentations extends BuiltInOperation,
@hasuniqueobjectrepresentations {
override string toString() { result = "__has_unique_object_representations" }
override string getAPrimaryQlClass() { result = "BuiltInOperationHasUniqueObjectRepresentations" }
}
/**
* A C/C++ `__builtin_bit_cast` built-in operation (used by some implementations
* of `std::bit_cast`).
*
* Performs a bit cast from a value to a type.
* ```
* __builtin_bit_cast(Type, value);
* ```
*/
class BuiltInBitCast extends BuiltInOperation, @builtinbitcast {
override string toString() { result = "__builtin_bit_cast" }
override string getAPrimaryQlClass() { result = "BuiltInBitCast" }
}

View File

@@ -255,10 +255,8 @@ class FunctionCall extends Call, @funbindexpr {
/**
* Gets the function called by this call.
*
* In the case of virtual function calls, the result is the most-specific function in the override tree
* such that the target at runtime will be one of `result.getAnOverridingFunction*()`. The most-specific
* function is determined by the compiler based on the compile time type of the object the function is a
* member of.
* In the case of virtual function calls, the result is the most-specific function in the override tree (as
* determined by the compiler) such that the target at runtime will be one of `result.getAnOverridingFunction*()`.
*/
override Function getTarget() { funbind(underlyingElement(this), unresolveElement(result)) }

View File

@@ -49,9 +49,6 @@ class Expr extends StmtParent, @expr {
/** Gets the enclosing variable of this expression, if any. */
Variable getEnclosingVariable() { result = exprEnclosingElement(this) }
/** Gets the enclosing variable or function of this expression. */
Declaration getEnclosingDeclaration() { result = exprEnclosingElement(this) }
/** Gets a child of this expression. */
Expr getAChild() { exists(int n | result = this.getChild(n)) }
@@ -596,12 +593,9 @@ class ParenthesisExpr extends Conversion, @parexpr {
}
/**
* A C/C++ expression that could not be resolved, or that can no longer be
* represented due to a database upgrade or downgrade.
* A C/C++ expression that has not been resolved.
*
* If the expression could not be resolved, it has type `ErroneousType`. In the
* case of a database upgrade or downgrade, the original type from before the
* upgrade or downgrade is kept if that type can be represented.
* It is assigned `ErroneousType` as its type.
*/
class ErrorExpr extends Expr, @errorexpr {
override string toString() { result = "<error expr>" }

View File

@@ -4,7 +4,11 @@
* qualified.
*
* This file contains classes that mirror the standard AST classes for C++, but
* these classes are only concerned with naming.
* these classes are only concerned with naming. The other difference is that
* these classes don't use the `ResolveClass.qll` mechanisms like
* `unresolveElement` because these classes should eventually be part of the
* implementation of `ResolveClass.qll`, allowing it to match up classes when
* their qualified names and parameters match.
*/
private import semmle.code.cpp.Declaration as D

View File

@@ -115,13 +115,15 @@ private module Cached {
*/
cached
predicate isClass(@usertype t) {
usertypes(t, _, 1) or
usertypes(t, _, 2) or
usertypes(t, _, 3) or
usertypes(t, _, 6) or
usertypes(t, _, 10) or
usertypes(t, _, 11) or
usertypes(t, _, 12)
(
usertypes(t, _, 1) or
usertypes(t, _, 2) or
usertypes(t, _, 3) or
usertypes(t, _, 6) or
usertypes(t, _, 10) or
usertypes(t, _, 11) or
usertypes(t, _, 12)
)
}
cached

View File

@@ -1,57 +0,0 @@
private predicate hasDefinition(@globalvariable g) {
exists(@var_decl vd | var_decls(vd, g, _, _, _) | var_def(vd))
}
private predicate onlyOneCompleteGlobalVariableExistsWithMangledName(@mangledname name) {
strictcount(@globalvariable g | hasDefinition(g) and mangled_name(g, name)) = 1
}
/** Holds if `g` is a unique global variable with a definition named `name`. */
private predicate isGlobalWithMangledNameAndWithDefinition(@mangledname name, @globalvariable g) {
hasDefinition(g) and
mangled_name(g, name) and
onlyOneCompleteGlobalVariableExistsWithMangledName(name)
}
/** Holds if `g` is a global variable without a definition named `name`. */
private predicate isGlobalWithMangledNameAndWithoutDefinition(@mangledname name, @globalvariable g) {
not hasDefinition(g) and
mangled_name(g, name)
}
/**
* Holds if `incomplete` is a global variable without a definition, and there exists
* a unique global variable `complete` with the same name that does have a definition.
*/
private predicate hasTwinWithDefinition(@globalvariable incomplete, @globalvariable complete) {
exists(@mangledname name |
not variable_instantiation(incomplete, complete) and
isGlobalWithMangledNameAndWithoutDefinition(name, incomplete) and
isGlobalWithMangledNameAndWithDefinition(name, complete)
)
}
import Cached
cached
private module Cached {
/**
* If `v` is a global variable without a definition, and there exists a unique
* global variable with the same name that does have a definition, then the
* result is that unique global variable. Otherwise, the result is `v`.
*/
cached
@variable resolveGlobalVariable(@variable v) {
hasTwinWithDefinition(v, result)
or
not hasTwinWithDefinition(v, _) and
result = v
}
cached
predicate isVariable(@variable v) {
not v instanceof @globalvariable
or
v = resolveGlobalVariable(_)
}
}

View File

@@ -90,20 +90,14 @@ abstract class Configuration extends string {
/** Holds if data flow out of `node` is prohibited. */
predicate isBarrierOut(Node node) { none() }
/**
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited.
*/
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
predicate isBarrierGuard(BarrierGuard guard) { none() }
/**
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited when
* the flow state is `state`
*/
deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
/**
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
@@ -341,29 +335,6 @@ private predicate outBarrier(NodeEx node, Configuration config) {
)
}
/** A bridge class to access the deprecated `isBarrierGuard`. */
private class BarrierGuardGuardedNodeBridge extends Unit {
abstract predicate guardedNode(Node n, Configuration config);
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
}
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
deprecated override predicate guardedNode(Node n, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
}
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
}
}
pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n |
@@ -377,7 +348,10 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
not config.isSink(n) and
not config.isSink(n, _)
or
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config)
exists(BarrierGuard g |
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
)
}
@@ -386,7 +360,10 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
exists(Node n | node.asNode() = n |
config.isBarrier(n, state)
or
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config)
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
)
}
@@ -428,7 +405,7 @@ private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
simpleLocalFlowStepExt(n1, n2) and
stepFilter(node1, node2, config)
)
or
@@ -447,7 +424,7 @@ private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configurat
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
config.isAdditionalFlowStep(n1, n2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config)
)
@@ -466,7 +443,7 @@ private predicate additionalLocalStateStep(
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and
not stateBarrier(node1, s1, config) and
@@ -481,7 +458,7 @@ private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
jumpStepCached(n1, n2) and
stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
)
@@ -494,7 +471,7 @@ private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration c
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
config.isAdditionalFlowStep(n1, n2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -507,7 +484,7 @@ private predicate additionalJumpStateStep(
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and
not stateBarrier(node1, s1, config) and
@@ -518,7 +495,7 @@ private predicate additionalJumpStateStep(
pragma[nomagic]
private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) {
readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and
readSet(node1.asNode(), c, node2.asNode()) and
stepFilter(node1, node2, config)
or
exists(Node n |
@@ -562,8 +539,7 @@ pragma[nomagic]
private predicate store(
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
) {
store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()),
contentType) and
store(node1.asNode(), tc, node2.asNode(), contentType) and
read(_, tc.getContent(), _, config) and
stepFilter(node1, node2, config)
}
@@ -3878,11 +3854,16 @@ class PathNode extends TPathNode {
/** Gets the associated configuration. */
Configuration getConfiguration() { none() }
private PathNode getASuccessorIfHidden() {
this.(PathNodeImpl).isHidden() and
result = this.(PathNodeImpl).getASuccessorImpl()
}
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() {
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
reach(this) and
reach(result)
result = this.(PathNodeImpl).getASuccessorImpl().getASuccessorIfHidden*() and
not this.(PathNodeImpl).isHidden() and
not result.(PathNodeImpl).isHidden()
}
/** Holds if this node is a source. */
@@ -3890,18 +3871,7 @@ class PathNode extends TPathNode {
}
abstract private class PathNodeImpl extends PathNode {
abstract PathNodeImpl getASuccessorImpl();
private PathNodeImpl getASuccessorIfHidden() {
this.isHidden() and
result = this.getASuccessorImpl()
}
final PathNodeImpl getANonHiddenSuccessor() {
result = this.getASuccessorImpl().getASuccessorIfHidden*() and
not this.isHidden() and
not result.isHidden()
}
abstract PathNode getASuccessorImpl();
abstract NodeEx getNodeEx();
@@ -3944,17 +3914,15 @@ abstract private class PathNodeImpl extends PathNode {
}
/** Holds if `n` can reach a sink. */
private predicate directReach(PathNodeImpl n) {
n instanceof PathNodeSink or directReach(n.getANonHiddenSuccessor())
private predicate directReach(PathNode n) {
n instanceof PathNodeSink or directReach(n.getASuccessor())
}
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
}
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and directReach(n2) }
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
@@ -3963,7 +3931,7 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
*/
module PathGraph {
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b }
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b and reach(a) and reach(b) }
/** Holds if `n` is a node in the graph of data flow path explanations. */
query predicate nodes(PathNode n, string key, string val) {
@@ -4081,7 +4049,7 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink {
override Configuration getConfiguration() { result = config }
override PathNodeImpl getASuccessorImpl() { none() }
override PathNode getASuccessorImpl() { none() }
override predicate isSource() { sourceNode(node, state, config) }
}
@@ -4397,8 +4365,8 @@ private module Subpaths {
}
pragma[nomagic]
private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getANonHiddenSuccessor() and
private predicate hasSuccessor(PathNode pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getASuccessor() and
succNode = succ.getNodeEx()
}
@@ -4407,9 +4375,9 @@ private module Subpaths {
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
* `ret -> out` is summarized as the edge `arg -> out`.
*/
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
pragma[only_bind_into](arg).getASuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
hasSuccessor(pragma[only_bind_into](arg), par, p) and
not ret.isHidden() and
@@ -4422,12 +4390,12 @@ private module Subpaths {
/**
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
*/
predicate retReach(PathNodeImpl n) {
predicate retReach(PathNode n) {
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
or
exists(PathNodeImpl mid |
exists(PathNode mid |
retReach(mid) and
n.getANonHiddenSuccessor() = mid and
n.getASuccessor() = mid and
not subpaths(_, mid, _, _)
)
}

View File

@@ -90,20 +90,14 @@ abstract class Configuration extends string {
/** Holds if data flow out of `node` is prohibited. */
predicate isBarrierOut(Node node) { none() }
/**
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited.
*/
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
predicate isBarrierGuard(BarrierGuard guard) { none() }
/**
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited when
* the flow state is `state`
*/
deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
/**
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
@@ -341,29 +335,6 @@ private predicate outBarrier(NodeEx node, Configuration config) {
)
}
/** A bridge class to access the deprecated `isBarrierGuard`. */
private class BarrierGuardGuardedNodeBridge extends Unit {
abstract predicate guardedNode(Node n, Configuration config);
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
}
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
deprecated override predicate guardedNode(Node n, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
}
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
}
}
pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n |
@@ -377,7 +348,10 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
not config.isSink(n) and
not config.isSink(n, _)
or
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config)
exists(BarrierGuard g |
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
)
}
@@ -386,7 +360,10 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
exists(Node n | node.asNode() = n |
config.isBarrier(n, state)
or
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config)
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
)
}
@@ -428,7 +405,7 @@ private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
simpleLocalFlowStepExt(n1, n2) and
stepFilter(node1, node2, config)
)
or
@@ -447,7 +424,7 @@ private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configurat
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
config.isAdditionalFlowStep(n1, n2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config)
)
@@ -466,7 +443,7 @@ private predicate additionalLocalStateStep(
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and
not stateBarrier(node1, s1, config) and
@@ -481,7 +458,7 @@ private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
jumpStepCached(n1, n2) and
stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
)
@@ -494,7 +471,7 @@ private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration c
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
config.isAdditionalFlowStep(n1, n2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -507,7 +484,7 @@ private predicate additionalJumpStateStep(
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and
not stateBarrier(node1, s1, config) and
@@ -518,7 +495,7 @@ private predicate additionalJumpStateStep(
pragma[nomagic]
private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) {
readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and
readSet(node1.asNode(), c, node2.asNode()) and
stepFilter(node1, node2, config)
or
exists(Node n |
@@ -562,8 +539,7 @@ pragma[nomagic]
private predicate store(
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
) {
store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()),
contentType) and
store(node1.asNode(), tc, node2.asNode(), contentType) and
read(_, tc.getContent(), _, config) and
stepFilter(node1, node2, config)
}
@@ -3878,11 +3854,16 @@ class PathNode extends TPathNode {
/** Gets the associated configuration. */
Configuration getConfiguration() { none() }
private PathNode getASuccessorIfHidden() {
this.(PathNodeImpl).isHidden() and
result = this.(PathNodeImpl).getASuccessorImpl()
}
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() {
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
reach(this) and
reach(result)
result = this.(PathNodeImpl).getASuccessorImpl().getASuccessorIfHidden*() and
not this.(PathNodeImpl).isHidden() and
not result.(PathNodeImpl).isHidden()
}
/** Holds if this node is a source. */
@@ -3890,18 +3871,7 @@ class PathNode extends TPathNode {
}
abstract private class PathNodeImpl extends PathNode {
abstract PathNodeImpl getASuccessorImpl();
private PathNodeImpl getASuccessorIfHidden() {
this.isHidden() and
result = this.getASuccessorImpl()
}
final PathNodeImpl getANonHiddenSuccessor() {
result = this.getASuccessorImpl().getASuccessorIfHidden*() and
not this.isHidden() and
not result.isHidden()
}
abstract PathNode getASuccessorImpl();
abstract NodeEx getNodeEx();
@@ -3944,17 +3914,15 @@ abstract private class PathNodeImpl extends PathNode {
}
/** Holds if `n` can reach a sink. */
private predicate directReach(PathNodeImpl n) {
n instanceof PathNodeSink or directReach(n.getANonHiddenSuccessor())
private predicate directReach(PathNode n) {
n instanceof PathNodeSink or directReach(n.getASuccessor())
}
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
}
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and directReach(n2) }
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
@@ -3963,7 +3931,7 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
*/
module PathGraph {
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b }
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b and reach(a) and reach(b) }
/** Holds if `n` is a node in the graph of data flow path explanations. */
query predicate nodes(PathNode n, string key, string val) {
@@ -4081,7 +4049,7 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink {
override Configuration getConfiguration() { result = config }
override PathNodeImpl getASuccessorImpl() { none() }
override PathNode getASuccessorImpl() { none() }
override predicate isSource() { sourceNode(node, state, config) }
}
@@ -4397,8 +4365,8 @@ private module Subpaths {
}
pragma[nomagic]
private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getANonHiddenSuccessor() and
private predicate hasSuccessor(PathNode pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getASuccessor() and
succNode = succ.getNodeEx()
}
@@ -4407,9 +4375,9 @@ private module Subpaths {
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
* `ret -> out` is summarized as the edge `arg -> out`.
*/
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
pragma[only_bind_into](arg).getASuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
hasSuccessor(pragma[only_bind_into](arg), par, p) and
not ret.isHidden() and
@@ -4422,12 +4390,12 @@ private module Subpaths {
/**
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
*/
predicate retReach(PathNodeImpl n) {
predicate retReach(PathNode n) {
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
or
exists(PathNodeImpl mid |
exists(PathNode mid |
retReach(mid) and
n.getANonHiddenSuccessor() = mid and
n.getASuccessor() = mid and
not subpaths(_, mid, _, _)
)
}

View File

@@ -90,20 +90,14 @@ abstract class Configuration extends string {
/** Holds if data flow out of `node` is prohibited. */
predicate isBarrierOut(Node node) { none() }
/**
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited.
*/
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
predicate isBarrierGuard(BarrierGuard guard) { none() }
/**
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited when
* the flow state is `state`
*/
deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
/**
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
@@ -341,29 +335,6 @@ private predicate outBarrier(NodeEx node, Configuration config) {
)
}
/** A bridge class to access the deprecated `isBarrierGuard`. */
private class BarrierGuardGuardedNodeBridge extends Unit {
abstract predicate guardedNode(Node n, Configuration config);
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
}
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
deprecated override predicate guardedNode(Node n, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
}
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
}
}
pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n |
@@ -377,7 +348,10 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
not config.isSink(n) and
not config.isSink(n, _)
or
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config)
exists(BarrierGuard g |
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
)
}
@@ -386,7 +360,10 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
exists(Node n | node.asNode() = n |
config.isBarrier(n, state)
or
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config)
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
)
}
@@ -428,7 +405,7 @@ private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
simpleLocalFlowStepExt(n1, n2) and
stepFilter(node1, node2, config)
)
or
@@ -447,7 +424,7 @@ private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configurat
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
config.isAdditionalFlowStep(n1, n2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config)
)
@@ -466,7 +443,7 @@ private predicate additionalLocalStateStep(
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and
not stateBarrier(node1, s1, config) and
@@ -481,7 +458,7 @@ private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
jumpStepCached(n1, n2) and
stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
)
@@ -494,7 +471,7 @@ private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration c
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
config.isAdditionalFlowStep(n1, n2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -507,7 +484,7 @@ private predicate additionalJumpStateStep(
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and
not stateBarrier(node1, s1, config) and
@@ -518,7 +495,7 @@ private predicate additionalJumpStateStep(
pragma[nomagic]
private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) {
readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and
readSet(node1.asNode(), c, node2.asNode()) and
stepFilter(node1, node2, config)
or
exists(Node n |
@@ -562,8 +539,7 @@ pragma[nomagic]
private predicate store(
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
) {
store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()),
contentType) and
store(node1.asNode(), tc, node2.asNode(), contentType) and
read(_, tc.getContent(), _, config) and
stepFilter(node1, node2, config)
}
@@ -3878,11 +3854,16 @@ class PathNode extends TPathNode {
/** Gets the associated configuration. */
Configuration getConfiguration() { none() }
private PathNode getASuccessorIfHidden() {
this.(PathNodeImpl).isHidden() and
result = this.(PathNodeImpl).getASuccessorImpl()
}
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() {
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
reach(this) and
reach(result)
result = this.(PathNodeImpl).getASuccessorImpl().getASuccessorIfHidden*() and
not this.(PathNodeImpl).isHidden() and
not result.(PathNodeImpl).isHidden()
}
/** Holds if this node is a source. */
@@ -3890,18 +3871,7 @@ class PathNode extends TPathNode {
}
abstract private class PathNodeImpl extends PathNode {
abstract PathNodeImpl getASuccessorImpl();
private PathNodeImpl getASuccessorIfHidden() {
this.isHidden() and
result = this.getASuccessorImpl()
}
final PathNodeImpl getANonHiddenSuccessor() {
result = this.getASuccessorImpl().getASuccessorIfHidden*() and
not this.isHidden() and
not result.isHidden()
}
abstract PathNode getASuccessorImpl();
abstract NodeEx getNodeEx();
@@ -3944,17 +3914,15 @@ abstract private class PathNodeImpl extends PathNode {
}
/** Holds if `n` can reach a sink. */
private predicate directReach(PathNodeImpl n) {
n instanceof PathNodeSink or directReach(n.getANonHiddenSuccessor())
private predicate directReach(PathNode n) {
n instanceof PathNodeSink or directReach(n.getASuccessor())
}
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
}
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and directReach(n2) }
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
@@ -3963,7 +3931,7 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
*/
module PathGraph {
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b }
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b and reach(a) and reach(b) }
/** Holds if `n` is a node in the graph of data flow path explanations. */
query predicate nodes(PathNode n, string key, string val) {
@@ -4081,7 +4049,7 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink {
override Configuration getConfiguration() { result = config }
override PathNodeImpl getASuccessorImpl() { none() }
override PathNode getASuccessorImpl() { none() }
override predicate isSource() { sourceNode(node, state, config) }
}
@@ -4397,8 +4365,8 @@ private module Subpaths {
}
pragma[nomagic]
private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getANonHiddenSuccessor() and
private predicate hasSuccessor(PathNode pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getASuccessor() and
succNode = succ.getNodeEx()
}
@@ -4407,9 +4375,9 @@ private module Subpaths {
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
* `ret -> out` is summarized as the edge `arg -> out`.
*/
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
pragma[only_bind_into](arg).getASuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
hasSuccessor(pragma[only_bind_into](arg), par, p) and
not ret.isHidden() and
@@ -4422,12 +4390,12 @@ private module Subpaths {
/**
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
*/
predicate retReach(PathNodeImpl n) {
predicate retReach(PathNode n) {
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
or
exists(PathNodeImpl mid |
exists(PathNode mid |
retReach(mid) and
n.getANonHiddenSuccessor() = mid and
n.getASuccessor() = mid and
not subpaths(_, mid, _, _)
)
}

View File

@@ -90,20 +90,14 @@ abstract class Configuration extends string {
/** Holds if data flow out of `node` is prohibited. */
predicate isBarrierOut(Node node) { none() }
/**
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited.
*/
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
predicate isBarrierGuard(BarrierGuard guard) { none() }
/**
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited when
* the flow state is `state`
*/
deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
/**
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
@@ -341,29 +335,6 @@ private predicate outBarrier(NodeEx node, Configuration config) {
)
}
/** A bridge class to access the deprecated `isBarrierGuard`. */
private class BarrierGuardGuardedNodeBridge extends Unit {
abstract predicate guardedNode(Node n, Configuration config);
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
}
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
deprecated override predicate guardedNode(Node n, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
}
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
}
}
pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n |
@@ -377,7 +348,10 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
not config.isSink(n) and
not config.isSink(n, _)
or
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config)
exists(BarrierGuard g |
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
)
}
@@ -386,7 +360,10 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
exists(Node n | node.asNode() = n |
config.isBarrier(n, state)
or
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config)
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
)
}
@@ -428,7 +405,7 @@ private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
simpleLocalFlowStepExt(n1, n2) and
stepFilter(node1, node2, config)
)
or
@@ -447,7 +424,7 @@ private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configurat
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
config.isAdditionalFlowStep(n1, n2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config)
)
@@ -466,7 +443,7 @@ private predicate additionalLocalStateStep(
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and
not stateBarrier(node1, s1, config) and
@@ -481,7 +458,7 @@ private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
jumpStepCached(n1, n2) and
stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
)
@@ -494,7 +471,7 @@ private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration c
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
config.isAdditionalFlowStep(n1, n2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -507,7 +484,7 @@ private predicate additionalJumpStateStep(
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and
not stateBarrier(node1, s1, config) and
@@ -518,7 +495,7 @@ private predicate additionalJumpStateStep(
pragma[nomagic]
private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) {
readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and
readSet(node1.asNode(), c, node2.asNode()) and
stepFilter(node1, node2, config)
or
exists(Node n |
@@ -562,8 +539,7 @@ pragma[nomagic]
private predicate store(
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
) {
store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()),
contentType) and
store(node1.asNode(), tc, node2.asNode(), contentType) and
read(_, tc.getContent(), _, config) and
stepFilter(node1, node2, config)
}
@@ -3878,11 +3854,16 @@ class PathNode extends TPathNode {
/** Gets the associated configuration. */
Configuration getConfiguration() { none() }
private PathNode getASuccessorIfHidden() {
this.(PathNodeImpl).isHidden() and
result = this.(PathNodeImpl).getASuccessorImpl()
}
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() {
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
reach(this) and
reach(result)
result = this.(PathNodeImpl).getASuccessorImpl().getASuccessorIfHidden*() and
not this.(PathNodeImpl).isHidden() and
not result.(PathNodeImpl).isHidden()
}
/** Holds if this node is a source. */
@@ -3890,18 +3871,7 @@ class PathNode extends TPathNode {
}
abstract private class PathNodeImpl extends PathNode {
abstract PathNodeImpl getASuccessorImpl();
private PathNodeImpl getASuccessorIfHidden() {
this.isHidden() and
result = this.getASuccessorImpl()
}
final PathNodeImpl getANonHiddenSuccessor() {
result = this.getASuccessorImpl().getASuccessorIfHidden*() and
not this.isHidden() and
not result.isHidden()
}
abstract PathNode getASuccessorImpl();
abstract NodeEx getNodeEx();
@@ -3944,17 +3914,15 @@ abstract private class PathNodeImpl extends PathNode {
}
/** Holds if `n` can reach a sink. */
private predicate directReach(PathNodeImpl n) {
n instanceof PathNodeSink or directReach(n.getANonHiddenSuccessor())
private predicate directReach(PathNode n) {
n instanceof PathNodeSink or directReach(n.getASuccessor())
}
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
}
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and directReach(n2) }
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
@@ -3963,7 +3931,7 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
*/
module PathGraph {
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b }
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b and reach(a) and reach(b) }
/** Holds if `n` is a node in the graph of data flow path explanations. */
query predicate nodes(PathNode n, string key, string val) {
@@ -4081,7 +4049,7 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink {
override Configuration getConfiguration() { result = config }
override PathNodeImpl getASuccessorImpl() { none() }
override PathNode getASuccessorImpl() { none() }
override predicate isSource() { sourceNode(node, state, config) }
}
@@ -4397,8 +4365,8 @@ private module Subpaths {
}
pragma[nomagic]
private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getANonHiddenSuccessor() and
private predicate hasSuccessor(PathNode pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getASuccessor() and
succNode = succ.getNodeEx()
}
@@ -4407,9 +4375,9 @@ private module Subpaths {
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
* `ret -> out` is summarized as the edge `arg -> out`.
*/
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
pragma[only_bind_into](arg).getASuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
hasSuccessor(pragma[only_bind_into](arg), par, p) and
not ret.isHidden() and
@@ -4422,12 +4390,12 @@ private module Subpaths {
/**
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
*/
predicate retReach(PathNodeImpl n) {
predicate retReach(PathNode n) {
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
or
exists(PathNodeImpl mid |
exists(PathNode mid |
retReach(mid) and
n.getANonHiddenSuccessor() = mid and
n.getASuccessor() = mid and
not subpaths(_, mid, _, _)
)
}

View File

@@ -100,7 +100,7 @@ class Node extends TIRDataFlowNode {
Declaration getEnclosingCallable() { none() } // overridden in subclasses
/** Gets the function to which this node belongs, if any. */
Declaration getFunction() { none() } // overridden in subclasses
Function getFunction() { none() } // overridden in subclasses
/** Gets the type of this node. */
IRType getType() { none() } // overridden in subclasses
@@ -196,7 +196,7 @@ class InstructionNode extends Node, TInstructionNode {
override Declaration getEnclosingCallable() { result = this.getFunction() }
override Declaration getFunction() { result = instr.getEnclosingFunction() }
override Function getFunction() { result = instr.getEnclosingFunction() }
override IRType getType() { result = instr.getResultIRType() }
@@ -222,7 +222,7 @@ class OperandNode extends Node, TOperandNode {
override Declaration getEnclosingCallable() { result = this.getFunction() }
override Declaration getFunction() { result = op.getUse().getEnclosingFunction() }
override Function getFunction() { result = op.getUse().getEnclosingFunction() }
override IRType getType() { result = op.getIRType() }
@@ -274,7 +274,7 @@ class StoreNodeInstr extends StoreNode, TStoreNodeInstr {
/** Gets the underlying instruction. */
Instruction getInstruction() { result = instr }
override Declaration getFunction() { result = this.getInstruction().getEnclosingFunction() }
override Function getFunction() { result = this.getInstruction().getEnclosingFunction() }
override IRType getType() { result = this.getInstruction().getResultIRType() }
@@ -328,7 +328,7 @@ class StoreNodeOperand extends StoreNode, TStoreNodeOperand {
/** Gets the underlying operand. */
Operand getOperand() { result = operand }
override Declaration getFunction() { result = operand.getDef().getEnclosingFunction() }
override Function getFunction() { result = operand.getDef().getEnclosingFunction() }
override IRType getType() { result = operand.getIRType() }
@@ -384,7 +384,7 @@ class ReadNode extends Node, TReadNode {
override Declaration getEnclosingCallable() { result = this.getFunction() }
override Declaration getFunction() { result = this.getInstruction().getEnclosingFunction() }
override Function getFunction() { result = this.getInstruction().getEnclosingFunction() }
override IRType getType() { result = this.getInstruction().getResultIRType() }
@@ -436,7 +436,7 @@ class SsaPhiNode extends Node, TSsaPhiNode {
override Declaration getEnclosingCallable() { result = this.getFunction() }
override Declaration getFunction() { result = phi.getBasicBlock().getEnclosingFunction() }
override Function getFunction() { result = phi.getBasicBlock().getEnclosingFunction() }
override IRType getType() { result instanceof IRVoidType }
@@ -673,7 +673,7 @@ class VariableNode extends Node, TVariableNode {
/** Gets the variable corresponding to this node. */
Variable getVariable() { result = v }
override Declaration getFunction() { none() }
override Function getFunction() { none() }
override Declaration getEnclosingCallable() {
// When flow crosses from one _enclosing callable_ to another, the
@@ -1092,56 +1092,6 @@ class ContentSet instanceof Content {
}
/**
* Holds if the guard `g` validates the expression `e` upon evaluating to `branch`.
*
* The expression `e` is expected to be a syntactic part of the guard `g`.
* For example, the guard `g` might be a call `isSafe(x)` and the expression `e`
* the argument `x`.
*/
signature predicate guardChecksSig(IRGuardCondition g, Expr e, boolean branch);
/**
* Provides a set of barrier nodes for a guard that validates an expression.
*
* This is expected to be used in `isBarrier`/`isSanitizer` definitions
* in data flow and taint tracking.
*/
module BarrierGuard<guardChecksSig/3 guardChecks> {
/** Gets a node that is safely guarded by the given guard check. */
ExprNode getABarrierNode() {
exists(IRGuardCondition g, ValueNumber value, boolean edge |
guardChecks(g, value.getAnInstruction().getConvertedResultExpression(), edge) and
result.asInstruction() = value.getAnInstruction() and
g.controls(result.asInstruction().getBlock(), edge)
)
}
}
/**
* Holds if the guard `g` validates the instruction `instr` upon evaluating to `branch`.
*/
signature predicate instructionGuardChecksSig(IRGuardCondition g, Instruction instr, boolean branch);
/**
* Provides a set of barrier nodes for a guard that validates an instruction.
*
* This is expected to be used in `isBarrier`/`isSanitizer` definitions
* in data flow and taint tracking.
*/
module InstructionBarrierGuard<instructionGuardChecksSig/3 instructionGuardChecks> {
/** Gets a node that is safely guarded by the given guard check. */
ExprNode getABarrierNode() {
exists(IRGuardCondition g, ValueNumber value, boolean edge |
instructionGuardChecks(g, value.getAnInstruction(), edge) and
result.asInstruction() = value.getAnInstruction() and
g.controls(result.asInstruction().getBlock(), edge)
)
}
}
/**
* DEPRECATED: Use `BarrierGuard` module instead.
*
* A guard that validates some instruction.
*
* To use this in a configuration, extend the class and provide a
@@ -1150,7 +1100,7 @@ module InstructionBarrierGuard<instructionGuardChecksSig/3 instructionGuardCheck
*
* It is important that all extending classes in scope are disjoint.
*/
deprecated class BarrierGuard extends IRGuardCondition {
class BarrierGuard extends IRGuardCondition {
/** Override this predicate to hold if this guard validates `instr` upon evaluating to `b`. */
predicate checksInstr(Instruction instr, boolean b) { none() }

View File

@@ -94,6 +94,12 @@ private string getNodeProperty(DataFlow::Node node, string key) {
any(DataFlow::Configuration cfg).isBarrierIn(node) and kind = "in"
or
any(DataFlow::Configuration cfg).isBarrierOut(node) and kind = "out"
or
exists(DataFlow::BarrierGuard guard |
any(DataFlow::Configuration cfg).isBarrierGuard(guard) and
node = guard.getAGuardedNode() and
kind = "guard(" + guard.getResultId() + ")"
)
|
kind, ", "
)

View File

@@ -163,6 +163,12 @@ predicate defaultImplicitTaintRead(DataFlow::Node node, DataFlow::Content c) { n
*/
predicate defaultTaintSanitizer(DataFlow::Node node) { none() }
/**
* Holds if `guard` should be a sanitizer guard in all global taint flow configurations
* but not in local taint.
*/
predicate defaultTaintSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
/**
* Holds if taint can flow from `instrIn` to `instrOut` through a call to a
* modeled function.

View File

@@ -116,30 +116,20 @@ abstract class Configuration extends DataFlow::Configuration {
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
/**
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
*
* Holds if taint propagation through nodes guarded by `guard` is prohibited.
*/
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
deprecated final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
this.isSanitizerGuard(guard)
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
this.isSanitizerGuard(guard) or defaultTaintSanitizerGuard(guard)
}
/**
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
*
* Holds if taint propagation through nodes guarded by `guard` is prohibited
* when the flow state is `state`.
*/
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
none()
}
predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { none() }
deprecated final override predicate isBarrierGuard(
DataFlow::BarrierGuard guard, DataFlow::FlowState state
) {
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
this.isSanitizerGuard(guard, state)
}

View File

@@ -116,30 +116,20 @@ abstract class Configuration extends DataFlow::Configuration {
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
/**
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
*
* Holds if taint propagation through nodes guarded by `guard` is prohibited.
*/
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
deprecated final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
this.isSanitizerGuard(guard)
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
this.isSanitizerGuard(guard) or defaultTaintSanitizerGuard(guard)
}
/**
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
*
* Holds if taint propagation through nodes guarded by `guard` is prohibited
* when the flow state is `state`.
*/
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
none()
}
predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { none() }
deprecated final override predicate isBarrierGuard(
DataFlow::BarrierGuard guard, DataFlow::FlowState state
) {
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
this.isSanitizerGuard(guard, state)
}

View File

@@ -116,30 +116,20 @@ abstract class Configuration extends DataFlow::Configuration {
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
/**
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
*
* Holds if taint propagation through nodes guarded by `guard` is prohibited.
*/
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
deprecated final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
this.isSanitizerGuard(guard)
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
this.isSanitizerGuard(guard) or defaultTaintSanitizerGuard(guard)
}
/**
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
*
* Holds if taint propagation through nodes guarded by `guard` is prohibited
* when the flow state is `state`.
*/
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
none()
}
predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { none() }
deprecated final override predicate isBarrierGuard(
DataFlow::BarrierGuard guard, DataFlow::FlowState state
) {
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
this.isSanitizerGuard(guard, state)
}

View File

@@ -16,7 +16,7 @@ class IRConfiguration extends TIRConfiguration {
/**
* Holds if IR should be created for function `func`. By default, holds for all functions.
*/
predicate shouldCreateIRForFunction(Language::Declaration func) { any() }
predicate shouldCreateIRForFunction(Language::Function func) { any() }
/**
* Holds if the strings used as part of an IR dump should be generated for function `func`.
@@ -25,7 +25,7 @@ class IRConfiguration extends TIRConfiguration {
* of debug strings for IR that will not be dumped. We still generate the actual IR for these
* functions, however, to preserve the results of any interprocedural analysis.
*/
predicate shouldEvaluateDebugStringsForFunction(Language::Declaration func) { any() }
predicate shouldEvaluateDebugStringsForFunction(Language::Function func) { any() }
}
private newtype TIREscapeAnalysisConfiguration = MkIREscapeAnalysisConfiguration()

View File

@@ -97,7 +97,7 @@ class IRBlockBase extends TIRBlock {
/**
* Gets the `Function` that contains this block.
*/
final Language::Declaration getEnclosingFunction() {
final Language::Function getEnclosingFunction() {
result = getFirstInstruction(this).getEnclosingFunction()
}
}

View File

@@ -524,23 +524,4 @@ module InstructionConsistency {
"' has a `this` argument operand that is not an address, in function '$@'." and
irFunc = getInstructionIRFunction(instr, irFuncText)
}
query predicate nonUniqueIRVariable(
Instruction instr, string message, OptionalIRFunction irFunc, string irFuncText
) {
exists(VariableInstruction vi, IRVariable v1, IRVariable v2 |
instr = vi and vi.getIRVariable() = v1 and vi.getIRVariable() = v2 and v1 != v2
) and
message =
"Variable instruction '" + instr.toString() +
"' has multiple associated variables, in function '$@'." and
irFunc = getInstructionIRFunction(instr, irFuncText)
or
instr.getOpcode() instanceof Opcode::VariableAddress and
not instr instanceof VariableInstruction and
message =
"Variable address instruction '" + instr.toString() +
"' has no associated variable, in function '$@'." and
irFunc = getInstructionIRFunction(instr, irFuncText)
}
}

View File

@@ -18,7 +18,7 @@ private import Imports::IRType
* by the AST-to-IR translation (`IRTempVariable`).
*/
class IRVariable extends TIRVariable {
Language::Declaration func;
Language::Function func;
IRVariable() {
this = TIRUserVariable(_, _, func) or
@@ -79,7 +79,7 @@ class IRVariable extends TIRVariable {
/**
* Gets the function that references this variable.
*/
final Language::Declaration getEnclosingFunction() { result = func }
final Language::Function getEnclosingFunction() { result = func }
}
/**
@@ -246,7 +246,7 @@ class IREllipsisVariable extends IRTempVariable, IRParameter {
final override string toString() { result = "#ellipsis" }
final override int getIndex() { result = func.(Language::Function).getNumberOfParameters() }
final override int getIndex() { result = func.getNumberOfParameters() }
}
/**

View File

@@ -194,7 +194,7 @@ class Instruction extends Construction::TStageInstruction {
/**
* Gets the function that contains this instruction.
*/
final Language::Declaration getEnclosingFunction() {
final Language::Function getEnclosingFunction() {
result = this.getEnclosingIRFunction().getFunction()
}

View File

@@ -26,20 +26,20 @@ class PrintIRConfiguration extends TPrintIRConfiguration {
* Holds if the IR for `func` should be printed. By default, holds for all
* functions.
*/
predicate shouldPrintFunction(Language::Declaration decl) { any() }
predicate shouldPrintFunction(Language::Function func) { any() }
}
/**
* Override of `IRConfiguration` to only evaluate debug strings for the functions that are to be dumped.
*/
private class FilteredIRConfiguration extends IRConfiguration {
override predicate shouldEvaluateDebugStringsForFunction(Language::Declaration func) {
override predicate shouldEvaluateDebugStringsForFunction(Language::Function func) {
shouldPrintFunction(func)
}
}
private predicate shouldPrintFunction(Language::Declaration decl) {
exists(PrintIRConfiguration config | config.shouldPrintFunction(decl))
private predicate shouldPrintFunction(Language::Function func) {
exists(PrintIRConfiguration config | config.shouldPrintFunction(func))
}
private string getAdditionalInstructionProperty(Instruction instr, string key) {

View File

@@ -5,28 +5,23 @@
private import IRFunctionBaseInternal
private newtype TIRFunction =
TFunctionIRFunction(Language::Function func) { IRConstruction::Raw::functionHasIR(func) } or
TVarInitIRFunction(Language::GlobalVariable var) { IRConstruction::Raw::varHasIRFunc(var) }
MkIRFunction(Language::Function func) { IRConstruction::Raw::functionHasIR(func) }
/**
* The IR for a function. This base class contains only the predicates that are the same between all
* phases of the IR. Each instantiation of `IRFunction` extends this class.
*/
class IRFunctionBase extends TIRFunction {
Language::Declaration decl;
Language::Function func;
IRFunctionBase() {
this = TFunctionIRFunction(decl)
or
this = TVarInitIRFunction(decl)
}
IRFunctionBase() { this = MkIRFunction(func) }
/** Gets a textual representation of this element. */
final string toString() { result = "IR: " + decl.toString() }
final string toString() { result = "IR: " + func.toString() }
/** Gets the function whose IR is represented. */
final Language::Declaration getFunction() { result = decl }
final Language::Function getFunction() { result = func }
/** Gets the location of the function. */
final Language::Location getLocation() { result = decl.getLocation() }
final Language::Location getLocation() { result = func.getLocation() }
}

View File

@@ -2,21 +2,21 @@ private import TIRVariableInternal
private import Imports::TempVariableTag
newtype TIRVariable =
TIRUserVariable(Language::Variable var, Language::LanguageType type, Language::Declaration func) {
TIRUserVariable(Language::Variable var, Language::LanguageType type, Language::Function func) {
Construction::hasUserVariable(func, var, type)
} or
TIRTempVariable(
Language::Declaration func, Language::AST ast, TempVariableTag tag, Language::LanguageType type
Language::Function func, Language::AST ast, TempVariableTag tag, Language::LanguageType type
) {
Construction::hasTempVariable(func, ast, tag, type)
} or
TIRDynamicInitializationFlag(
Language::Declaration func, Language::Variable var, Language::LanguageType type
Language::Function func, Language::Variable var, Language::LanguageType type
) {
Construction::hasDynamicInitializationFlag(func, var, type)
} or
TIRStringLiteral(
Language::Declaration func, Language::AST ast, Language::LanguageType type,
Language::Function func, Language::AST ast, Language::LanguageType type,
Language::StringLiteral literal
) {
Construction::hasStringLiteral(func, ast, type, literal)

View File

@@ -97,7 +97,7 @@ class IRBlockBase extends TIRBlock {
/**
* Gets the `Function` that contains this block.
*/
final Language::Declaration getEnclosingFunction() {
final Language::Function getEnclosingFunction() {
result = getFirstInstruction(this).getEnclosingFunction()
}
}

View File

@@ -524,23 +524,4 @@ module InstructionConsistency {
"' has a `this` argument operand that is not an address, in function '$@'." and
irFunc = getInstructionIRFunction(instr, irFuncText)
}
query predicate nonUniqueIRVariable(
Instruction instr, string message, OptionalIRFunction irFunc, string irFuncText
) {
exists(VariableInstruction vi, IRVariable v1, IRVariable v2 |
instr = vi and vi.getIRVariable() = v1 and vi.getIRVariable() = v2 and v1 != v2
) and
message =
"Variable instruction '" + instr.toString() +
"' has multiple associated variables, in function '$@'." and
irFunc = getInstructionIRFunction(instr, irFuncText)
or
instr.getOpcode() instanceof Opcode::VariableAddress and
not instr instanceof VariableInstruction and
message =
"Variable address instruction '" + instr.toString() +
"' has no associated variable, in function '$@'." and
irFunc = getInstructionIRFunction(instr, irFuncText)
}
}

View File

@@ -18,7 +18,7 @@ private import Imports::IRType
* by the AST-to-IR translation (`IRTempVariable`).
*/
class IRVariable extends TIRVariable {
Language::Declaration func;
Language::Function func;
IRVariable() {
this = TIRUserVariable(_, _, func) or
@@ -79,7 +79,7 @@ class IRVariable extends TIRVariable {
/**
* Gets the function that references this variable.
*/
final Language::Declaration getEnclosingFunction() { result = func }
final Language::Function getEnclosingFunction() { result = func }
}
/**
@@ -246,7 +246,7 @@ class IREllipsisVariable extends IRTempVariable, IRParameter {
final override string toString() { result = "#ellipsis" }
final override int getIndex() { result = func.(Language::Function).getNumberOfParameters() }
final override int getIndex() { result = func.getNumberOfParameters() }
}
/**

View File

@@ -194,7 +194,7 @@ class Instruction extends Construction::TStageInstruction {
/**
* Gets the function that contains this instruction.
*/
final Language::Declaration getEnclosingFunction() {
final Language::Function getEnclosingFunction() {
result = this.getEnclosingIRFunction().getFunction()
}

View File

@@ -26,20 +26,20 @@ class PrintIRConfiguration extends TPrintIRConfiguration {
* Holds if the IR for `func` should be printed. By default, holds for all
* functions.
*/
predicate shouldPrintFunction(Language::Declaration decl) { any() }
predicate shouldPrintFunction(Language::Function func) { any() }
}
/**
* Override of `IRConfiguration` to only evaluate debug strings for the functions that are to be dumped.
*/
private class FilteredIRConfiguration extends IRConfiguration {
override predicate shouldEvaluateDebugStringsForFunction(Language::Declaration func) {
override predicate shouldEvaluateDebugStringsForFunction(Language::Function func) {
shouldPrintFunction(func)
}
}
private predicate shouldPrintFunction(Language::Declaration decl) {
exists(PrintIRConfiguration config | config.shouldPrintFunction(decl))
private predicate shouldPrintFunction(Language::Function func) {
exists(PrintIRConfiguration config | config.shouldPrintFunction(func))
}
private string getAdditionalInstructionProperty(Instruction instr, string key) {

View File

@@ -13,7 +13,6 @@ private import TranslatedElement
private import TranslatedExpr
private import TranslatedStmt
private import TranslatedFunction
private import TranslatedGlobalVar
TranslatedElement getInstructionTranslatedElement(Instruction instruction) {
instruction = TRawInstruction(result, _)
@@ -36,41 +35,29 @@ module Raw {
cached
predicate functionHasIR(Function func) { exists(getTranslatedFunction(func)) }
cached
predicate varHasIRFunc(GlobalOrNamespaceVariable var) {
var.hasInitializer() and
(
not var.getType().isDeeplyConst()
or
var.getInitializer().getExpr() instanceof StringLiteral
)
}
cached
predicate hasInstruction(TranslatedElement element, InstructionTag tag) {
element.hasInstruction(_, tag, _)
}
cached
predicate hasUserVariable(Declaration decl, Variable var, CppType type) {
getTranslatedFunction(decl).hasUserVariable(var, type)
or
getTranslatedVarInit(decl).hasUserVariable(var, type)
predicate hasUserVariable(Function func, Variable var, CppType type) {
getTranslatedFunction(func).hasUserVariable(var, type)
}
cached
predicate hasTempVariable(Declaration decl, Locatable ast, TempVariableTag tag, CppType type) {
predicate hasTempVariable(Function func, Locatable ast, TempVariableTag tag, CppType type) {
exists(TranslatedElement element |
element.getAst() = ast and
decl = element.getFunction() and
func = element.getFunction() and
element.hasTempVariable(tag, type)
)
}
cached
predicate hasStringLiteral(Declaration decl, Locatable ast, CppType type, StringLiteral literal) {
predicate hasStringLiteral(Function func, Locatable ast, CppType type, StringLiteral literal) {
literal = ast and
literal.getEnclosingDeclaration() = decl and
literal.getEnclosingFunction() = func and
getTypeForPRValue(literal.getType()) = type
}

View File

@@ -180,7 +180,7 @@ abstract class TranslatedSideEffects extends TranslatedElement {
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = getAst() }
final override Declaration getFunction() { result = getExpr().getEnclosingDeclaration() }
final override Function getFunction() { result = getExpr().getEnclosingFunction() }
final override TranslatedElement getChild(int i) {
result =
@@ -375,7 +375,7 @@ abstract class TranslatedSideEffect extends TranslatedElement {
kind instanceof GotoEdge
}
final override Declaration getFunction() { result = getParent().getFunction() }
final override Function getFunction() { result = getParent().getFunction() }
final override Instruction getPrimaryInstructionForSideEffect(InstructionTag tag) {
tag = OnlyInstructionTag() and
@@ -436,6 +436,13 @@ abstract class TranslatedArgumentSideEffect extends TranslatedSideEffect {
result = index
}
/**
* Gets the `TranslatedFunction` containing this expression.
*/
final TranslatedFunction getEnclosingFunction() {
result = getTranslatedFunction(call.getEnclosingFunction())
}
final override predicate sideEffectInstruction(Opcode opcode, CppType type) {
opcode = sideEffectOpcode and
(

View File

@@ -25,9 +25,9 @@ private Element getRealParent(Expr expr) {
result.(Destructor).getADestruction() = expr
}
IRUserVariable getIRUserVariable(Declaration decl, Variable var) {
IRUserVariable getIRUserVariable(Function func, Variable var) {
result.getVariable() = var and
result.getEnclosingFunction() = decl
result.getEnclosingFunction() = func
}
IRTempVariable getIRTempVariable(Locatable ast, TempVariableTag tag) {
@@ -67,8 +67,7 @@ private predicate ignoreExprAndDescendants(Expr expr) {
exists(Initializer init, StaticStorageDurationVariable var |
init = var.getInitializer() and
not var.hasDynamicInitialization() and
expr = init.getExpr().getFullyConverted() and
not var instanceof GlobalOrNamespaceVariable
expr = init.getExpr().getFullyConverted()
)
or
// Ignore descendants of `__assume` expressions, since we translated these to `NoOp`.
@@ -118,8 +117,7 @@ private predicate ignoreExprOnly(Expr expr) {
// should not be translated.
exists(NewOrNewArrayExpr new | expr = new.getAllocatorCall().getArgument(0))
or
not translateFunction(expr.getEnclosingFunction()) and
not Raw::varHasIRFunc(expr.getEnclosingVariable())
not translateFunction(expr.getEnclosingFunction())
or
// We do not yet translate destructors properly, so for now we ignore the
// destructor call. We do, however, translate the expression being
@@ -664,8 +662,7 @@ newtype TTranslatedElement =
opcode = getASideEffectOpcode(call, -1)
} or
// The side effect that initializes newly-allocated memory.
TTranslatedAllocationSideEffect(AllocationExpr expr) { not ignoreSideEffects(expr) } or
TTranslatedGlobalOrNamespaceVarInit(GlobalOrNamespaceVariable var) { Raw::varHasIRFunc(var) }
TTranslatedAllocationSideEffect(AllocationExpr expr) { not ignoreSideEffects(expr) }
/**
* Gets the index of the first explicitly initialized element in `initList`
@@ -795,7 +792,7 @@ abstract class TranslatedElement extends TTranslatedElement {
/**
* Gets the `Function` that contains this element.
*/
abstract Declaration getFunction();
abstract Function getFunction();
/**
* Gets the successor instruction of the instruction that was generated by
@@ -945,14 +942,3 @@ abstract class TranslatedElement extends TTranslatedElement {
*/
final TranslatedElement getParent() { result.getAChild() = this }
}
/**
* Represents the IR translation of a root element, either a function or a global variable.
*/
abstract class TranslatedRootElement extends TranslatedElement {
TranslatedRootElement() {
this instanceof TTranslatedFunction
or
this instanceof TTranslatedGlobalOrNamespaceVarInit
}
}

View File

@@ -12,7 +12,6 @@ private import TranslatedElement
private import TranslatedFunction
private import TranslatedInitialization
private import TranslatedStmt
private import TranslatedGlobalVar
import TranslatedCall
/**
@@ -79,7 +78,7 @@ abstract class TranslatedExpr extends TranslatedElement {
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
final override Declaration getFunction() { result = expr.getEnclosingDeclaration() }
final override Function getFunction() { result = expr.getEnclosingFunction() }
/**
* Gets the expression from which this `TranslatedExpr` is generated.
@@ -89,10 +88,8 @@ abstract class TranslatedExpr extends TranslatedElement {
/**
* Gets the `TranslatedFunction` containing this expression.
*/
final TranslatedRootElement getEnclosingFunction() {
final TranslatedFunction getEnclosingFunction() {
result = getTranslatedFunction(expr.getEnclosingFunction())
or
result = getTranslatedVarInit(expr.getEnclosingVariable())
}
}
@@ -790,7 +787,7 @@ class TranslatedThisExpr extends TranslatedNonConstantExpr {
override IRVariable getInstructionVariable(InstructionTag tag) {
tag = ThisAddressTag() and
result = this.getEnclosingFunction().(TranslatedFunction).getThisVariable()
result = this.getEnclosingFunction().getThisVariable()
}
}
@@ -841,7 +838,7 @@ class TranslatedNonFieldVariableAccess extends TranslatedVariableAccess {
override IRVariable getInstructionVariable(InstructionTag tag) {
tag = OnlyInstructionTag() and
result = getIRUserVariable(expr.getEnclosingDeclaration(), expr.getTarget())
result = getIRUserVariable(expr.getEnclosingFunction(), expr.getTarget())
}
}
@@ -2525,7 +2522,7 @@ class TranslatedVarArgsStart extends TranslatedNonConstantExpr {
final override IRVariable getInstructionVariable(InstructionTag tag) {
tag = VarArgsStartEllipsisAddressTag() and
result = this.getEnclosingFunction().(TranslatedFunction).getEllipsisVariable()
result = this.getEnclosingFunction().getEllipsisVariable()
}
final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {

View File

@@ -58,7 +58,7 @@ predicate hasReturnValue(Function func) { not func.getUnspecifiedType() instance
* Represents the IR translation of a function. This is the root elements for
* all other elements associated with this function.
*/
class TranslatedFunction extends TranslatedRootElement, TTranslatedFunction {
class TranslatedFunction extends TranslatedElement, TTranslatedFunction {
Function func;
TranslatedFunction() { this = TTranslatedFunction(func) }

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