mirror of
https://github.com/github/codeql.git
synced 2026-05-18 21:27:08 +02:00
Compare commits
1 Commits
redsun82/r
...
dbartol/re
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cd07af62e9 |
3
.bazelrc
3
.bazelrc
@@ -2,9 +2,6 @@ common --enable_platform_specific_config
|
||||
# because we use --override_module with `%workspace%`, the lock file is not stable
|
||||
common --lockfile_mode=off
|
||||
|
||||
# Build release binaries by default, can be overwritten to in local.bazelrc and set to `fastbuild` or `dbg`
|
||||
build --compilation_mode opt
|
||||
|
||||
# when building from this repository in isolation, the internal repository will not be found at ..
|
||||
# where `MODULE.bazel` looks for it. The following will get us past the module loading phase, so
|
||||
# that we can build things that do not rely on that
|
||||
|
||||
9
.devcontainer/swift/Dockerfile
Normal file
9
.devcontainer/swift/Dockerfile
Normal file
@@ -0,0 +1,9 @@
|
||||
# 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
|
||||
25
.devcontainer/swift/devcontainer.json
Normal file
25
.devcontainer/swift/devcontainer.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
34
.devcontainer/swift/root.sh
Executable file
34
.devcontainer/swift/root.sh
Executable file
@@ -0,0 +1,34 @@
|
||||
set -xe
|
||||
|
||||
BAZELISK_VERSION=v1.12.0
|
||||
BAZELISK_DOWNLOAD_SHA=6b0bcb2ea15bca16fffabe6fda75803440375354c085480fe361d2cbf32501db
|
||||
|
||||
# install git lfs apt source
|
||||
curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | bash
|
||||
|
||||
# install gh apt source
|
||||
(type -p wget >/dev/null || (sudo apt update && sudo apt-get install wget -y)) \
|
||||
&& sudo mkdir -p -m 755 /etc/apt/keyrings \
|
||||
&& wget -qO- https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null \
|
||||
&& sudo chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg \
|
||||
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
|
||||
|
||||
apt-get update
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
apt-get -y install --no-install-recommends \
|
||||
zlib1g-dev \
|
||||
uuid-dev \
|
||||
python3-distutils \
|
||||
python3-pip \
|
||||
bash-completion \
|
||||
git-lfs \
|
||||
gh
|
||||
|
||||
# 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
|
||||
20
.devcontainer/swift/update-codeql.sh
Executable file
20
.devcontainer/swift/update-codeql.sh
Executable file
@@ -0,0 +1,20 @@
|
||||
#!/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
|
||||
15
.devcontainer/swift/user.sh
Executable file
15
.devcontainer/swift/user.sh
Executable file
@@ -0,0 +1,15 @@
|
||||
set -xe
|
||||
|
||||
git lfs install
|
||||
|
||||
# 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
|
||||
14
.github/pull_request_template.md
vendored
Normal file
14
.github/pull_request_template.md
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
### Pull Request checklist
|
||||
|
||||
#### All query authors
|
||||
|
||||
- [ ] A change note is added if necessary. See [the documentation](https://github.com/github/codeql/blob/main/docs/change-notes.md) in this repository.
|
||||
- [ ] All new queries have appropriate `.qhelp`. See [the documentation](https://github.com/github/codeql/blob/main/docs/query-help-style-guide.md) in this repository.
|
||||
- [ ] QL tests are added if necessary. See [Testing custom queries](https://docs.github.com/en/code-security/codeql-cli/using-the-advanced-functionality-of-the-codeql-cli/testing-custom-queries) in the GitHub documentation.
|
||||
- [ ] New and changed queries have correct query metadata. See [the documentation](https://github.com/github/codeql/blob/main/docs/query-metadata-style-guide.md) in this repository.
|
||||
|
||||
#### Internal query authors only
|
||||
|
||||
- [ ] Autofixes generated based on these changes are valid, only needed if this PR makes significant changes to `.ql`, `.qll`, or `.qhelp` files. See [the documentation](https://github.com/github/codeql-team/blob/main/docs/best-practices/validating-autofix-for-query-changes.md) (internal access required).
|
||||
- [ ] Changes are validated [at scale](https://github.com/github/codeql-dca/) (internal access required).
|
||||
- [ ] Adding a new query? Consider also [adding the query to autofix](https://github.com/github/codeml-autofix/blob/main/docs/updating-query-support.md#adding-a-new-query-to-the-query-suite).
|
||||
6
.github/workflows/swift.yml
vendored
6
.github/workflows/swift.yml
vendored
@@ -48,6 +48,12 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./swift/actions/build-and-test
|
||||
build-and-test-linux:
|
||||
if: github.repository_owner == 'github'
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./swift/actions/build-and-test
|
||||
qltests-macos:
|
||||
if: ${{ github.repository_owner == 'github' && github.event_name == 'pull_request' }}
|
||||
needs: build-and-test-macos
|
||||
|
||||
197
Cargo.lock
generated
197
Cargo.lock
generated
@@ -156,9 +156,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.7.0"
|
||||
version = "2.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1be3f42a67d6d345ecd59f675f3f012d6974981560836e938c22b424b85ce1be"
|
||||
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
||||
|
||||
[[package]]
|
||||
name = "borsh"
|
||||
@@ -268,7 +268,7 @@ version = "0.98.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d5f2eb1cd6054da221bd1ac0197fb2fe5e2caf3dcb93619398fc1433f8f09093"
|
||||
dependencies = [
|
||||
"bitflags 2.7.0",
|
||||
"bitflags 2.6.0",
|
||||
"chalk-derive",
|
||||
]
|
||||
|
||||
@@ -318,9 +318,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.26"
|
||||
version = "4.5.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8eb5e908ef3a6efbe1ed62520fb7287959888c88485abe072543190ecc66783"
|
||||
checksum = "9560b07a799281c7e0958b9296854d6fafd4c5f31444a7e5bb1ad6dde5ccf1bd"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
@@ -328,9 +328,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.26"
|
||||
version = "4.5.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96b01801b5fc6a0a232407abc821660c9c6d25a1cafc0d4f85f29fb8d9afc121"
|
||||
checksum = "874e0dd3eb68bf99058751ac9712f622e61e6f393a94f7128fa26e3f02f5c7cd"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
@@ -436,7 +436,6 @@ dependencies = [
|
||||
"serde_json",
|
||||
"serde_with",
|
||||
"stderrlog",
|
||||
"toml",
|
||||
"triomphe",
|
||||
]
|
||||
|
||||
@@ -999,7 +998,7 @@ version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
|
||||
dependencies = [
|
||||
"bitflags 2.7.0",
|
||||
"bitflags 2.6.0",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
]
|
||||
@@ -1121,7 +1120,7 @@ version = "6.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d"
|
||||
dependencies = [
|
||||
"bitflags 2.7.0",
|
||||
"bitflags 2.6.0",
|
||||
"crossbeam-channel",
|
||||
"filetime",
|
||||
"fsevent-sys",
|
||||
@@ -1294,9 +1293,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.93"
|
||||
version = "1.0.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
|
||||
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
@@ -1329,7 +1328,7 @@ version = "0.87.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28b782af0a7a8df16ddf43cd70da9f17bc3b1ce712c9e4992b6edb16f5f53632"
|
||||
dependencies = [
|
||||
"bitflags 2.7.0",
|
||||
"bitflags 2.6.0",
|
||||
"ra-ap-rustc_index",
|
||||
"tracing",
|
||||
]
|
||||
@@ -1390,9 +1389,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ra_ap_base_db"
|
||||
version = "0.0.258"
|
||||
version = "0.0.257"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "548b95b278a8f6f888a0bb6cb7bf4201fe920d3800cd99770054e5eb72f3cd6a"
|
||||
checksum = "55bd06c212246716572baf2babd2f4e8b2bbfedccdb2deb5107dc67f0cd9f727"
|
||||
dependencies = [
|
||||
"la-arena",
|
||||
"lz4_flex",
|
||||
@@ -1411,9 +1410,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ra_ap_cfg"
|
||||
version = "0.0.258"
|
||||
version = "0.0.257"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "921e2b0232d1e8352eb9f476bb55c1d8bcbed0531adc17c74aa711fef015c851"
|
||||
checksum = "4b507e0a9d182ac490400992264006b057d24f26164fb015a4927bedf4381d9f"
|
||||
dependencies = [
|
||||
"ra_ap_intern",
|
||||
"ra_ap_tt",
|
||||
@@ -1423,15 +1422,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ra_ap_edition"
|
||||
version = "0.0.258"
|
||||
version = "0.0.257"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7cc6633305d878cafb4a4482e7e7002d1a5d7b15fa837728b6613ff5336f8a4"
|
||||
checksum = "287c134d67e3bfb606211b039acc711c3dfd74b61dc570beb18556901d2a4cde"
|
||||
|
||||
[[package]]
|
||||
name = "ra_ap_hir"
|
||||
version = "0.0.258"
|
||||
version = "0.0.257"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e3f6b31381a297e5bb4fa76108a2cf7bf8d35067a130f932aa6fdfb733ba3a1"
|
||||
checksum = "cf94ce7ef4564b34584ddecc20c948c746370256c1dd96babe1dff06f9992821"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"either",
|
||||
@@ -1454,12 +1453,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ra_ap_hir_def"
|
||||
version = "0.0.258"
|
||||
version = "0.0.257"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84144bdda7af170e660d312982889622f4a5361c1bb74df2afa2a6ce17d48644"
|
||||
checksum = "95b60cb43d1dd97c6288436277174f09440a81e56c42c9c00b3747669ec18933"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bitflags 2.7.0",
|
||||
"bitflags 2.6.0",
|
||||
"cov-mark",
|
||||
"dashmap",
|
||||
"drop_bomb",
|
||||
@@ -1491,9 +1490,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ra_ap_hir_expand"
|
||||
version = "0.0.258"
|
||||
version = "0.0.257"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "441661b394acfa4f3ac4cb54386f8ee8b451504ec167b0bf0e4200da1bbca50d"
|
||||
checksum = "0e2884baf95b2ab8b7f6d88e0b3d3dcf9bc9c9fede8b6353cca1f93ec0db02df"
|
||||
dependencies = [
|
||||
"cov-mark",
|
||||
"either",
|
||||
@@ -1519,12 +1518,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ra_ap_hir_ty"
|
||||
version = "0.0.258"
|
||||
version = "0.0.257"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6feea30dff289f33a8ed76172ff4cb299db22d224f88735aa2c7f49ba1e5e77f"
|
||||
checksum = "562c8a0bf46e3ace2493b8c42b6cfb506a6b992e2376e3f1b18b0252bf8b226b"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bitflags 2.7.0",
|
||||
"bitflags 2.6.0",
|
||||
"chalk-derive",
|
||||
"chalk-ir",
|
||||
"chalk-recursive",
|
||||
@@ -1559,12 +1558,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ra_ap_ide_db"
|
||||
version = "0.0.258"
|
||||
version = "0.0.257"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7e33bd5a0139b6c74d34ed963494115abe3f9c95cf5936871ab3d9b548ccbbdf"
|
||||
checksum = "d16df71464447314e043790d407246af3d692815cd826bbfab9318ba50b0543a"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bitflags 2.7.0",
|
||||
"bitflags 2.6.0",
|
||||
"cov-mark",
|
||||
"crossbeam-channel",
|
||||
"either",
|
||||
@@ -1590,9 +1589,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ra_ap_intern"
|
||||
version = "0.0.258"
|
||||
version = "0.0.257"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "faa7ee24ae9bf4d2536ef7fb6de35f30856edbf7b3d6ac02e5a2532118896569"
|
||||
checksum = "29dd636c9c7c0b3ac0736a8e6e31202cae7b0b378ac1a8d73dd2c1f71c5931a4"
|
||||
dependencies = [
|
||||
"dashmap",
|
||||
"hashbrown 0.14.5",
|
||||
@@ -1603,15 +1602,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ra_ap_limit"
|
||||
version = "0.0.258"
|
||||
version = "0.0.257"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90d8a2aecbd488cf79b430bd5abe6650da44ae58b31cd6052c909dbd3f5d5926"
|
||||
checksum = "4d1d98e79549c0a75f35d534042cbb3358a498985726bd5ae8f8f420e323a6ea"
|
||||
|
||||
[[package]]
|
||||
name = "ra_ap_load-cargo"
|
||||
version = "0.0.258"
|
||||
version = "0.0.257"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e2372aadd32e85460de595891c8b3562126166bc94fdc24508d6784c9d93357"
|
||||
checksum = "7d448f55f96ac9c5ecfdea9261bc122f9b586f4e43b8fb53e62a54a11090d479"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"crossbeam-channel",
|
||||
@@ -1631,9 +1630,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ra_ap_mbe"
|
||||
version = "0.0.258"
|
||||
version = "0.0.257"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf69ba82adb6e436617ecd09c0ff58006f376060dff437eb9fd383c2983f6d01"
|
||||
checksum = "5ff107e50b96ceacd2046e9c1ffae526721f14a6e5c6671dff2be8ad6252fb23"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"cov-mark",
|
||||
@@ -1652,9 +1651,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ra_ap_parser"
|
||||
version = "0.0.258"
|
||||
version = "0.0.257"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f499b6c33a588d60ed9722d057954a21ec01913b97a5693ff40ba4828ffa7b9"
|
||||
checksum = "af7c6b15845145bc4f1351c4e6f3a06c3c390dfc0a8fd1e40ee3f05b6f73ba77"
|
||||
dependencies = [
|
||||
"drop_bomb",
|
||||
"ra-ap-rustc_lexer",
|
||||
@@ -1665,18 +1664,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ra_ap_paths"
|
||||
version = "0.0.258"
|
||||
version = "0.0.257"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5a16df131fa641a4af4d9488152b7b332a6a30e93bc655fdbe88f555ba28825"
|
||||
checksum = "01e41f198abdce6161d071fb88fb906189f9a6ee55dd7cfa1ba7bf5da41b2cd2"
|
||||
dependencies = [
|
||||
"camino",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ra_ap_proc_macro_api"
|
||||
version = "0.0.258"
|
||||
version = "0.0.257"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3480e0d07197ebcc2db5836b0c39625e07b0d77c6471a2a748e5bdf54ce556e3"
|
||||
checksum = "c719165f2e0e42706644e223f3b80dbab41061c4f60132d4a6a282bb67df6ef2"
|
||||
dependencies = [
|
||||
"indexmap 2.7.0",
|
||||
"ra_ap_intern",
|
||||
@@ -1693,9 +1692,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ra_ap_profile"
|
||||
version = "0.0.258"
|
||||
version = "0.0.257"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95b707dd9c92139030587d81b3333428f48af8f4728330ed12101ab0bb431d72"
|
||||
checksum = "43cf9a02881c4ce8107d2eb7454a4d386438fc99ee5bba021ff829b76cf29807"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
@@ -1705,9 +1704,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ra_ap_project_model"
|
||||
version = "0.0.258"
|
||||
version = "0.0.257"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "551a0de5a16f0538fbaf401a319d81d1a034f7aa014e46ac87c5bd74229a211b"
|
||||
checksum = "9238f0e90f2f9e7ab6a8c27916326668ab9d0971a1131b3d2ce51d806077af6a"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cargo_metadata",
|
||||
@@ -1731,9 +1730,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ra_ap_salsa"
|
||||
version = "0.0.258"
|
||||
version = "0.0.257"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ec0c82d9e5affbf7d582750b301d279589787a5ac729f95756f5a0b0bf2b4a4"
|
||||
checksum = "288a0cd35aca45106f613e92a52c7fe63109c8ad2adfddd9181b55a8ced5fba4"
|
||||
dependencies = [
|
||||
"indexmap 2.7.0",
|
||||
"itertools 0.12.1",
|
||||
@@ -1749,9 +1748,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ra_ap_salsa-macros"
|
||||
version = "0.0.258"
|
||||
version = "0.0.257"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8440192eb549dda1cdefc95eaa1fc42ad13cfbd303add757517d77c81e7dc2e1"
|
||||
checksum = "a417dc1192f6e1739560dac84f4d8ed18e4e0228144f13eba66191d7be494528"
|
||||
dependencies = [
|
||||
"heck 0.4.1",
|
||||
"proc-macro2",
|
||||
@@ -1761,9 +1760,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ra_ap_span"
|
||||
version = "0.0.258"
|
||||
version = "0.0.257"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "18690685d10da2577d7821d46c0de5a884bf1755e59635cbb1a795451e2a4acc"
|
||||
checksum = "10c82d730d56e5c0fadb2029f4347ef67b2453586a94cee40a151178ba77d1b4"
|
||||
dependencies = [
|
||||
"hashbrown 0.14.5",
|
||||
"la-arena",
|
||||
@@ -1777,9 +1776,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ra_ap_stdx"
|
||||
version = "0.0.258"
|
||||
version = "0.0.257"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4016934faae8413b4ad3f1bf063c7ffccdcfdf3f67ff32f4a79a197a3c1cb0da"
|
||||
checksum = "0b39817ff288eb2d922878e8b517a4569246606dab4313665e2fa9470ae3602a"
|
||||
dependencies = [
|
||||
"always-assert",
|
||||
"crossbeam-channel",
|
||||
@@ -1792,9 +1791,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ra_ap_syntax"
|
||||
version = "0.0.258"
|
||||
version = "0.0.257"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e8e381d21d166d12b11906171f82382473d60abfead0c4acc6d7d07150f87f73"
|
||||
checksum = "135493df963d932d4e4a9d9058db990384eb0a2fa694a06ecd1b161b0502c32e"
|
||||
dependencies = [
|
||||
"cov-mark",
|
||||
"either",
|
||||
@@ -1812,9 +1811,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ra_ap_syntax-bridge"
|
||||
version = "0.0.258"
|
||||
version = "0.0.257"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "65f1960218acd2ed8e486e7bd24f80a7eb89591906c6b0831296b2a75c556b2f"
|
||||
checksum = "a95c0fd654ff10425387c24c9b28004fda5794db212990b2a997938429e0c499"
|
||||
dependencies = [
|
||||
"ra_ap_intern",
|
||||
"ra_ap_parser",
|
||||
@@ -1828,9 +1827,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ra_ap_toolchain"
|
||||
version = "0.0.258"
|
||||
version = "0.0.257"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c9195f69ff02f076f5a726c7fbafa2b4639d00235906cb44e52ca75cd8b33c30"
|
||||
checksum = "1b5e4c88d75ba247f15dfa28a1291e3e75c887bc2b6d00f1fa0cc17789111840"
|
||||
dependencies = [
|
||||
"camino",
|
||||
"home",
|
||||
@@ -1838,9 +1837,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ra_ap_tt"
|
||||
version = "0.0.258"
|
||||
version = "0.0.257"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ac261d79d3ec475a1f3b2a758d3e466f2b9d7d883fb72239b06979bf6880018"
|
||||
checksum = "f04de8deab5777101652f9c79275785589fe5c7375d0f18207edb040ffaead9b"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"ra-ap-rustc_lexer",
|
||||
@@ -1851,9 +1850,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ra_ap_vfs"
|
||||
version = "0.0.258"
|
||||
version = "0.0.257"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee35a171beccbb01b4ede1d9ad91dee487a3742d7cc39efd7aed6961027cbe78"
|
||||
checksum = "78c33cc88cb19b3b6d8af79d07a6989871025ef092af61f8d261a5e63117390e"
|
||||
dependencies = [
|
||||
"crossbeam-channel",
|
||||
"fst",
|
||||
@@ -1867,9 +1866,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ra_ap_vfs-notify"
|
||||
version = "0.0.258"
|
||||
version = "0.0.257"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b234b7651eb5d61f18d4f4643590bb8b1fd59ef766a1059741c09c540ec8cd86"
|
||||
checksum = "f690622dc77b2f6cae03ad3a019fca808802dae0915977d186928d9a202c4761"
|
||||
dependencies = [
|
||||
"crossbeam-channel",
|
||||
"notify",
|
||||
@@ -1938,7 +1937,7 @@ version = "0.5.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834"
|
||||
dependencies = [
|
||||
"bitflags 2.7.0",
|
||||
"bitflags 2.6.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2095,15 +2094,6 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_spanned"
|
||||
version = "0.6.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_with"
|
||||
version = "3.12.0"
|
||||
@@ -2217,9 +2207,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.96"
|
||||
version = "2.0.95"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80"
|
||||
checksum = "46f71c0377baf4ef1cc3e3402ded576dccc315800fbc62dfc7fe04b009773b4a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -2313,40 +2303,6 @@ dependencies = [
|
||||
"time-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.8.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"toml_edit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_datetime"
|
||||
version = "0.6.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
version = "0.22.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5"
|
||||
dependencies = [
|
||||
"indexmap 2.7.0",
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
version = "0.1.41"
|
||||
@@ -2798,15 +2754,6 @@ version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.6.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8d71a593cc5c42ad7876e2c1fda56f314f3754c084128833e64f1345ff8a03a"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yansi"
|
||||
version = "1.0.1"
|
||||
|
||||
40
MODULE.bazel
40
MODULE.bazel
@@ -86,7 +86,7 @@ use_repo(
|
||||
"vendor__anyhow-1.0.95",
|
||||
"vendor__argfile-0.2.1",
|
||||
"vendor__chrono-0.4.39",
|
||||
"vendor__clap-4.5.26",
|
||||
"vendor__clap-4.5.24",
|
||||
"vendor__dunce-1.0.5",
|
||||
"vendor__either-1.13.0",
|
||||
"vendor__encoding-0.2.33",
|
||||
@@ -100,23 +100,23 @@ use_repo(
|
||||
"vendor__mustache-0.9.0",
|
||||
"vendor__num-traits-0.2.19",
|
||||
"vendor__num_cpus-1.16.0",
|
||||
"vendor__proc-macro2-1.0.93",
|
||||
"vendor__proc-macro2-1.0.92",
|
||||
"vendor__quote-1.0.38",
|
||||
"vendor__ra_ap_base_db-0.0.258",
|
||||
"vendor__ra_ap_cfg-0.0.258",
|
||||
"vendor__ra_ap_hir-0.0.258",
|
||||
"vendor__ra_ap_hir_def-0.0.258",
|
||||
"vendor__ra_ap_hir_expand-0.0.258",
|
||||
"vendor__ra_ap_ide_db-0.0.258",
|
||||
"vendor__ra_ap_intern-0.0.258",
|
||||
"vendor__ra_ap_load-cargo-0.0.258",
|
||||
"vendor__ra_ap_parser-0.0.258",
|
||||
"vendor__ra_ap_paths-0.0.258",
|
||||
"vendor__ra_ap_project_model-0.0.258",
|
||||
"vendor__ra_ap_span-0.0.258",
|
||||
"vendor__ra_ap_stdx-0.0.258",
|
||||
"vendor__ra_ap_syntax-0.0.258",
|
||||
"vendor__ra_ap_vfs-0.0.258",
|
||||
"vendor__ra_ap_base_db-0.0.257",
|
||||
"vendor__ra_ap_cfg-0.0.257",
|
||||
"vendor__ra_ap_hir-0.0.257",
|
||||
"vendor__ra_ap_hir_def-0.0.257",
|
||||
"vendor__ra_ap_hir_expand-0.0.257",
|
||||
"vendor__ra_ap_ide_db-0.0.257",
|
||||
"vendor__ra_ap_intern-0.0.257",
|
||||
"vendor__ra_ap_load-cargo-0.0.257",
|
||||
"vendor__ra_ap_parser-0.0.257",
|
||||
"vendor__ra_ap_paths-0.0.257",
|
||||
"vendor__ra_ap_project_model-0.0.257",
|
||||
"vendor__ra_ap_span-0.0.257",
|
||||
"vendor__ra_ap_stdx-0.0.257",
|
||||
"vendor__ra_ap_syntax-0.0.257",
|
||||
"vendor__ra_ap_vfs-0.0.257",
|
||||
"vendor__rand-0.8.5",
|
||||
"vendor__rayon-1.10.0",
|
||||
"vendor__regex-1.11.1",
|
||||
@@ -124,8 +124,7 @@ use_repo(
|
||||
"vendor__serde_json-1.0.135",
|
||||
"vendor__serde_with-3.12.0",
|
||||
"vendor__stderrlog-0.6.0",
|
||||
"vendor__syn-2.0.96",
|
||||
"vendor__toml-0.8.19",
|
||||
"vendor__syn-2.0.95",
|
||||
"vendor__tracing-0.1.41",
|
||||
"vendor__tracing-subscriber-0.3.19",
|
||||
"vendor__tree-sitter-0.24.6",
|
||||
@@ -218,7 +217,6 @@ use_repo(
|
||||
"kotlin-compiler-2.0.0-RC1",
|
||||
"kotlin-compiler-2.0.20-Beta2",
|
||||
"kotlin-compiler-2.1.0-Beta1",
|
||||
"kotlin-compiler-2.1.20-Beta1",
|
||||
"kotlin-compiler-embeddable-1.5.0",
|
||||
"kotlin-compiler-embeddable-1.5.10",
|
||||
"kotlin-compiler-embeddable-1.5.20",
|
||||
@@ -233,7 +231,6 @@ use_repo(
|
||||
"kotlin-compiler-embeddable-2.0.0-RC1",
|
||||
"kotlin-compiler-embeddable-2.0.20-Beta2",
|
||||
"kotlin-compiler-embeddable-2.1.0-Beta1",
|
||||
"kotlin-compiler-embeddable-2.1.20-Beta1",
|
||||
"kotlin-stdlib-1.5.0",
|
||||
"kotlin-stdlib-1.5.10",
|
||||
"kotlin-stdlib-1.5.20",
|
||||
@@ -248,7 +245,6 @@ use_repo(
|
||||
"kotlin-stdlib-2.0.0-RC1",
|
||||
"kotlin-stdlib-2.0.20-Beta2",
|
||||
"kotlin-stdlib-2.1.0-Beta1",
|
||||
"kotlin-stdlib-2.1.20-Beta1",
|
||||
)
|
||||
|
||||
go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk")
|
||||
|
||||
@@ -2,16 +2,10 @@ if (($null -ne $env:LGTM_INDEX_INCLUDE) -or ($null -ne $env:LGTM_INDEX_EXCLUDE)
|
||||
Write-Output 'Path filters set. Passing them through to the JavaScript extractor.'
|
||||
} else {
|
||||
Write-Output 'No path filters set. Using the default filters.'
|
||||
# Note: We're adding the `reusable_workflows` subdirectories to proactively
|
||||
# record workflows that were called cross-repo, check them out locally,
|
||||
# and enable an interprocedural analysis across the workflow files.
|
||||
# These workflows follow the convention `.github/reusable_workflows/<nwo>/*.ya?ml`
|
||||
$DefaultPathFilters = @(
|
||||
'exclude:**/*',
|
||||
'include:.github/workflows/*.yml',
|
||||
'include:.github/workflows/*.yaml',
|
||||
'include:.github/reusable_workflows/**/*.yml',
|
||||
'include:.github/reusable_workflows/**/*.yaml',
|
||||
'include:.github/workflows/**/*.yml',
|
||||
'include:.github/workflows/**/*.yaml',
|
||||
'include:**/action.yml',
|
||||
'include:**/action.yaml'
|
||||
)
|
||||
|
||||
@@ -2,16 +2,10 @@
|
||||
|
||||
set -eu
|
||||
|
||||
# Note: We're adding the `reusable_workflows` subdirectories to proactively
|
||||
# record workflows that were called cross-repo, check them out locally,
|
||||
# and enable an interprocedural analysis across the workflow files.
|
||||
# These workflows follow the convention `.github/reusable_workflows/<nwo>/*.ya?ml`
|
||||
DEFAULT_PATH_FILTERS=$(cat << END
|
||||
exclude:**/*
|
||||
include:.github/workflows/*.yml
|
||||
include:.github/workflows/*.yaml
|
||||
include:.github/reusable_workflows/**/*.yml
|
||||
include:.github/reusable_workflows/**/*.yaml
|
||||
include:.github/workflows/**/*.yml
|
||||
include:.github/workflows/**/*.yaml
|
||||
include:**/action.yml
|
||||
include:**/action.yaml
|
||||
END
|
||||
|
||||
@@ -1,10 +1,3 @@
|
||||
## 0.4.2
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Fixed data for vulnerable versions of `actions/download-artifact` and `rlespinasse/github-slug-action` (following GHSA-cxww-7g56-2vh6 and GHSA-6q4m-7476-932w).
|
||||
* Improved `untrustedGhCommandDataModel` regex for `gh pr view` and Bash taint analysis in GitHub Actions.
|
||||
|
||||
## 0.4.1
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
## 0.4.2
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Fixed data for vulnerable versions of `actions/download-artifact` and `rlespinasse/github-slug-action` (following GHSA-cxww-7g56-2vh6 and GHSA-6q4m-7476-932w).
|
||||
* Improved `untrustedGhCommandDataModel` regex for `gh pr view` and Bash taint analysis in GitHub Actions.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.4.2
|
||||
lastReleaseVersion: 0.4.1
|
||||
|
||||
@@ -695,19 +695,6 @@ module Bash {
|
||||
not varMatchesRegexTest(script, var2, alphaNumericRegex())
|
||||
)
|
||||
or
|
||||
exists(string var2, string value2, string var3, string value3 |
|
||||
// VAR2=$(cmd)
|
||||
// VAR3=$VAR2
|
||||
// echo "FIELD=${VAR3:-default}" >> $GITHUB_ENV (field, file_write_value)
|
||||
containsCmdSubstitution(value2, cmd) and
|
||||
script.getAnAssignment(var2, value2) and
|
||||
containsParameterExpansion(value3, var2, _, _) and
|
||||
script.getAnAssignment(var3, value3) and
|
||||
containsParameterExpansion(expr, var3, _, _) and
|
||||
not varMatchesRegexTest(script, var2, alphaNumericRegex()) and
|
||||
not varMatchesRegexTest(script, var3, alphaNumericRegex())
|
||||
)
|
||||
or
|
||||
// var reaches the file write directly
|
||||
// echo "FIELD=$(cmd)" >> $GITHUB_ENV (field, file_write_value)
|
||||
containsCmdSubstitution(expr, cmd)
|
||||
|
||||
@@ -134,10 +134,6 @@ private module Implementation implements CfgShared::InputSig<Location> {
|
||||
SuccessorType getAMatchingSuccessorType(Completion c) { result = c.getAMatchingSuccessorType() }
|
||||
|
||||
predicate isAbnormalExitType(SuccessorType t) { none() }
|
||||
|
||||
int idOfAstNode(AstNode node) { none() }
|
||||
|
||||
int idOfCfgScope(CfgScope scope) { none() }
|
||||
}
|
||||
|
||||
module CfgImpl = CfgShared::Make<Location, Implementation>;
|
||||
|
||||
@@ -7,29 +7,26 @@ extensions:
|
||||
# PULL REQUESTS
|
||||
#
|
||||
# HEAD_REF=$(gh pr view "${{ github.event.issue.number }}" --json headRefName -q '.headRefName')
|
||||
- ["gh\\s+pr\\b.*\\bview\\b.*\\bheadRefName\\b", "branch,oneline"]
|
||||
- ["gh\\s+pr\\b.*\\bview\\b.*\\.headRefName.*", "branch,oneline"]
|
||||
# TITLE=$(gh pr view $PR_NUMBER --json title --jq .title)
|
||||
# TITLE=$(gh pr view $PR_NUMBER --json "title")
|
||||
- ["gh\\s+pr\\b.*\\bview\\b.*\\btitle\\b", "title,oneline"]
|
||||
- ["gh\\s+pr\\b.*\\bview\\b.*\\.title.*", "title,oneline"]
|
||||
# BODY=$(gh pr view $PR_NUMBER --json body --jq .body)
|
||||
- ["gh\\s+pr\\b.*\\bview\\b.*\\bbody\\b", "text,multiline"]
|
||||
- ["gh\\s+pr\\b.*\\bview\\b.*\\.body.*", "text,multiline"]
|
||||
# COMMENTS="$(gh pr view --repo ${{ github.repository }} "$PR_NUMBER" --json "body,comments" -q '.body, .comments[].body')"
|
||||
- ["gh\\s+pr\\b.*\\bview\\b.*\\bcomments\\b", "text,multiline"]
|
||||
- ["gh\\s+pr\\b.*\\bview\\b.*\\.comments.*", "text,multiline"]
|
||||
# CHANGED_FILES="$(gh pr view --repo ${{ github.repository }} ${{ needs.check-comment.outputs.pull_number }} --json files --jq '.files.[].path')"
|
||||
- ["gh\\s+pr\\b.*\\bview\\b.*\\bfiles\\b", "filename,multiline"]
|
||||
- ["gh\\s+pr\\b.*\\bview\\b.*\\.files.*", "filename,multiline"]
|
||||
# AUTHOR=$(gh pr view ${ORI_PR} -R ${REPO} --json author -q '.author.login')
|
||||
- ["gh\\s+pr\\b.*\\bview\\b.*\\bauthor\\b", "username,oneline"]
|
||||
- ["gh\\s+pr\\b.*\\bview\\b.*\\.author.*", "username,oneline"]
|
||||
#
|
||||
# ISSUES
|
||||
#
|
||||
# TITLE=$(gh issue view "$ISSUE_NUMBER" --json title --jq '.title')
|
||||
# TITLE=$(gh issue view "$ISSUE_NUMBER" --json title,body)
|
||||
# TITLE=$(gh issue view "$ISSUE_NUMBER" --json "title,body")
|
||||
- ["gh\\s+issue\\b.*\\bview\\b.*\\btitle\\b", "title,oneline"]
|
||||
- ["gh\\s+issue\\b.*\\bview\\b.*\\.title.*", "title,oneline"]
|
||||
# BODY=$(gh issue view -R ${GITHUB_REPOSITORY} ${ORIGINAL_ISSUE_NUMBER} --json title,body,assignees --jq .body)
|
||||
- ["gh\\s+issue\\b.*\\bview\\b.*\\bbody\\b", "text,multiline"]
|
||||
- ["gh\\s+issue\\b.*\\bview\\b.*\\.body.*", "text,multiline"]
|
||||
# COMMENTS=$(gh issue view "$ISSUE_NUMBER" --json comments --jq '.comments[].body')
|
||||
- ["gh\\s+issue\\b.*\\bview\\b.*\\bcomments\\b", "text,multiline"]
|
||||
- ["gh\\s+issue\\b.*\\bview\\b.*\\.comments.*", "text,multiline"]
|
||||
#
|
||||
# API
|
||||
#
|
||||
|
||||
@@ -6,12 +6,38 @@ extensions:
|
||||
|
||||
# gh api /repos/actions/download-artifact/tags --jq 'map({name: .name, sha: .commit.sha})' --paginate | jq -r '.[] | "- \"\(.name)\", \"\(.sha)\""'
|
||||
|
||||
#
|
||||
# actions/download-artifact
|
||||
# https://github.com/advisories/GHSA-cxww-7g56-2vh6 Affected versions: >= 4.0.0, < 4.1.3
|
||||
- ["actions/download-artifact", "v4.1.2", "eaceaf801fd36c7dee90939fad912460b18a1ffe", "4.1.3"]
|
||||
- ["actions/download-artifact", "v4.1.1", "6b208ae046db98c579e8a3aa621ab581ff575935", "4.1.3"]
|
||||
- ["actions/download-artifact", "v4.1.0", "f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110", "4.1.3"]
|
||||
- ["actions/download-artifact", "v4.0.0", "7a1cd3216ca9260cd8022db641d960b1db4d1be4", "4.1.3"]
|
||||
- ["actions/download-artifact", "v4.1.6", "9c19ed7fe5d278cd354c7dfd5d3b88589c7e2395", "4.1.7"]
|
||||
- ["actions/download-artifact", "v4.1.5", "8caf195ad4b1dee92908e23f56eeb0696f1dd42d", "4.1.7"]
|
||||
- ["actions/download-artifact", "v4.1.4", "c850b930e6ba138125429b7e5c93fc707a7f8427", "4.1.7"]
|
||||
- ["actions/download-artifact", "v4.1.3", "87c55149d96e628cc2ef7e6fc2aab372015aec85", "4.1.7"]
|
||||
- ["actions/download-artifact", "v4.1.2", "eaceaf801fd36c7dee90939fad912460b18a1ffe", "4.1.7"]
|
||||
- ["actions/download-artifact", "v4.1.1", "6b208ae046db98c579e8a3aa621ab581ff575935", "4.1.7"]
|
||||
- ["actions/download-artifact", "v4.1.0", "f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110", "4.1.7"]
|
||||
- ["actions/download-artifact", "v4.0.0", "7a1cd3216ca9260cd8022db641d960b1db4d1be4", "4.1.7"]
|
||||
- ["actions/download-artifact", "v3.0.2", "9bc31d5ccc31df68ecc42ccf4149144866c47d8a", "4.1.7"]
|
||||
- ["actions/download-artifact", "v3.0.1", "9782bd6a9848b53b110e712e20e42d89988822b7", "4.1.7"]
|
||||
- ["actions/download-artifact", "v3.0.0", "fb598a63ae348fa914e94cd0ff38f362e927b741", "4.1.7"]
|
||||
- ["actions/download-artifact", "v3", "9bc31d5ccc31df68ecc42ccf4149144866c47d8a", "4.1.7"]
|
||||
- ["actions/download-artifact", "v3-node20", "246d7188e736d3686f6d19628d253ede9697bd55", "4.1.7"]
|
||||
- ["actions/download-artifact", "v2.1.1", "cbed621e49e4c01b044d60f6c80ea4ed6328b281", "4.1.7"]
|
||||
- ["actions/download-artifact", "v2.1.0", "f023be2c48cc18debc3bacd34cb396e0295e2869", "4.1.7"]
|
||||
- ["actions/download-artifact", "v2.0.10", "3be87be14a055c47b01d3bd88f8fe02320a9bb60", "4.1.7"]
|
||||
- ["actions/download-artifact", "v2.0.9", "158ca71f7c614ae705e79f25522ef4658df18253", "4.1.7"]
|
||||
- ["actions/download-artifact", "v2.0.8", "4a7a711286f30c025902c28b541c10e147a9b843", "4.1.7"]
|
||||
- ["actions/download-artifact", "v2.0.7", "f144d3c3916a86f4d6b11ff379d17a49d8f85dbc", "4.1.7"]
|
||||
- ["actions/download-artifact", "v2.0.6", "f8e41fbffeebb48c0273438d220bb2387727471f", "4.1.7"]
|
||||
- ["actions/download-artifact", "v2.0.5", "c3f5d00c8784369c43779f3d2611769594a61f7a", "4.1.7"]
|
||||
- ["actions/download-artifact", "v2.0.4", "b3cedea9bed36890c824f4065163b667eeca272b", "4.1.7"]
|
||||
- ["actions/download-artifact", "v2.0.3", "80d2d4023c185001eacb50e37afd7dd667ba8044", "4.1.7"]
|
||||
- ["actions/download-artifact", "v2.0.2", "381af06b4268a1e0ad7b7c7e5a09f1894977120f", "4.1.7"]
|
||||
- ["actions/download-artifact", "v2.0.1", "1ac47ba4b6af92e65d0438b64ce1ea49ce1cc48d", "4.1.7"]
|
||||
- ["actions/download-artifact", "v2.0", "1de1dea89c32dcb1f37183c96fe85cfe067b682a", "4.1.7"]
|
||||
- ["actions/download-artifact", "v2", "cbed621e49e4c01b044d60f6c80ea4ed6328b281", "4.1.7"]
|
||||
- ["actions/download-artifact", "v1.0.0", "18f0f591fbc635562c815484d73b6e8e3980482e", "4.1.7"]
|
||||
- ["actions/download-artifact", "v1", "18f0f591fbc635562c815484d73b6e8e3980482e", "4.1.7"]
|
||||
- ["actions/download-artifact", "1.0.0", "18f0f591fbc635562c815484d73b6e8e3980482e", "4.1.7"]
|
||||
|
||||
# tj-actions/changed-files
|
||||
# https://github.com/advisories/GHSA-mcph-m25j-8j63
|
||||
@@ -504,13 +530,22 @@ extensions:
|
||||
- ["gradle/gradle-build-action", "v1", "b3afdc78a7849557ab26e243ccf07548086da025", "2.4.2"]
|
||||
|
||||
# rlespinasse/github-slug-action
|
||||
# https://github.com/advisories/GHSA-6q4m-7476-932w Affected versions: >= 4.0.0, < 4.4.1
|
||||
# https://github.com/advisories/GHSA-6q4m-7476-932w
|
||||
# CVE-2023-27581
|
||||
- ["rlespinasse/github-slug-action", "v4.4.1", "102b1a064a9b145e56556e22b18b19c624538d94", "4.4.1"]
|
||||
- ["rlespinasse/github-slug-action", "v4.4.0", "a362e5fb42057a3a23a62218b050838f1bacca5d", "4.4.1"]
|
||||
- ["rlespinasse/github-slug-action", "v4.3.2", "b011e83cf8cb29e22dda828db30586691ae164e4", "4.4.1"]
|
||||
- ["rlespinasse/github-slug-action", "v4.3.1", "00198f89920d4454e37e4b27af2b7a8eba79c530", "4.4.1"]
|
||||
- ["rlespinasse/github-slug-action", "v4.3.0", "9c3571fd3dba541bfdaebc001482a49a1c1f136a", "4.4.1"]
|
||||
- ["rlespinasse/github-slug-action", "v4.2.5", "0141d9b38d1f21c3b3de63229e20b7b0ad7ef0f4", "4.4.1"]
|
||||
- ["rlespinasse/github-slug-action", "v3.9.0", "2daab132aa3a6e23ea9d409f9946b3bf6468cc77", "4.4.1"]
|
||||
- ["rlespinasse/github-slug-action", "v3.8.0", "4a00c29bc1c0a737315b4200af6c6991bb4ace18", "4.4.1"]
|
||||
- ["rlespinasse/github-slug-action", "v3.7.1", "5150a26d43ce06608443c66efea46fc6f3c50d38", "4.4.1"]
|
||||
- ["rlespinasse/github-slug-action", "v3.7.0", "ebfc49c0e9cd081acb7ba0634d8d6a711b4c73cf", "4.4.1"]
|
||||
- ["rlespinasse/github-slug-action", "v3", "2daab132aa3a6e23ea9d409f9946b3bf6468cc77", "4.4.1"]
|
||||
- ["rlespinasse/github-slug-action", "v3.x", "2daab132aa3a6e23ea9d409f9946b3bf6468cc77", "4.4.1"]
|
||||
- ["rlespinasse/github-slug-action", "v2.x", "9d2c65418d6ecbbd3c08e686997b30482e9f4a80", "4.4.1"]
|
||||
- ["rlespinasse/github-slug-action", "v1.1.x", "fbf6d7b9c7af4e8d06135dbc7d774e717d788731", "4.4.1"]
|
||||
- ["rlespinasse/github-slug-action", "4.2.5", "0141d9b38d1f21c3b3de63229e20b7b0ad7ef0f4", "4.4.1"]
|
||||
- ["rlespinasse/github-slug-action", "4.2.4", "33cd7a701db9c2baf4ad705d930ade51a9f25c14", "4.4.1"]
|
||||
- ["rlespinasse/github-slug-action", "4.2.3", "1615fcb48b5315152b3733b7bed1a9f5dfada6e3", "4.4.1"]
|
||||
@@ -520,6 +555,25 @@ extensions:
|
||||
- ["rlespinasse/github-slug-action", "4.1.0", "88f3ee8f6f5d1955de92f1fe2fdb301fd40207c6", "4.4.1"]
|
||||
- ["rlespinasse/github-slug-action", "4.0.1", "cd9871b66e11e9562e3f72469772fe100be4c95a", "4.4.1"]
|
||||
- ["rlespinasse/github-slug-action", "4.0.0", "bd31a9f564f7930eea1ecfc8d0e6aebc4bc3279f", "4.4.1"]
|
||||
- ["rlespinasse/github-slug-action", "3.6.1", "1bf76b7bc6ef7dc6ba597ff790f956d9082479d7", "4.4.1"]
|
||||
- ["rlespinasse/github-slug-action", "3.6.0", "172fe43594a58b5938e248ec757ada60cdb17e18", "4.4.1"]
|
||||
- ["rlespinasse/github-slug-action", "3.5.1", "016823880d193a56b180527cf7ee52f13c3cfe33", "4.4.1"]
|
||||
- ["rlespinasse/github-slug-action", "3.5.0", "4060fda2690bcebaabcd86db4fbc8e1c2817c835", "4.4.1"]
|
||||
- ["rlespinasse/github-slug-action", "3.4.0", "0c099abd978b382cb650281af13913c1905fdd50", "4.4.1"]
|
||||
- ["rlespinasse/github-slug-action", "3.3.0", "d1880ea5b39f611effb9f3f83f4d35bff34083a6", "4.4.1"]
|
||||
- ["rlespinasse/github-slug-action", "3.2.0", "c8d8ee50d00177c1e80dd57905fc61f81e437279", "4.4.1"]
|
||||
- ["rlespinasse/github-slug-action", "3.1.0", "e4699e49fcf890a3172a02c56ba78d867dbb9fd5", "4.4.1"]
|
||||
- ["rlespinasse/github-slug-action", "3.0.0", "6a873bec5ac11c6d2a11756b8763356da63a8939", "4.4.1"]
|
||||
- ["rlespinasse/github-slug-action", "2.2.0", "9d2c65418d6ecbbd3c08e686997b30482e9f4a80", "4.4.1"]
|
||||
- ["rlespinasse/github-slug-action", "2.1.1", "72cfc4cb1f36c102c48541cb59511a6267e89c95", "4.4.1"]
|
||||
- ["rlespinasse/github-slug-action", "2.1.0", "1172ed1802078eb665a55c252fc180138b907c51", "4.4.1"]
|
||||
- ["rlespinasse/github-slug-action", "2.0.0", "ca9a67fa1f1126b377a9d80dc1ea354284c71d21", "4.4.1"]
|
||||
- ["rlespinasse/github-slug-action", "1.2.0", "fbf6d7b9c7af4e8d06135dbc7d774e717d788731", "4.4.1"]
|
||||
- ["rlespinasse/github-slug-action", "1.1.1", "242e04c2d28ac5db296e5d8203dfd7dc6bcc17a9", "4.4.1"]
|
||||
- ["rlespinasse/github-slug-action", "1.1.0", "881085bcae8c3443a89cc9401f3e1c60fb014ed2", "4.4.1"]
|
||||
- ["rlespinasse/github-slug-action", "1.0.2", "a35a1a486a260cfd99c5b6f8c6034a2929ba9b3f", "4.4.1"]
|
||||
- ["rlespinasse/github-slug-action", "1.0.1", "e46186066296e23235242d0877e2b4fe54003d54", "4.4.1"]
|
||||
- ["rlespinasse/github-slug-action", "1.0.0", "9671420482a6e4c59c06f2d2d9e0605e941b1287", "4.4.1"]
|
||||
|
||||
# Azure/setup-kubectl
|
||||
# https://github.com/advisories/GHSA-p756-rfxh-x63h
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/actions-all
|
||||
version: 0.4.3-dev
|
||||
version: 0.4.1
|
||||
library: true
|
||||
warnOnImplicitThis: true
|
||||
dependencies:
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
## 0.4.2
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.4.1
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.4.2
|
||||
lastReleaseVersion: 0.4.1
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
- description: Extended and experimental security queries for GitHub Actions
|
||||
- import: codeql-suites/actions-code-scanning.qls
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/actions-queries
|
||||
version: 0.4.3-dev
|
||||
version: 0.4.1
|
||||
library: false
|
||||
warnOnImplicitThis: true
|
||||
groups: [actions, queries]
|
||||
|
||||
@@ -6,7 +6,7 @@ on:
|
||||
|
||||
jobs:
|
||||
test1:
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-22.04
|
||||
outputs:
|
||||
job_output: ${{ steps.source.outputs.value }}
|
||||
steps:
|
||||
|
||||
@@ -491,7 +491,7 @@ jobs:
|
||||
|
||||
send_results:
|
||||
name: Send results to webhook
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-22.04
|
||||
if: always()
|
||||
needs: [
|
||||
setup,
|
||||
|
||||
@@ -106,27 +106,7 @@ jobs:
|
||||
COMMENTS=$(gh api /repos/test/test/pulls/${PR_NUMBER}/comments --jq '.[].body')
|
||||
echo "comments=$COMMENTS" >> "$GITHUB_OUTPUT"
|
||||
- run: echo "${{ steps.comments.outputs.comments}}"
|
||||
pulls3:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- id: title1
|
||||
run: |
|
||||
DETAILS=$(gh pr view $PR_NUMBER --json "title,author,headRefName")
|
||||
TITLE=$(echo $DETAILS | jq -r '.title')
|
||||
echo "title=$TITLE" >> "$GITHUB_OUTPUT"
|
||||
- run: echo "${{ steps.title1.outputs.title}}"
|
||||
- id: title2
|
||||
run: |
|
||||
TITLE=$(gh pr view $PR_NUMBER --json "title,author,headRefName")
|
||||
TITLE=$(echo $TITLE | jq -r '.title')
|
||||
echo "title=$TITLE" >> "$GITHUB_OUTPUT"
|
||||
- run: echo "${{ steps.title2.outputs.title}}"
|
||||
- id: title3
|
||||
run: |
|
||||
TITLE=$(gh issue view "$ISSUE_NUMBER" --json title,author)
|
||||
TITLE=$(echo $TITLE | jq -r '.title')
|
||||
echo "title=$TITLE" >> "$GITHUB_OUTPUT"
|
||||
- run: echo "${{ steps.title3.outputs.title}}"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ on:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-22.04
|
||||
if: >
|
||||
(github.event.workflow_run.event == 'pull_request' ||
|
||||
github.event.workflow_run.event == 'pull_request_target') &&
|
||||
|
||||
@@ -3,7 +3,7 @@ on:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Run Issue form parser
|
||||
id: parse
|
||||
|
||||
@@ -128,14 +128,10 @@ edges
|
||||
| .github/workflows/test9.yml:12:9:20:6 | Uses Step: issue_body_parser_request | .github/workflows/test9.yml:10:17:10:70 | steps.issue_body_parser_request.outputs.payload | provenance | |
|
||||
| .github/workflows/test9.yml:12:9:20:6 | Uses Step: issue_body_parser_request | .github/workflows/test9.yml:20:20:20:73 | steps.issue_body_parser_request.outputs.payload | provenance | |
|
||||
| .github/workflows/test11.yml:19:7:21:4 | Job outputs node [pr_num] | .github/workflows/test11.yml:54:20:54:60 | needs.get-artifacts.outputs.pr_num | provenance | |
|
||||
| .github/workflows/test11.yml:19:7:21:4 | Job outputs node [ref] | .github/workflows/test11.yml:55:20:55:57 | needs.get-artifacts.outputs.ref | provenance | |
|
||||
| .github/workflows/test11.yml:19:16:19:50 | steps.set-ref.outputs.pr_num | .github/workflows/test11.yml:19:7:21:4 | Job outputs node [pr_num] | provenance | |
|
||||
| .github/workflows/test11.yml:20:13:20:44 | steps.set-ref.outputs.ref | .github/workflows/test11.yml:19:7:21:4 | Job outputs node [ref] | provenance | |
|
||||
| .github/workflows/test11.yml:22:9:30:6 | Uses Step | .github/workflows/test11.yml:32:14:44:44 | pr_num=$(jq -r '.pull_request.number' artifacts/event_file/event.json)\nif [ -z "$pr_num" ] \|\| [ "$pr_num" == "null" ]; then\n pr_num=""\nfi\n\nref=$pr_num\nif [ -z "$ref" ] \|\| [ "$ref" == "null" ]; then\n ref=${{ github.ref }}\nfi\n\necho "pr_num=$pr_num" >> $GITHUB_OUTPUT\necho "ref=$ref" >> $GITHUB_OUTPUT\n | provenance | Config |
|
||||
| .github/workflows/test11.yml:30:9:46:2 | Run Step: set-ref [pr_num] | .github/workflows/test11.yml:19:16:19:50 | steps.set-ref.outputs.pr_num | provenance | |
|
||||
| .github/workflows/test11.yml:30:9:46:2 | Run Step: set-ref [ref] | .github/workflows/test11.yml:20:13:20:44 | steps.set-ref.outputs.ref | provenance | |
|
||||
| .github/workflows/test11.yml:32:14:44:44 | pr_num=$(jq -r '.pull_request.number' artifacts/event_file/event.json)\nif [ -z "$pr_num" ] \|\| [ "$pr_num" == "null" ]; then\n pr_num=""\nfi\n\nref=$pr_num\nif [ -z "$ref" ] \|\| [ "$ref" == "null" ]; then\n ref=${{ github.ref }}\nfi\n\necho "pr_num=$pr_num" >> $GITHUB_OUTPUT\necho "ref=$ref" >> $GITHUB_OUTPUT\n | .github/workflows/test11.yml:30:9:46:2 | Run Step: set-ref [pr_num] | provenance | |
|
||||
| .github/workflows/test11.yml:32:14:44:44 | pr_num=$(jq -r '.pull_request.number' artifacts/event_file/event.json)\nif [ -z "$pr_num" ] \|\| [ "$pr_num" == "null" ]; then\n pr_num=""\nfi\n\nref=$pr_num\nif [ -z "$ref" ] \|\| [ "$ref" == "null" ]; then\n ref=${{ github.ref }}\nfi\n\necho "pr_num=$pr_num" >> $GITHUB_OUTPUT\necho "ref=$ref" >> $GITHUB_OUTPUT\n | .github/workflows/test11.yml:30:9:46:2 | Run Step: set-ref [ref] | provenance | |
|
||||
| .github/workflows/test14.yml:13:9:16:6 | Run Step: changed-files [files] | .github/workflows/test14.yml:16:21:16:60 | steps.changed-files.outputs.files | provenance | |
|
||||
| .github/workflows/test14.yml:14:14:15:117 | echo "files=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)" >> "$GITHUB_OUTPUT"\n | .github/workflows/test14.yml:13:9:16:6 | Run Step: changed-files [files] | provenance | |
|
||||
| .github/workflows/test14.yml:23:9:27:6 | Run Step: changed-files [files] | .github/workflows/test14.yml:27:21:27:60 | steps.changed-files.outputs.files | provenance | |
|
||||
@@ -203,12 +199,6 @@ edges
|
||||
| .github/workflows/test19.yml:100:14:102:48 | BODY=$(gh api /repos/test/test/issues/${{PR_NUMBER}} --jq ".body")\necho "body=$BODY" >> "$GITHUB_OUTPUT"\n | .github/workflows/test19.yml:99:9:103:6 | Run Step: body [body] | provenance | |
|
||||
| .github/workflows/test19.yml:104:9:108:6 | Run Step: comments [comments] | .github/workflows/test19.yml:108:21:108:57 | steps.comments.outputs.comments | provenance | |
|
||||
| .github/workflows/test19.yml:105:14:107:56 | COMMENTS=$(gh api /repos/test/test/pulls/${PR_NUMBER}/comments --jq '.[].body')\necho "comments=$COMMENTS" >> "$GITHUB_OUTPUT"\n | .github/workflows/test19.yml:104:9:108:6 | Run Step: comments [comments] | provenance | |
|
||||
| .github/workflows/test19.yml:112:9:117:6 | Run Step: title1 [title] | .github/workflows/test19.yml:117:21:117:52 | steps.title1.outputs.title | provenance | |
|
||||
| .github/workflows/test19.yml:113:14:116:50 | DETAILS=$(gh pr view $PR_NUMBER --json "title,author,headRefName")\nTITLE=$(echo $DETAILS \| jq -r '.title')\necho "title=$TITLE" >> "$GITHUB_OUTPUT"\n | .github/workflows/test19.yml:112:9:117:6 | Run Step: title1 [title] | provenance | |
|
||||
| .github/workflows/test19.yml:118:9:123:6 | Run Step: title2 [title] | .github/workflows/test19.yml:123:21:123:52 | steps.title2.outputs.title | provenance | |
|
||||
| .github/workflows/test19.yml:119:14:122:50 | TITLE=$(gh pr view $PR_NUMBER --json "title,author,headRefName")\nTITLE=$(echo $TITLE \| jq -r '.title')\necho "title=$TITLE" >> "$GITHUB_OUTPUT"\n | .github/workflows/test19.yml:118:9:123:6 | Run Step: title2 [title] | provenance | |
|
||||
| .github/workflows/test19.yml:124:9:129:6 | Run Step: title3 [title] | .github/workflows/test19.yml:129:21:129:52 | steps.title3.outputs.title | provenance | |
|
||||
| .github/workflows/test19.yml:125:14:128:50 | TITLE=$(gh issue view "$ISSUE_NUMBER" --json title,author)\nTITLE=$(echo $TITLE \| jq -r '.title')\necho "title=$TITLE" >> "$GITHUB_OUTPUT"\n | .github/workflows/test19.yml:124:9:129:6 | Run Step: title3 [title] | provenance | |
|
||||
| .github/workflows/test24.yml:8:9:17:6 | Uses Step: parse | .github/workflows/test24.yml:19:17:19:50 | steps.parse.outputs.payload | provenance | |
|
||||
| .github/workflows/test25.yml:9:9:12:6 | Uses Step: parse | .github/workflows/test25.yml:12:20:12:50 | steps.parse.outputs.data | provenance | |
|
||||
| .github/workflows/test25.yml:9:9:12:6 | Uses Step: parse | .github/workflows/test25.yml:13:20:13:58 | toJSON(steps.parse.outputs.data) | provenance | |
|
||||
@@ -505,15 +495,11 @@ nodes
|
||||
| .github/workflows/test10.yml:423:34:423:77 | github.event.workflow_run.head_branch | semmle.label | github.event.workflow_run.head_branch |
|
||||
| .github/workflows/test10.yml:518:34:518:77 | github.event.workflow_run.head_branch | semmle.label | github.event.workflow_run.head_branch |
|
||||
| .github/workflows/test11.yml:19:7:21:4 | Job outputs node [pr_num] | semmle.label | Job outputs node [pr_num] |
|
||||
| .github/workflows/test11.yml:19:7:21:4 | Job outputs node [ref] | semmle.label | Job outputs node [ref] |
|
||||
| .github/workflows/test11.yml:19:16:19:50 | steps.set-ref.outputs.pr_num | semmle.label | steps.set-ref.outputs.pr_num |
|
||||
| .github/workflows/test11.yml:20:13:20:44 | steps.set-ref.outputs.ref | semmle.label | steps.set-ref.outputs.ref |
|
||||
| .github/workflows/test11.yml:22:9:30:6 | Uses Step | semmle.label | Uses Step |
|
||||
| .github/workflows/test11.yml:30:9:46:2 | Run Step: set-ref [pr_num] | semmle.label | Run Step: set-ref [pr_num] |
|
||||
| .github/workflows/test11.yml:30:9:46:2 | Run Step: set-ref [ref] | semmle.label | Run Step: set-ref [ref] |
|
||||
| .github/workflows/test11.yml:32:14:44:44 | pr_num=$(jq -r '.pull_request.number' artifacts/event_file/event.json)\nif [ -z "$pr_num" ] \|\| [ "$pr_num" == "null" ]; then\n pr_num=""\nfi\n\nref=$pr_num\nif [ -z "$ref" ] \|\| [ "$ref" == "null" ]; then\n ref=${{ github.ref }}\nfi\n\necho "pr_num=$pr_num" >> $GITHUB_OUTPUT\necho "ref=$ref" >> $GITHUB_OUTPUT\n | semmle.label | pr_num=$(jq -r '.pull_request.number' artifacts/event_file/event.json)\nif [ -z "$pr_num" ] \|\| [ "$pr_num" == "null" ]; then\n pr_num=""\nfi\n\nref=$pr_num\nif [ -z "$ref" ] \|\| [ "$ref" == "null" ]; then\n ref=${{ github.ref }}\nfi\n\necho "pr_num=$pr_num" >> $GITHUB_OUTPUT\necho "ref=$ref" >> $GITHUB_OUTPUT\n |
|
||||
| .github/workflows/test11.yml:54:20:54:60 | needs.get-artifacts.outputs.pr_num | semmle.label | needs.get-artifacts.outputs.pr_num |
|
||||
| .github/workflows/test11.yml:55:20:55:57 | needs.get-artifacts.outputs.ref | semmle.label | needs.get-artifacts.outputs.ref |
|
||||
| .github/workflows/test12.yml:10:21:10:67 | github.event.pull_request.title \|\| "foo" | semmle.label | github.event.pull_request.title \|\| "foo" |
|
||||
| .github/workflows/test13.yml:10:21:10:57 | github.event.changes.body.from | semmle.label | github.event.changes.body.from |
|
||||
| .github/workflows/test13.yml:11:21:11:58 | github.event.changes.title.from | semmle.label | github.event.changes.title.from |
|
||||
@@ -620,15 +606,6 @@ nodes
|
||||
| .github/workflows/test19.yml:104:9:108:6 | Run Step: comments [comments] | semmle.label | Run Step: comments [comments] |
|
||||
| .github/workflows/test19.yml:105:14:107:56 | COMMENTS=$(gh api /repos/test/test/pulls/${PR_NUMBER}/comments --jq '.[].body')\necho "comments=$COMMENTS" >> "$GITHUB_OUTPUT"\n | semmle.label | COMMENTS=$(gh api /repos/test/test/pulls/${PR_NUMBER}/comments --jq '.[].body')\necho "comments=$COMMENTS" >> "$GITHUB_OUTPUT"\n |
|
||||
| .github/workflows/test19.yml:108:21:108:57 | steps.comments.outputs.comments | semmle.label | steps.comments.outputs.comments |
|
||||
| .github/workflows/test19.yml:112:9:117:6 | Run Step: title1 [title] | semmle.label | Run Step: title1 [title] |
|
||||
| .github/workflows/test19.yml:113:14:116:50 | DETAILS=$(gh pr view $PR_NUMBER --json "title,author,headRefName")\nTITLE=$(echo $DETAILS \| jq -r '.title')\necho "title=$TITLE" >> "$GITHUB_OUTPUT"\n | semmle.label | DETAILS=$(gh pr view $PR_NUMBER --json "title,author,headRefName")\nTITLE=$(echo $DETAILS \| jq -r '.title')\necho "title=$TITLE" >> "$GITHUB_OUTPUT"\n |
|
||||
| .github/workflows/test19.yml:117:21:117:52 | steps.title1.outputs.title | semmle.label | steps.title1.outputs.title |
|
||||
| .github/workflows/test19.yml:118:9:123:6 | Run Step: title2 [title] | semmle.label | Run Step: title2 [title] |
|
||||
| .github/workflows/test19.yml:119:14:122:50 | TITLE=$(gh pr view $PR_NUMBER --json "title,author,headRefName")\nTITLE=$(echo $TITLE \| jq -r '.title')\necho "title=$TITLE" >> "$GITHUB_OUTPUT"\n | semmle.label | TITLE=$(gh pr view $PR_NUMBER --json "title,author,headRefName")\nTITLE=$(echo $TITLE \| jq -r '.title')\necho "title=$TITLE" >> "$GITHUB_OUTPUT"\n |
|
||||
| .github/workflows/test19.yml:123:21:123:52 | steps.title2.outputs.title | semmle.label | steps.title2.outputs.title |
|
||||
| .github/workflows/test19.yml:124:9:129:6 | Run Step: title3 [title] | semmle.label | Run Step: title3 [title] |
|
||||
| .github/workflows/test19.yml:125:14:128:50 | TITLE=$(gh issue view "$ISSUE_NUMBER" --json title,author)\nTITLE=$(echo $TITLE \| jq -r '.title')\necho "title=$TITLE" >> "$GITHUB_OUTPUT"\n | semmle.label | TITLE=$(gh issue view "$ISSUE_NUMBER" --json title,author)\nTITLE=$(echo $TITLE \| jq -r '.title')\necho "title=$TITLE" >> "$GITHUB_OUTPUT"\n |
|
||||
| .github/workflows/test19.yml:129:21:129:52 | steps.title3.outputs.title | semmle.label | steps.title3.outputs.title |
|
||||
| .github/workflows/test21.yml:22:35:22:73 | github.event.head_commit.message | semmle.label | github.event.head_commit.message |
|
||||
| .github/workflows/test21.yml:23:36:23:74 | github.event.head_commit.message | semmle.label | github.event.head_commit.message |
|
||||
| .github/workflows/test21.yml:24:50:24:88 | github.event.head_commit.message | semmle.label | github.event.head_commit.message |
|
||||
@@ -790,7 +767,6 @@ subpaths
|
||||
| .github/workflows/test9.yml:31:42:31:99 | fromJson(needs.parse-issue.outputs.payload).version | .github/workflows/test9.yml:12:9:20:6 | Uses Step: issue_body_parser_request | .github/workflows/test9.yml:31:42:31:99 | fromJson(needs.parse-issue.outputs.payload).version | Potential code injection in $@, which may be controlled by an external user ($@). | .github/workflows/test9.yml:31:42:31:99 | fromJson(needs.parse-issue.outputs.payload).version | ${{ fromJson(needs.parse-issue.outputs.payload).version }} | .github/workflows/test9.yml:4:3:4:15 | issue_comment | issue_comment |
|
||||
| .github/workflows/test9.yml:39:42:39:72 | github.event.issue.title | .github/workflows/test9.yml:39:42:39:72 | github.event.issue.title | .github/workflows/test9.yml:39:42:39:72 | github.event.issue.title | Potential code injection in $@, which may be controlled by an external user ($@). | .github/workflows/test9.yml:39:42:39:72 | github.event.issue.title | ${{ github.event.issue.title }} | .github/workflows/test9.yml:4:3:4:15 | issue_comment | issue_comment |
|
||||
| .github/workflows/test11.yml:54:20:54:60 | needs.get-artifacts.outputs.pr_num | .github/workflows/test11.yml:22:9:30:6 | Uses Step | .github/workflows/test11.yml:54:20:54:60 | needs.get-artifacts.outputs.pr_num | Potential code injection in $@, which may be controlled by an external user ($@). | .github/workflows/test11.yml:54:20:54:60 | needs.get-artifacts.outputs.pr_num | ${{ needs.get-artifacts.outputs.pr_num }} | .github/workflows/test11.yml:4:3:4:14 | workflow_run | workflow_run |
|
||||
| .github/workflows/test11.yml:55:20:55:57 | needs.get-artifacts.outputs.ref | .github/workflows/test11.yml:22:9:30:6 | Uses Step | .github/workflows/test11.yml:55:20:55:57 | needs.get-artifacts.outputs.ref | Potential code injection in $@, which may be controlled by an external user ($@). | .github/workflows/test11.yml:55:20:55:57 | needs.get-artifacts.outputs.ref | ${{ needs.get-artifacts.outputs.ref }} | .github/workflows/test11.yml:4:3:4:14 | workflow_run | workflow_run |
|
||||
| .github/workflows/test12.yml:10:21:10:67 | github.event.pull_request.title \|\| "foo" | .github/workflows/test12.yml:10:21:10:67 | github.event.pull_request.title \|\| "foo" | .github/workflows/test12.yml:10:21:10:67 | github.event.pull_request.title \|\| "foo" | Potential code injection in $@, which may be controlled by an external user ($@). | .github/workflows/test12.yml:10:21:10:67 | github.event.pull_request.title \|\| "foo" | ${{ github.event.pull_request.title \|\| "foo" }} | .github/workflows/test12.yml:4:3:4:21 | pull_request_target | pull_request_target |
|
||||
| .github/workflows/test13.yml:10:21:10:57 | github.event.changes.body.from | .github/workflows/test13.yml:10:21:10:57 | github.event.changes.body.from | .github/workflows/test13.yml:10:21:10:57 | github.event.changes.body.from | Potential code injection in $@, which may be controlled by an external user ($@). | .github/workflows/test13.yml:10:21:10:57 | github.event.changes.body.from | ${{ github.event.changes.body.from }} | .github/workflows/test13.yml:4:3:4:21 | pull_request_target | pull_request_target |
|
||||
| .github/workflows/test13.yml:11:21:11:58 | github.event.changes.title.from | .github/workflows/test13.yml:11:21:11:58 | github.event.changes.title.from | .github/workflows/test13.yml:11:21:11:58 | github.event.changes.title.from | Potential code injection in $@, which may be controlled by an external user ($@). | .github/workflows/test13.yml:11:21:11:58 | github.event.changes.title.from | ${{ github.event.changes.title.from }} | .github/workflows/test13.yml:4:3:4:21 | pull_request_target | pull_request_target |
|
||||
@@ -831,9 +807,6 @@ subpaths
|
||||
| .github/workflows/test19.yml:98:21:98:51 | steps.title.outputs.title | .github/workflows/test19.yml:95:14:97:50 | TITLE=$(gh api /repos/test/test/issues/${{PR_NUMBER}} --jq ".title")\necho "title=$TITLE" >> "$GITHUB_OUTPUT"\n | .github/workflows/test19.yml:98:21:98:51 | steps.title.outputs.title | Potential code injection in $@, which may be controlled by an external user ($@). | .github/workflows/test19.yml:98:21:98:51 | steps.title.outputs.title | ${{ steps.title.outputs.title}} | .github/workflows/test19.yml:4:3:4:21 | pull_request_target | pull_request_target |
|
||||
| .github/workflows/test19.yml:103:21:103:49 | steps.body.outputs.body | .github/workflows/test19.yml:100:14:102:48 | BODY=$(gh api /repos/test/test/issues/${{PR_NUMBER}} --jq ".body")\necho "body=$BODY" >> "$GITHUB_OUTPUT"\n | .github/workflows/test19.yml:103:21:103:49 | steps.body.outputs.body | Potential code injection in $@, which may be controlled by an external user ($@). | .github/workflows/test19.yml:103:21:103:49 | steps.body.outputs.body | ${{ steps.body.outputs.body}} | .github/workflows/test19.yml:4:3:4:21 | pull_request_target | pull_request_target |
|
||||
| .github/workflows/test19.yml:108:21:108:57 | steps.comments.outputs.comments | .github/workflows/test19.yml:105:14:107:56 | COMMENTS=$(gh api /repos/test/test/pulls/${PR_NUMBER}/comments --jq '.[].body')\necho "comments=$COMMENTS" >> "$GITHUB_OUTPUT"\n | .github/workflows/test19.yml:108:21:108:57 | steps.comments.outputs.comments | Potential code injection in $@, which may be controlled by an external user ($@). | .github/workflows/test19.yml:108:21:108:57 | steps.comments.outputs.comments | ${{ steps.comments.outputs.comments}} | .github/workflows/test19.yml:4:3:4:21 | pull_request_target | pull_request_target |
|
||||
| .github/workflows/test19.yml:117:21:117:52 | steps.title1.outputs.title | .github/workflows/test19.yml:113:14:116:50 | DETAILS=$(gh pr view $PR_NUMBER --json "title,author,headRefName")\nTITLE=$(echo $DETAILS \| jq -r '.title')\necho "title=$TITLE" >> "$GITHUB_OUTPUT"\n | .github/workflows/test19.yml:117:21:117:52 | steps.title1.outputs.title | Potential code injection in $@, which may be controlled by an external user ($@). | .github/workflows/test19.yml:117:21:117:52 | steps.title1.outputs.title | ${{ steps.title1.outputs.title}} | .github/workflows/test19.yml:4:3:4:21 | pull_request_target | pull_request_target |
|
||||
| .github/workflows/test19.yml:123:21:123:52 | steps.title2.outputs.title | .github/workflows/test19.yml:119:14:122:50 | TITLE=$(gh pr view $PR_NUMBER --json "title,author,headRefName")\nTITLE=$(echo $TITLE \| jq -r '.title')\necho "title=$TITLE" >> "$GITHUB_OUTPUT"\n | .github/workflows/test19.yml:123:21:123:52 | steps.title2.outputs.title | Potential code injection in $@, which may be controlled by an external user ($@). | .github/workflows/test19.yml:123:21:123:52 | steps.title2.outputs.title | ${{ steps.title2.outputs.title}} | .github/workflows/test19.yml:4:3:4:21 | pull_request_target | pull_request_target |
|
||||
| .github/workflows/test19.yml:129:21:129:52 | steps.title3.outputs.title | .github/workflows/test19.yml:125:14:128:50 | TITLE=$(gh issue view "$ISSUE_NUMBER" --json title,author)\nTITLE=$(echo $TITLE \| jq -r '.title')\necho "title=$TITLE" >> "$GITHUB_OUTPUT"\n | .github/workflows/test19.yml:129:21:129:52 | steps.title3.outputs.title | Potential code injection in $@, which may be controlled by an external user ($@). | .github/workflows/test19.yml:129:21:129:52 | steps.title3.outputs.title | ${{ steps.title3.outputs.title}} | .github/workflows/test19.yml:4:3:4:21 | pull_request_target | pull_request_target |
|
||||
| .github/workflows/test24.yml:19:17:19:50 | steps.parse.outputs.payload | .github/workflows/test24.yml:8:9:17:6 | Uses Step: parse | .github/workflows/test24.yml:19:17:19:50 | steps.parse.outputs.payload | Potential code injection in $@, which may be controlled by an external user ($@). | .github/workflows/test24.yml:19:17:19:50 | steps.parse.outputs.payload | ${{ steps.parse.outputs.payload }} | .github/workflows/test24.yml:2:3:2:8 | issues | issues |
|
||||
| .github/workflows/test25.yml:12:20:12:50 | steps.parse.outputs.data | .github/workflows/test25.yml:9:9:12:6 | Uses Step: parse | .github/workflows/test25.yml:12:20:12:50 | steps.parse.outputs.data | Potential code injection in $@, which may be controlled by an external user ($@). | .github/workflows/test25.yml:12:20:12:50 | steps.parse.outputs.data | ${{ steps.parse.outputs.data }} | .github/workflows/test25.yml:3:5:3:10 | issues | issues |
|
||||
| .github/workflows/test25.yml:13:20:13:58 | toJSON(steps.parse.outputs.data) | .github/workflows/test25.yml:9:9:12:6 | Uses Step: parse | .github/workflows/test25.yml:13:20:13:58 | toJSON(steps.parse.outputs.data) | Potential code injection in $@, which may be controlled by an external user ($@). | .github/workflows/test25.yml:13:20:13:58 | toJSON(steps.parse.outputs.data) | ${{ toJSON(steps.parse.outputs.data) }} | .github/workflows/test25.yml:3:5:3:10 | issues | issues |
|
||||
|
||||
@@ -128,14 +128,10 @@ edges
|
||||
| .github/workflows/test9.yml:12:9:20:6 | Uses Step: issue_body_parser_request | .github/workflows/test9.yml:10:17:10:70 | steps.issue_body_parser_request.outputs.payload | provenance | |
|
||||
| .github/workflows/test9.yml:12:9:20:6 | Uses Step: issue_body_parser_request | .github/workflows/test9.yml:20:20:20:73 | steps.issue_body_parser_request.outputs.payload | provenance | |
|
||||
| .github/workflows/test11.yml:19:7:21:4 | Job outputs node [pr_num] | .github/workflows/test11.yml:54:20:54:60 | needs.get-artifacts.outputs.pr_num | provenance | |
|
||||
| .github/workflows/test11.yml:19:7:21:4 | Job outputs node [ref] | .github/workflows/test11.yml:55:20:55:57 | needs.get-artifacts.outputs.ref | provenance | |
|
||||
| .github/workflows/test11.yml:19:16:19:50 | steps.set-ref.outputs.pr_num | .github/workflows/test11.yml:19:7:21:4 | Job outputs node [pr_num] | provenance | |
|
||||
| .github/workflows/test11.yml:20:13:20:44 | steps.set-ref.outputs.ref | .github/workflows/test11.yml:19:7:21:4 | Job outputs node [ref] | provenance | |
|
||||
| .github/workflows/test11.yml:22:9:30:6 | Uses Step | .github/workflows/test11.yml:32:14:44:44 | pr_num=$(jq -r '.pull_request.number' artifacts/event_file/event.json)\nif [ -z "$pr_num" ] \|\| [ "$pr_num" == "null" ]; then\n pr_num=""\nfi\n\nref=$pr_num\nif [ -z "$ref" ] \|\| [ "$ref" == "null" ]; then\n ref=${{ github.ref }}\nfi\n\necho "pr_num=$pr_num" >> $GITHUB_OUTPUT\necho "ref=$ref" >> $GITHUB_OUTPUT\n | provenance | Config |
|
||||
| .github/workflows/test11.yml:30:9:46:2 | Run Step: set-ref [pr_num] | .github/workflows/test11.yml:19:16:19:50 | steps.set-ref.outputs.pr_num | provenance | |
|
||||
| .github/workflows/test11.yml:30:9:46:2 | Run Step: set-ref [ref] | .github/workflows/test11.yml:20:13:20:44 | steps.set-ref.outputs.ref | provenance | |
|
||||
| .github/workflows/test11.yml:32:14:44:44 | pr_num=$(jq -r '.pull_request.number' artifacts/event_file/event.json)\nif [ -z "$pr_num" ] \|\| [ "$pr_num" == "null" ]; then\n pr_num=""\nfi\n\nref=$pr_num\nif [ -z "$ref" ] \|\| [ "$ref" == "null" ]; then\n ref=${{ github.ref }}\nfi\n\necho "pr_num=$pr_num" >> $GITHUB_OUTPUT\necho "ref=$ref" >> $GITHUB_OUTPUT\n | .github/workflows/test11.yml:30:9:46:2 | Run Step: set-ref [pr_num] | provenance | |
|
||||
| .github/workflows/test11.yml:32:14:44:44 | pr_num=$(jq -r '.pull_request.number' artifacts/event_file/event.json)\nif [ -z "$pr_num" ] \|\| [ "$pr_num" == "null" ]; then\n pr_num=""\nfi\n\nref=$pr_num\nif [ -z "$ref" ] \|\| [ "$ref" == "null" ]; then\n ref=${{ github.ref }}\nfi\n\necho "pr_num=$pr_num" >> $GITHUB_OUTPUT\necho "ref=$ref" >> $GITHUB_OUTPUT\n | .github/workflows/test11.yml:30:9:46:2 | Run Step: set-ref [ref] | provenance | |
|
||||
| .github/workflows/test14.yml:13:9:16:6 | Run Step: changed-files [files] | .github/workflows/test14.yml:16:21:16:60 | steps.changed-files.outputs.files | provenance | |
|
||||
| .github/workflows/test14.yml:14:14:15:117 | echo "files=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)" >> "$GITHUB_OUTPUT"\n | .github/workflows/test14.yml:13:9:16:6 | Run Step: changed-files [files] | provenance | |
|
||||
| .github/workflows/test14.yml:23:9:27:6 | Run Step: changed-files [files] | .github/workflows/test14.yml:27:21:27:60 | steps.changed-files.outputs.files | provenance | |
|
||||
@@ -203,12 +199,6 @@ edges
|
||||
| .github/workflows/test19.yml:100:14:102:48 | BODY=$(gh api /repos/test/test/issues/${{PR_NUMBER}} --jq ".body")\necho "body=$BODY" >> "$GITHUB_OUTPUT"\n | .github/workflows/test19.yml:99:9:103:6 | Run Step: body [body] | provenance | |
|
||||
| .github/workflows/test19.yml:104:9:108:6 | Run Step: comments [comments] | .github/workflows/test19.yml:108:21:108:57 | steps.comments.outputs.comments | provenance | |
|
||||
| .github/workflows/test19.yml:105:14:107:56 | COMMENTS=$(gh api /repos/test/test/pulls/${PR_NUMBER}/comments --jq '.[].body')\necho "comments=$COMMENTS" >> "$GITHUB_OUTPUT"\n | .github/workflows/test19.yml:104:9:108:6 | Run Step: comments [comments] | provenance | |
|
||||
| .github/workflows/test19.yml:112:9:117:6 | Run Step: title1 [title] | .github/workflows/test19.yml:117:21:117:52 | steps.title1.outputs.title | provenance | |
|
||||
| .github/workflows/test19.yml:113:14:116:50 | DETAILS=$(gh pr view $PR_NUMBER --json "title,author,headRefName")\nTITLE=$(echo $DETAILS \| jq -r '.title')\necho "title=$TITLE" >> "$GITHUB_OUTPUT"\n | .github/workflows/test19.yml:112:9:117:6 | Run Step: title1 [title] | provenance | |
|
||||
| .github/workflows/test19.yml:118:9:123:6 | Run Step: title2 [title] | .github/workflows/test19.yml:123:21:123:52 | steps.title2.outputs.title | provenance | |
|
||||
| .github/workflows/test19.yml:119:14:122:50 | TITLE=$(gh pr view $PR_NUMBER --json "title,author,headRefName")\nTITLE=$(echo $TITLE \| jq -r '.title')\necho "title=$TITLE" >> "$GITHUB_OUTPUT"\n | .github/workflows/test19.yml:118:9:123:6 | Run Step: title2 [title] | provenance | |
|
||||
| .github/workflows/test19.yml:124:9:129:6 | Run Step: title3 [title] | .github/workflows/test19.yml:129:21:129:52 | steps.title3.outputs.title | provenance | |
|
||||
| .github/workflows/test19.yml:125:14:128:50 | TITLE=$(gh issue view "$ISSUE_NUMBER" --json title,author)\nTITLE=$(echo $TITLE \| jq -r '.title')\necho "title=$TITLE" >> "$GITHUB_OUTPUT"\n | .github/workflows/test19.yml:124:9:129:6 | Run Step: title3 [title] | provenance | |
|
||||
| .github/workflows/test24.yml:8:9:17:6 | Uses Step: parse | .github/workflows/test24.yml:19:17:19:50 | steps.parse.outputs.payload | provenance | |
|
||||
| .github/workflows/test25.yml:9:9:12:6 | Uses Step: parse | .github/workflows/test25.yml:12:20:12:50 | steps.parse.outputs.data | provenance | |
|
||||
| .github/workflows/test25.yml:9:9:12:6 | Uses Step: parse | .github/workflows/test25.yml:13:20:13:58 | toJSON(steps.parse.outputs.data) | provenance | |
|
||||
@@ -505,15 +495,11 @@ nodes
|
||||
| .github/workflows/test10.yml:423:34:423:77 | github.event.workflow_run.head_branch | semmle.label | github.event.workflow_run.head_branch |
|
||||
| .github/workflows/test10.yml:518:34:518:77 | github.event.workflow_run.head_branch | semmle.label | github.event.workflow_run.head_branch |
|
||||
| .github/workflows/test11.yml:19:7:21:4 | Job outputs node [pr_num] | semmle.label | Job outputs node [pr_num] |
|
||||
| .github/workflows/test11.yml:19:7:21:4 | Job outputs node [ref] | semmle.label | Job outputs node [ref] |
|
||||
| .github/workflows/test11.yml:19:16:19:50 | steps.set-ref.outputs.pr_num | semmle.label | steps.set-ref.outputs.pr_num |
|
||||
| .github/workflows/test11.yml:20:13:20:44 | steps.set-ref.outputs.ref | semmle.label | steps.set-ref.outputs.ref |
|
||||
| .github/workflows/test11.yml:22:9:30:6 | Uses Step | semmle.label | Uses Step |
|
||||
| .github/workflows/test11.yml:30:9:46:2 | Run Step: set-ref [pr_num] | semmle.label | Run Step: set-ref [pr_num] |
|
||||
| .github/workflows/test11.yml:30:9:46:2 | Run Step: set-ref [ref] | semmle.label | Run Step: set-ref [ref] |
|
||||
| .github/workflows/test11.yml:32:14:44:44 | pr_num=$(jq -r '.pull_request.number' artifacts/event_file/event.json)\nif [ -z "$pr_num" ] \|\| [ "$pr_num" == "null" ]; then\n pr_num=""\nfi\n\nref=$pr_num\nif [ -z "$ref" ] \|\| [ "$ref" == "null" ]; then\n ref=${{ github.ref }}\nfi\n\necho "pr_num=$pr_num" >> $GITHUB_OUTPUT\necho "ref=$ref" >> $GITHUB_OUTPUT\n | semmle.label | pr_num=$(jq -r '.pull_request.number' artifacts/event_file/event.json)\nif [ -z "$pr_num" ] \|\| [ "$pr_num" == "null" ]; then\n pr_num=""\nfi\n\nref=$pr_num\nif [ -z "$ref" ] \|\| [ "$ref" == "null" ]; then\n ref=${{ github.ref }}\nfi\n\necho "pr_num=$pr_num" >> $GITHUB_OUTPUT\necho "ref=$ref" >> $GITHUB_OUTPUT\n |
|
||||
| .github/workflows/test11.yml:54:20:54:60 | needs.get-artifacts.outputs.pr_num | semmle.label | needs.get-artifacts.outputs.pr_num |
|
||||
| .github/workflows/test11.yml:55:20:55:57 | needs.get-artifacts.outputs.ref | semmle.label | needs.get-artifacts.outputs.ref |
|
||||
| .github/workflows/test12.yml:10:21:10:67 | github.event.pull_request.title \|\| "foo" | semmle.label | github.event.pull_request.title \|\| "foo" |
|
||||
| .github/workflows/test13.yml:10:21:10:57 | github.event.changes.body.from | semmle.label | github.event.changes.body.from |
|
||||
| .github/workflows/test13.yml:11:21:11:58 | github.event.changes.title.from | semmle.label | github.event.changes.title.from |
|
||||
@@ -620,15 +606,6 @@ nodes
|
||||
| .github/workflows/test19.yml:104:9:108:6 | Run Step: comments [comments] | semmle.label | Run Step: comments [comments] |
|
||||
| .github/workflows/test19.yml:105:14:107:56 | COMMENTS=$(gh api /repos/test/test/pulls/${PR_NUMBER}/comments --jq '.[].body')\necho "comments=$COMMENTS" >> "$GITHUB_OUTPUT"\n | semmle.label | COMMENTS=$(gh api /repos/test/test/pulls/${PR_NUMBER}/comments --jq '.[].body')\necho "comments=$COMMENTS" >> "$GITHUB_OUTPUT"\n |
|
||||
| .github/workflows/test19.yml:108:21:108:57 | steps.comments.outputs.comments | semmle.label | steps.comments.outputs.comments |
|
||||
| .github/workflows/test19.yml:112:9:117:6 | Run Step: title1 [title] | semmle.label | Run Step: title1 [title] |
|
||||
| .github/workflows/test19.yml:113:14:116:50 | DETAILS=$(gh pr view $PR_NUMBER --json "title,author,headRefName")\nTITLE=$(echo $DETAILS \| jq -r '.title')\necho "title=$TITLE" >> "$GITHUB_OUTPUT"\n | semmle.label | DETAILS=$(gh pr view $PR_NUMBER --json "title,author,headRefName")\nTITLE=$(echo $DETAILS \| jq -r '.title')\necho "title=$TITLE" >> "$GITHUB_OUTPUT"\n |
|
||||
| .github/workflows/test19.yml:117:21:117:52 | steps.title1.outputs.title | semmle.label | steps.title1.outputs.title |
|
||||
| .github/workflows/test19.yml:118:9:123:6 | Run Step: title2 [title] | semmle.label | Run Step: title2 [title] |
|
||||
| .github/workflows/test19.yml:119:14:122:50 | TITLE=$(gh pr view $PR_NUMBER --json "title,author,headRefName")\nTITLE=$(echo $TITLE \| jq -r '.title')\necho "title=$TITLE" >> "$GITHUB_OUTPUT"\n | semmle.label | TITLE=$(gh pr view $PR_NUMBER --json "title,author,headRefName")\nTITLE=$(echo $TITLE \| jq -r '.title')\necho "title=$TITLE" >> "$GITHUB_OUTPUT"\n |
|
||||
| .github/workflows/test19.yml:123:21:123:52 | steps.title2.outputs.title | semmle.label | steps.title2.outputs.title |
|
||||
| .github/workflows/test19.yml:124:9:129:6 | Run Step: title3 [title] | semmle.label | Run Step: title3 [title] |
|
||||
| .github/workflows/test19.yml:125:14:128:50 | TITLE=$(gh issue view "$ISSUE_NUMBER" --json title,author)\nTITLE=$(echo $TITLE \| jq -r '.title')\necho "title=$TITLE" >> "$GITHUB_OUTPUT"\n | semmle.label | TITLE=$(gh issue view "$ISSUE_NUMBER" --json title,author)\nTITLE=$(echo $TITLE \| jq -r '.title')\necho "title=$TITLE" >> "$GITHUB_OUTPUT"\n |
|
||||
| .github/workflows/test19.yml:129:21:129:52 | steps.title3.outputs.title | semmle.label | steps.title3.outputs.title |
|
||||
| .github/workflows/test21.yml:22:35:22:73 | github.event.head_commit.message | semmle.label | github.event.head_commit.message |
|
||||
| .github/workflows/test21.yml:23:36:23:74 | github.event.head_commit.message | semmle.label | github.event.head_commit.message |
|
||||
| .github/workflows/test21.yml:24:50:24:88 | github.event.head_commit.message | semmle.label | github.event.head_commit.message |
|
||||
|
||||
@@ -7,15 +7,15 @@ jobs:
|
||||
test1:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/download-artifact@v1 # SECURE
|
||||
- uses: actions/download-artifact@v1.0.0 # SECURE
|
||||
- uses: actions/download-artifact@v2 # SECURE
|
||||
- uses: actions/download-artifact@v2.1.0 # SECURE
|
||||
- uses: actions/download-artifact@v3 # SECURE
|
||||
- uses: actions/download-artifact@v3.0.2 # SECURE
|
||||
- uses: actions/download-artifact@v1
|
||||
- uses: actions/download-artifact@v1.0.0
|
||||
- uses: actions/download-artifact@v2
|
||||
- uses: actions/download-artifact@v2.1.0
|
||||
- uses: actions/download-artifact@v3
|
||||
- uses: actions/download-artifact@v3.0.2
|
||||
- uses: actions/download-artifact@v4.1.0
|
||||
- uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2
|
||||
- uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 # SECURE
|
||||
- uses: actions/download-artifact@87c55149d96e628cc2ef7e6fc2aab372015aec85 # v4.1.3
|
||||
- uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
|
||||
- uses: actions/download-artifact@v4 # SECURE
|
||||
- uses: actions/download-artifact@v4.1.7 # SECURE
|
||||
- uses: actions/download-artifact@v4.1.8 # SECURE
|
||||
|
||||
@@ -1,2 +1,9 @@
|
||||
| .github/workflows/test1.yml:16:9:17:6 | Uses Step | The workflow is using a known vulnerable version ($@) of the $@ action. Update it to $@ | .github/workflows/test1.yml:16:9:17:6 | Uses Step | v4.1.0 | .github/workflows/test1.yml:16:9:17:6 | Uses Step | actions/download-artifact | .github/workflows/test1.yml:16:9:17:6 | Uses Step | 4.1.3 |
|
||||
| .github/workflows/test1.yml:17:9:18:6 | Uses Step | The workflow is using a known vulnerable version ($@) of the $@ action. Update it to $@ | .github/workflows/test1.yml:17:9:18:6 | Uses Step | eaceaf801fd36c7dee90939fad912460b18a1ffe | .github/workflows/test1.yml:17:9:18:6 | Uses Step | actions/download-artifact | .github/workflows/test1.yml:17:9:18:6 | Uses Step | 4.1.3 |
|
||||
| .github/workflows/test1.yml:10:9:11:6 | Uses Step | The workflow is using a known vulnerable version ($@) of the $@ action. Update it to $@ | .github/workflows/test1.yml:10:9:11:6 | Uses Step | v1 | .github/workflows/test1.yml:10:9:11:6 | Uses Step | actions/download-artifact | .github/workflows/test1.yml:10:9:11:6 | Uses Step | 4.1.7 |
|
||||
| .github/workflows/test1.yml:11:9:12:6 | Uses Step | The workflow is using a known vulnerable version ($@) of the $@ action. Update it to $@ | .github/workflows/test1.yml:11:9:12:6 | Uses Step | v1.0.0 | .github/workflows/test1.yml:11:9:12:6 | Uses Step | actions/download-artifact | .github/workflows/test1.yml:11:9:12:6 | Uses Step | 4.1.7 |
|
||||
| .github/workflows/test1.yml:12:9:13:6 | Uses Step | The workflow is using a known vulnerable version ($@) of the $@ action. Update it to $@ | .github/workflows/test1.yml:12:9:13:6 | Uses Step | v2 | .github/workflows/test1.yml:12:9:13:6 | Uses Step | actions/download-artifact | .github/workflows/test1.yml:12:9:13:6 | Uses Step | 4.1.7 |
|
||||
| .github/workflows/test1.yml:13:9:14:6 | Uses Step | The workflow is using a known vulnerable version ($@) of the $@ action. Update it to $@ | .github/workflows/test1.yml:13:9:14:6 | Uses Step | v2.1.0 | .github/workflows/test1.yml:13:9:14:6 | Uses Step | actions/download-artifact | .github/workflows/test1.yml:13:9:14:6 | Uses Step | 4.1.7 |
|
||||
| .github/workflows/test1.yml:14:9:15:6 | Uses Step | The workflow is using a known vulnerable version ($@) of the $@ action. Update it to $@ | .github/workflows/test1.yml:14:9:15:6 | Uses Step | v3 | .github/workflows/test1.yml:14:9:15:6 | Uses Step | actions/download-artifact | .github/workflows/test1.yml:14:9:15:6 | Uses Step | 4.1.7 |
|
||||
| .github/workflows/test1.yml:15:9:16:6 | Uses Step | The workflow is using a known vulnerable version ($@) of the $@ action. Update it to $@ | .github/workflows/test1.yml:15:9:16:6 | Uses Step | v3.0.2 | .github/workflows/test1.yml:15:9:16:6 | Uses Step | actions/download-artifact | .github/workflows/test1.yml:15:9:16:6 | Uses Step | 4.1.7 |
|
||||
| .github/workflows/test1.yml:16:9:17:6 | Uses Step | The workflow is using a known vulnerable version ($@) of the $@ action. Update it to $@ | .github/workflows/test1.yml:16:9:17:6 | Uses Step | v4.1.0 | .github/workflows/test1.yml:16:9:17:6 | Uses Step | actions/download-artifact | .github/workflows/test1.yml:16:9:17:6 | Uses Step | 4.1.7 |
|
||||
| .github/workflows/test1.yml:17:9:18:6 | Uses Step | The workflow is using a known vulnerable version ($@) of the $@ action. Update it to $@ | .github/workflows/test1.yml:17:9:18:6 | Uses Step | 87c55149d96e628cc2ef7e6fc2aab372015aec85 | .github/workflows/test1.yml:17:9:18:6 | Uses Step | actions/download-artifact | .github/workflows/test1.yml:17:9:18:6 | Uses Step | 4.1.7 |
|
||||
| .github/workflows/test1.yml:18:9:19:6 | Uses Step | The workflow is using a known vulnerable version ($@) of the $@ action. Update it to $@ | .github/workflows/test1.yml:18:9:19:6 | Uses Step | 9bc31d5ccc31df68ecc42ccf4149144866c47d8a | .github/workflows/test1.yml:18:9:19:6 | Uses Step | actions/download-artifact | .github/workflows/test1.yml:18:9:19:6 | Uses Step | 4.1.7 |
|
||||
|
||||
@@ -25,7 +25,7 @@ jobs:
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- uses: actions/download-artifact@v4.0.0
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: results
|
||||
- run: python test.py
|
||||
|
||||
@@ -7,7 +7,7 @@ on:
|
||||
jobs:
|
||||
test1:
|
||||
if: github.event.comment.body == '@metabase-bot run visual tests'
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Fetch issue
|
||||
uses: octokit/request-action@v2.x
|
||||
|
||||
@@ -7,7 +7,7 @@ on:
|
||||
jobs:
|
||||
test1:
|
||||
if: github.event.comment.body == '@metabase-bot run visual tests'
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Fetch issue
|
||||
uses: octokit/request-action@v2.x
|
||||
|
||||
@@ -21,9 +21,9 @@ jobs:
|
||||
matrix:
|
||||
include:
|
||||
- language: javascript
|
||||
os: ubuntu-24.04
|
||||
os: ubuntu-22.04
|
||||
- language: ruby
|
||||
os: ubuntu-24.04-16core
|
||||
os: ubuntu-22.04-16core
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,17 +0,0 @@
|
||||
class Stmt extends @stmt {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
class Location extends @location_stmt {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
predicate isConstevalIf(Stmt stmt) {
|
||||
exists(int kind | stmts(stmt, kind, _) | kind = 38 or kind = 39)
|
||||
}
|
||||
|
||||
from Stmt stmt, int kind, int kind_new, Location location
|
||||
where
|
||||
stmts(stmt, kind, location) and
|
||||
if isConstevalIf(stmt) then kind_new = 7 else kind_new = kind // Turns consteval if into a block with two block statements in it
|
||||
select stmt, kind_new, location
|
||||
@@ -1,5 +0,0 @@
|
||||
description: Support (not) consteval if
|
||||
compatibility: full
|
||||
consteval_if_then.rel: delete
|
||||
consteval_if_else.rel: delete
|
||||
stmts.rel: run stmts.qlo
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,21 +0,0 @@
|
||||
class PreprocessorDirective extends @preprocdirect {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
class Location extends @location_default {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
bindingset[kind]
|
||||
int getKind(int kind) {
|
||||
if kind = 14
|
||||
then result = 6 // Represent MSFT #import as #include
|
||||
else
|
||||
if kind = 15 or kind = 6
|
||||
then result = 3 // Represent #elifdef and #elifndef as #elif
|
||||
else result = kind
|
||||
}
|
||||
|
||||
from PreprocessorDirective ppd, int kind, Location l
|
||||
where preprocdirects(ppd, kind, l)
|
||||
select ppd, getKind(kind), l
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,3 +0,0 @@
|
||||
description: Support #elifdef, #elifndef and #import
|
||||
compatibility: full
|
||||
preprocdirects.rel: run preprocdirects.qlo
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,3 +0,0 @@
|
||||
description: Improve user types and proxy classes
|
||||
compatibility: full
|
||||
usertypes.rel: run usertypes.qlo
|
||||
@@ -1,10 +0,0 @@
|
||||
class UserType extends @usertype {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
bindingset[kind]
|
||||
int getKind(int kind) { if kind in [15, 16, 17] then result = 6 else result = kind }
|
||||
|
||||
from UserType usertype, string name, int kind
|
||||
where usertypes(usertype, name, kind)
|
||||
select usertype, name, getKind(kind)
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,4 +0,0 @@
|
||||
description: Mix typedefs and usings
|
||||
compatibility: full
|
||||
usertypes.rel: run usertypes.qlo
|
||||
usertype_alias_kind.rel: delete
|
||||
@@ -1,20 +0,0 @@
|
||||
class UserType extends @usertype {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
int getTyperefKind(UserType usertype) {
|
||||
usertype_alias_kind(usertype, 0) and
|
||||
result = 5
|
||||
or
|
||||
usertype_alias_kind(usertype, 1) and
|
||||
result = 14
|
||||
}
|
||||
|
||||
bindingset[kind]
|
||||
int getKind(UserType usertype, int kind) {
|
||||
if kind = 18 then result = getTyperefKind(usertype) else result = kind
|
||||
}
|
||||
|
||||
from UserType usertype, string name, int kind
|
||||
where usertypes(usertype, name, kind)
|
||||
select usertype, name, getKind(usertype, kind)
|
||||
@@ -1,23 +1,7 @@
|
||||
## 4.0.0
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
* Deleted the deprecated `getAllocatorCall` predicate from `DeleteOrDeleteArrayExpr`, use `getDeallocatorCall` instead.
|
||||
|
||||
### New Features
|
||||
|
||||
* A new predicate `getOffsetInClass` was added to the `Field` class, which computes the byte offset of a field relative to a given `Class`.
|
||||
* New classes `PreprocessorElifdef` and `PreprocessorElifndef` were introduced, which represents the C23/C++23 `#elifdef` and `#elifndef` preprocessor directives.
|
||||
* A new class `TypeLibraryImport` was introduced, which represents the `#import` preprocessor directive as used by the Microsoft Visual C++ for importing type libraries.
|
||||
|
||||
## 3.2.0
|
||||
|
||||
### New Features
|
||||
|
||||
* Add a new predicate `getAnIndirectBarrier` to the parameterized module `InstructionBarrierGuard` in `semmle.code.cpp.dataflow.new.DataFlow` for computing indirect dataflow nodes that are guarded by a given instruction. This predicate is similar to the `getAnIndirectBarrier` predicate on the parameterized module `BarrierGuard`.
|
||||
* A new predicate `getDecltype` was added to the `ProxyClass` class, which yields the decltype for the proxy class.
|
||||
* Template classes that are of `struct` type are now also instances of the `Struct` class.
|
||||
* Template classes that are of `union` type are now also instances of the `Union` class.
|
||||
* A new abstract class `ConfigurationTestFile` (`semmle.code.cpp.ConfigurationTestFile.ConfigurationTestFile`) was introduced, which represents files created to test the build configuration. A subclass `CmakeTryCompileFile` of `ConfigurationTestFile` was also introduced, which represents files created by CMake to test the build configuration.
|
||||
* New predicates `getARequiresClause`, `getTemplateRequiresClause` and `getFunctionRequiresClause` were added to the `FunctionDeclarationEntry` class, which yield the requires clauses when the entry represents a function template declaration with requires clauses.
|
||||
* A new predicate `getRequiresClause` was added to the `TypeDeclarationEntry` class, which yields the requires clause when the entry represents a class template declaration with a requires clause.
|
||||
@@ -28,11 +12,6 @@
|
||||
* A new class `ConceptIdExpr` was introduced, which represents C++20 concept id expressions.
|
||||
* A new class `Concept` was introduced, which represents C++20 concepts.
|
||||
* The `getTemplateArgumentType` and `getTemplateArgumentValue` predicates of the `Declaration` class now also yield template arguments of concepts.
|
||||
* A new class `ConstevalIfStmt` was introduced, which represents the C++23 `if consteval` and `if ! consteval` statements.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* `DefaultOptions::exits` now holds for C23 functions with the `_Noreturn` or `___Noreturn__` attribute.
|
||||
|
||||
## 3.1.0
|
||||
|
||||
|
||||
@@ -54,11 +54,11 @@ class Options extends string {
|
||||
*
|
||||
* By default, this holds for `exit`, `_exit`, `_Exit`, `abort`,
|
||||
* `__assert_fail`, `longjmp`, `__builtin_unreachable` and any
|
||||
* function with a `noreturn`, `__noreturn__`, or `_Noreturn`
|
||||
* attribute or `noreturn` specifier.
|
||||
* function with a `noreturn` or `__noreturn__` attribute or
|
||||
* `noreturn` specifier.
|
||||
*/
|
||||
predicate exits(Function f) {
|
||||
f.getAnAttribute().hasName(["noreturn", "__noreturn__", "_Noreturn"])
|
||||
f.getAnAttribute().hasName(["noreturn", "__noreturn__"])
|
||||
or
|
||||
f.getASpecifier().hasName("noreturn")
|
||||
or
|
||||
|
||||
@@ -2,10 +2,6 @@
|
||||
|
||||
### New Features
|
||||
|
||||
* Add a new predicate `getAnIndirectBarrier` to the parameterized module `InstructionBarrierGuard` in `semmle.code.cpp.dataflow.new.DataFlow` for computing indirect dataflow nodes that are guarded by a given instruction. This predicate is similar to the `getAnIndirectBarrier` predicate on the parameterized module `BarrierGuard`.
|
||||
* A new predicate `getDecltype` was added to the `ProxyClass` class, which yields the decltype for the proxy class.
|
||||
* Template classes that are of `struct` type are now also instances of the `Struct` class.
|
||||
* Template classes that are of `union` type are now also instances of the `Union` class.
|
||||
* A new abstract class `ConfigurationTestFile` (`semmle.code.cpp.ConfigurationTestFile.ConfigurationTestFile`) was introduced, which represents files created to test the build configuration. A subclass `CmakeTryCompileFile` of `ConfigurationTestFile` was also introduced, which represents files created by CMake to test the build configuration.
|
||||
* New predicates `getARequiresClause`, `getTemplateRequiresClause` and `getFunctionRequiresClause` were added to the `FunctionDeclarationEntry` class, which yield the requires clauses when the entry represents a function template declaration with requires clauses.
|
||||
* A new predicate `getRequiresClause` was added to the `TypeDeclarationEntry` class, which yields the requires clause when the entry represents a class template declaration with a requires clause.
|
||||
@@ -16,8 +12,3 @@
|
||||
* A new class `ConceptIdExpr` was introduced, which represents C++20 concept id expressions.
|
||||
* A new class `Concept` was introduced, which represents C++20 concepts.
|
||||
* The `getTemplateArgumentType` and `getTemplateArgumentValue` predicates of the `Declaration` class now also yield template arguments of concepts.
|
||||
* A new class `ConstevalIfStmt` was introduced, which represents the C++23 `if consteval` and `if ! consteval` statements.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* `DefaultOptions::exits` now holds for C23 functions with the `_Noreturn` or `___Noreturn__` attribute.
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
## 4.0.0
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
* Deleted the deprecated `getAllocatorCall` predicate from `DeleteOrDeleteArrayExpr`, use `getDeallocatorCall` instead.
|
||||
|
||||
### New Features
|
||||
|
||||
* A new predicate `getOffsetInClass` was added to the `Field` class, which computes the byte offset of a field relative to a given `Class`.
|
||||
* New classes `PreprocessorElifdef` and `PreprocessorElifndef` were introduced, which represents the C23/C++23 `#elifdef` and `#elifndef` preprocessor directives.
|
||||
* A new class `TypeLibraryImport` was introduced, which represents the `#import` preprocessor directive as used by the Microsoft Visual C++ for importing type libraries.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 4.0.0
|
||||
lastReleaseVersion: 3.2.0
|
||||
|
||||
@@ -87,11 +87,11 @@ module LiteralAlgorithmTracerConfig implements DataFlow::ConfigSig {
|
||||
// False positives in OpenSSL also observed for CRYPTO_strndup (filtering any CRYPTO_* function)
|
||||
// due to setting a null byte in the string
|
||||
(
|
||||
isPossibleOpenSSLFunction(source.getFunction())
|
||||
isPossibleOpenSSLFunction(source.getEnclosingCallable())
|
||||
implies
|
||||
(
|
||||
not source.getFunction().getName().matches("OBJ_%") and
|
||||
not source.getFunction().getName().matches("CRYPTO_%")
|
||||
not source.getEnclosingCallable().getName().matches("OBJ_%") and
|
||||
not source.getEnclosingCallable().getName().matches("CRYPTO_%")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-all
|
||||
version: 4.0.1-dev
|
||||
version: 3.2.0
|
||||
groups: cpp
|
||||
dbscheme: semmlecode.cpp.dbscheme
|
||||
extractor: cpp
|
||||
|
||||
@@ -869,7 +869,7 @@ class AbstractClass extends Class {
|
||||
* `FullClassTemplateSpecialization`.
|
||||
*/
|
||||
class TemplateClass extends Class {
|
||||
TemplateClass() { usertypes(underlyingElement(this), _, [15, 16, 17]) }
|
||||
TemplateClass() { usertypes(underlyingElement(this), _, 6) }
|
||||
|
||||
/**
|
||||
* Gets a class instantiated from this template.
|
||||
@@ -1076,19 +1076,13 @@ class VirtualBaseClass extends Class {
|
||||
}
|
||||
|
||||
/**
|
||||
* The proxy class (where needed) associated with a template parameter or a
|
||||
* decltype, as in the following code:
|
||||
* ```cpp
|
||||
* The proxy class (where needed) associated with a template parameter, as
|
||||
* in the following code:
|
||||
* ```
|
||||
* template <typename T>
|
||||
* struct S : T { // the type of this T is a proxy class
|
||||
* ...
|
||||
* };
|
||||
*
|
||||
* template <typename T>
|
||||
* concept C =
|
||||
* decltype(std::span{std::declval<T&>()})::extent
|
||||
* != std::dynamic_extent;
|
||||
* // the type of decltype(std::span{std::declval<T&>()}) is a proxy class
|
||||
* ```
|
||||
*/
|
||||
class ProxyClass extends UserType {
|
||||
@@ -1099,13 +1093,10 @@ class ProxyClass extends UserType {
|
||||
/** Gets the location of the proxy class. */
|
||||
override Location getLocation() { result = this.getTemplateParameter().getDefinitionLocation() }
|
||||
|
||||
/** Gets the template parameter for which this is the proxy class, if any. */
|
||||
/** Gets the template parameter for which this is the proxy class. */
|
||||
TypeTemplateParameter getTemplateParameter() {
|
||||
is_proxy_class_for(underlyingElement(this), unresolveElement(result))
|
||||
}
|
||||
|
||||
/** Gets the decltype for which this is the proxy class, if any. */
|
||||
Decltype getDecltype() { is_proxy_class_for(underlyingElement(this), unresolveElement(result)) }
|
||||
}
|
||||
|
||||
// Unpacks "array of ... of array of t" into t.
|
||||
|
||||
@@ -5,30 +5,6 @@
|
||||
import semmle.code.cpp.Variable
|
||||
import semmle.code.cpp.Enum
|
||||
|
||||
private predicate hasAFieldWithOffset(Class c, Field f, int offset) {
|
||||
// Base case: `f` is a field in `c`.
|
||||
f = c.getAField() and
|
||||
offset = f.getByteOffset() and
|
||||
not f.getUnspecifiedType().(Class).hasDefinition()
|
||||
or
|
||||
// Otherwise, we find the struct that is a field of `c` which then has
|
||||
// the field `f` as a member.
|
||||
exists(Field g |
|
||||
g = c.getAField() and
|
||||
// Find the field with the largest offset that's less than or equal to
|
||||
// offset. That's the struct we need to search recursively.
|
||||
g =
|
||||
max(Field cand, int candOffset |
|
||||
cand = c.getAField() and
|
||||
candOffset = cand.getByteOffset() and
|
||||
offset >= candOffset
|
||||
|
|
||||
cand order by candOffset
|
||||
) and
|
||||
hasAFieldWithOffset(g.getUnspecifiedType(), f, offset - g.getByteOffset())
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A C structure member or C++ non-static member variable. For example the
|
||||
* member variable `m` in the following code (but not `s`):
|
||||
@@ -100,27 +76,6 @@ class Field extends MemberVariable {
|
||||
rank[result + 1](int index | cls.getCanonicalMember(index).(Field).isInitializable())
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the offset (in bytes) of this field starting at `c`.
|
||||
*
|
||||
* For example, consider:
|
||||
* ```cpp
|
||||
* struct S1 {
|
||||
* int a;
|
||||
* void* b;
|
||||
* };
|
||||
*
|
||||
* struct S2 {
|
||||
* S1 s1;
|
||||
* char c;
|
||||
* };
|
||||
* ```
|
||||
* If `f` represents the field `s1` and `c` represents the class `S2` then
|
||||
* `f.getOffsetInClass(S2) = 0` holds. Likewise, if `f` represents the
|
||||
* field `a`, then `f.getOffsetInClass(c) = 0` holds.
|
||||
*/
|
||||
int getOffsetInClass(Class c) { hasAFieldWithOffset(c, this, result) }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -57,9 +57,9 @@ class IncludeNext extends Include, @ppd_include_next {
|
||||
}
|
||||
|
||||
/**
|
||||
* An Objective C `#import` preprocessor directive (supported by GCC as
|
||||
* an extension in C). For example the following code contains one `Import`
|
||||
* directive:
|
||||
* A `#import` preprocessor directive (used heavily in Objective C, and
|
||||
* supported by GCC as an extension in C). For example the following code
|
||||
* contains one `Import` directive:
|
||||
* ```
|
||||
* #import <header3.h>
|
||||
* ```
|
||||
@@ -67,14 +67,3 @@ class IncludeNext extends Include, @ppd_include_next {
|
||||
class Import extends Include, @ppd_objc_import {
|
||||
override string toString() { result = "#import " + this.getIncludeText() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A Microsoft `#import` preprocessor directive for importing a type library.
|
||||
* For example the following code contains one `TypeLibraryImport` directive:
|
||||
* ```
|
||||
* #import "library.tlb"
|
||||
* ```
|
||||
*/
|
||||
class TypeLibraryImport extends Include, @ppd_ms_import {
|
||||
override string toString() { result = "#import " + this.getIncludeText() }
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ private class TPreprocessorBranchDirective = @ppd_branch or @ppd_else or @ppd_en
|
||||
|
||||
/**
|
||||
* A C/C++ preprocessor branch related directive: `#if`, `#ifdef`,
|
||||
* `#ifndef`, `#elif`, `#elifdef`, `#elifndef`, `#else` or `#endif`.
|
||||
* `#ifndef`, `#elif`, `#else` or `#endif`.
|
||||
*/
|
||||
class PreprocessorBranchDirective extends PreprocessorDirective, TPreprocessorBranchDirective {
|
||||
/**
|
||||
@@ -74,8 +74,8 @@ class PreprocessorBranchDirective extends PreprocessorDirective, TPreprocessorBr
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the next `#elif`, `#elifdef`, `#elifndef`, `#else` or `#endif` matching
|
||||
* this branching directive.
|
||||
* Gets the next `#elif`, `#else` or `#endif` matching this branching
|
||||
* directive.
|
||||
*
|
||||
* For example `somePreprocessorBranchDirective.getIf().getNext()` gets
|
||||
* the second directive in the same construct as
|
||||
@@ -88,8 +88,8 @@ class PreprocessorBranchDirective extends PreprocessorDirective, TPreprocessorBr
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the index of this branching directive within the matching `#if`,
|
||||
* `#ifdef` or `#ifndef`.
|
||||
* Gets the index of this branching directive within the matching #if,
|
||||
* #ifdef or #ifndef.
|
||||
*/
|
||||
private int getIndexInBranch(PreprocessorBranch branch) {
|
||||
this =
|
||||
@@ -102,8 +102,8 @@ class PreprocessorBranchDirective extends PreprocessorDirective, TPreprocessorBr
|
||||
}
|
||||
|
||||
/**
|
||||
* A C/C++ preprocessor branching directive: `#if`, `#ifdef`, `#ifndef`,
|
||||
* `#elif`, `#elifdef`, or `#elifndef`.
|
||||
* A C/C++ preprocessor branching directive: `#if`, `#ifdef`, `#ifndef`, or
|
||||
* `#elif`.
|
||||
*
|
||||
* A branching directive has a condition and that condition may be evaluated
|
||||
* at compile-time. As a result, the preprocessor will either take the
|
||||
@@ -151,8 +151,8 @@ class PreprocessorBranch extends PreprocessorBranchDirective, @ppd_branch {
|
||||
* #endif
|
||||
* ```
|
||||
* For the related notion of a directive which causes branching (which
|
||||
* includes `#if`, plus also `#ifdef`, `#ifndef`, `#elif`, `#elifdef`,
|
||||
* and `#elifndef`), see `PreprocessorBranch`.
|
||||
* includes `#if`, plus also `#ifdef`, `#ifndef`, and `#elif`), see
|
||||
* `PreprocessorBranch`.
|
||||
*/
|
||||
class PreprocessorIf extends PreprocessorBranch, @ppd_if {
|
||||
override string toString() { result = "#if " + this.getHead() }
|
||||
@@ -222,40 +222,6 @@ class PreprocessorElif extends PreprocessorBranch, @ppd_elif {
|
||||
override string toString() { result = "#elif " + this.getHead() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A C/C++ preprocessor `#elifdef` directive. For example there is a
|
||||
* `PreprocessorElifdef` on the third line of the following code:
|
||||
* ```
|
||||
* #ifdef MYDEFINE1
|
||||
* // ...
|
||||
* #elifdef MYDEFINE2
|
||||
* // ...
|
||||
* #else
|
||||
* // ...
|
||||
* #endif
|
||||
* ```
|
||||
*/
|
||||
class PreprocessorElifdef extends PreprocessorBranch, @ppd_elifdef {
|
||||
override string toString() { result = "#elifdef " + this.getHead() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A C/C++ preprocessor `#elifndef` directive. For example there is a
|
||||
* `PreprocessorElifndef` on the third line of the following code:
|
||||
* ```
|
||||
* #ifdef MYDEFINE1
|
||||
* // ...
|
||||
* #elifndef MYDEFINE2
|
||||
* // ...
|
||||
* #else
|
||||
* // ...
|
||||
* #endif
|
||||
* ```
|
||||
*/
|
||||
class PreprocessorElifndef extends PreprocessorBranch, @ppd_elifndef {
|
||||
override string toString() { result = "#elifndef " + this.getHead() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A C/C++ preprocessor `#endif` directive. For example there is a
|
||||
* `PreprocessorEndif` on the third line of the following code:
|
||||
|
||||
@@ -912,10 +912,6 @@ private predicate namedStmtChildPredicates(Locatable s, Element e, string pred)
|
||||
or
|
||||
s.(ConstexprIfStmt).getElse() = e and pred = "getElse()"
|
||||
or
|
||||
s.(ConstevalIfStmt).getThen() = e and pred = "getThen()"
|
||||
or
|
||||
s.(ConstevalIfStmt).getElse() = e and pred = "getElse()"
|
||||
or
|
||||
s.(Handler).getParameter() = e and pred = "getParameter()"
|
||||
or
|
||||
s.(IfStmt).getInitialization() = e and pred = "getInitialization()"
|
||||
|
||||
@@ -20,7 +20,7 @@ import semmle.code.cpp.Class
|
||||
* ```
|
||||
*/
|
||||
class Struct extends Class {
|
||||
Struct() { usertypes(underlyingElement(this), _, [1, 3, 15, 17]) }
|
||||
Struct() { usertypes(underlyingElement(this), _, 1) or usertypes(underlyingElement(this), _, 3) }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "Struct" }
|
||||
|
||||
|
||||
@@ -52,7 +52,9 @@ deprecated class TemplateParameter = TypeTemplateParameter;
|
||||
* ```
|
||||
*/
|
||||
class TypeTemplateParameter extends UserType, TemplateParameterImpl {
|
||||
TypeTemplateParameter() { usertypes(underlyingElement(this), _, [7, 8]) }
|
||||
TypeTemplateParameter() {
|
||||
usertypes(underlyingElement(this), _, 7) or usertypes(underlyingElement(this), _, 8)
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() { result = "TypeTemplateParameter" }
|
||||
|
||||
|
||||
@@ -406,7 +406,10 @@ class IntegralOrEnumType extends Type {
|
||||
isIntegralType(underlyingElement(this), _)
|
||||
or
|
||||
// Enum type
|
||||
usertypes(underlyingElement(this), _, [4, 13])
|
||||
(
|
||||
usertypes(underlyingElement(this), _, 4) or
|
||||
usertypes(underlyingElement(this), _, 13)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,10 @@ private import semmle.code.cpp.internal.ResolveClass
|
||||
* ```
|
||||
*/
|
||||
class TypedefType extends UserType {
|
||||
TypedefType() { usertypes(underlyingElement(this), _, 18) }
|
||||
TypedefType() {
|
||||
usertypes(underlyingElement(this), _, 5) or
|
||||
usertypes(underlyingElement(this), _, 14)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the base type of this typedef type.
|
||||
@@ -54,7 +57,7 @@ class TypedefType extends UserType {
|
||||
* ```
|
||||
*/
|
||||
class CTypedefType extends TypedefType {
|
||||
CTypedefType() { usertype_alias_kind(underlyingElement(this), 0) }
|
||||
CTypedefType() { usertypes(underlyingElement(this), _, 5) }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "CTypedefType" }
|
||||
|
||||
@@ -70,7 +73,7 @@ class CTypedefType extends TypedefType {
|
||||
* ```
|
||||
*/
|
||||
class UsingAliasTypedefType extends TypedefType {
|
||||
UsingAliasTypedefType() { usertype_alias_kind(underlyingElement(this), 1) }
|
||||
UsingAliasTypedefType() { usertypes(underlyingElement(this), _, 14) }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "UsingAliasTypedefType" }
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ import semmle.code.cpp.Struct
|
||||
* ```
|
||||
*/
|
||||
class Union extends Struct {
|
||||
Union() { usertypes(underlyingElement(this), _, [3, 17]) }
|
||||
Union() { usertypes(underlyingElement(this), _, 3) }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "Union" }
|
||||
|
||||
|
||||
@@ -47,16 +47,10 @@ class UserType extends Type, Declaration, NameQualifyingElement, AccessHolder, @
|
||||
else result = this.getADeclarationLocation()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private TypeDeclarationEntry getADeclarationEntryBase() {
|
||||
type_decls(underlyingElement(result), unresolveElement(this), _)
|
||||
}
|
||||
|
||||
override TypeDeclarationEntry getADeclarationEntry() {
|
||||
pragma[only_bind_into](result) = pragma[only_bind_into](this).getADeclarationEntryBase()
|
||||
or
|
||||
not exists(this.getADeclarationEntryBase()) and
|
||||
exists(Class t | this.(Class).isConstructedFrom(t) and result = t.getADeclarationEntry())
|
||||
if type_decls(_, unresolveElement(this), _)
|
||||
then type_decls(underlyingElement(result), unresolveElement(this), _)
|
||||
else exists(Class t | this.(Class).isConstructedFrom(t) and result = t.getADeclarationEntry())
|
||||
}
|
||||
|
||||
override Location getADeclarationLocation() { result = this.getADeclarationEntry().getLocation() }
|
||||
|
||||
@@ -24,78 +24,6 @@ predicate memberMayBeVarSize(Class c, MemberVariable v) {
|
||||
exists(ArrayType t | t = v.getUnspecifiedType() | not t.getArraySize() > 1)
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a chain of accesses of the form `x.f1.f2...fn` this
|
||||
* predicate gives the type of `x`. Note that `x` may be an implicit
|
||||
* `this` expression.
|
||||
*/
|
||||
private Class getRootType(FieldAccess fa) {
|
||||
// If the object is accessed inside a member function then the root will
|
||||
// be a(n implicit) `this`. And the root type will be the type of `this`.
|
||||
exists(VariableAccess root |
|
||||
root = fa.getQualifier*() and
|
||||
result =
|
||||
root.getQualifier()
|
||||
.(ThisExpr)
|
||||
.getUnspecifiedType()
|
||||
.(PointerType)
|
||||
.getBaseType()
|
||||
.getUnspecifiedType()
|
||||
)
|
||||
or
|
||||
// Otherwise, if this is not inside a member function there will not be
|
||||
// a(n implicit) `this`. And the root type is the type of the outermost
|
||||
// access.
|
||||
exists(VariableAccess root |
|
||||
root = fa.getQualifier+() and
|
||||
not exists(root.getQualifier()) and
|
||||
// We strip the type because the root may be a pointer. For example `p` in:
|
||||
// struct S { char buffer[10]; };
|
||||
// S* p = ...;
|
||||
// strcpy(p->buffer, "abc");
|
||||
result = root.getUnspecifiedType().stripType()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the size of the buffer access at `va`.
|
||||
*/
|
||||
private int getSize(VariableAccess va) {
|
||||
exists(Variable v | va.getTarget() = v |
|
||||
// If `v` is not a field then the size of the buffer is just
|
||||
// the size of the type of `v`.
|
||||
exists(Type t |
|
||||
t = v.getUnspecifiedType() and
|
||||
not v instanceof Field and
|
||||
not t instanceof ReferenceType and
|
||||
result = t.getSize()
|
||||
)
|
||||
or
|
||||
exists(Class c |
|
||||
// Otherwise, we find the "outermost" object and compute the size
|
||||
// as the difference between the size of the type of the "outermost
|
||||
// object" and the offset of the field relative to that type.
|
||||
// For example, consider the following structs:
|
||||
// ```
|
||||
// struct S {
|
||||
// uint32_t x;
|
||||
// uint32_t y;
|
||||
// };
|
||||
// struct S2 {
|
||||
// S s;
|
||||
// uint32_t z;
|
||||
// };
|
||||
// ```
|
||||
// Given an object `S2 s2` the size of the buffer `&s2.s.y`
|
||||
// is the size of the base object type (i.e., `S2`) minutes the offset
|
||||
// of `y` relative to the type `S2` (i.e., `4`). So the size of the
|
||||
// buffer is `12 - 4 = 8`.
|
||||
c = getRootType(va) and
|
||||
result = c.getSize() - v.(Field).getOffsetInClass(c)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `bufferExpr` is an allocation-like expression.
|
||||
*
|
||||
@@ -126,11 +54,22 @@ private int isSource(Expr bufferExpr, Element why) {
|
||||
result = bufferExpr.(AllocationExpr).getSizeBytes() and
|
||||
why = bufferExpr
|
||||
or
|
||||
exists(Variable v |
|
||||
v = why and
|
||||
exists(Type bufferType |
|
||||
// buffer is the address of a variable
|
||||
why = bufferExpr.(AddressOfExpr).getAddressable() and
|
||||
result = getSize(bufferExpr.(AddressOfExpr).getOperand())
|
||||
bufferType = why.(Variable).getUnspecifiedType() and
|
||||
result = bufferType.getSize() and
|
||||
not bufferType instanceof ReferenceType and
|
||||
not any(Union u).getAMemberVariable() = why
|
||||
)
|
||||
or
|
||||
exists(Union bufferType |
|
||||
// buffer is the address of a union member; in this case, we
|
||||
// take the size of the union itself rather the union member, since
|
||||
// it's usually OK to access that amount (e.g. clearing with memset).
|
||||
why = bufferExpr.(AddressOfExpr).getAddressable() and
|
||||
bufferType.getAMemberVariable() = why and
|
||||
result = bufferType.getSize()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -102,76 +102,49 @@ abstract private class GuardConditionImpl extends Expr {
|
||||
this.valueControls(controlled, any(BooleanValue bv | bv.getValue() = testIsTrue))
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if (determined by this guard) `left < right + k` evaluates to `isLessThan` if this
|
||||
* expression evaluates to `testIsTrue`. Note that there's a 4-argument
|
||||
* ("unary") and a 5-argument ("binary") version of this predicate (see `comparesEq`).
|
||||
*/
|
||||
/** Holds if (determined by this guard) `left < right + k` evaluates to `isLessThan` if this expression evaluates to `testIsTrue`. */
|
||||
pragma[inline]
|
||||
abstract predicate comparesLt(Expr left, Expr right, int k, boolean isLessThan, boolean testIsTrue);
|
||||
|
||||
/**
|
||||
* Holds if (determined by this guard) `left < right + k` must be `isLessThan` in `block`.
|
||||
* If `isLessThan = false` then this implies `left >= right + k`. Note that there's a 4-argument
|
||||
* ("unary") and a 5-argument ("binary") version of this predicate (see `comparesEq`).
|
||||
* If `isLessThan = false` then this implies `left >= right + k`.
|
||||
*/
|
||||
pragma[inline]
|
||||
abstract predicate ensuresLt(Expr left, Expr right, int k, BasicBlock block, boolean isLessThan);
|
||||
|
||||
/**
|
||||
* Holds if (determined by this guard) `e < k` evaluates to `isLessThan` if
|
||||
* this expression evaluates to `value`. Note that there's a 4-argument
|
||||
* ("unary") and a 5-argument ("binary") version of this predicate (see `comparesEq`).
|
||||
* this expression evaluates to `value`.
|
||||
*/
|
||||
pragma[inline]
|
||||
abstract predicate comparesLt(Expr e, int k, boolean isLessThan, AbstractValue value);
|
||||
|
||||
/**
|
||||
* Holds if (determined by this guard) `e < k` must be `isLessThan` in `block`.
|
||||
* If `isLessThan = false` then this implies `e >= k`. Note that there's a 4-argument
|
||||
* ("unary") and a 5-argument ("binary") version of this predicate (see `comparesEq`).
|
||||
* If `isLessThan = false` then this implies `e >= k`.
|
||||
*/
|
||||
pragma[inline]
|
||||
abstract predicate ensuresLt(Expr e, int k, BasicBlock block, boolean isLessThan);
|
||||
|
||||
/**
|
||||
* Holds if (determined by this guard) `left == right + k` evaluates to `areEqual` if this
|
||||
* expression evaluates to `testIsTrue`. Note that there's a 4-argument ("unary") and a
|
||||
* 5-argument ("binary") version of `comparesEq` and they are not equivalent:
|
||||
* - the unary version is suitable for guards where there is no expression representing the
|
||||
* right-hand side, such as `if (x)`, and also works for equality with an integer constant
|
||||
* (such as `if (x == k)`).
|
||||
* - the binary version is the more general case for comparison of any expressions (not
|
||||
* necessarily integer).
|
||||
*/
|
||||
/** Holds if (determined by this guard) `left == right + k` evaluates to `areEqual` if this expression evaluates to `testIsTrue`. */
|
||||
pragma[inline]
|
||||
abstract predicate comparesEq(Expr left, Expr right, int k, boolean areEqual, boolean testIsTrue);
|
||||
|
||||
/**
|
||||
* Holds if (determined by this guard) `left == right + k` must be `areEqual` in `block`.
|
||||
* If `areEqual = false` then this implies `left != right + k`. Note that there's a 4-argument
|
||||
* ("unary") and a 5-argument ("binary") version of this predicate (see `comparesEq`).
|
||||
* If `areEqual = false` then this implies `left != right + k`.
|
||||
*/
|
||||
pragma[inline]
|
||||
abstract predicate ensuresEq(Expr left, Expr right, int k, BasicBlock block, boolean areEqual);
|
||||
|
||||
/**
|
||||
* Holds if (determined by this guard) `e == k` evaluates to `areEqual` if this expression
|
||||
* evaluates to `value`. Note that there's a 4-argument ("unary") and a 5-argument ("binary")
|
||||
* version of `comparesEq` and they are not equivalent:
|
||||
* - the unary version is suitable for guards where there is no expression representing the
|
||||
* right-hand side, such as `if (x)`, and also works for equality with an integer constant
|
||||
* (such as `if (x == k)`).
|
||||
* - the binary version is the more general case for comparison of any expressions (not
|
||||
* necessarily integer).
|
||||
*/
|
||||
/** Holds if (determined by this guard) `e == k` evaluates to `areEqual` if this expression evaluates to `value`. */
|
||||
pragma[inline]
|
||||
abstract predicate comparesEq(Expr e, int k, boolean areEqual, AbstractValue value);
|
||||
|
||||
/**
|
||||
* Holds if (determined by this guard) `e == k` must be `areEqual` in `block`.
|
||||
* If `areEqual = false` then this implies `e != k`. Note that there's a 4-argument
|
||||
* ("unary") and a 5-argument ("binary") version of this predicate (see `comparesEq`).
|
||||
* If `areEqual = false` then this implies `e != k`.
|
||||
*/
|
||||
pragma[inline]
|
||||
abstract predicate ensuresEq(Expr e, int k, BasicBlock block, boolean areEqual);
|
||||
@@ -260,114 +233,6 @@ private class GuardConditionFromBinaryLogicalOperator extends GuardConditionImpl
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `ir` controls `block`, meaning that `block` is only
|
||||
* entered if the value of this condition is `v`. This helper
|
||||
* predicate does not necessarily hold for binary logical operations like
|
||||
* `&&` and `||`. See the detailed explanation on predicate `controls`.
|
||||
*/
|
||||
private predicate controlsBlock(IRGuardCondition ir, BasicBlock controlled, AbstractValue v) {
|
||||
exists(IRBlock irb |
|
||||
ir.valueControls(irb, v) and
|
||||
nonExcludedIRAndBasicBlock(irb, controlled) and
|
||||
not isUnreachedBlock(irb)
|
||||
)
|
||||
}
|
||||
|
||||
private class GuardConditionFromNotExpr extends GuardConditionImpl {
|
||||
IRGuardCondition ir;
|
||||
|
||||
GuardConditionFromNotExpr() {
|
||||
// Users often expect the `x` in `!x` to also be a guard condition. But
|
||||
// from the perspective of the IR the `x` is just the left-hand side of a
|
||||
// comparison against 0 so it's not included as a normal
|
||||
// `IRGuardCondition`. So to align with user expectations we make that `x`
|
||||
// a `GuardCondition`.
|
||||
exists(NotExpr notExpr |
|
||||
this = notExpr.getOperand() and
|
||||
ir.getUnconvertedResultExpression() = notExpr
|
||||
)
|
||||
}
|
||||
|
||||
override predicate valueControls(BasicBlock controlled, AbstractValue v) {
|
||||
// This condition must determine the flow of control; that is, this
|
||||
// node must be a top-level condition.
|
||||
controlsBlock(ir, controlled, v.getDualValue())
|
||||
}
|
||||
|
||||
pragma[inline]
|
||||
override predicate comparesLt(Expr left, Expr right, int k, boolean isLessThan, boolean testIsTrue) {
|
||||
exists(Instruction li, Instruction ri |
|
||||
li.getUnconvertedResultExpression() = left and
|
||||
ri.getUnconvertedResultExpression() = right and
|
||||
ir.comparesLt(li.getAUse(), ri.getAUse(), k, isLessThan, testIsTrue.booleanNot())
|
||||
)
|
||||
}
|
||||
|
||||
pragma[inline]
|
||||
override predicate comparesLt(Expr e, int k, boolean isLessThan, AbstractValue value) {
|
||||
exists(Instruction i |
|
||||
i.getUnconvertedResultExpression() = e and
|
||||
ir.comparesLt(i.getAUse(), k, isLessThan, value.getDualValue())
|
||||
)
|
||||
}
|
||||
|
||||
pragma[inline]
|
||||
override predicate ensuresLt(Expr left, Expr right, int k, BasicBlock block, boolean isLessThan) {
|
||||
exists(Instruction li, Instruction ri, boolean testIsTrue |
|
||||
li.getUnconvertedResultExpression() = left and
|
||||
ri.getUnconvertedResultExpression() = right and
|
||||
ir.comparesLt(li.getAUse(), ri.getAUse(), k, isLessThan, testIsTrue.booleanNot()) and
|
||||
this.controls(block, testIsTrue)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[inline]
|
||||
override predicate ensuresLt(Expr e, int k, BasicBlock block, boolean isLessThan) {
|
||||
exists(Instruction i, AbstractValue value |
|
||||
i.getUnconvertedResultExpression() = e and
|
||||
ir.comparesLt(i.getAUse(), k, isLessThan, value.getDualValue()) and
|
||||
this.valueControls(block, value)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[inline]
|
||||
override predicate comparesEq(Expr left, Expr right, int k, boolean areEqual, boolean testIsTrue) {
|
||||
exists(Instruction li, Instruction ri |
|
||||
li.getUnconvertedResultExpression() = left and
|
||||
ri.getUnconvertedResultExpression() = right and
|
||||
ir.comparesEq(li.getAUse(), ri.getAUse(), k, areEqual, testIsTrue.booleanNot())
|
||||
)
|
||||
}
|
||||
|
||||
pragma[inline]
|
||||
override predicate ensuresEq(Expr left, Expr right, int k, BasicBlock block, boolean areEqual) {
|
||||
exists(Instruction li, Instruction ri, boolean testIsTrue |
|
||||
li.getUnconvertedResultExpression() = left and
|
||||
ri.getUnconvertedResultExpression() = right and
|
||||
ir.comparesEq(li.getAUse(), ri.getAUse(), k, areEqual, testIsTrue.booleanNot()) and
|
||||
this.controls(block, testIsTrue)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[inline]
|
||||
override predicate comparesEq(Expr e, int k, boolean areEqual, AbstractValue value) {
|
||||
exists(Instruction i |
|
||||
i.getUnconvertedResultExpression() = e and
|
||||
ir.comparesEq(i.getAUse(), k, areEqual, value.getDualValue())
|
||||
)
|
||||
}
|
||||
|
||||
pragma[inline]
|
||||
override predicate ensuresEq(Expr e, int k, BasicBlock block, boolean areEqual) {
|
||||
exists(Instruction i, AbstractValue value |
|
||||
i.getUnconvertedResultExpression() = e and
|
||||
ir.comparesEq(i.getAUse(), k, areEqual, value.getDualValue()) and
|
||||
this.valueControls(block, value)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A Boolean condition in the AST that guards one or more basic blocks and has a corresponding IR
|
||||
* instruction.
|
||||
@@ -380,7 +245,7 @@ private class GuardConditionFromIR extends GuardConditionImpl {
|
||||
override predicate valueControls(BasicBlock controlled, AbstractValue v) {
|
||||
// This condition must determine the flow of control; that is, this
|
||||
// node must be a top-level condition.
|
||||
controlsBlock(ir, controlled, v)
|
||||
this.controlsBlock(controlled, v)
|
||||
}
|
||||
|
||||
pragma[inline]
|
||||
@@ -454,6 +319,20 @@ private class GuardConditionFromIR extends GuardConditionImpl {
|
||||
this.valueControls(block, value)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this condition controls `block`, meaning that `block` is only
|
||||
* entered if the value of this condition is `v`. This helper
|
||||
* predicate does not necessarily hold for binary logical operations like
|
||||
* `&&` and `||`. See the detailed explanation on predicate `controls`.
|
||||
*/
|
||||
private predicate controlsBlock(BasicBlock controlled, AbstractValue v) {
|
||||
exists(IRBlock irb |
|
||||
ir.valueControls(irb, v) and
|
||||
nonExcludedIRAndBasicBlock(irb, controlled) and
|
||||
not isUnreachedBlock(irb)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private predicate excludeAsControlledInstruction(Instruction instr) {
|
||||
@@ -709,7 +588,7 @@ class IRGuardCondition extends Instruction {
|
||||
/** Holds if (determined by this guard) `op == k` evaluates to `areEqual` if this expression evaluates to `value`. */
|
||||
pragma[inline]
|
||||
predicate comparesEq(Operand op, int k, boolean areEqual, AbstractValue value) {
|
||||
unary_compares_eq(valueNumber(this), op, k, areEqual, value)
|
||||
unary_compares_eq(valueNumber(this), op, k, areEqual, false, value)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -731,7 +610,7 @@ class IRGuardCondition extends Instruction {
|
||||
pragma[inline]
|
||||
predicate ensuresEq(Operand op, int k, IRBlock block, boolean areEqual) {
|
||||
exists(AbstractValue value |
|
||||
unary_compares_eq(valueNumber(this), op, k, areEqual, value) and
|
||||
unary_compares_eq(valueNumber(this), op, k, areEqual, false, value) and
|
||||
this.valueControls(block, value)
|
||||
)
|
||||
}
|
||||
@@ -757,7 +636,7 @@ class IRGuardCondition extends Instruction {
|
||||
pragma[inline]
|
||||
predicate ensuresEqEdge(Operand op, int k, IRBlock pred, IRBlock succ, boolean areEqual) {
|
||||
exists(AbstractValue value |
|
||||
unary_compares_eq(valueNumber(this), op, k, areEqual, value) and
|
||||
unary_compares_eq(valueNumber(this), op, k, areEqual, false, value) and
|
||||
this.valueControlsEdge(pred, succ, value)
|
||||
)
|
||||
}
|
||||
@@ -968,72 +847,77 @@ private module Cached {
|
||||
compares_eq(test.(BuiltinExpectCallValueNumber).getCondition(), left, right, k, areEqual, value)
|
||||
}
|
||||
|
||||
private predicate isConvertedBool(Instruction instr) {
|
||||
instr.getResultIRType() instanceof IRBooleanType
|
||||
or
|
||||
isConvertedBool(instr.(ConvertInstruction).getUnary())
|
||||
or
|
||||
isConvertedBool(instr.(BuiltinExpectCallInstruction).getCondition())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `op == k` is `areEqual` given that `test` is equal to `value`.
|
||||
*
|
||||
* Many internal predicates in this file have a `inNonZeroCase` column.
|
||||
* Ideally, the `k` column would be a type such as `Option<int>::Option`, to
|
||||
* represent whether we have a concrete value `k` such that `op == k`, or whether
|
||||
* we only know that `op != 0`.
|
||||
* However, cannot instantiate `Option` with an infinite type. Thus the boolean
|
||||
* `inNonZeroCase` is used to distinquish the `Some` (where we have a concrete
|
||||
* value `k`) and `None` cases (where we only know that `op != 0`).
|
||||
*
|
||||
* Thus, if `inNonZeroCase = true` then `op != 0` and the value of `k` is
|
||||
* meaningless.
|
||||
*
|
||||
* To see why `inNonZeroCase` is needed consider the following C program:
|
||||
* ```c
|
||||
* char* p = ...;
|
||||
* if(p) {
|
||||
* use(p);
|
||||
* }
|
||||
* ```
|
||||
* in C++ there would be an int-to-bool conversion on `p`. However, since C
|
||||
* does not have booleans there is no conversion. We want to be able to
|
||||
* conclude that `p` is non-zero in the true branch, so we need to give `k`
|
||||
* some value. However, simply setting `k = 1` would make the rest of the
|
||||
* analysis think that `k == 1` holds inside the branch. So we distinquish
|
||||
* between the above case and
|
||||
* ```c
|
||||
* if(p == 1) {
|
||||
* use(p)
|
||||
* }
|
||||
* ```
|
||||
* by setting `inNonZeroCase` to `true` in the former case, but not in the
|
||||
* latter.
|
||||
*/
|
||||
cached
|
||||
predicate unary_compares_eq(
|
||||
ValueNumber test, Operand op, int k, boolean areEqual, AbstractValue value
|
||||
ValueNumber test, Operand op, int k, boolean areEqual, boolean inNonZeroCase,
|
||||
AbstractValue value
|
||||
) {
|
||||
/* The simple case where the test *is* the comparison so areEqual = testIsTrue xor eq. */
|
||||
exists(AbstractValue v | unary_simple_comparison_eq(test, op, k, v) |
|
||||
exists(AbstractValue v | unary_simple_comparison_eq(test, op, k, inNonZeroCase, v) |
|
||||
areEqual = true and value = v
|
||||
or
|
||||
areEqual = false and value = v.getDualValue()
|
||||
)
|
||||
or
|
||||
unary_complex_eq(test, op, k, areEqual, value)
|
||||
unary_complex_eq(test, op, k, areEqual, inNonZeroCase, value)
|
||||
or
|
||||
/* (x is true => (op == k)) => (!x is false => (op == k)) */
|
||||
exists(AbstractValue dual |
|
||||
exists(AbstractValue dual, boolean inNonZeroCase0 |
|
||||
value = dual.getDualValue() and
|
||||
unary_compares_eq(test.(LogicalNotValueNumber).getUnary(), op, k, areEqual, dual)
|
||||
unary_compares_eq(test.(LogicalNotValueNumber).getUnary(), op, k, inNonZeroCase0, areEqual,
|
||||
dual)
|
||||
|
|
||||
k = 0 and inNonZeroCase = inNonZeroCase0
|
||||
or
|
||||
k != 0 and inNonZeroCase = true
|
||||
)
|
||||
or
|
||||
// ((test is `areEqual` => op == const + k2) and const == `k1`) =>
|
||||
// test is `areEqual` => op == k1 + k2
|
||||
inNonZeroCase = false and
|
||||
exists(int k1, int k2, Instruction const |
|
||||
compares_eq(test, op, const.getAUse(), k2, areEqual, value) and
|
||||
int_value(const) = k1 and
|
||||
k = k1 + k2
|
||||
)
|
||||
or
|
||||
exists(CompareValueNumber cmp, Operand left, Operand right, AbstractValue v |
|
||||
test = cmp and
|
||||
pragma[only_bind_into](cmp)
|
||||
.hasOperands(pragma[only_bind_into](left), pragma[only_bind_into](right)) and
|
||||
isConvertedBool(left.getDef()) and
|
||||
int_value(right.getDef()) = 0 and
|
||||
unary_compares_eq(valueNumberOfOperand(left), op, k, areEqual, v)
|
||||
|
|
||||
cmp instanceof CompareNEValueNumber and
|
||||
v = value
|
||||
or
|
||||
cmp instanceof CompareEQValueNumber and
|
||||
v.getDualValue() = value
|
||||
)
|
||||
or
|
||||
unary_compares_eq(test.(BuiltinExpectCallValueNumber).getCondition(), op, k, areEqual, value)
|
||||
or
|
||||
exists(BinaryLogicalOperation logical, Expr operand, boolean b |
|
||||
test.getAnInstruction().getUnconvertedResultExpression() = logical and
|
||||
op.getDef().getUnconvertedResultExpression() = operand and
|
||||
logical.impliesValue(operand, b, value.(BooleanValue).getValue())
|
||||
|
|
||||
k = 1 and
|
||||
areEqual = b
|
||||
or
|
||||
k = 0 and
|
||||
areEqual = b.booleanNot()
|
||||
)
|
||||
unary_compares_eq(test.(BuiltinExpectCallValueNumber).getCondition(), op, k, areEqual,
|
||||
inNonZeroCase, value)
|
||||
}
|
||||
|
||||
/** Rearrange various simple comparisons into `left == right + k` form. */
|
||||
@@ -1055,64 +939,74 @@ private module Cached {
|
||||
* Holds if `op` is an operand that is eventually used in a unary comparison
|
||||
* with a constant.
|
||||
*/
|
||||
private predicate mayBranchOn(Instruction instr) {
|
||||
exists(ConditionalBranchInstruction branch | branch.getCondition() = instr)
|
||||
private predicate isRelevantUnaryComparisonOperand(Operand op) {
|
||||
// Base case: `op` is an operand of a `CompareEQInstruction` or `CompareNEInstruction`,
|
||||
// and the other operand is a constant.
|
||||
exists(CompareInstruction eq, Instruction instr |
|
||||
eq.hasOperands(op, instr.getAUse()) and
|
||||
exists(int_value(instr))
|
||||
|
|
||||
eq instanceof CompareEQInstruction
|
||||
or
|
||||
eq instanceof CompareNEInstruction
|
||||
)
|
||||
or
|
||||
// C doesn't have int-to-bool conversions, so `if(x)` will just generate:
|
||||
// r2_1(glval<int>) = VariableAddress[x]
|
||||
// r2_2(int) = Load[x] : &:r2_1, m1_6
|
||||
// v2_3(void) = ConditionalBranch : r2_2
|
||||
exists(ConditionalBranchInstruction branch | branch.getConditionOperand() = op)
|
||||
or
|
||||
// If `!x` is a relevant unary comparison then so is `x`.
|
||||
exists(LogicalNotInstruction logicalNot |
|
||||
mayBranchOn(logicalNot) and
|
||||
logicalNot.getUnary() = instr
|
||||
isRelevantUnaryComparisonOperand(unique( | | logicalNot.getAUse())) and
|
||||
logicalNot.getUnaryOperand() = op
|
||||
)
|
||||
or
|
||||
// If `y` is a relevant unary comparison and `y = x` then so is `x`.
|
||||
not op.isDefinitionInexact() and
|
||||
exists(CopyInstruction copy |
|
||||
mayBranchOn(copy) and
|
||||
instr = copy.getSourceValue()
|
||||
isRelevantUnaryComparisonOperand(unique( | | copy.getAUse())) and
|
||||
op = copy.getSourceValueOperand()
|
||||
)
|
||||
or
|
||||
// If phi(x1, x2) is a relevant unary comparison then so are `x1` and `x2`.
|
||||
not op.isDefinitionInexact() and
|
||||
exists(PhiInstruction phi |
|
||||
mayBranchOn(phi) and
|
||||
instr = phi.getAnInput()
|
||||
isRelevantUnaryComparisonOperand(unique( | | phi.getAUse())) and
|
||||
op = phi.getAnInputOperand()
|
||||
)
|
||||
or
|
||||
// If `__builtin_expect(x)` is a relevant unary comparison then so is `x`.
|
||||
exists(BuiltinExpectCallInstruction call |
|
||||
mayBranchOn(call) and
|
||||
instr = call.getCondition()
|
||||
isRelevantUnaryComparisonOperand(unique( | | call.getAUse())) and
|
||||
op = call.getConditionOperand()
|
||||
)
|
||||
}
|
||||
|
||||
/** Rearrange various simple comparisons into `op == k` form. */
|
||||
private predicate unary_simple_comparison_eq(
|
||||
ValueNumber test, Operand op, int k, AbstractValue value
|
||||
ValueNumber test, Operand op, int k, boolean inNonZeroCase, AbstractValue value
|
||||
) {
|
||||
exists(CaseEdge case, SwitchConditionValueNumber condition |
|
||||
condition = test and
|
||||
op = condition.getExpressionOperand() and
|
||||
case = value.(MatchValue).getCase() and
|
||||
exists(condition.getSuccessor(case)) and
|
||||
case.getValue().toInt() = k
|
||||
case.getValue().toInt() = k and
|
||||
inNonZeroCase = false
|
||||
)
|
||||
or
|
||||
exists(Instruction const | int_value(const) = k |
|
||||
value.(BooleanValue).getValue() = true and
|
||||
test.(CompareEQValueNumber).hasOperands(op, const.getAUse())
|
||||
or
|
||||
value.(BooleanValue).getValue() = false and
|
||||
test.(CompareNEValueNumber).hasOperands(op, const.getAUse())
|
||||
)
|
||||
or
|
||||
exists(BooleanValue bv |
|
||||
bv = value and
|
||||
mayBranchOn(op.getDef()) and
|
||||
op = test.getAUse()
|
||||
|
|
||||
k = 0 and
|
||||
bv.getValue() = false
|
||||
or
|
||||
isRelevantUnaryComparisonOperand(op) and
|
||||
op.getDef() = test.getAnInstruction() and
|
||||
(
|
||||
k = 1 and
|
||||
bv.getValue() = true
|
||||
value.(BooleanValue).getValue() = true and
|
||||
inNonZeroCase = true
|
||||
or
|
||||
k = 0 and
|
||||
value.(BooleanValue).getValue() = false and
|
||||
inNonZeroCase = false
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1167,12 +1061,13 @@ private module Cached {
|
||||
* an instruction that compares the value of `__builtin_expect(op == k, _)` to `0`.
|
||||
*/
|
||||
private predicate unary_builtin_expect_eq(
|
||||
CompareValueNumber cmp, Operand op, int k, boolean areEqual, AbstractValue value
|
||||
CompareValueNumber cmp, Operand op, int k, boolean areEqual, boolean inNonZeroCase,
|
||||
AbstractValue value
|
||||
) {
|
||||
exists(BuiltinExpectCallValueNumber call, Instruction const, AbstractValue innerValue |
|
||||
int_value(const) = 0 and
|
||||
cmp.hasOperands(call.getAUse(), const.getAUse()) and
|
||||
unary_compares_eq(call.getCondition(), op, k, areEqual, innerValue)
|
||||
unary_compares_eq(call.getCondition(), op, k, areEqual, inNonZeroCase, innerValue)
|
||||
|
|
||||
cmp instanceof CompareNEValueNumber and
|
||||
value = innerValue
|
||||
@@ -1183,13 +1078,14 @@ private module Cached {
|
||||
}
|
||||
|
||||
private predicate unary_complex_eq(
|
||||
ValueNumber test, Operand op, int k, boolean areEqual, AbstractValue value
|
||||
ValueNumber test, Operand op, int k, boolean areEqual, boolean inNonZeroCase,
|
||||
AbstractValue value
|
||||
) {
|
||||
unary_sub_eq(test, op, k, areEqual, value)
|
||||
unary_sub_eq(test, op, k, areEqual, inNonZeroCase, value)
|
||||
or
|
||||
unary_add_eq(test, op, k, areEqual, value)
|
||||
unary_add_eq(test, op, k, areEqual, inNonZeroCase, value)
|
||||
or
|
||||
unary_builtin_expect_eq(test, op, k, areEqual, value)
|
||||
unary_builtin_expect_eq(test, op, k, areEqual, inNonZeroCase, value)
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1451,17 +1347,20 @@ private module Cached {
|
||||
|
||||
// op - x == c => op == (c+x)
|
||||
private predicate unary_sub_eq(
|
||||
ValueNumber test, Operand op, int k, boolean areEqual, AbstractValue value
|
||||
ValueNumber test, Operand op, int k, boolean areEqual, boolean inNonZeroCase,
|
||||
AbstractValue value
|
||||
) {
|
||||
inNonZeroCase = false and
|
||||
exists(SubInstruction sub, int c, int x |
|
||||
unary_compares_eq(test, sub.getAUse(), c, areEqual, value) and
|
||||
unary_compares_eq(test, sub.getAUse(), c, areEqual, inNonZeroCase, value) and
|
||||
op = sub.getLeftOperand() and
|
||||
x = int_value(sub.getRight()) and
|
||||
k = c + x
|
||||
)
|
||||
or
|
||||
inNonZeroCase = false and
|
||||
exists(PointerSubInstruction sub, int c, int x |
|
||||
unary_compares_eq(test, sub.getAUse(), c, areEqual, value) and
|
||||
unary_compares_eq(test, sub.getAUse(), c, areEqual, inNonZeroCase, value) and
|
||||
op = sub.getLeftOperand() and
|
||||
x = int_value(sub.getRight()) and
|
||||
k = c + x
|
||||
@@ -1516,10 +1415,12 @@ private module Cached {
|
||||
|
||||
// left + x == right + c => left == right + (c-x)
|
||||
private predicate unary_add_eq(
|
||||
ValueNumber test, Operand left, int k, boolean areEqual, AbstractValue value
|
||||
ValueNumber test, Operand left, int k, boolean areEqual, boolean inNonZeroCase,
|
||||
AbstractValue value
|
||||
) {
|
||||
inNonZeroCase = false and
|
||||
exists(AddInstruction lhs, int c, int x |
|
||||
unary_compares_eq(test, lhs.getAUse(), c, areEqual, value) and
|
||||
unary_compares_eq(test, lhs.getAUse(), c, areEqual, inNonZeroCase, value) and
|
||||
(
|
||||
left = lhs.getLeftOperand() and x = int_value(lhs.getRight())
|
||||
or
|
||||
@@ -1528,8 +1429,9 @@ private module Cached {
|
||||
k = c - x
|
||||
)
|
||||
or
|
||||
inNonZeroCase = false and
|
||||
exists(PointerAddInstruction lhs, int c, int x |
|
||||
unary_compares_eq(test, lhs.getAUse(), c, areEqual, value) and
|
||||
unary_compares_eq(test, lhs.getAUse(), c, areEqual, inNonZeroCase, value) and
|
||||
(
|
||||
left = lhs.getLeftOperand() and x = int_value(lhs.getRight())
|
||||
or
|
||||
@@ -1551,25 +1453,3 @@ private module Cached {
|
||||
}
|
||||
|
||||
private import Cached
|
||||
|
||||
/**
|
||||
* Holds if `left < right + k` evaluates to `isLt` given that some guard
|
||||
* evaluates to `value`.
|
||||
*
|
||||
* To find the specific guard that performs the comparison
|
||||
* use `IRGuards.comparesLt`.
|
||||
*/
|
||||
predicate comparesLt(Operand left, Operand right, int k, boolean isLt, AbstractValue value) {
|
||||
compares_lt(_, left, right, k, isLt, value)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `left = right + k` evaluates to `isLt` given that some guard
|
||||
* evaluates to `value`.
|
||||
*
|
||||
* To find the specific guard that performs the comparison
|
||||
* use `IRGuards.comparesEq`.
|
||||
*/
|
||||
predicate comparesEq(Operand left, Operand right, int k, boolean isLt, AbstractValue value) {
|
||||
compares_eq(_, left, right, k, isLt, value)
|
||||
}
|
||||
|
||||
@@ -876,25 +876,6 @@ private predicate subEdge(Pos p1, Node n1, Node n2, Pos p2) {
|
||||
p2.nodeAfter(n2, s)
|
||||
)
|
||||
or
|
||||
// NotConstevalIfStmt -> { then, else } ->
|
||||
exists(ConstevalIfStmt s |
|
||||
p1.nodeAt(n1, s) and
|
||||
p2.nodeBefore(n2, s.getThen())
|
||||
or
|
||||
p1.nodeAt(n1, s) and
|
||||
p2.nodeBefore(n2, s.getElse())
|
||||
or
|
||||
p1.nodeAt(n1, s) and
|
||||
not exists(s.getElse()) and
|
||||
p2.nodeAfter(n2, s)
|
||||
or
|
||||
p1.nodeAfter(n1, s.getThen()) and
|
||||
p2.nodeAfter(n2, s)
|
||||
or
|
||||
p1.nodeAfter(n1, s.getElse()) and
|
||||
p2.nodeAfter(n2, s)
|
||||
)
|
||||
or
|
||||
// WhileStmt -> condition ; body -> condition ; after dtors -> after
|
||||
exists(WhileStmt s |
|
||||
p1.nodeAt(n1, s) and
|
||||
|
||||
@@ -1110,6 +1110,11 @@ class DeleteOrDeleteArrayExpr extends Expr, TDeleteOrDeleteArrayExpr {
|
||||
expr_deallocator(underlyingElement(this), unresolveElement(result), _)
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: use `getDeallocatorCall` instead.
|
||||
*/
|
||||
deprecated FunctionCall getAllocatorCall() { result = this.getChild(0) }
|
||||
|
||||
/**
|
||||
* Gets the call to a non-default `operator delete`/`delete[]` that deallocates storage, if any.
|
||||
*
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
/**
|
||||
* This library offers a view of preprocessor branches (`#if`, `#ifdef`,
|
||||
* `#ifndef`, `#elif`, `#elifdef`, `#elifndef`, and `#else`) as blocks of
|
||||
* code between the opening and closing directives, with navigable
|
||||
* parent-child relationships to other blocks. The main class is
|
||||
* `PreprocessorBlock`.
|
||||
* `#ifndef`, `#elif` and `#else`) as blocks of code between the opening and
|
||||
* closing directives, with navigable parent-child relationships to other
|
||||
* blocks. The main class is `PreprocessorBlock`.
|
||||
*/
|
||||
|
||||
import cpp
|
||||
@@ -33,10 +32,10 @@ private int getPreprocIndex(PreprocessorBranchDirective directive) {
|
||||
|
||||
/**
|
||||
* A chunk of code from one preprocessor branch (`#if`, `#ifdef`,
|
||||
* `#ifndef`, `#elif`, `#elifdef`, `#elifndef`, or `#else`) to the
|
||||
* directive that closes it (`#elif`, `#elifdef`, `#elifndef`, `#else`,
|
||||
* or `#endif`). The `getParent()` method allows these blocks to be
|
||||
* navigated as a tree, with the root being the entire file.
|
||||
* `#ifndef`, `#elif` or `#else`) to the directive that closes it
|
||||
* (`#elif`, `#else` or `#endif`). The `getParent()` method
|
||||
* allows these blocks to be navigated as a tree, with the root
|
||||
* being the entire file.
|
||||
*/
|
||||
class PreprocessorBlock extends @element {
|
||||
PreprocessorBlock() {
|
||||
|
||||
@@ -227,11 +227,11 @@ class ProxyClass extends UserType {
|
||||
}
|
||||
|
||||
class TypeTemplateParameter extends UserType {
|
||||
TypeTemplateParameter() { usertypes(this, _, [7, 8]) }
|
||||
TypeTemplateParameter() { usertypes(this, _, 7) or usertypes(this, _, 8) }
|
||||
}
|
||||
|
||||
class TemplateClass extends UserType {
|
||||
TemplateClass() { usertypes(this, _, [15, 16, 17]) }
|
||||
TemplateClass() { usertypes(this, _, 6) }
|
||||
|
||||
UserType getAnInstantiation() {
|
||||
class_instantiation(result, this) and
|
||||
|
||||
@@ -114,7 +114,15 @@ private module Cached {
|
||||
* Holds if `t` is a struct, class, union, or template.
|
||||
*/
|
||||
cached
|
||||
predicate isClass(@usertype t) { usertypes(t, _, [1, 2, 3, 15, 16, 17]) }
|
||||
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)
|
||||
}
|
||||
|
||||
cached
|
||||
predicate isType(@type t) {
|
||||
|
||||
@@ -152,7 +152,7 @@ private module VirtualDispatch {
|
||||
ReturnNode node, ReturnKind kind, DataFlowCallable callable
|
||||
) {
|
||||
node.getKind() = kind and
|
||||
node.getFunction() = callable.getUnderlyingCallable()
|
||||
node.getEnclosingCallable() = callable.getUnderlyingCallable()
|
||||
}
|
||||
|
||||
/** Call through a function pointer. */
|
||||
|
||||
@@ -333,7 +333,9 @@ private module IndirectInstructions {
|
||||
import IndirectInstructions
|
||||
|
||||
/** Gets the callable in which this node occurs. */
|
||||
DataFlowCallable nodeGetEnclosingCallable(Node n) { result = n.getEnclosingCallable() }
|
||||
DataFlowCallable nodeGetEnclosingCallable(Node n) {
|
||||
result.getUnderlyingCallable() = n.getEnclosingCallable()
|
||||
}
|
||||
|
||||
/** Holds if `p` is a `ParameterNode` of `c` with position `pos`. */
|
||||
predicate isParameterNode(ParameterNode p, DataFlowCallable c, ParameterPosition pos) {
|
||||
@@ -380,7 +382,7 @@ private class SideEffectArgumentNode extends ArgumentNode, SideEffectOperandNode
|
||||
exists(int indirectionIndex |
|
||||
pos = TIndirectionPosition(argumentIndex, pragma[only_bind_into](indirectionIndex)) and
|
||||
this.getCallInstruction() = dfCall.asCallInstruction() and
|
||||
super.hasAddressOperandAndIndirectionIndex(arg, pragma[only_bind_into](indirectionIndex))
|
||||
super.hasAddressOperandAndIndirectionIndex(_, pragma[only_bind_into](indirectionIndex))
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1010,7 +1012,9 @@ class CastNode extends Node {
|
||||
|
||||
cached
|
||||
private newtype TDataFlowCallable =
|
||||
TSourceCallable(Cpp::Declaration decl) or
|
||||
TSourceCallable(Cpp::Declaration decl) {
|
||||
not decl instanceof FlowSummaryImpl::Public::SummarizedCallable
|
||||
} or
|
||||
TSummarizedCallable(FlowSummaryImpl::Public::SummarizedCallable c)
|
||||
|
||||
/**
|
||||
@@ -1123,21 +1127,7 @@ class DataFlowCall extends TDataFlowCall {
|
||||
/**
|
||||
* Gets the `Function` that the call targets, if this is statically known.
|
||||
*/
|
||||
Function getStaticCallSourceTarget() { none() }
|
||||
|
||||
/**
|
||||
* Gets the target of this call. If a summarized callable exists for the
|
||||
* target this is chosen, and otherwise the callable is the implementation
|
||||
* from the source code.
|
||||
*/
|
||||
DataFlowCallable getStaticCallTarget() {
|
||||
exists(Function target | target = this.getStaticCallSourceTarget() |
|
||||
not exists(TSummarizedCallable(target)) and
|
||||
result.asSourceCallable() = target
|
||||
or
|
||||
result.asSummarizedCallable() = target
|
||||
)
|
||||
}
|
||||
DataFlowCallable getStaticCallTarget() { none() }
|
||||
|
||||
/**
|
||||
* Gets the `index`'th argument operand. The qualifier is considered to have index `-1`.
|
||||
@@ -1183,12 +1173,14 @@ private class NormalCall extends DataFlowCall, TNormalCall {
|
||||
|
||||
override CallTargetOperand getCallTargetOperand() { result = call.getCallTargetOperand() }
|
||||
|
||||
override Function getStaticCallSourceTarget() { result = call.getStaticCallTarget() }
|
||||
override DataFlowCallable getStaticCallTarget() {
|
||||
result.getUnderlyingCallable() = call.getStaticCallTarget()
|
||||
}
|
||||
|
||||
override ArgumentOperand getArgumentOperand(int index) { result = call.getArgumentOperand(index) }
|
||||
|
||||
override DataFlowCallable getEnclosingCallable() {
|
||||
result.asSourceCallable() = call.getEnclosingFunction()
|
||||
result.getUnderlyingCallable() = call.getEnclosingFunction()
|
||||
}
|
||||
|
||||
override string toString() { result = call.toString() }
|
||||
@@ -1339,12 +1331,7 @@ predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c)
|
||||
/** Holds if `call` is a lambda call of kind `kind` where `receiver` is the lambda expression. */
|
||||
predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
|
||||
(
|
||||
call.(SummaryCall).getReceiver() = receiver.(FlowSummaryNode).getSummaryNode()
|
||||
or
|
||||
// No need to infer a lambda call if we already have a static dispatch target.
|
||||
// We only need to check this in the disjunct since a `SummaryCall` never
|
||||
// has a result for `getStaticCallTarget`.
|
||||
not exists(call.getStaticCallTarget()) and
|
||||
call.(SummaryCall).getReceiver() = receiver.(FlowSummaryNode).getSummaryNode() or
|
||||
call.asCallInstruction().getCallTargetOperand() = receiver.asOperand()
|
||||
) and
|
||||
exists(kind)
|
||||
|
||||
@@ -146,7 +146,7 @@ class Node extends TIRDataFlowNode {
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
DataFlowCallable getEnclosingCallable() { none() } // overridden in subclasses
|
||||
Declaration getEnclosingCallable() { none() } // overridden in subclasses
|
||||
|
||||
/** Gets the function to which this node belongs, if any. */
|
||||
Declaration getFunction() { none() } // overridden in subclasses
|
||||
@@ -508,9 +508,7 @@ private class Node0 extends Node, TNode0 {
|
||||
|
||||
Node0() { this = TNode0(node) }
|
||||
|
||||
override DataFlowCallable getEnclosingCallable() {
|
||||
result.asSourceCallable() = node.getEnclosingCallable()
|
||||
}
|
||||
override Declaration getEnclosingCallable() { result = node.getEnclosingCallable() }
|
||||
|
||||
override Declaration getFunction() { result = node.getFunction() }
|
||||
|
||||
@@ -575,9 +573,7 @@ class PostUpdateNodeImpl extends PartialDefinitionNode, TPostUpdateNodeImpl {
|
||||
|
||||
override Declaration getFunction() { result = operand.getUse().getEnclosingFunction() }
|
||||
|
||||
override DataFlowCallable getEnclosingCallable() {
|
||||
result = this.getPreUpdateNode().getEnclosingCallable()
|
||||
}
|
||||
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||
|
||||
/** Gets the operand associated with this node. */
|
||||
Operand getOperand() { result = operand }
|
||||
@@ -630,9 +626,7 @@ class SsaPhiNode extends Node, TSsaPhiNode {
|
||||
/** Gets the phi node associated with this node. */
|
||||
Ssa::PhiNode getPhiNode() { result = phi }
|
||||
|
||||
override DataFlowCallable getEnclosingCallable() {
|
||||
result.asSourceCallable() = this.getFunction()
|
||||
}
|
||||
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||
|
||||
override Declaration getFunction() { result = phi.getBasicBlock().getEnclosingFunction() }
|
||||
|
||||
@@ -715,9 +709,7 @@ class SsaPhiInputNode extends Node, TSsaPhiInputNode {
|
||||
/** Gets the basic block in which this input originates. */
|
||||
IRBlock getBlock() { result = block }
|
||||
|
||||
override DataFlowCallable getEnclosingCallable() {
|
||||
result.asSourceCallable() = this.getFunction()
|
||||
}
|
||||
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||
|
||||
override Declaration getFunction() { result = phi.getBasicBlock().getEnclosingFunction() }
|
||||
|
||||
@@ -746,9 +738,7 @@ class SsaIteratorNode extends Node, TSsaIteratorNode {
|
||||
/** Gets the phi node associated with this node. */
|
||||
IteratorFlow::IteratorFlowNode getIteratorFlowNode() { result = node }
|
||||
|
||||
override DataFlowCallable getEnclosingCallable() {
|
||||
result.asSourceCallable() = this.getFunction()
|
||||
}
|
||||
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||
|
||||
override Declaration getFunction() { result = node.getFunction() }
|
||||
|
||||
@@ -767,11 +757,9 @@ class SsaIteratorNode extends Node, TSsaIteratorNode {
|
||||
class SideEffectOperandNode extends Node instanceof IndirectOperand {
|
||||
CallInstruction call;
|
||||
int argumentIndex;
|
||||
ArgumentOperand arg;
|
||||
|
||||
SideEffectOperandNode() {
|
||||
arg = call.getArgumentOperand(argumentIndex) and
|
||||
IndirectOperand.super.hasOperandAndIndirectionIndex(arg, _)
|
||||
IndirectOperand.super.hasOperandAndIndirectionIndex(call.getArgumentOperand(argumentIndex), _)
|
||||
}
|
||||
|
||||
CallInstruction getCallInstruction() { result = call }
|
||||
@@ -783,9 +771,7 @@ class SideEffectOperandNode extends Node instanceof IndirectOperand {
|
||||
|
||||
int getArgumentIndex() { result = argumentIndex }
|
||||
|
||||
override DataFlowCallable getEnclosingCallable() {
|
||||
result.asSourceCallable() = this.getFunction()
|
||||
}
|
||||
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||
|
||||
override Declaration getFunction() { result = call.getEnclosingFunction() }
|
||||
|
||||
@@ -806,9 +792,7 @@ class FinalGlobalValue extends Node, TFinalGlobalValue {
|
||||
/** Gets the underlying SSA use. */
|
||||
Ssa::GlobalUse getGlobalUse() { result = globalUse }
|
||||
|
||||
override DataFlowCallable getEnclosingCallable() {
|
||||
result.asSourceCallable() = this.getFunction()
|
||||
}
|
||||
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||
|
||||
override Declaration getFunction() { result = globalUse.getIRFunction().getFunction() }
|
||||
|
||||
@@ -838,9 +822,7 @@ class InitialGlobalValue extends Node, TInitialGlobalValue {
|
||||
/** Gets the underlying SSA definition. */
|
||||
Ssa::GlobalDef getGlobalDef() { result = globalDef }
|
||||
|
||||
override DataFlowCallable getEnclosingCallable() {
|
||||
result.asSourceCallable() = this.getFunction()
|
||||
}
|
||||
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||
|
||||
override Declaration getFunction() { result = globalDef.getIRFunction().getFunction() }
|
||||
|
||||
@@ -871,9 +853,7 @@ class BodyLessParameterNodeImpl extends Node, TBodyLessParameterNodeImpl {
|
||||
|
||||
BodyLessParameterNodeImpl() { this = TBodyLessParameterNodeImpl(p, indirectionIndex) }
|
||||
|
||||
override DataFlowCallable getEnclosingCallable() {
|
||||
result.asSourceCallable() = this.getFunction()
|
||||
}
|
||||
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||
|
||||
override Declaration getFunction() { result = p.getFunction() }
|
||||
|
||||
@@ -919,9 +899,7 @@ class FlowSummaryNode extends Node, TFlowSummaryNode {
|
||||
* Gets the enclosing callable. For a `FlowSummaryNode` this is always the
|
||||
* summarized function this node is part of.
|
||||
*/
|
||||
override DataFlowCallable getEnclosingCallable() {
|
||||
result.asSummarizedCallable() = this.getSummarizedCallable()
|
||||
}
|
||||
override Declaration getEnclosingCallable() { result = this.getSummarizedCallable() }
|
||||
|
||||
override Location getLocationImpl() { result = this.getSummarizedCallable().getLocation() }
|
||||
|
||||
@@ -942,7 +920,7 @@ class IndirectReturnNode extends Node {
|
||||
.hasOperandAndIndirectionIndex(any(ReturnValueInstruction ret).getReturnAddressOperand(), _)
|
||||
}
|
||||
|
||||
override SourceCallable getEnclosingCallable() { result.asSourceCallable() = this.getFunction() }
|
||||
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||
|
||||
/**
|
||||
* Holds if this node represents the value that is returned to the caller
|
||||
@@ -1136,12 +1114,12 @@ private module RawIndirectNodes {
|
||||
/** Gets the underlying indirection index. */
|
||||
int getIndirectionIndex() { result = indirectionIndex }
|
||||
|
||||
override Declaration getFunction() { result = node.getFunction() }
|
||||
|
||||
override DataFlowCallable getEnclosingCallable() {
|
||||
result.asSourceCallable() = node.getEnclosingCallable()
|
||||
override Declaration getFunction() {
|
||||
result = this.getOperand().getDef().getEnclosingFunction()
|
||||
}
|
||||
|
||||
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||
|
||||
override predicate isGLValue() { this.getOperand().isGLValue() }
|
||||
|
||||
override DataFlowType getType() {
|
||||
@@ -1182,11 +1160,9 @@ private module RawIndirectNodes {
|
||||
/** Gets the underlying indirection index. */
|
||||
int getIndirectionIndex() { result = indirectionIndex }
|
||||
|
||||
override Declaration getFunction() { result = node.getFunction() }
|
||||
override Declaration getFunction() { result = this.getInstruction().getEnclosingFunction() }
|
||||
|
||||
override DataFlowCallable getEnclosingCallable() {
|
||||
result.asSourceCallable() = node.getEnclosingCallable()
|
||||
}
|
||||
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||
|
||||
override predicate isGLValue() { this.getInstruction().isGLValue() }
|
||||
|
||||
@@ -1286,9 +1262,7 @@ class FinalParameterNode extends Node, TFinalParameterNode {
|
||||
|
||||
override Declaration getFunction() { result = p.getFunction() }
|
||||
|
||||
override DataFlowCallable getEnclosingCallable() {
|
||||
result.asSourceCallable() = this.getFunction()
|
||||
}
|
||||
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||
|
||||
override DataFlowType getType() { result = getTypeImpl(p.getUnderlyingType(), indirectionIndex) }
|
||||
|
||||
@@ -1330,29 +1304,7 @@ abstract private class AbstractParameterNode extends Node {
|
||||
* implicit `this` parameter is considered to have position `-1`, and
|
||||
* pointer-indirection parameters are at further negative positions.
|
||||
*/
|
||||
predicate isSourceParameterOf(Function f, ParameterPosition pos) { none() }
|
||||
|
||||
/**
|
||||
* Holds if this node is the parameter of `sc` at the specified position. The
|
||||
* implicit `this` parameter is considered to have position `-1`, and
|
||||
* pointer-indirection parameters are at further negative positions.
|
||||
*/
|
||||
predicate isSummaryParameterOf(
|
||||
FlowSummaryImpl::Public::SummarizedCallable sc, ParameterPosition pos
|
||||
) {
|
||||
none()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this node is the parameter of `c` at the specified position. The
|
||||
* implicit `this` parameter is considered to have position `-1`, and
|
||||
* pointer-indirection parameters are at further negative positions.
|
||||
*/
|
||||
final predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
|
||||
this.isSummaryParameterOf(c.asSummarizedCallable(), pos)
|
||||
or
|
||||
this.isSourceParameterOf(c.asSourceCallable(), pos)
|
||||
}
|
||||
abstract predicate isParameterOf(DataFlowCallable f, ParameterPosition pos);
|
||||
|
||||
/** Gets the `Parameter` associated with this node, if it exists. */
|
||||
Parameter getParameter() { none() } // overridden by subclasses
|
||||
@@ -1408,14 +1360,12 @@ private class IndirectInstructionParameterNode extends AbstractIndirectParameter
|
||||
/** Gets the parameter whose indirection is initialized. */
|
||||
override Parameter getParameter() { result = init.getParameter() }
|
||||
|
||||
override DataFlowCallable getEnclosingCallable() {
|
||||
result.asSourceCallable() = this.getFunction()
|
||||
}
|
||||
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||
|
||||
override Declaration getFunction() { result = init.getEnclosingFunction() }
|
||||
|
||||
override predicate isSourceParameterOf(Function f, ParameterPosition pos) {
|
||||
this.getFunction() = f and
|
||||
override predicate isParameterOf(DataFlowCallable f, ParameterPosition pos) {
|
||||
this.getEnclosingCallable() = f.getUnderlyingCallable() and
|
||||
exists(int argumentIndex, int indirectionIndex |
|
||||
indirectPositionHasArgumentIndexAndIndex(pos, argumentIndex, indirectionIndex) and
|
||||
indirectParameterNodeHasArgumentIndexAndIndex(this, argumentIndex, indirectionIndex)
|
||||
@@ -1472,8 +1422,9 @@ private class ExplicitParameterInstructionNode extends AbstractExplicitParameter
|
||||
{
|
||||
ExplicitParameterInstructionNode() { exists(instr.getParameter()) }
|
||||
|
||||
override predicate isSourceParameterOf(Function f, ParameterPosition pos) {
|
||||
f.getParameter(pos.(DirectPosition).getIndex()) = instr.getParameter()
|
||||
override predicate isParameterOf(DataFlowCallable f, ParameterPosition pos) {
|
||||
f.getUnderlyingCallable().(Function).getParameter(pos.(DirectPosition).getIndex()) =
|
||||
instr.getParameter()
|
||||
}
|
||||
|
||||
override string toStringImpl() { result = instr.getParameter().toString() }
|
||||
@@ -1487,9 +1438,9 @@ class ThisParameterInstructionNode extends AbstractExplicitParameterNode,
|
||||
{
|
||||
ThisParameterInstructionNode() { instr.getIRVariable() instanceof IRThisVariable }
|
||||
|
||||
override predicate isSourceParameterOf(Function f, ParameterPosition pos) {
|
||||
override predicate isParameterOf(DataFlowCallable f, ParameterPosition pos) {
|
||||
pos.(DirectPosition).getIndex() = -1 and
|
||||
instr.getEnclosingFunction() = f
|
||||
instr.getEnclosingFunction() = f.getUnderlyingCallable()
|
||||
}
|
||||
|
||||
override string toStringImpl() { result = "this" }
|
||||
@@ -1507,10 +1458,8 @@ class SummaryParameterNode extends AbstractParameterNode, FlowSummaryNode {
|
||||
FlowSummaryImpl::Private::summaryParameterNode(this.getSummaryNode(), result)
|
||||
}
|
||||
|
||||
override predicate isSummaryParameterOf(
|
||||
FlowSummaryImpl::Public::SummarizedCallable c, ParameterPosition p
|
||||
) {
|
||||
c = this.getSummarizedCallable() and
|
||||
override predicate isParameterOf(DataFlowCallable c, ParameterPosition p) {
|
||||
c.getUnderlyingCallable() = this.getSummarizedCallable() and
|
||||
p = this.getPosition()
|
||||
}
|
||||
}
|
||||
@@ -1520,9 +1469,12 @@ private class DirectBodyLessParameterNode extends AbstractExplicitParameterNode,
|
||||
{
|
||||
DirectBodyLessParameterNode() { indirectionIndex = 0 }
|
||||
|
||||
override predicate isSourceParameterOf(Function f, ParameterPosition pos) {
|
||||
this.getFunction() = f and
|
||||
f.getParameter(pos.(DirectPosition).getIndex()) = p
|
||||
override predicate isParameterOf(DataFlowCallable f, ParameterPosition pos) {
|
||||
exists(Function func |
|
||||
this.getFunction() = func and
|
||||
f.asSourceCallable() = func and
|
||||
func.getParameter(pos.(DirectPosition).getIndex()) = p
|
||||
)
|
||||
}
|
||||
|
||||
override Parameter getParameter() { result = p }
|
||||
@@ -1533,11 +1485,12 @@ private class IndirectBodyLessParameterNode extends AbstractIndirectParameterNod
|
||||
{
|
||||
IndirectBodyLessParameterNode() { not this instanceof DirectBodyLessParameterNode }
|
||||
|
||||
override predicate isSourceParameterOf(Function f, ParameterPosition pos) {
|
||||
exists(int argumentPosition |
|
||||
this.getFunction() = f and
|
||||
f.getParameter(argumentPosition) = p and
|
||||
indirectPositionHasArgumentIndexAndIndex(pos, argumentPosition, indirectionIndex)
|
||||
override predicate isParameterOf(DataFlowCallable f, ParameterPosition pos) {
|
||||
exists(Function func, int argumentPosition |
|
||||
this.getFunction() = func and
|
||||
f.asSourceCallable() = func and
|
||||
indirectPositionHasArgumentIndexAndIndex(pos, argumentPosition, indirectionIndex) and
|
||||
func.getParameter(argumentPosition) = p
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1650,13 +1603,13 @@ class VariableNode extends Node, TGlobalLikeVariableNode {
|
||||
|
||||
override Declaration getFunction() { none() }
|
||||
|
||||
override DataFlowCallable getEnclosingCallable() {
|
||||
override Declaration getEnclosingCallable() {
|
||||
// When flow crosses from one _enclosing callable_ to another, the
|
||||
// interprocedural data-flow library discards call contexts and inserts a
|
||||
// node in the big-step relation used for human-readable path explanations.
|
||||
// Therefore we want a distinct enclosing callable for each `VariableNode`,
|
||||
// and that can be the `Variable` itself.
|
||||
result.asSourceCallable() = v
|
||||
result = v
|
||||
}
|
||||
|
||||
override DataFlowType getType() {
|
||||
@@ -2541,36 +2494,6 @@ module InstructionBarrierGuard<instructionGuardChecksSig/3 instructionGuardCheck
|
||||
result = TSsaPhiInputNode(phi, input)
|
||||
)
|
||||
}
|
||||
|
||||
bindingset[value, n]
|
||||
pragma[inline_late]
|
||||
private predicate indirectOperandHasValueNumber(ValueNumber value, int indirectionIndex, Node n) {
|
||||
exists(Operand use |
|
||||
use = value.getAnInstruction().getAUse() and
|
||||
n.asIndirectOperand(indirectionIndex) = use
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an indirect node with indirection index `indirectionIndex` that is
|
||||
* safely guarded by the given guard check.
|
||||
*/
|
||||
Node getAnIndirectBarrierNode(int indirectionIndex) {
|
||||
exists(IRGuardCondition g, ValueNumber value, boolean edge |
|
||||
instructionGuardChecks(g, pragma[only_bind_into](value.getAnInstruction()), edge) and
|
||||
indirectOperandHasValueNumber(value, indirectionIndex, result) and
|
||||
controls(g, result, edge)
|
||||
)
|
||||
or
|
||||
exists(
|
||||
IRGuardCondition g, boolean branch, Ssa::DefinitionExt def, IRBlock input, Ssa::PhiNode phi
|
||||
|
|
||||
instructionGuardChecks(g, def.getARead().asIndirectOperand(indirectionIndex).getDef(), branch) and
|
||||
guardControlsPhiInput(g, branch, def, pragma[only_bind_into](input),
|
||||
pragma[only_bind_into](phi)) and
|
||||
result = TSsaPhiInputNode(phi, input)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -587,8 +587,8 @@ module ProductFlow {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate interprocEdge1(
|
||||
DataFlowCallable predDecl, DataFlowCallable succDecl, Flow1::PathNode pred1,
|
||||
Flow1::PathNode succ1, TKind kind
|
||||
Declaration predDecl, Declaration succDecl, Flow1::PathNode pred1, Flow1::PathNode succ1,
|
||||
TKind kind
|
||||
) {
|
||||
Flow1::PathGraph::edges(pred1, succ1, _, _) and
|
||||
predDecl != succDecl and
|
||||
@@ -607,8 +607,8 @@ module ProductFlow {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate interprocEdge2(
|
||||
DataFlowCallable predDecl, DataFlowCallable succDecl, Flow2::PathNode pred2,
|
||||
Flow2::PathNode succ2, TKind kind
|
||||
Declaration predDecl, Declaration succDecl, Flow2::PathNode pred2, Flow2::PathNode succ2,
|
||||
TKind kind
|
||||
) {
|
||||
Flow2::PathGraph::edges(pred2, succ2, _, _) and
|
||||
predDecl != succDecl and
|
||||
@@ -628,7 +628,7 @@ module ProductFlow {
|
||||
private predicate interprocEdgePair(
|
||||
Flow1::PathNode pred1, Flow2::PathNode pred2, Flow1::PathNode succ1, Flow2::PathNode succ2
|
||||
) {
|
||||
exists(DataFlowCallable predDecl, DataFlowCallable succDecl, TKind kind |
|
||||
exists(Declaration predDecl, Declaration succDecl, TKind kind |
|
||||
interprocEdge1(predDecl, succDecl, pred1, succ1, kind) and
|
||||
interprocEdge2(predDecl, succDecl, pred2, succ2, kind)
|
||||
)
|
||||
|
||||
@@ -899,24 +899,6 @@ class MemoryLocation extends FinalMemoryLocation {
|
||||
MemoryLocation() { not useOverlapWithBusyDef(this) }
|
||||
}
|
||||
|
||||
bindingset[fun]
|
||||
pragma[inline_late]
|
||||
private MemoryLocation getUnknownMemoryLocation(IRFunction fun, boolean isMayAccess) {
|
||||
result = TUnknownMemoryLocation(fun, isMayAccess)
|
||||
}
|
||||
|
||||
bindingset[fun]
|
||||
pragma[inline_late]
|
||||
private MemoryLocation getAllAliasedMemory(IRFunction fun, boolean isMayAccess) {
|
||||
result = TAllAliasedMemory(fun, isMayAccess)
|
||||
}
|
||||
|
||||
bindingset[fun]
|
||||
pragma[inline_late]
|
||||
private MemoryLocation getAllNonLocalMemory(IRFunction fun, boolean isMayAccess) {
|
||||
result = TAllNonLocalMemory(fun, isMayAccess)
|
||||
}
|
||||
|
||||
MemoryLocation getResultMemoryLocation(Instruction instr) {
|
||||
not canReuseSsaForOldResult(instr) and
|
||||
exists(MemoryAccessKind kind, boolean isMayAccess |
|
||||
@@ -944,7 +926,7 @@ MemoryLocation getResultMemoryLocation(Instruction instr) {
|
||||
// And otherwise we assign it a memory location that groups all the relevant memory locations into one.
|
||||
result = getGroupedMemoryLocation(var, unbindBool(isMayAccess), false)
|
||||
)
|
||||
else result = getUnknownMemoryLocation(instr.getEnclosingIRFunction(), isMayAccess)
|
||||
else result = TUnknownMemoryLocation(instr.getEnclosingIRFunction(), isMayAccess)
|
||||
)
|
||||
or
|
||||
kind instanceof EntireAllocationMemoryAccess and
|
||||
@@ -953,10 +935,10 @@ MemoryLocation getResultMemoryLocation(Instruction instr) {
|
||||
unbindBool(isMayAccess))
|
||||
or
|
||||
kind instanceof EscapedMemoryAccess and
|
||||
result = getAllAliasedMemory(instr.getEnclosingIRFunction(), isMayAccess)
|
||||
result = TAllAliasedMemory(instr.getEnclosingIRFunction(), isMayAccess)
|
||||
or
|
||||
kind instanceof NonLocalMemoryAccess and
|
||||
result = getAllNonLocalMemory(instr.getEnclosingIRFunction(), isMayAccess)
|
||||
result = TAllNonLocalMemory(instr.getEnclosingIRFunction(), isMayAccess)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -171,23 +171,6 @@ module Raw {
|
||||
// forwarded the result of another translated expression.
|
||||
instruction = translatedExpr.getInstruction(_)
|
||||
)
|
||||
or
|
||||
// Consider the snippet `if(x) { ... }` where `x` is an integer.
|
||||
// In C++ there is a `BoolConversion` conversion on `x` which generates a
|
||||
// `CompareNEInstruction` whose `getInstructionConvertedResultExpression`
|
||||
// is the `BoolConversion` (by the logic in the disjunct above). Thus,
|
||||
// calling `getInstructionUnconvertedResultExpression` on the
|
||||
// `CompareNEInstruction` gives `x` in C++ code.
|
||||
// However, in C there is no such conversion to return. So instead we have
|
||||
// to map the result of `getInstructionConvertedResultExpression` on the
|
||||
// `CompareNEInstruction` to `x` manually. This ensures that calling
|
||||
// `getInstructionUnconvertedResultExpression` on the `CompareNEInstruction`
|
||||
// gives `x` in both the C case and C++ case.
|
||||
exists(TranslatedValueCondition translatedValueCondition |
|
||||
translatedValueCondition = getTranslatedCondition(result) and
|
||||
translatedValueCondition.shouldGenerateCompareNE() and
|
||||
instruction = translatedValueCondition.getInstruction(ValueConditionCompareTag())
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
|
||||
@@ -38,11 +38,7 @@ newtype TInstructionTag =
|
||||
AllocationSizeTag() or
|
||||
AllocationElementSizeTag() or
|
||||
AllocationExtentConvertTag() or
|
||||
ValueConditionCompareTag() or
|
||||
ValueConditionConstantTag() or
|
||||
ValueConditionConditionalBranchTag() or
|
||||
ValueConditionConditionalConstantTag() or
|
||||
ValueConditionConditionalCompareTag() or
|
||||
ConditionValueTrueTempAddressTag() or
|
||||
ConditionValueTrueConstantTag() or
|
||||
ConditionValueTrueStoreTag() or
|
||||
@@ -53,8 +49,6 @@ newtype TInstructionTag =
|
||||
ConditionValueResultLoadTag() or
|
||||
BoolConversionConstantTag() or
|
||||
BoolConversionCompareTag() or
|
||||
NotExprOperationTag() or
|
||||
NotExprConstantTag() or
|
||||
ResultCopyTag() or
|
||||
LoadTag() or // Implicit load due to lvalue-to-rvalue conversion
|
||||
CatchTag() or
|
||||
@@ -173,14 +167,6 @@ string getInstructionTagId(TInstructionTag tag) {
|
||||
or
|
||||
tag = ValueConditionConditionalBranchTag() and result = "ValCondCondBranch"
|
||||
or
|
||||
tag = ValueConditionConditionalConstantTag() and result = "ValueConditionConditionalConstant"
|
||||
or
|
||||
tag = ValueConditionConditionalCompareTag() and result = "ValueConditionConditionalCompare"
|
||||
or
|
||||
tag = ValueConditionCompareTag() and result = "ValCondCondCompare"
|
||||
or
|
||||
tag = ValueConditionConstantTag() and result = "ValCondConstant"
|
||||
or
|
||||
tag = ConditionValueTrueTempAddressTag() and result = "CondValTrueTempAddr"
|
||||
or
|
||||
tag = ConditionValueTrueConstantTag() and result = "CondValTrueConst"
|
||||
@@ -201,10 +187,6 @@ string getInstructionTagId(TInstructionTag tag) {
|
||||
or
|
||||
tag = BoolConversionCompareTag() and result = "BoolConvComp"
|
||||
or
|
||||
tag = NotExprOperationTag() and result = "NotExprOperation"
|
||||
or
|
||||
tag = NotExprConstantTag() and result = "NotExprWithBoolConversionConstant"
|
||||
or
|
||||
tag = ResultCopyTag() and result = "ResultCopy"
|
||||
or
|
||||
tag = LoadTag() and result = "Load" // Implicit load due to lvalue-to-rvalue conversion
|
||||
|
||||
@@ -47,7 +47,7 @@ abstract class TranslatedFlexibleCondition extends TranslatedCondition, Conditio
|
||||
{
|
||||
TranslatedFlexibleCondition() { this = TTranslatedFlexibleCondition(expr) }
|
||||
|
||||
final override predicate handlesDestructorsExplicitly() { none() } // TODO: this needs to be revisited when we get unnamed destructors
|
||||
final override predicate handlesDestructorsExplicitly() { none() } // TODO: this needs to be revisted when we get unnamed destructors
|
||||
|
||||
final override TranslatedElement getChild(int id) { id = 0 and result = this.getOperand() }
|
||||
|
||||
@@ -187,24 +187,7 @@ class TranslatedValueCondition extends TranslatedCondition, TTranslatedValueCond
|
||||
|
||||
final override predicate handlesDestructorsExplicitly() { none() } // TODO: this needs to be revisted when we get unnamed destructors
|
||||
|
||||
private Type getValueExprType() {
|
||||
result = this.getValueExpr().getExprType().getUnspecifiedType()
|
||||
}
|
||||
|
||||
predicate shouldGenerateCompareNE() { not this.getValueExprType() instanceof BoolType }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
this.shouldGenerateCompareNE() and
|
||||
(
|
||||
tag = ValueConditionCompareTag() and
|
||||
opcode instanceof Opcode::CompareNE and
|
||||
resultType = getBoolType()
|
||||
or
|
||||
tag = ValueConditionConstantTag() and
|
||||
opcode instanceof Opcode::Constant and
|
||||
resultType = getTypeForPRValue(this.getValueExprType())
|
||||
)
|
||||
or
|
||||
tag = ValueConditionConditionalBranchTag() and
|
||||
opcode instanceof Opcode::ConditionalBranch and
|
||||
resultType = getVoidType()
|
||||
@@ -212,24 +195,11 @@ class TranslatedValueCondition extends TranslatedCondition, TTranslatedValueCond
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getValueExpr() and
|
||||
kind instanceof GotoEdge and
|
||||
if this.shouldGenerateCompareNE()
|
||||
then result = this.getInstruction(ValueConditionConstantTag())
|
||||
else result = this.getInstruction(ValueConditionConditionalBranchTag())
|
||||
result = this.getInstruction(ValueConditionConditionalBranchTag()) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
this.shouldGenerateCompareNE() and
|
||||
(
|
||||
tag = ValueConditionConstantTag() and
|
||||
kind instanceof GotoEdge and
|
||||
result = this.getInstruction(ValueConditionCompareTag())
|
||||
or
|
||||
tag = ValueConditionCompareTag() and
|
||||
kind instanceof GotoEdge and
|
||||
result = this.getInstruction(ValueConditionConditionalBranchTag())
|
||||
)
|
||||
or
|
||||
tag = ValueConditionConditionalBranchTag() and
|
||||
(
|
||||
kind instanceof TrueEdge and
|
||||
@@ -241,26 +211,9 @@ class TranslatedValueCondition extends TranslatedCondition, TTranslatedValueCond
|
||||
}
|
||||
|
||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
this.shouldGenerateCompareNE() and
|
||||
tag = ValueConditionCompareTag() and
|
||||
(
|
||||
operandTag instanceof LeftOperandTag and
|
||||
result = this.getValueExpr().getResult()
|
||||
or
|
||||
operandTag instanceof RightOperandTag and
|
||||
result = this.getInstruction(ValueConditionConstantTag())
|
||||
)
|
||||
or
|
||||
tag = ValueConditionConditionalBranchTag() and
|
||||
operandTag instanceof ConditionOperandTag and
|
||||
if this.shouldGenerateCompareNE()
|
||||
then result = this.getInstruction(ValueConditionCompareTag())
|
||||
else result = this.getValueExpr().getResult()
|
||||
}
|
||||
|
||||
override string getInstructionConstantValue(InstructionTag tag) {
|
||||
tag = ValueConditionConstantTag() and
|
||||
result = "0"
|
||||
result = this.getValueExpr().getResult()
|
||||
}
|
||||
|
||||
private TranslatedExpr getValueExpr() { result = getTranslatedExpr(expr) }
|
||||
|
||||
@@ -166,7 +166,7 @@ private predicate ignoreExpr(Expr expr) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the side effects of `expr` should be ignored for the purposes of IR generation.
|
||||
* Holds if the side effects of `expr` should be ignoredf for the purposes of IR generation.
|
||||
*
|
||||
* In cases involving `constexpr`, a call can wind up as a constant expression. `ignoreExpr()` will
|
||||
* not hold for such a call, since we do need to translate the call (as a constant), but we need to
|
||||
|
||||
@@ -59,19 +59,10 @@ abstract class TranslatedExpr extends TranslatedElement {
|
||||
|
||||
final CppType getResultType() {
|
||||
if this.isResultGLValue()
|
||||
then result = getTypeForGLValue(this.getExprType())
|
||||
else result = getTypeForPRValue(this.getExprType())
|
||||
then result = getTypeForGLValue(expr.getType())
|
||||
else result = getTypeForPRValue(expr.getType())
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type of `expr`.
|
||||
*
|
||||
* This predicate can be overwritten in subclasses to modify the result
|
||||
* of `getResultType` which determines the type of the instruction that
|
||||
* generates the result of `expr`.
|
||||
*/
|
||||
Type getExprType() { result = expr.getType() }
|
||||
|
||||
/**
|
||||
* Holds if the result of this `TranslatedExpr` is a glvalue.
|
||||
*/
|
||||
@@ -1271,10 +1262,9 @@ abstract class TranslatedSingleInstructionExpr extends TranslatedNonConstantExpr
|
||||
|
||||
class TranslatedUnaryExpr extends TranslatedSingleInstructionExpr {
|
||||
TranslatedUnaryExpr() {
|
||||
expr instanceof ComplementExpr
|
||||
or
|
||||
expr instanceof UnaryPlusExpr
|
||||
or
|
||||
expr instanceof NotExpr or
|
||||
expr instanceof ComplementExpr or
|
||||
expr instanceof UnaryPlusExpr or
|
||||
expr instanceof UnaryMinusExpr
|
||||
}
|
||||
|
||||
@@ -1308,6 +1298,8 @@ class TranslatedUnaryExpr extends TranslatedSingleInstructionExpr {
|
||||
}
|
||||
|
||||
final override Opcode getOpcode() {
|
||||
expr instanceof NotExpr and result instanceof Opcode::LogicalNot
|
||||
or
|
||||
expr instanceof ComplementExpr and result instanceof Opcode::BitComplement
|
||||
or
|
||||
expr instanceof UnaryPlusExpr and result instanceof Opcode::CopyValue
|
||||
@@ -1320,100 +1312,6 @@ class TranslatedUnaryExpr extends TranslatedSingleInstructionExpr {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The IR translation of a `NotExpr`.
|
||||
*
|
||||
* In C++ an operation such as `!x` where `x` is an `int` will generate
|
||||
* ```
|
||||
* r1(glval<int>) = VariableAddress[x] :
|
||||
* r2(int) = Load : &r1
|
||||
* r3(int) = Constant[0] :
|
||||
* r4(bool) = CompareNE : r2, r3
|
||||
* r5(bool) = LogicalNot : r4
|
||||
* ```
|
||||
* since C does not do implicit int-to-bool casts we need to generate the
|
||||
* `Constant[0]`, `CompareNE`, and `LogicalNot` instructions manually, but
|
||||
* we simplify this and generate `Constant[0]`, `CompareEQ` instead.
|
||||
*/
|
||||
class TranslatedNotExpr extends TranslatedNonConstantExpr {
|
||||
override NotExpr expr;
|
||||
|
||||
override Type getExprType() { result instanceof BoolType }
|
||||
|
||||
private Type getOperandType() { result = this.getOperand().getExprType().getUnspecifiedType() }
|
||||
|
||||
predicate shouldGenerateEq() { not this.getOperandType() instanceof BoolType }
|
||||
|
||||
final override Instruction getFirstInstruction(EdgeKind kind) {
|
||||
result = this.getOperand().getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInstruction(NotExprOperationTag())
|
||||
}
|
||||
|
||||
final override TranslatedElement getChildInternal(int id) {
|
||||
id = 0 and result = this.getOperand()
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
this.shouldGenerateEq() and
|
||||
tag = NotExprConstantTag() and
|
||||
opcode instanceof Opcode::Constant and
|
||||
resultType = getTypeForPRValue(this.getOperandType())
|
||||
or
|
||||
resultType = getBoolType() and
|
||||
tag = NotExprOperationTag() and
|
||||
if this.shouldGenerateEq()
|
||||
then opcode instanceof Opcode::CompareEQ
|
||||
else opcode instanceof Opcode::LogicalNot
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
tag = NotExprOperationTag() and
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
or
|
||||
tag = NotExprConstantTag() and
|
||||
kind instanceof GotoEdge and
|
||||
result = this.getInstruction(NotExprOperationTag())
|
||||
}
|
||||
|
||||
final override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getOperand() and
|
||||
kind instanceof GotoEdge and
|
||||
if this.shouldGenerateEq()
|
||||
then result = this.getInstruction(NotExprConstantTag())
|
||||
else result = this.getInstruction(NotExprOperationTag())
|
||||
}
|
||||
|
||||
final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag = NotExprOperationTag() and
|
||||
if this.shouldGenerateEq()
|
||||
then (
|
||||
result = this.getOperand().getResult() and
|
||||
operandTag instanceof LeftOperandTag
|
||||
or
|
||||
result = this.getInstruction(NotExprConstantTag()) and
|
||||
operandTag instanceof RightOperandTag
|
||||
) else (
|
||||
operandTag instanceof UnaryOperandTag and
|
||||
result = this.getOperand().getResult()
|
||||
)
|
||||
}
|
||||
|
||||
private TranslatedExpr getOperand() {
|
||||
result = getTranslatedExpr(expr.getOperand().getFullyConverted())
|
||||
}
|
||||
|
||||
final override Instruction getResult() { result = this.getInstruction(NotExprOperationTag()) }
|
||||
|
||||
override string getInstructionConstantValue(InstructionTag tag) {
|
||||
this.shouldGenerateEq() and
|
||||
tag = NotExprConstantTag() and
|
||||
result = "0"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* IR translation of a `co_await` or `co_yield` expression.
|
||||
*
|
||||
@@ -1856,12 +1754,6 @@ class TranslatedBinaryOperation extends TranslatedSingleInstructionExpr {
|
||||
result = comparisonOpcode(expr)
|
||||
}
|
||||
|
||||
override Type getExprType() {
|
||||
if exists(comparisonOpcode(expr))
|
||||
then result instanceof BoolType
|
||||
else result = super.getExprType()
|
||||
}
|
||||
|
||||
override int getInstructionElementSize(InstructionTag tag) {
|
||||
tag = OnlyInstructionTag() and
|
||||
exists(Opcode opcode |
|
||||
@@ -2965,10 +2857,6 @@ class TranslatedBinaryConditionalExpr extends TranslatedConditionalExpr {
|
||||
result = this.getCondition().getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
private Type getConditionType() {
|
||||
result = this.getCondition().getExprType().getUnspecifiedType()
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
super.hasInstruction(opcode, tag, resultType)
|
||||
or
|
||||
@@ -2976,35 +2864,11 @@ class TranslatedBinaryConditionalExpr extends TranslatedConditionalExpr {
|
||||
tag = ValueConditionConditionalBranchTag() and
|
||||
opcode instanceof Opcode::ConditionalBranch and
|
||||
resultType = getVoidType()
|
||||
or
|
||||
exists(Type t |
|
||||
t = this.getConditionType() and
|
||||
not t instanceof BoolType
|
||||
|
|
||||
tag = ValueConditionConditionalConstantTag() and
|
||||
opcode instanceof Opcode::Constant and
|
||||
resultType = getTypeForPRValue(t)
|
||||
or
|
||||
tag = ValueConditionConditionalCompareTag() and
|
||||
opcode instanceof Opcode::CompareNE and
|
||||
resultType = getBoolType()
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
result = super.getInstructionSuccessorInternal(tag, kind)
|
||||
or
|
||||
not this.getConditionType() instanceof BoolType and
|
||||
(
|
||||
tag = ValueConditionConditionalConstantTag() and
|
||||
kind instanceof GotoEdge and
|
||||
result = this.getInstruction(ValueConditionConditionalCompareTag())
|
||||
or
|
||||
tag = ValueConditionConditionalCompareTag() and
|
||||
kind instanceof GotoEdge and
|
||||
result = this.getInstruction(ValueConditionConditionalBranchTag())
|
||||
)
|
||||
or
|
||||
tag = ValueConditionConditionalBranchTag() and
|
||||
(
|
||||
kind instanceof TrueEdge and
|
||||
@@ -3020,19 +2884,7 @@ class TranslatedBinaryConditionalExpr extends TranslatedConditionalExpr {
|
||||
or
|
||||
tag = ValueConditionConditionalBranchTag() and
|
||||
operandTag instanceof ConditionOperandTag and
|
||||
if this.getConditionType() instanceof BoolType
|
||||
then result = this.getCondition().getResult()
|
||||
else result = this.getInstruction(ValueConditionConditionalCompareTag())
|
||||
or
|
||||
not this.getConditionType() instanceof BoolType and
|
||||
tag = ValueConditionConditionalCompareTag() and
|
||||
(
|
||||
operandTag instanceof LeftOperandTag and
|
||||
result = this.getCondition().getResult()
|
||||
or
|
||||
operandTag instanceof RightOperandTag and
|
||||
result = this.getInstruction(ValueConditionConditionalConstantTag())
|
||||
)
|
||||
result = this.getCondition().getResult()
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
@@ -3040,9 +2892,7 @@ class TranslatedBinaryConditionalExpr extends TranslatedConditionalExpr {
|
||||
or
|
||||
kind instanceof GotoEdge and
|
||||
child = this.getCondition() and
|
||||
if this.getConditionType() instanceof BoolType
|
||||
then result = this.getInstruction(ValueConditionConditionalBranchTag())
|
||||
else result = this.getInstruction(ValueConditionConditionalConstantTag())
|
||||
result = this.getInstruction(ValueConditionConditionalBranchTag())
|
||||
}
|
||||
|
||||
private TranslatedExpr getCondition() {
|
||||
@@ -3059,11 +2909,6 @@ class TranslatedBinaryConditionalExpr extends TranslatedConditionalExpr {
|
||||
// always converting the "then" operand to `bool`, which is almost always the wrong type.
|
||||
result = getTranslatedExpr(expr.getThen().getExplicitlyConverted())
|
||||
}
|
||||
|
||||
override string getInstructionConstantValue(InstructionTag tag) {
|
||||
tag = ValueConditionConditionalConstantTag() and
|
||||
result = "0"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1098,61 +1098,6 @@ class TranslatedConstExprIfStmt extends TranslatedIfLikeStmt {
|
||||
override predicate hasElse() { exists(stmt.getElse()) }
|
||||
}
|
||||
|
||||
class TranslatedConstevalIfStmt extends TranslatedStmt {
|
||||
override ConstevalIfStmt stmt;
|
||||
|
||||
override Instruction getFirstInstruction(EdgeKind kind) {
|
||||
if not this.hasEvaluatedBranch()
|
||||
then
|
||||
kind instanceof GotoEdge and
|
||||
result = this.getInstruction(OnlyInstructionTag())
|
||||
else result = this.getEvaluatedBranch().getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
override TranslatedElement getChildInternal(int id) {
|
||||
id = 0 and
|
||||
result = this.getThen()
|
||||
or
|
||||
id = 1 and
|
||||
result = this.getElse()
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
not this.hasEvaluatedBranch() and
|
||||
opcode instanceof Opcode::NoOp and
|
||||
tag = OnlyInstructionTag() and
|
||||
resultType = getVoidType()
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
if not this.hasEvaluatedBranch()
|
||||
then result = this.getInstruction(OnlyInstructionTag())
|
||||
else result = this.getEvaluatedBranch().getALastInstruction()
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() { result = this.getEvaluatedBranch() }
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
(child = this.getThen() or child = this.getElse()) and
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
TranslatedStmt getEvaluatedBranch() {
|
||||
result = getTranslatedStmt(stmt.getRuntimeEvaluatedBranch())
|
||||
}
|
||||
|
||||
predicate hasEvaluatedBranch() { stmt.hasRuntimeEvaluatedBranch() }
|
||||
|
||||
TranslatedStmt getThen() { result = getTranslatedStmt(stmt.getThen()) }
|
||||
|
||||
TranslatedStmt getElse() { result = getTranslatedStmt(stmt.getElse()) }
|
||||
}
|
||||
|
||||
abstract class TranslatedLoop extends TranslatedStmt, ConditionContext {
|
||||
override Loop stmt;
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import semmle.code.cpp.models.interfaces.ArrayFunction
|
||||
import semmle.code.cpp.models.interfaces.Taint
|
||||
import semmle.code.cpp.models.interfaces.DataFlow
|
||||
import semmle.code.cpp.models.interfaces.Alias
|
||||
import semmle.code.cpp.models.interfaces.SideEffect
|
||||
|
||||
@@ -9,7 +8,7 @@ import semmle.code.cpp.models.interfaces.SideEffect
|
||||
* guaranteed to be side-effect free.
|
||||
*/
|
||||
private class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunction,
|
||||
SideEffectFunction, DataFlowFunction
|
||||
SideEffectFunction
|
||||
{
|
||||
PureStrFunction() {
|
||||
this.hasGlobalOrStdOrBslName([
|
||||
@@ -26,48 +25,23 @@ private class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunctio
|
||||
this.getParameter(bufParam).getUnspecifiedType() instanceof PointerType
|
||||
}
|
||||
|
||||
/** Holds if `i` is a locale parameter that does not carry taint. */
|
||||
private predicate isLocaleParameter(ParameterIndex i) {
|
||||
this.getName().matches("%\\_l") and i + 1 = this.getNumberOfParameters()
|
||||
}
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
// For these functions we add taint flow according to the following rules:
|
||||
// 1. If the parameter is of a pointer type then there is taint from the
|
||||
// indirection of the parameter. Otherwise, there is taint from the
|
||||
// parameter.
|
||||
// 2. If the return value is of a pointer type then there is taint to the
|
||||
// indirection of the return. Otherwise, there is taint to the return.
|
||||
exists(ParameterIndex i |
|
||||
exists(this.getParameter(i)) and
|
||||
(
|
||||
input.isParameter(i) and
|
||||
exists(this.getParameter(i))
|
||||
or
|
||||
input.isParameterDeref(i) and
|
||||
this.getParameter(i).getUnspecifiedType() instanceof PointerType
|
||||
) and
|
||||
// Functions that end with _l also take a locale argument (always as the last argument),
|
||||
// and we don't want taint from those arguments.
|
||||
not this.isLocaleParameter(i)
|
||||
|
|
||||
if this.getParameter(i).getUnspecifiedType() instanceof PointerType
|
||||
then input.isParameterDeref(i)
|
||||
else input.isParameter(i)
|
||||
(not this.getName().matches("%\\_l") or exists(this.getParameter(i + 1)))
|
||||
) and
|
||||
(
|
||||
if this.getUnspecifiedType() instanceof PointerType
|
||||
then output.isReturnValueDeref()
|
||||
else output.isReturnValue()
|
||||
)
|
||||
or
|
||||
// If there is taint flow from *input to *output then there is also taint
|
||||
// flow from input to output.
|
||||
this.hasTaintFlow(input.getIndirectionInput(), output.getIndirectionOutput()) and
|
||||
// No need to add taint flow if we already have data flow.
|
||||
not this.hasDataFlow(input, output)
|
||||
}
|
||||
|
||||
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
|
||||
exists(int i |
|
||||
input.isParameter(i) and
|
||||
not this.isLocaleParameter(i) and
|
||||
// These functions always return the same pointer as they are given
|
||||
this.hasGlobalOrStdOrBslName([strrev(), strlwr(), strupr()]) and
|
||||
this.getParameter(i).getUnspecifiedType() instanceof PointerType and
|
||||
output.isReturnValueDeref() and
|
||||
this.getUnspecifiedType() instanceof PointerType
|
||||
or
|
||||
output.isReturnValue()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -121,11 +121,11 @@ predicate relOpWithSwapAndNegate(
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `cmp` is an equality operation (`==` or `!=`) with fully-converted
|
||||
* Holds if `cmp` is an equality operation (`==` or `!=`) with fully-converted
|
||||
* children `lhs` and `rhs`, and `isEQ` is true if `cmp` is an
|
||||
* `==` operation and false if it is an `!=` operation.
|
||||
*
|
||||
* For example, if `cmp` is `x == 5` then
|
||||
* For example, if `rel` is `x == 5` then
|
||||
* `eqOpWithSwap(cmp, x, 5, true)` holds.
|
||||
*/
|
||||
private predicate eqOp(EqualityOperation cmp, Expr lhs, Expr rhs, boolean isEQ) {
|
||||
|
||||
@@ -769,32 +769,26 @@ private float getLowerBoundsImpl(Expr expr) {
|
||||
exists(float x, float y |
|
||||
x = getFullyConvertedLowerBounds(maxExpr.getLeftOperand()) and
|
||||
y = getFullyConvertedLowerBounds(maxExpr.getRightOperand()) and
|
||||
result = x.maximum(y)
|
||||
if x >= y then result = x else result = y
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(ConditionalExpr condExpr, Expr conv, float ub, float lb |
|
||||
// ConditionalExpr (true branch)
|
||||
exists(ConditionalExpr condExpr |
|
||||
expr = condExpr and
|
||||
conv = condExpr.getCondition().getFullyConverted() and
|
||||
// Use `boolConversionUpperBound` to determine whether the condition
|
||||
// might evaluate to `true`.
|
||||
lb = boolConversionLowerBound(conv) and
|
||||
ub = boolConversionUpperBound(conv)
|
||||
|
|
||||
// Both branches can be taken
|
||||
ub = 1 and
|
||||
lb = 0 and
|
||||
exists(float thenLb, float elseLb |
|
||||
thenLb = getFullyConvertedLowerBounds(condExpr.getThen()) and
|
||||
elseLb = getFullyConvertedLowerBounds(condExpr.getElse()) and
|
||||
result = thenLb.minimum(elseLb)
|
||||
)
|
||||
or
|
||||
// Only the `true` branch can be taken
|
||||
ub = 1 and lb != 0 and result = getFullyConvertedLowerBounds(condExpr.getThen())
|
||||
or
|
||||
// Only the `false` branch can be taken
|
||||
ub != 1 and lb = 0 and result = getFullyConvertedLowerBounds(condExpr.getElse())
|
||||
boolConversionUpperBound(condExpr.getCondition().getFullyConverted()) = 1 and
|
||||
result = getFullyConvertedLowerBounds(condExpr.getThen())
|
||||
)
|
||||
or
|
||||
// ConditionalExpr (false branch)
|
||||
exists(ConditionalExpr condExpr |
|
||||
expr = condExpr and
|
||||
// Use `boolConversionLowerBound` to determine whether the condition
|
||||
// might evaluate to `false`.
|
||||
boolConversionLowerBound(condExpr.getCondition().getFullyConverted()) = 0 and
|
||||
result = getFullyConvertedLowerBounds(condExpr.getElse())
|
||||
)
|
||||
or
|
||||
exists(AddExpr addExpr, float xLow, float yLow |
|
||||
@@ -979,32 +973,26 @@ private float getUpperBoundsImpl(Expr expr) {
|
||||
exists(float x, float y |
|
||||
x = getFullyConvertedUpperBounds(minExpr.getLeftOperand()) and
|
||||
y = getFullyConvertedUpperBounds(minExpr.getRightOperand()) and
|
||||
result = x.minimum(y)
|
||||
if x <= y then result = x else result = y
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(ConditionalExpr condExpr, Expr conv, float ub, float lb |
|
||||
// ConditionalExpr (true branch)
|
||||
exists(ConditionalExpr condExpr |
|
||||
expr = condExpr and
|
||||
conv = condExpr.getCondition().getFullyConverted() and
|
||||
// Use `boolConversionUpperBound` to determine whether the condition
|
||||
// might evaluate to `true`.
|
||||
lb = boolConversionLowerBound(conv) and
|
||||
ub = boolConversionUpperBound(conv)
|
||||
|
|
||||
// Both branches can be taken
|
||||
ub = 1 and
|
||||
lb = 0 and
|
||||
exists(float thenLb, float elseLb |
|
||||
thenLb = getFullyConvertedUpperBounds(condExpr.getThen()) and
|
||||
elseLb = getFullyConvertedUpperBounds(condExpr.getElse()) and
|
||||
result = thenLb.maximum(elseLb)
|
||||
)
|
||||
or
|
||||
// Only the `true` branch can be taken
|
||||
ub = 1 and lb != 0 and result = getFullyConvertedUpperBounds(condExpr.getThen())
|
||||
or
|
||||
// Only the `false` branch can be taken
|
||||
ub != 1 and lb = 0 and result = getFullyConvertedUpperBounds(condExpr.getElse())
|
||||
boolConversionUpperBound(condExpr.getCondition().getFullyConverted()) = 1 and
|
||||
result = getFullyConvertedUpperBounds(condExpr.getThen())
|
||||
)
|
||||
or
|
||||
// ConditionalExpr (false branch)
|
||||
exists(ConditionalExpr condExpr |
|
||||
expr = condExpr and
|
||||
// Use `boolConversionLowerBound` to determine whether the condition
|
||||
// might evaluate to `false`.
|
||||
boolConversionLowerBound(condExpr.getCondition().getFullyConverted()) = 0 and
|
||||
result = getFullyConvertedUpperBounds(condExpr.getElse())
|
||||
)
|
||||
or
|
||||
exists(AddExpr addExpr, float xHigh, float yHigh |
|
||||
@@ -1152,7 +1140,10 @@ private float getUpperBoundsImpl(Expr expr) {
|
||||
not expr instanceof SimpleRangeAnalysisExpr
|
||||
or
|
||||
// A modeled expression for range analysis
|
||||
result = expr.(SimpleRangeAnalysisExpr).getUpperBounds()
|
||||
exists(SimpleRangeAnalysisExpr rangeAnalysisExpr |
|
||||
rangeAnalysisExpr = expr and
|
||||
result = rangeAnalysisExpr.getUpperBounds()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1603,7 +1594,7 @@ private module SimpleRangeAnalysisCached {
|
||||
* the lower bound of the expression after all the casts have been applied,
|
||||
* call `lowerBound` like this:
|
||||
*
|
||||
* lowerBound(expr.getFullyConverted())
|
||||
* `lowerBound(expr.getFullyConverted())`
|
||||
*/
|
||||
cached
|
||||
float lowerBound(Expr expr) {
|
||||
@@ -1622,7 +1613,7 @@ private module SimpleRangeAnalysisCached {
|
||||
* the upper bound of the expression after all the casts have been applied,
|
||||
* call `upperBound` like this:
|
||||
*
|
||||
* upperBound(expr.getFullyConverted())
|
||||
* `upperBound(expr.getFullyConverted())`
|
||||
*/
|
||||
cached
|
||||
float upperBound(Expr expr) {
|
||||
|
||||
@@ -437,154 +437,6 @@ class ConstexprIfStmt extends ConditionalStmt, @stmt_constexpr_if {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A C/C++ '(not) consteval if'. For example, the `if consteval` statement
|
||||
* in the following code:
|
||||
* ```cpp
|
||||
* if consteval {
|
||||
* ...
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class ConstevalIfStmt extends Stmt, @stmt_consteval_or_not_consteval_if {
|
||||
override string getAPrimaryQlClass() { result = "ConstevalIfStmt" }
|
||||
|
||||
override string toString() {
|
||||
if this.isNot() then result = "if ! consteval ..." else result = "if consteval ..."
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this is a 'not consteval if' statement.
|
||||
*
|
||||
* For example, this holds for
|
||||
* ```cpp
|
||||
* if ! consteval { return true; }
|
||||
* ```
|
||||
* but not for
|
||||
* ```cpp
|
||||
* if consteval { return true; }
|
||||
* ```
|
||||
*/
|
||||
predicate isNot() { this instanceof @stmt_not_consteval_if }
|
||||
|
||||
/**
|
||||
* Gets the 'then' statement of this '(not) consteval if' statement.
|
||||
*
|
||||
* For example, for
|
||||
* ```cpp
|
||||
* if consteval { return true; }
|
||||
* ```
|
||||
* the result is the `BlockStmt` `{ return true; }`.
|
||||
*/
|
||||
Stmt getThen() { consteval_if_then(underlyingElement(this), unresolveElement(result)) }
|
||||
|
||||
/**
|
||||
* Gets the 'else' statement of this '(not) constexpr if' statement, if any.
|
||||
*
|
||||
* For example, for
|
||||
* ```cpp
|
||||
* if consteval { return true; } else { return false; }
|
||||
* ```
|
||||
* the result is the `BlockStmt` `{ return false; }`, and for
|
||||
* ```cpp
|
||||
* if consteval { return true; }
|
||||
* ```
|
||||
* there is no result.
|
||||
*/
|
||||
Stmt getElse() { consteval_if_else(underlyingElement(this), unresolveElement(result)) }
|
||||
|
||||
/**
|
||||
* Holds if this '(not) constexpr if' statement has an 'else' statement.
|
||||
*
|
||||
* For example, this holds for
|
||||
* ```cpp
|
||||
* if consteval { return true; } else { return false; }
|
||||
* ```
|
||||
* but not for
|
||||
* ```cpp
|
||||
* if consteval { return true; }
|
||||
* ```
|
||||
*/
|
||||
predicate hasElse() { exists(this.getElse()) }
|
||||
|
||||
override predicate mayBeImpure() {
|
||||
this.getThen().mayBeImpure() or
|
||||
this.getElse().mayBeImpure()
|
||||
}
|
||||
|
||||
override predicate mayBeGloballyImpure() {
|
||||
this.getThen().mayBeGloballyImpure() or
|
||||
this.getElse().mayBeGloballyImpure()
|
||||
}
|
||||
|
||||
override MacroInvocation getGeneratingMacro() {
|
||||
this.getThen().getGeneratingMacro() = result and
|
||||
(this.hasElse() implies this.getElse().getGeneratingMacro() = result)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the statement of this '(not) consteval if' statement evaluated during compile time, if any.
|
||||
*
|
||||
* For example, for
|
||||
* ```cpp
|
||||
* if ! consteval { return true; } else { return false; }
|
||||
* ```
|
||||
* the result is the `BlockStmt` `{ return false; }`, and for
|
||||
* ```cpp
|
||||
* if ! consteval { return true; }
|
||||
* ```
|
||||
* there is no result.
|
||||
*/
|
||||
Stmt getCompileTimeEvaluatedBranch() {
|
||||
if this.isNot() then result = this.getElse() else result = this.getThen()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this '(not) constexpr if' statement has a compile time evaluated statement.
|
||||
*
|
||||
* For example, this holds for
|
||||
* ```cpp
|
||||
* if ! consteval { return true; } else { return false; }
|
||||
* ```
|
||||
* but not for
|
||||
* ```cpp
|
||||
* if ! consteval { return true; }
|
||||
* ```
|
||||
*/
|
||||
predicate hasCompileTimeEvaluatedBranch() { exists(this.getCompileTimeEvaluatedBranch()) }
|
||||
|
||||
/**
|
||||
* Gets the statement of this '(not) consteval if' statement evaluated during runtime, if any.
|
||||
*
|
||||
* For example, for
|
||||
* ```cpp
|
||||
* if consteval { return true; } else { return false; }
|
||||
* ```
|
||||
* the result is the `BlockStmt` `{ return false; }`, and for
|
||||
* ```cpp
|
||||
* if consteval { return true; }
|
||||
* ```
|
||||
* there is no result.
|
||||
*/
|
||||
Stmt getRuntimeEvaluatedBranch() {
|
||||
if this.isNot() then result = this.getThen() else result = this.getElse()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this '(not) constexpr if' statement has a runtime evaluated statement.
|
||||
*
|
||||
* For example, this holds for
|
||||
* ```cpp
|
||||
* if consteval { return true; } else { return false; }
|
||||
* ```
|
||||
* but not for
|
||||
* ```cpp
|
||||
* if consteval { return true; }
|
||||
* ```
|
||||
*/
|
||||
predicate hasRuntimeEvaluatedBranch() { exists(this.getRuntimeEvaluatedBranch()) }
|
||||
}
|
||||
|
||||
private class TLoop = @stmt_while or @stmt_end_test_while or @stmt_range_based_for or @stmt_for;
|
||||
|
||||
/**
|
||||
|
||||
@@ -148,81 +148,119 @@ class HashCons extends HCBase {
|
||||
|
||||
/** Gets the kind of the HC. This can be useful for debugging. */
|
||||
string getKind() {
|
||||
result = this.getKind0()
|
||||
or
|
||||
not exists(this.getKind0()) and result = "error"
|
||||
}
|
||||
|
||||
private string getKind0() {
|
||||
this instanceof HC_IntLiteral and result = "IntLiteral"
|
||||
or
|
||||
this instanceof HC_EnumConstantAccess and result = "EnumConstantAccess"
|
||||
or
|
||||
this instanceof HC_FloatLiteral and result = "FloatLiteral"
|
||||
or
|
||||
this instanceof HC_StringLiteral and result = "StringLiteral"
|
||||
or
|
||||
this instanceof HC_Nullptr and result = "Nullptr"
|
||||
or
|
||||
this instanceof HC_Variable and result = "Variable"
|
||||
or
|
||||
this instanceof HC_FieldAccess and result = "FieldAccess"
|
||||
or
|
||||
this instanceof HC_Deref and result = "Deref"
|
||||
or
|
||||
this instanceof HC_ThisExpr and result = "ThisExpr"
|
||||
or
|
||||
this instanceof HC_Conversion and result = "Conversion"
|
||||
or
|
||||
this instanceof HC_BinaryOp and result = "BinaryOp"
|
||||
or
|
||||
this instanceof HC_UnaryOp and result = "UnaryOp"
|
||||
or
|
||||
this instanceof HC_ArrayAccess and result = "ArrayAccess"
|
||||
or
|
||||
this instanceof HC_Unanalyzable and result = "Unanalyzable"
|
||||
or
|
||||
this instanceof HC_NonmemberFunctionCall and result = "NonmemberFunctionCall"
|
||||
or
|
||||
this instanceof HC_MemberFunctionCall and result = "MemberFunctionCall"
|
||||
or
|
||||
this instanceof HC_NewExpr and result = "NewExpr"
|
||||
or
|
||||
this instanceof HC_NewArrayExpr and result = "NewArrayExpr"
|
||||
or
|
||||
this instanceof HC_SizeofType and result = "SizeofTypeOperator"
|
||||
or
|
||||
this instanceof HC_SizeofExpr and result = "SizeofExprOperator"
|
||||
or
|
||||
this instanceof HC_AlignofType and result = "AlignofTypeOperator"
|
||||
or
|
||||
this instanceof HC_AlignofExpr and result = "AlignofExprOperator"
|
||||
or
|
||||
this instanceof HC_UuidofOperator and result = "UuidofOperator"
|
||||
or
|
||||
this instanceof HC_TypeidType and result = "TypeidType"
|
||||
or
|
||||
this instanceof HC_TypeidExpr and result = "TypeidExpr"
|
||||
or
|
||||
this instanceof HC_ArrayAggregateLiteral and result = "ArrayAggregateLiteral"
|
||||
or
|
||||
this instanceof HC_ClassAggregateLiteral and result = "ClassAggregateLiteral"
|
||||
or
|
||||
this instanceof HC_DeleteExpr and result = "DeleteExpr"
|
||||
or
|
||||
this instanceof HC_DeleteArrayExpr and result = "DeleteArrayExpr"
|
||||
or
|
||||
this instanceof HC_ThrowExpr and result = "ThrowExpr"
|
||||
or
|
||||
this instanceof HC_ReThrowExpr and result = "ReThrowExpr"
|
||||
or
|
||||
this instanceof HC_ExprCall and result = "ExprCall"
|
||||
or
|
||||
this instanceof HC_ConditionalExpr and result = "ConditionalExpr"
|
||||
or
|
||||
this instanceof HC_NoExceptExpr and result = "NoExceptExpr"
|
||||
or
|
||||
this instanceof HC_AllocatorArgZero and result = "AllocatorArgZero"
|
||||
if this instanceof HC_IntLiteral
|
||||
then result = "IntLiteral"
|
||||
else
|
||||
if this instanceof HC_EnumConstantAccess
|
||||
then result = "EnumConstantAccess"
|
||||
else
|
||||
if this instanceof HC_FloatLiteral
|
||||
then result = "FloatLiteral"
|
||||
else
|
||||
if this instanceof HC_StringLiteral
|
||||
then result = "StringLiteral"
|
||||
else
|
||||
if this instanceof HC_Nullptr
|
||||
then result = "Nullptr"
|
||||
else
|
||||
if this instanceof HC_Variable
|
||||
then result = "Variable"
|
||||
else
|
||||
if this instanceof HC_FieldAccess
|
||||
then result = "FieldAccess"
|
||||
else
|
||||
if this instanceof HC_Deref
|
||||
then result = "Deref"
|
||||
else
|
||||
if this instanceof HC_ThisExpr
|
||||
then result = "ThisExpr"
|
||||
else
|
||||
if this instanceof HC_Conversion
|
||||
then result = "Conversion"
|
||||
else
|
||||
if this instanceof HC_BinaryOp
|
||||
then result = "BinaryOp"
|
||||
else
|
||||
if this instanceof HC_UnaryOp
|
||||
then result = "UnaryOp"
|
||||
else
|
||||
if this instanceof HC_ArrayAccess
|
||||
then result = "ArrayAccess"
|
||||
else
|
||||
if this instanceof HC_Unanalyzable
|
||||
then result = "Unanalyzable"
|
||||
else
|
||||
if this instanceof HC_NonmemberFunctionCall
|
||||
then result = "NonmemberFunctionCall"
|
||||
else
|
||||
if this instanceof HC_MemberFunctionCall
|
||||
then result = "MemberFunctionCall"
|
||||
else
|
||||
if this instanceof HC_NewExpr
|
||||
then result = "NewExpr"
|
||||
else
|
||||
if this instanceof HC_NewArrayExpr
|
||||
then result = "NewArrayExpr"
|
||||
else
|
||||
if this instanceof HC_SizeofType
|
||||
then result = "SizeofTypeOperator"
|
||||
else
|
||||
if this instanceof HC_SizeofExpr
|
||||
then result = "SizeofExprOperator"
|
||||
else
|
||||
if this instanceof HC_AlignofType
|
||||
then result = "AlignofTypeOperator"
|
||||
else
|
||||
if this instanceof HC_AlignofExpr
|
||||
then result = "AlignofExprOperator"
|
||||
else
|
||||
if this instanceof HC_UuidofOperator
|
||||
then result = "UuidofOperator"
|
||||
else
|
||||
if this instanceof HC_TypeidType
|
||||
then result = "TypeidType"
|
||||
else
|
||||
if this instanceof HC_TypeidExpr
|
||||
then result = "TypeidExpr"
|
||||
else
|
||||
if this instanceof HC_ArrayAggregateLiteral
|
||||
then result = "ArrayAggregateLiteral"
|
||||
else
|
||||
if this instanceof HC_ClassAggregateLiteral
|
||||
then result = "ClassAggregateLiteral"
|
||||
else
|
||||
if this instanceof HC_DeleteExpr
|
||||
then result = "DeleteExpr"
|
||||
else
|
||||
if this instanceof HC_DeleteArrayExpr
|
||||
then result = "DeleteArrayExpr"
|
||||
else
|
||||
if this instanceof HC_ThrowExpr
|
||||
then result = "ThrowExpr"
|
||||
else
|
||||
if this instanceof HC_ReThrowExpr
|
||||
then result = "ReThrowExpr"
|
||||
else
|
||||
if this instanceof HC_ExprCall
|
||||
then result = "ExprCall"
|
||||
else
|
||||
if
|
||||
this instanceof
|
||||
HC_ConditionalExpr
|
||||
then result = "ConditionalExpr"
|
||||
else
|
||||
if
|
||||
this instanceof
|
||||
HC_NoExceptExpr
|
||||
then result = "NoExceptExpr"
|
||||
else
|
||||
if
|
||||
this instanceof
|
||||
HC_AllocatorArgZero
|
||||
then
|
||||
result =
|
||||
"AllocatorArgZero"
|
||||
else result = "error"
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -771,13 +771,12 @@ decltypes(
|
||||
|
||||
/*
|
||||
case @usertype.kind of
|
||||
| 0 = @unknown_usertype
|
||||
| 1 = @struct
|
||||
1 = @struct
|
||||
| 2 = @class
|
||||
| 3 = @union
|
||||
| 4 = @enum
|
||||
// ... 5 = @typedef deprecated // classic C: typedef typedef type name
|
||||
// ... 6 = @template deprecated
|
||||
| 5 = @typedef // classic C: typedef typedef type name
|
||||
| 6 = @template
|
||||
| 7 = @template_parameter
|
||||
| 8 = @template_template_parameter
|
||||
| 9 = @proxy_class // a proxy class associated with a template parameter
|
||||
@@ -785,11 +784,7 @@ case @usertype.kind of
|
||||
// ... 11 objc_protocol deprecated
|
||||
// ... 12 objc_category deprecated
|
||||
| 13 = @scoped_enum
|
||||
// ... 14 = @using_alias deprecated // a using name = type style typedef
|
||||
| 15 = @template_struct
|
||||
| 16 = @template_class
|
||||
| 17 = @template_union
|
||||
| 18 = @alias
|
||||
| 14 = @using_alias // a using name = type style typedef
|
||||
;
|
||||
*/
|
||||
|
||||
@@ -812,17 +807,6 @@ usertype_uuid(
|
||||
string uuid: string ref
|
||||
);
|
||||
|
||||
/*
|
||||
case @usertype.alias_kind of
|
||||
| 0 = @typedef
|
||||
| 1 = @alias
|
||||
*/
|
||||
|
||||
usertype_alias_kind(
|
||||
int id: @usertype ref,
|
||||
int alias_kind: int ref
|
||||
)
|
||||
|
||||
nontype_template_parameters(
|
||||
int id: @expr ref
|
||||
);
|
||||
@@ -859,11 +843,9 @@ class_template_argument_value(
|
||||
int arg_value: @expr ref
|
||||
);
|
||||
|
||||
@user_or_decltype = @usertype | @decltype;
|
||||
|
||||
is_proxy_class_for(
|
||||
unique int id: @usertype ref,
|
||||
int templ_param_id: @user_or_decltype ref
|
||||
unique int templ_param_id: @usertype ref
|
||||
);
|
||||
|
||||
type_mentions(
|
||||
@@ -2164,8 +2146,6 @@ case @stmt.kind of
|
||||
// ... 34 @stmt_finally_end deprecated
|
||||
| 35 = @stmt_constexpr_if
|
||||
| 37 = @stmt_co_return
|
||||
| 38 = @stmt_consteval_if
|
||||
| 39 = @stmt_not_consteval_if
|
||||
;
|
||||
|
||||
type_vla(
|
||||
@@ -2208,18 +2188,6 @@ constexpr_if_else(
|
||||
int else_id: @stmt ref
|
||||
);
|
||||
|
||||
@stmt_consteval_or_not_consteval_if = @stmt_consteval_if | @stmt_not_consteval_if;
|
||||
|
||||
consteval_if_then(
|
||||
unique int constexpr_if_stmt: @stmt_consteval_or_not_consteval_if ref,
|
||||
int then_id: @stmt ref
|
||||
);
|
||||
|
||||
consteval_if_else(
|
||||
unique int constexpr_if_stmt: @stmt_consteval_or_not_consteval_if ref,
|
||||
int else_id: @stmt ref
|
||||
);
|
||||
|
||||
while_body(
|
||||
unique int while_stmt: @stmt_while ref,
|
||||
int body_id: @stmt ref
|
||||
@@ -2330,15 +2298,12 @@ case @preprocdirect.kind of
|
||||
| 11 = @ppd_pragma
|
||||
| 12 = @ppd_objc_import
|
||||
| 13 = @ppd_include_next
|
||||
| 14 = @ppd_ms_import
|
||||
| 15 = @ppd_elifdef
|
||||
| 16 = @ppd_elifndef
|
||||
| 18 = @ppd_warning
|
||||
;
|
||||
|
||||
@ppd_include = @ppd_plain_include | @ppd_objc_import | @ppd_include_next | @ppd_ms_import;
|
||||
@ppd_include = @ppd_plain_include | @ppd_objc_import | @ppd_include_next;
|
||||
|
||||
@ppd_branch = @ppd_if | @ppd_ifdef | @ppd_ifndef | @ppd_elif | @ppd_elifdef | @ppd_elifndef;
|
||||
@ppd_branch = @ppd_if | @ppd_ifdef | @ppd_ifndef | @ppd_elif;
|
||||
|
||||
preprocpair(
|
||||
int begin : @ppd_branch ref,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,2 +0,0 @@
|
||||
description: Support #elifdef, #elifndef and #import
|
||||
compatibility: partial
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user