mirror of
https://github.com/github/codeql.git
synced 2026-05-25 00:27:09 +02:00
Merge branch 'main' into jb1/isLibraryFile-nomagic
This commit is contained in:
2
.bazelrc
2
.bazelrc
@@ -1,5 +1,4 @@
|
||||
common --enable_platform_specific_config
|
||||
common --enable_bzlmod
|
||||
# because we use --override_module with `%workspace%`, the lock file is not stable
|
||||
common --lockfile_mode=off
|
||||
|
||||
@@ -25,6 +24,5 @@ common --registry=https://bcr.bazel.build
|
||||
|
||||
common --@rules_dotnet//dotnet/settings:strict_deps=false
|
||||
common --experimental_isolated_extension_usages
|
||||
common --incompatible_use_plus_in_repo_names
|
||||
|
||||
try-import %workspace%/local.bazelrc
|
||||
|
||||
@@ -1 +1 @@
|
||||
5f5d70b6c4d2fb1a889479569107f1692239e8a7
|
||||
8.0.0rc1
|
||||
|
||||
2
.github/codeql/codeql-config.yml
vendored
2
.github/codeql/codeql-config.yml
vendored
@@ -9,3 +9,5 @@ paths-ignore:
|
||||
- '/python/'
|
||||
- '/javascript/ql/test'
|
||||
- '/javascript/extractor/tests'
|
||||
- '/rust/ql/test'
|
||||
- '/rust/ql/integration-tests'
|
||||
|
||||
4
.github/labeler.yml
vendored
4
.github/labeler.yml
vendored
@@ -38,6 +38,10 @@ Swift:
|
||||
- swift/**/*
|
||||
- change-notes/**/*swift*
|
||||
|
||||
Actions:
|
||||
- actions/**/*
|
||||
- change-notes/**/*actions*
|
||||
|
||||
documentation:
|
||||
- "**/*.qhelp"
|
||||
- "**/*.md"
|
||||
|
||||
2
.github/workflows/build-ripunzip.yml
vendored
2
.github/workflows/build-ripunzip.yml
vendored
@@ -17,7 +17,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-20.04, macos-12, windows-2019]
|
||||
os: [ubuntu-20.04, macos-13, windows-2019]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
28
.github/workflows/powershell-pr-check.yml
vendored
Normal file
28
.github/workflows/powershell-pr-check.yml
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
name: PowerShell PR Check
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
powershell-pr-check:
|
||||
name: powershell-pr-check
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'microsoft/codeql'
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
token: ${{ secrets.WORKFLOW_TOKEN }}
|
||||
- name: Setup CodeQL
|
||||
uses: ./.github/actions/fetch-codeql
|
||||
with:
|
||||
channel: release
|
||||
- name: Compile PowerShell Queries
|
||||
run: |
|
||||
codeql query compile --check-only --keep-going powershell/ql/src
|
||||
64
.github/workflows/rust-analysis.yml
vendored
Normal file
64
.github/workflows/rust-analysis.yml
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
name: "Code scanning - Rust"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- 'rc/*'
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
- 'rc/*'
|
||||
paths:
|
||||
- '**/*.rs'
|
||||
- '**/Cargo.toml'
|
||||
- '.github/codeql/codeql-config.yml'
|
||||
- '.github/workflows/rust-analysis.yml'
|
||||
schedule:
|
||||
- cron: '0 9 * * 1'
|
||||
|
||||
env:
|
||||
CODEQL_ENABLE_EXPERIMENTAL_FEATURES: "true"
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
strategy:
|
||||
matrix:
|
||||
language: [ 'rust' ]
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
security-events: write
|
||||
pull-requests: read
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Query latest nightly CodeQL bundle
|
||||
shell: bash
|
||||
id: codeql
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
REPO=dsp-testing/codeql-cli-nightlies
|
||||
TAG=$(
|
||||
gh release list -R $REPO -L1 --exclude-drafts --json tagName -q ".[] | .tagName"
|
||||
)
|
||||
echo "nightly_bundle=https://github.com/$REPO/releases/download/$TAG/codeql-bundle-linux64.tar.zst" \
|
||||
| tee -a "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@main
|
||||
with:
|
||||
tools: ${{ steps.codeql.outputs.nightly_bundle }}
|
||||
languages: ${{ matrix.language }}
|
||||
config-file: ./.github/codeql/codeql-config.yml
|
||||
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@main
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@main
|
||||
4
.github/workflows/swift.yml
vendored
4
.github/workflows/swift.yml
vendored
@@ -44,7 +44,7 @@ jobs:
|
||||
# without waiting for the macOS build
|
||||
build-and-test-macos:
|
||||
if: github.repository_owner == 'github'
|
||||
runs-on: macos-12-xl
|
||||
runs-on: macos-13-xlarge
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./swift/actions/build-and-test
|
||||
@@ -64,7 +64,7 @@ jobs:
|
||||
qltests-macos:
|
||||
if: ${{ github.repository_owner == 'github' && github.event_name == 'pull_request' }}
|
||||
needs: build-and-test-macos
|
||||
runs-on: macos-12-xl
|
||||
runs-on: macos-13-xlarge
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./swift/actions/run-ql-tests
|
||||
|
||||
11
.github/workflows/sync-main.yml
vendored
11
.github/workflows/sync-main.yml
vendored
@@ -21,17 +21,22 @@ jobs:
|
||||
run: |
|
||||
git config user.name Dilan Bhalla
|
||||
git config user.email dilanbhalla@microsoft.com
|
||||
- name: Fetch
|
||||
- name: Sync Main
|
||||
shell: bash
|
||||
run: |
|
||||
set -x
|
||||
git fetch
|
||||
git remote add upstream https://github.com/github/codeql.git
|
||||
git fetch upstream --tags --force
|
||||
- name: Sync Main
|
||||
git merge codeql-cli/latest
|
||||
- name: Setup CodeQL
|
||||
uses: ./.github/actions/fetch-codeql
|
||||
- name: Compile PowerShell Queries
|
||||
run: |
|
||||
codeql query compile --check-only --keep-going powershell/ql/src
|
||||
- name: Complete Sync
|
||||
shell: bash
|
||||
run: |
|
||||
git merge codeql-cli/latest
|
||||
git push origin main
|
||||
git push origin --tags --force
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
/ql/ @github/codeql-ql-for-ql-reviewers
|
||||
|
||||
# Bazel (excluding BUILD.bazel files)
|
||||
WORKSPACE.bazel @github/codeql-ci-reviewers
|
||||
MODULE.bazel @github/codeql-ci-reviewers
|
||||
.bazelversion @github/codeql-ci-reviewers
|
||||
.bazelrc @github/codeql-ci-reviewers
|
||||
|
||||
27
Cargo.lock
generated
27
Cargo.lock
generated
@@ -384,6 +384,7 @@ dependencies = [
|
||||
"clap",
|
||||
"codeql-extractor",
|
||||
"figment",
|
||||
"glob",
|
||||
"itertools 0.13.0",
|
||||
"log",
|
||||
"num-traits",
|
||||
@@ -631,6 +632,7 @@ dependencies = [
|
||||
"atomic",
|
||||
"pear",
|
||||
"serde",
|
||||
"serde_yaml",
|
||||
"uncased",
|
||||
"version_check",
|
||||
]
|
||||
@@ -704,6 +706,12 @@ dependencies = [
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glob"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
|
||||
|
||||
[[package]]
|
||||
name = "globset"
|
||||
version = "0.4.15"
|
||||
@@ -2058,6 +2066,19 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_yaml"
|
||||
version = "0.9.34+deprecated"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47"
|
||||
dependencies = [
|
||||
"indexmap 2.5.0",
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
"unsafe-libyaml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sharded-slab"
|
||||
version = "0.1.7"
|
||||
@@ -2381,6 +2402,12 @@ version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "229730647fbc343e3a80e463c1db7f78f3855d3f3739bee0dda773c9a037c90a"
|
||||
|
||||
[[package]]
|
||||
name = "unsafe-libyaml"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861"
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
version = "0.2.2"
|
||||
|
||||
@@ -18,14 +18,14 @@ bazel_dep(name = "platforms", version = "0.0.10")
|
||||
bazel_dep(name = "rules_go", version = "0.50.0")
|
||||
bazel_dep(name = "rules_pkg", version = "1.0.1")
|
||||
bazel_dep(name = "rules_nodejs", version = "6.2.0-codeql.1")
|
||||
bazel_dep(name = "rules_python", version = "0.35.0")
|
||||
bazel_dep(name = "bazel_skylib", version = "1.6.1")
|
||||
bazel_dep(name = "rules_python", version = "0.36.0")
|
||||
bazel_dep(name = "bazel_skylib", version = "1.7.1")
|
||||
bazel_dep(name = "abseil-cpp", version = "20240116.0", repo_name = "absl")
|
||||
bazel_dep(name = "nlohmann_json", version = "3.11.3", repo_name = "json")
|
||||
bazel_dep(name = "fmt", version = "10.0.0")
|
||||
bazel_dep(name = "rules_kotlin", version = "2.0.0-codeql.1")
|
||||
bazel_dep(name = "gazelle", version = "0.38.0")
|
||||
bazel_dep(name = "rules_dotnet", version = "0.15.1")
|
||||
bazel_dep(name = "rules_dotnet", version = "0.16.1")
|
||||
bazel_dep(name = "googletest", version = "1.14.0.bcr.1")
|
||||
bazel_dep(name = "rules_rust", version = "0.52.2")
|
||||
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
# please use MODULE.bazel to add dependencies
|
||||
# this empty file is required by internal repositories, don't remove it
|
||||
20
actions/BUILD.bazel
Normal file
20
actions/BUILD.bazel
Normal file
@@ -0,0 +1,20 @@
|
||||
load("//misc/bazel:pkg.bzl", "codeql_pack")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
[
|
||||
codeql_pack(
|
||||
name = "-".join(parts),
|
||||
srcs = [
|
||||
"//actions/extractor",
|
||||
],
|
||||
pack_prefix = "/".join(parts),
|
||||
)
|
||||
for parts in (
|
||||
[
|
||||
"experimental",
|
||||
"actions",
|
||||
],
|
||||
["actions"],
|
||||
)
|
||||
]
|
||||
10
actions/extractor/BUILD.bazel
Normal file
10
actions/extractor/BUILD.bazel
Normal file
@@ -0,0 +1,10 @@
|
||||
load("//misc/bazel:pkg.bzl", "codeql_pkg_files", "strip_prefix")
|
||||
|
||||
codeql_pkg_files(
|
||||
name = "extractor",
|
||||
srcs = [
|
||||
"codeql-extractor.yml",
|
||||
] + glob(["tools/**"]),
|
||||
strip_prefix = strip_prefix.from_pkg(),
|
||||
visibility = ["//actions:__pkg__"],
|
||||
)
|
||||
44
actions/extractor/codeql-extractor.yml
Normal file
44
actions/extractor/codeql-extractor.yml
Normal file
@@ -0,0 +1,44 @@
|
||||
name: "actions"
|
||||
aliases: []
|
||||
display_name: "GitHub Actions"
|
||||
version: 0.0.1
|
||||
column_kind: "utf16"
|
||||
unicode_newlines: true
|
||||
build_modes:
|
||||
- none
|
||||
file_coverage_languages: []
|
||||
github_api_languages: []
|
||||
scc_languages: []
|
||||
file_types:
|
||||
- name: workflow
|
||||
display_name: GitHub Actions workflow files
|
||||
extensions:
|
||||
- .yml
|
||||
- .yaml
|
||||
forwarded_extractor_name: javascript
|
||||
options:
|
||||
trap:
|
||||
title: TRAP options
|
||||
description: Options about how the extractor handles TRAP files
|
||||
type: object
|
||||
visibility: 3
|
||||
properties:
|
||||
cache:
|
||||
title: TRAP cache options
|
||||
description: Options about how the extractor handles its TRAP cache
|
||||
type: object
|
||||
properties:
|
||||
dir:
|
||||
title: TRAP cache directory
|
||||
description: The directory of the TRAP cache to use
|
||||
type: string
|
||||
bound:
|
||||
title: TRAP cache bound
|
||||
description: A soft limit (in MB) on the size of the TRAP cache
|
||||
type: string
|
||||
pattern: "[0-9]+"
|
||||
write:
|
||||
title: TRAP cache writeable
|
||||
description: Whether to write to the TRAP cache as well as reading it
|
||||
type: string
|
||||
pattern: "(true|TRUE|false|FALSE)"
|
||||
40
actions/extractor/tools/autobuild-impl.ps1
Normal file
40
actions/extractor/tools/autobuild-impl.ps1
Normal file
@@ -0,0 +1,40 @@
|
||||
if (($null -ne $env:LGTM_INDEX_INCLUDE) -or ($null -ne $env:LGTM_INDEX_EXCLUDE) -or ($null -ne $env:LGTM_INDEX_FILTERS)) {
|
||||
Write-Output 'Path filters set. Passing them through to the JavaScript extractor.'
|
||||
} else {
|
||||
Write-Output 'No path filters set. Using the default filters.'
|
||||
$DefaultPathFilters = @(
|
||||
'exclude:**/*',
|
||||
'include:.github/workflows/**/*.yml',
|
||||
'include:.github/workflows/**/*.yaml',
|
||||
'include:**/action.yml',
|
||||
'include:**/action.yaml'
|
||||
)
|
||||
|
||||
$env:LGTM_INDEX_FILTERS = $DefaultPathFilters -join "`n"
|
||||
}
|
||||
|
||||
# Find the JavaScript extractor directory via `codeql resolve extractor`.
|
||||
$CodeQL = Join-Path $env:CODEQL_DIST 'codeql.exe'
|
||||
$env:CODEQL_EXTRACTOR_JAVASCRIPT_ROOT = &$CodeQL resolve extractor --language javascript
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw 'Failed to resolve JavaScript extractor.'
|
||||
}
|
||||
|
||||
Write-Output "Found JavaScript extractor at '${env:CODEQL_EXTRACTOR_JAVASCRIPT_ROOT}'."
|
||||
|
||||
# Run the JavaScript autobuilder.
|
||||
$JavaScriptAutoBuild = Join-Path $env:CODEQL_EXTRACTOR_JAVASCRIPT_ROOT 'tools\autobuild.cmd'
|
||||
Write-Output "Running JavaScript autobuilder at '${JavaScriptAutoBuild}'."
|
||||
|
||||
# Copy the values of the Actions extractor environment variables to the JavaScript extractor environment variables.
|
||||
$env:CODEQL_EXTRACTOR_JAVASCRIPT_DIAGNOSTIC_DIR = $env:CODEQL_EXTRACTOR_ACTIONS_DIAGNOSTIC_DIR
|
||||
$env:CODEQL_EXTRACTOR_JAVASCRIPT_LOG_DIR = $env:CODEQL_EXTRACTOR_ACTIONS_LOG_DIR
|
||||
$env:CODEQL_EXTRACTOR_JAVASCRIPT_SCRATCH_DIR = $env:CODEQL_EXTRACTOR_ACTIONS_SCRATCH_DIR
|
||||
$env:CODEQL_EXTRACTOR_JAVASCRIPT_SOURCE_ARCHIVE_DIR = $env:CODEQL_EXTRACTOR_ACTIONS_SOURCE_ARCHIVE_DIR
|
||||
$env:CODEQL_EXTRACTOR_JAVASCRIPT_TRAP_DIR = $env:CODEQL_EXTRACTOR_ACTIONS_TRAP_DIR
|
||||
$env:CODEQL_EXTRACTOR_JAVASCRIPT_WIP_DATABASE = $env:CODEQL_EXTRACTOR_ACTIONS_WIP_DATABASE
|
||||
|
||||
&$JavaScriptAutoBuild
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "JavaScript autobuilder failed."
|
||||
}
|
||||
3
actions/extractor/tools/autobuild.cmd
Normal file
3
actions/extractor/tools/autobuild.cmd
Normal file
@@ -0,0 +1,3 @@
|
||||
@echo off
|
||||
rem All of the work is done in the PowerShell script
|
||||
powershell.exe %~dp0autobuild-impl.ps1
|
||||
39
actions/extractor/tools/autobuild.sh
Executable file
39
actions/extractor/tools/autobuild.sh
Executable file
@@ -0,0 +1,39 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -eu
|
||||
|
||||
DEFAULT_PATH_FILTERS=$(cat << END
|
||||
exclude:**/*
|
||||
include:.github/workflows/**/*.yml
|
||||
include:.github/workflows/**/*.yaml
|
||||
include:**/action.yml
|
||||
include:**/action.yaml
|
||||
END
|
||||
)
|
||||
|
||||
if [ -n "${LGTM_INDEX_INCLUDE:-}" ] || [ -n "${LGTM_INDEX_EXCLUDE:-}" ] || [ -n "${LGTM_INDEX_FILTERS:-}" ] ; then
|
||||
echo "Path filters set. Passing them through to the JavaScript extractor."
|
||||
else
|
||||
echo "No path filters set. Using the default filters."
|
||||
LGTM_INDEX_FILTERS="${DEFAULT_PATH_FILTERS}"
|
||||
export LGTM_INDEX_FILTERS
|
||||
fi
|
||||
|
||||
# Find the JavaScript extractor directory via `codeql resolve extractor`.
|
||||
CODEQL_EXTRACTOR_JAVASCRIPT_ROOT="$($CODEQL_DIST/codeql resolve extractor --language javascript)"
|
||||
export CODEQL_EXTRACTOR_JAVASCRIPT_ROOT
|
||||
|
||||
echo "Found JavaScript extractor at '${CODEQL_EXTRACTOR_JAVASCRIPT_ROOT}'."
|
||||
|
||||
# Run the JavaScript autobuilder
|
||||
JAVASCRIPT_AUTO_BUILD="${CODEQL_EXTRACTOR_JAVASCRIPT_ROOT}/tools/autobuild.sh"
|
||||
echo "Running JavaScript autobuilder at '${JAVASCRIPT_AUTO_BUILD}'."
|
||||
|
||||
# Copy the values of the Actions extractor environment variables to the JavaScript extractor environment variables.
|
||||
env CODEQL_EXTRACTOR_JAVASCRIPT_DIAGNOSTIC_DIR="${CODEQL_EXTRACTOR_ACTIONS_DIAGNOSTIC_DIR}" \
|
||||
CODEQL_EXTRACTOR_JAVASCRIPT_LOG_DIR="${CODEQL_EXTRACTOR_ACTIONS_LOG_DIR}" \
|
||||
CODEQL_EXTRACTOR_JAVASCRIPT_SCRATCH_DIR="${CODEQL_EXTRACTOR_ACTIONS_SCRATCH_DIR}" \
|
||||
CODEQL_EXTRACTOR_JAVASCRIPT_SOURCE_ARCHIVE_DIR="${CODEQL_EXTRACTOR_ACTIONS_SOURCE_ARCHIVE_DIR}" \
|
||||
CODEQL_EXTRACTOR_JAVASCRIPT_TRAP_DIR="${CODEQL_EXTRACTOR_ACTIONS_TRAP_DIR}" \
|
||||
CODEQL_EXTRACTOR_JAVASCRIPT_WIP_DATABASE="${CODEQL_EXTRACTOR_ACTIONS_WIP_DATABASE}" \
|
||||
${JAVASCRIPT_AUTO_BUILD}
|
||||
1
actions/ql/lib/actions.qll
Normal file
1
actions/ql/lib/actions.qll
Normal file
@@ -0,0 +1 @@
|
||||
predicate placeholder(int x) { x = 0 }
|
||||
12
actions/ql/lib/qlpack.yml
Normal file
12
actions/ql/lib/qlpack.yml
Normal file
@@ -0,0 +1,12 @@
|
||||
name: codeql/actions-all
|
||||
version: 0.0.1-dev
|
||||
library: true
|
||||
warnOnImplicitThis: true
|
||||
dependencies:
|
||||
codeql/util: ${workspace}
|
||||
codeql/yaml: ${workspace}
|
||||
codeql/controlflow: ${workspace}
|
||||
codeql/dataflow: ${workspace}
|
||||
codeql/javascript-all: ${workspace}
|
||||
extractor: actions
|
||||
groups: actions
|
||||
16
actions/ql/src/Placeholder.ql
Normal file
16
actions/ql/src/Placeholder.ql
Normal file
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* @name Placeholder Query
|
||||
* @description Placeholder
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 9.3
|
||||
* @precision high
|
||||
* @id actions/placeholder
|
||||
* @tags actions security
|
||||
*/
|
||||
|
||||
import actions
|
||||
import javascript
|
||||
|
||||
from File f
|
||||
select f, "Analyzed a file."
|
||||
8
actions/ql/src/qlpack.yml
Normal file
8
actions/ql/src/qlpack.yml
Normal file
@@ -0,0 +1,8 @@
|
||||
name: codeql/actions-queries
|
||||
version: 0.0.1-dev
|
||||
library: false
|
||||
groups: [actions, queries]
|
||||
extractor: actions
|
||||
dependencies:
|
||||
codeql/actions-all: ${workspace}
|
||||
warnOnImplicitThis: true
|
||||
23
actions/ql/test/library-tests/.github/workflows/shell.yml
vendored
Normal file
23
actions/ql/test/library-tests/.github/workflows/shell.yml
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
on: push
|
||||
|
||||
jobs:
|
||||
job1:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- shell: pwsh
|
||||
run: Write-Output "foo"
|
||||
job2:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: echo "foo"
|
||||
|
||||
job3:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- shell: bash
|
||||
run: echo "foo"
|
||||
job4:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- run: Write-Output "foo"
|
||||
|
||||
1
actions/ql/test/library-tests/Placeholder.expected
Normal file
1
actions/ql/test/library-tests/Placeholder.expected
Normal file
@@ -0,0 +1 @@
|
||||
| 1 |
|
||||
1
actions/ql/test/library-tests/Placeholder.ql
Normal file
1
actions/ql/test/library-tests/Placeholder.ql
Normal file
@@ -0,0 +1 @@
|
||||
select 1
|
||||
8
actions/ql/test/qlpack.yml
Normal file
8
actions/ql/test/qlpack.yml
Normal file
@@ -0,0 +1,8 @@
|
||||
name: codeql/actions-tests
|
||||
groups: [codeql, test]
|
||||
dependencies:
|
||||
codeql/actions-all: ${workspace}
|
||||
codeql/actions-queries: ${workspace}
|
||||
extractor: actions
|
||||
tests: .
|
||||
warnOnImplicitThis: true
|
||||
23
actions/ql/test/query-tests/Placeholder/.github/workflows/shell.yml
vendored
Normal file
23
actions/ql/test/query-tests/Placeholder/.github/workflows/shell.yml
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
on: push
|
||||
|
||||
jobs:
|
||||
job1:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- shell: pwsh
|
||||
run: Write-Output "foo"
|
||||
job2:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: echo "foo"
|
||||
|
||||
job3:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- shell: bash
|
||||
run: echo "foo"
|
||||
job4:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- run: Write-Output "foo"
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
| .github/workflows/shell.yml:0:0:0:0 | .github/workflows/shell.yml | Analyzed a file. |
|
||||
@@ -0,0 +1 @@
|
||||
Placeholder.ql
|
||||
@@ -351,9 +351,5 @@
|
||||
"Python model summaries test extension": [
|
||||
"python/ql/test/library-tests/dataflow/model-summaries/InlineTaintTest.ext.yml",
|
||||
"python/ql/test/library-tests/dataflow/model-summaries/NormalDataflowTest.ext.yml"
|
||||
],
|
||||
"Diagnostics.qll": [
|
||||
"ruby/ql/lib/codeql/ruby/Diagnostics.qll",
|
||||
"rust/ql/lib/codeql/rust/Diagnostics.qll"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
class Expr extends @expr {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
class Location extends @location_expr {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
predicate isExprRequirement(Expr expr) {
|
||||
exists(int kind | exprs(expr, kind, _) | kind = [391, 392, 393])
|
||||
}
|
||||
|
||||
from Expr expr, int kind, int kind_new, Location location
|
||||
where
|
||||
exprs(expr, kind, location) and
|
||||
if isExprRequirement(expr) then kind_new = 1 else kind_new = kind
|
||||
select expr, kind_new, location
|
||||
2323
cpp/downgrades/e51fad7a2436caefab0c6bd52f05e28e7cce4d92/old.dbscheme
Normal file
2323
cpp/downgrades/e51fad7a2436caefab0c6bd52f05e28e7cce4d92/old.dbscheme
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,17 @@
|
||||
class Parameter extends @parameter {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
class ParameterizedElement extends @parameterized_element {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
class Type extends @type {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
from Parameter param, ParameterizedElement pe, int index, Type type
|
||||
where
|
||||
params(param, pe, index, type) and
|
||||
not pe instanceof @requires_expr
|
||||
select param, pe, index, type
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,5 @@
|
||||
description: Support C++20 requires expressions
|
||||
compatibility: partial
|
||||
compound_requirement_is_noexcept.rel: delete
|
||||
exprs.rel: run exprs.qlo
|
||||
params.rel: run params.qlo
|
||||
@@ -1,3 +1,16 @@
|
||||
## 2.1.0
|
||||
|
||||
### New Features
|
||||
|
||||
* Added a new predicate `DataFlow::getARuntimeTarget` for getting a function that may be invoked by a `Call` expression. Unlike `Call.getTarget` this new predicate may also resolve function pointers.
|
||||
* Added the predicate `mayBeFromImplicitlyDeclaredFunction()` to the `Call` class to represent calls that may be the return value of an implicitly declared C function.
|
||||
* Added the predicate `getAnExplicitDeclarationEntry()` to the `Function` class to get a `FunctionDeclarationEntry` that is not implicit.
|
||||
* Added classes `RequiresExpr`, `SimpleRequirementExpr`, `TypeRequirementExpr`, `CompoundRequirementExpr`, and `NestedRequirementExpr` to represent C++20 requires expressions and the simple, type, compound, and nested requirements that can occur in `requires` expressions.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* The function call target resolution algorithm has been improved to resolve more calls through function pointers. As a result, dataflow queries may have more results.
|
||||
|
||||
## 2.0.2
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
12
cpp/ql/lib/change-notes/released/2.1.0.md
Normal file
12
cpp/ql/lib/change-notes/released/2.1.0.md
Normal file
@@ -0,0 +1,12 @@
|
||||
## 2.1.0
|
||||
|
||||
### New Features
|
||||
|
||||
* Added a new predicate `DataFlow::getARuntimeTarget` for getting a function that may be invoked by a `Call` expression. Unlike `Call.getTarget` this new predicate may also resolve function pointers.
|
||||
* Added the predicate `mayBeFromImplicitlyDeclaredFunction()` to the `Call` class to represent calls that may be the return value of an implicitly declared C function.
|
||||
* Added the predicate `getAnExplicitDeclarationEntry()` to the `Function` class to get a `FunctionDeclarationEntry` that is not implicit.
|
||||
* Added classes `RequiresExpr`, `SimpleRequirementExpr`, `TypeRequirementExpr`, `CompoundRequirementExpr`, and `NestedRequirementExpr` to represent C++20 requires expressions and the simple, type, compound, and nested requirements that can occur in `requires` expressions.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* The function call target resolution algorithm has been improved to resolve more calls through function pointers. As a result, dataflow queries may have more results.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 2.0.2
|
||||
lastReleaseVersion: 2.1.0
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-all
|
||||
version: 2.0.2
|
||||
version: 2.1.0
|
||||
groups: cpp
|
||||
dbscheme: semmlecode.cpp.dbscheme
|
||||
extractor: cpp
|
||||
|
||||
@@ -6,9 +6,156 @@ import semmle.code.cpp.exprs.Expr
|
||||
|
||||
/**
|
||||
* A C++ requires expression.
|
||||
*
|
||||
* For example, with `T` and `U` template parameters:
|
||||
* ```cpp
|
||||
* requires (T x, U y) { x + y; };
|
||||
* ```
|
||||
*/
|
||||
class RequiresExpr extends Expr, @requires_expr {
|
||||
override string toString() { result = "requires ..." }
|
||||
override string toString() {
|
||||
if exists(this.getAParameter())
|
||||
then result = "requires(...) { ... }"
|
||||
else result = "requires { ... }"
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() { result = "RequiresExpr" }
|
||||
|
||||
/**
|
||||
* Gets a requirement in this requires expression.
|
||||
*/
|
||||
RequirementExpr getARequirement() { result = this.getAChild() }
|
||||
|
||||
/**
|
||||
* Gets the nth requirement in this requires expression.
|
||||
*/
|
||||
RequirementExpr getRequirement(int n) { result = this.getChild(n) }
|
||||
|
||||
/**
|
||||
* Gets the number of requirements in this requires expression.
|
||||
*/
|
||||
int getNumberOfRequirements() { result = count(this.getARequirement()) }
|
||||
|
||||
/**
|
||||
* Gets a parameter of this requires expression, if any.
|
||||
*/
|
||||
Parameter getAParameter() { result.getRequiresExpr() = underlyingElement(this) }
|
||||
|
||||
/**
|
||||
* Gets the the nth parameter of this requires expression.
|
||||
*/
|
||||
Parameter getParameter(int n) {
|
||||
result.getRequiresExpr() = underlyingElement(this) and result.getIndex() = n
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of parameters of this requires expression.
|
||||
*/
|
||||
int getNumberOfParameters() { result = count(this.getAParameter()) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A C++ requirement in a requires expression.
|
||||
*/
|
||||
class RequirementExpr extends Expr { }
|
||||
|
||||
/**
|
||||
* A C++ simple requirement in a requires expression.
|
||||
*
|
||||
* For example, if:
|
||||
* ```cpp
|
||||
* requires(T x, U y) { x + y; };
|
||||
* ```
|
||||
* with `T` and `U` template parameters, then `x + y;` is a simple requirement.
|
||||
*/
|
||||
class SimpleRequirementExpr extends RequirementExpr {
|
||||
SimpleRequirementExpr() {
|
||||
this.getParent() instanceof RequiresExpr and
|
||||
not this instanceof TypeRequirementExpr and
|
||||
not this instanceof CompoundRequirementExpr and
|
||||
not this instanceof NestedRequirementExpr
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() { result = "SimpleRequirementExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A C++ type requirement in a requires expression.
|
||||
*
|
||||
* For example, if:
|
||||
* ```cpp
|
||||
* requires { typename T::a_field; };
|
||||
* ```
|
||||
* with `T` a template parameter, then `typename T::a_field;` is a type requirement.
|
||||
*/
|
||||
class TypeRequirementExpr extends RequirementExpr, TypeName {
|
||||
TypeRequirementExpr() { this.getParent() instanceof RequiresExpr }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "TypeRequirementExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A C++ compound requirement in a requires expression.
|
||||
*
|
||||
* For example, if:
|
||||
* ```cpp
|
||||
* requires(T x) { { x } noexcept -> std::same_as<int>; };
|
||||
* ```
|
||||
* with `T` a template parameter, then `{ x } noexcept -> std::same_as<int>;` is
|
||||
* a compound requirement.
|
||||
*/
|
||||
class CompoundRequirementExpr extends RequirementExpr, @compound_requirement {
|
||||
override string toString() {
|
||||
if exists(this.getReturnTypeRequirement())
|
||||
then result = "{ ... } -> ..."
|
||||
else result = "{ ... }"
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() { result = "CompoundRequirementExpr" }
|
||||
|
||||
/**
|
||||
* Gets the expression from the compound requirement.
|
||||
*/
|
||||
Expr getExpr() { result = this.getChild(0) }
|
||||
|
||||
/**
|
||||
* Gets the return type requirement from the compound requirement, if any.
|
||||
*/
|
||||
Expr getReturnTypeRequirement() { result = this.getChild(1) }
|
||||
|
||||
/**
|
||||
* Holds if the expression from the compound requirement must not be
|
||||
* potentially throwing.
|
||||
*/
|
||||
predicate isNoExcept() { compound_requirement_is_noexcept(underlyingElement(this)) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A C++ nested requirement in a requires expression.
|
||||
*
|
||||
* For example, if:
|
||||
* ```cpp
|
||||
* requires { requires std::is_same<T, int>::value; };
|
||||
* ```
|
||||
* with `T` a template parameter, then `requires std::is_same<T, int>::value;` is
|
||||
* a nested requirement.
|
||||
*/
|
||||
class NestedRequirementExpr extends Expr, @nested_requirement {
|
||||
override string toString() { result = "requires ..." }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "NestedRequirementExpr" }
|
||||
|
||||
/**
|
||||
* Gets the constraint from the nested requirement.
|
||||
*/
|
||||
Expr getConstraint() { result = this.getChild(0) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A C++ concept id expression.
|
||||
*/
|
||||
class ConceptIdExpr extends RequirementExpr, @concept_id {
|
||||
override string toString() { result = "concept<...>" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "ConceptIdExpr" }
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ class Element extends ElementBase {
|
||||
* or certain kinds of `Statement`.
|
||||
*/
|
||||
Element getParentScope() {
|
||||
// result instanceof class
|
||||
// result instanceof Class
|
||||
exists(Declaration m |
|
||||
m = this and
|
||||
result = m.getDeclaringType() and
|
||||
@@ -138,31 +138,40 @@ class Element extends ElementBase {
|
||||
or
|
||||
exists(TemplateClass tc | this = tc.getATemplateArgument() and result = tc)
|
||||
or
|
||||
// result instanceof namespace
|
||||
// result instanceof Namespace
|
||||
exists(Namespace n | result = n and n.getADeclaration() = this)
|
||||
or
|
||||
exists(FriendDecl d, Namespace n | this = d and n.getADeclaration() = d and result = n)
|
||||
or
|
||||
exists(Namespace n | this = n and result = n.getParentNamespace())
|
||||
or
|
||||
// result instanceof stmt
|
||||
// result instanceof Stmt
|
||||
exists(LocalVariable v |
|
||||
this = v and
|
||||
exists(DeclStmt ds | ds.getADeclaration() = v and result = ds.getParent())
|
||||
)
|
||||
or
|
||||
exists(Parameter p | this = p and result = p.getFunction())
|
||||
exists(Parameter p |
|
||||
this = p and
|
||||
(
|
||||
result = p.getFunction() or
|
||||
result = p.getCatchBlock().getParent().(Handler).getParent().(TryStmt).getParent() or
|
||||
result = p.getRequiresExpr().getEnclosingStmt().getParent()
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(GlobalVariable g, Namespace n | this = g and n.getADeclaration() = g and result = n)
|
||||
or
|
||||
exists(TemplateVariable tv | this = tv.getATemplateArgument() and result = tv)
|
||||
or
|
||||
exists(EnumConstant e | this = e and result = e.getDeclaringEnum())
|
||||
or
|
||||
// result instanceof block|function
|
||||
// result instanceof Block|Function
|
||||
exists(BlockStmt b | this = b and blockscope(unresolveElement(b), unresolveElement(result)))
|
||||
or
|
||||
exists(TemplateFunction tf | this = tf.getATemplateArgument() and result = tf)
|
||||
or
|
||||
// result instanceof stmt
|
||||
// result instanceof Stmt
|
||||
exists(ControlStructure s | this = s and result = s.getParent())
|
||||
or
|
||||
using_container(unresolveElement(result), underlyingElement(this))
|
||||
|
||||
@@ -230,6 +230,14 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a non-implicit function declaration entry.
|
||||
*/
|
||||
FunctionDeclarationEntry getAnExplicitDeclarationEntry() {
|
||||
result = this.getADeclarationEntry() and
|
||||
not result.isImplicit()
|
||||
}
|
||||
|
||||
private predicate declEntry(FunctionDeclarationEntry fde) {
|
||||
fun_decls(unresolveElement(fde), underlyingElement(this), _, _, _) and
|
||||
// If one .cpp file specializes a function, and another calls the
|
||||
|
||||
@@ -7,8 +7,8 @@ import semmle.code.cpp.Declaration
|
||||
private import semmle.code.cpp.internal.ResolveClass
|
||||
|
||||
/**
|
||||
* A C/C++ function parameter or catch block parameter. For example the
|
||||
* function parameter `p` and the catch block parameter `e` in the following
|
||||
* A C/C++ function parameter, catch block parameter, or requires expression parameter.
|
||||
* For example the function parameter `p` and the catch block parameter `e` in the following
|
||||
* code:
|
||||
* ```
|
||||
* void myFunction(int p) {
|
||||
@@ -20,8 +20,8 @@ private import semmle.code.cpp.internal.ResolveClass
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* For catch block parameters, there is a one-to-one correspondence between
|
||||
* the `Parameter` and its `ParameterDeclarationEntry`.
|
||||
* For catch block parameters and expression , there is a one-to-one
|
||||
* correspondence between the `Parameter` and its `VariableDeclarationEntry`.
|
||||
*
|
||||
* For function parameters, there is a one-to-many relationship between
|
||||
* `Parameter` and `ParameterDeclarationEntry`, because one function can
|
||||
@@ -73,7 +73,8 @@ class Parameter extends LocalScopeVariable, @parameter {
|
||||
}
|
||||
|
||||
private VariableDeclarationEntry getANamedDeclarationEntry() {
|
||||
result = this.getAnEffectiveDeclarationEntry() and result.getName() != ""
|
||||
result = this.getAnEffectiveDeclarationEntry() and
|
||||
exists(string name | var_decls(unresolveElement(result), _, _, name, _) | name != "")
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -118,6 +119,12 @@ class Parameter extends LocalScopeVariable, @parameter {
|
||||
*/
|
||||
BlockStmt getCatchBlock() { params(underlyingElement(this), unresolveElement(result), _, _) }
|
||||
|
||||
/**
|
||||
* Gets the requires expression to which the parameter belongs, if it is a
|
||||
* requires expression parameter.
|
||||
*/
|
||||
RequiresExpr getRequiresExpr() { params(underlyingElement(this), unresolveElement(result), _, _) }
|
||||
|
||||
/**
|
||||
* Gets the zero-based index of this parameter.
|
||||
*
|
||||
|
||||
@@ -82,6 +82,8 @@ private Declaration getAnEnclosingDeclaration(Locatable ast) {
|
||||
or
|
||||
result = ast.(Parameter).getCatchBlock().getEnclosingFunction()
|
||||
or
|
||||
result = ast.(Parameter).getRequiresExpr().getEnclosingFunction()
|
||||
or
|
||||
result = ast.(Expr).getEnclosingDeclaration()
|
||||
or
|
||||
result = ast.(Initializer).getDeclaration()
|
||||
@@ -101,7 +103,10 @@ private newtype TPrintAstNode =
|
||||
stmt.getADeclarationEntry() = entry and
|
||||
shouldPrintDeclaration(stmt.getEnclosingFunction())
|
||||
} or
|
||||
TParametersNode(Function func) { shouldPrintDeclaration(func) } or
|
||||
TFunctionParametersNode(Function func) { shouldPrintDeclaration(func) } or
|
||||
TRequiresExprParametersNode(RequiresExpr req) {
|
||||
shouldPrintDeclaration(getAnEnclosingDeclaration(req))
|
||||
} or
|
||||
TConstructorInitializersNode(Constructor ctor) {
|
||||
ctor.hasEntryPoint() and
|
||||
shouldPrintDeclaration(ctor)
|
||||
@@ -305,14 +310,14 @@ class ExprNode extends AstNode {
|
||||
|
||||
ExprNode() { expr = ast }
|
||||
|
||||
override AstNode getChildInternal(int childIndex) {
|
||||
result.getAst() = expr.getChild(childIndex)
|
||||
override PrintAstNode getChildInternal(int childIndex) {
|
||||
result.(AstNode).getAst() = expr.getChild(childIndex)
|
||||
or
|
||||
childIndex = max(int index | exists(expr.getChild(index)) or index = 0) + 1 and
|
||||
result.getAst() = expr.(ConditionDeclExpr).getInitializingExpr()
|
||||
result.(AstNode).getAst() = expr.(ConditionDeclExpr).getInitializingExpr()
|
||||
or
|
||||
exists(int destructorIndex |
|
||||
result.getAst() = expr.getImplicitDestructorCall(destructorIndex) and
|
||||
result.(AstNode).getAst() = expr.getImplicitDestructorCall(destructorIndex) and
|
||||
childIndex = destructorIndex + max(int index | exists(expr.getChild(index)) or index = 0) + 2
|
||||
)
|
||||
}
|
||||
@@ -331,7 +336,8 @@ class ExprNode extends AstNode {
|
||||
}
|
||||
|
||||
override string getChildAccessorPredicateInternal(int childIndex) {
|
||||
result = getChildAccessorWithoutConversions(ast, this.getChildInternal(childIndex).getAst())
|
||||
result =
|
||||
getChildAccessorWithoutConversions(ast, this.getChildInternal(childIndex).(AstNode).getAst())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -411,6 +417,26 @@ class StmtExprNode extends ExprNode {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A node representing a `RequiresExpr`
|
||||
*/
|
||||
class RequiresExprNode extends ExprNode {
|
||||
override RequiresExpr expr;
|
||||
|
||||
override PrintAstNode getChildInternal(int childIndex) {
|
||||
result = super.getChildInternal(childIndex)
|
||||
or
|
||||
childIndex = -1 and
|
||||
result.(RequiresExprParametersNode).getRequiresExpr() = expr
|
||||
}
|
||||
|
||||
override string getChildAccessorPredicateInternal(int childIndex) {
|
||||
result = super.getChildAccessorPredicateInternal(childIndex)
|
||||
or
|
||||
childIndex = -1 and result = "<params>"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A node representing a `DeclarationEntry`.
|
||||
*/
|
||||
@@ -570,10 +596,10 @@ class InitializerNode extends AstNode {
|
||||
/**
|
||||
* A node representing the parameters of a `Function`.
|
||||
*/
|
||||
class ParametersNode extends PrintAstNode, TParametersNode {
|
||||
class FunctionParametersNode extends PrintAstNode, TFunctionParametersNode {
|
||||
Function func;
|
||||
|
||||
ParametersNode() { this = TParametersNode(func) }
|
||||
FunctionParametersNode() { this = TFunctionParametersNode(func) }
|
||||
|
||||
final override string toString() { result = "" }
|
||||
|
||||
@@ -594,6 +620,33 @@ class ParametersNode extends PrintAstNode, TParametersNode {
|
||||
final Function getFunction() { result = func }
|
||||
}
|
||||
|
||||
/**
|
||||
* A node representing the parameters of a `RequiresExpr`.
|
||||
*/
|
||||
class RequiresExprParametersNode extends PrintAstNode, TRequiresExprParametersNode {
|
||||
RequiresExpr req;
|
||||
|
||||
RequiresExprParametersNode() { this = TRequiresExprParametersNode(req) }
|
||||
|
||||
final override string toString() { result = "" }
|
||||
|
||||
final override Location getLocation() { result = getRepresentativeLocation(req) }
|
||||
|
||||
override AstNode getChildInternal(int childIndex) {
|
||||
result.getAst() = req.getParameter(childIndex)
|
||||
}
|
||||
|
||||
override string getChildAccessorPredicateInternal(int childIndex) {
|
||||
exists(this.getChildInternal(childIndex)) and
|
||||
result = "getParameter(" + childIndex.toString() + ")"
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `RequiresExpr` for which this node represents the parameters.
|
||||
*/
|
||||
final RequiresExpr getRequiresExpr() { result = req }
|
||||
}
|
||||
|
||||
/**
|
||||
* A node representing the initializer list of a `Constructor`.
|
||||
*/
|
||||
@@ -697,7 +750,7 @@ class FunctionNode extends FunctionOrGlobalOrNamespaceVariableNode {
|
||||
|
||||
override PrintAstNode getChildInternal(int childIndex) {
|
||||
childIndex = 0 and
|
||||
result.(ParametersNode).getFunction() = func
|
||||
result.(FunctionParametersNode).getFunction() = func
|
||||
or
|
||||
childIndex = 1 and
|
||||
result.(ConstructorInitializersNode).getConstructor() = func
|
||||
@@ -921,6 +974,11 @@ private predicate namedExprChildPredicates(Expr expr, Element ele, string pred)
|
||||
or
|
||||
expr.(CommaExpr).getRightOperand() = ele and pred = "getRightOperand()"
|
||||
or
|
||||
expr.(CompoundRequirementExpr).getExpr() = ele and pred = "getExpr()"
|
||||
or
|
||||
expr.(CompoundRequirementExpr).getReturnTypeRequirement() = ele and
|
||||
pred = "getReturnTypeRequirement()"
|
||||
or
|
||||
expr.(ConditionDeclExpr).getVariableAccess() = ele and pred = "getVariableAccess()"
|
||||
or
|
||||
expr.(ConstructorFieldInit).getExpr() = ele and pred = "getExpr()"
|
||||
@@ -941,6 +999,8 @@ private predicate namedExprChildPredicates(Expr expr, Element ele, string pred)
|
||||
or
|
||||
expr.(LambdaExpression).getInitializer() = ele and pred = "getInitializer()"
|
||||
or
|
||||
expr.(NestedRequirementExpr).getConstraint() = ele and pred = "getConstraint()"
|
||||
or
|
||||
expr.(NewOrNewArrayExpr).getAllocatorCall() = ele and pred = "getAllocatorCall()"
|
||||
or
|
||||
expr.(NewOrNewArrayExpr).getAlignmentArgument() = ele and pred = "getAlignmentArgument()"
|
||||
@@ -980,6 +1040,11 @@ private predicate namedExprChildPredicates(Expr expr, Element ele, string pred)
|
||||
or
|
||||
expr.(UnaryOperation).getOperand() = ele and pred = "getOperand()"
|
||||
or
|
||||
exists(int n |
|
||||
expr.(RequiresExpr).getRequirement(n) = ele and
|
||||
pred = "getRequirement(" + n + ")"
|
||||
)
|
||||
or
|
||||
expr.(SizeofExprOperator).getExprOperand() = ele and pred = "getExprOperand()"
|
||||
or
|
||||
expr.(StmtExpr).getStmt() = ele and pred = "getStmt()"
|
||||
|
||||
@@ -241,6 +241,10 @@ class VariableDeclarationEntry extends DeclarationEntry, @var_decl {
|
||||
name != "" and result = name
|
||||
or
|
||||
name = "" and result = this.getVariable().(LocalVariable).getName()
|
||||
or
|
||||
name = "" and
|
||||
not this instanceof ParameterDeclarationEntry and
|
||||
result = this.getVariable().(Parameter).getName()
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -295,19 +299,11 @@ class ParameterDeclarationEntry extends VariableDeclarationEntry {
|
||||
|
||||
private string getAnonymousParameterDescription() {
|
||||
not exists(this.getName()) and
|
||||
exists(string idx |
|
||||
idx =
|
||||
((this.getIndex() + 1).toString() + "th")
|
||||
.replaceAll("1th", "1st")
|
||||
.replaceAll("2th", "2nd")
|
||||
.replaceAll("3th", "3rd")
|
||||
.replaceAll("11st", "11th")
|
||||
.replaceAll("12nd", "12th")
|
||||
.replaceAll("13rd", "13th") and
|
||||
exists(string anon |
|
||||
anon = "(unnamed parameter " + this.getIndex().toString() + ")" and
|
||||
if exists(this.getCanonicalName())
|
||||
then
|
||||
result = "declaration of " + this.getCanonicalName() + " as anonymous " + idx + " parameter"
|
||||
else result = "declaration of " + idx + " parameter"
|
||||
then result = "declaration of " + this.getCanonicalName() + " as " + anon
|
||||
else result = "declaration of " + anon
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -261,13 +261,17 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) {
|
||||
predicate isAdditionalFlowStep(
|
||||
Node node1, FlowState state1, Node node2, FlowState state2, string model
|
||||
) {
|
||||
getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and
|
||||
getConfig(state2) = getConfig(state1)
|
||||
getConfig(state2) = getConfig(state1) and
|
||||
model = ""
|
||||
or
|
||||
not singleConfiguration() and
|
||||
getConfig(state1).isAdditionalFlowStep(node1, node2) and
|
||||
state2 = state1
|
||||
state2 = state1 and
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate allowImplicitRead(Node node, ContentSet c) {
|
||||
|
||||
@@ -261,13 +261,17 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) {
|
||||
predicate isAdditionalFlowStep(
|
||||
Node node1, FlowState state1, Node node2, FlowState state2, string model
|
||||
) {
|
||||
getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and
|
||||
getConfig(state2) = getConfig(state1)
|
||||
getConfig(state2) = getConfig(state1) and
|
||||
model = ""
|
||||
or
|
||||
not singleConfiguration() and
|
||||
getConfig(state1).isAdditionalFlowStep(node1, node2) and
|
||||
state2 = state1
|
||||
state2 = state1 and
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate allowImplicitRead(Node node, ContentSet c) {
|
||||
|
||||
@@ -261,13 +261,17 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) {
|
||||
predicate isAdditionalFlowStep(
|
||||
Node node1, FlowState state1, Node node2, FlowState state2, string model
|
||||
) {
|
||||
getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and
|
||||
getConfig(state2) = getConfig(state1)
|
||||
getConfig(state2) = getConfig(state1) and
|
||||
model = ""
|
||||
or
|
||||
not singleConfiguration() and
|
||||
getConfig(state1).isAdditionalFlowStep(node1, node2) and
|
||||
state2 = state1
|
||||
state2 = state1 and
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate allowImplicitRead(Node node, ContentSet c) {
|
||||
|
||||
@@ -261,13 +261,17 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) {
|
||||
predicate isAdditionalFlowStep(
|
||||
Node node1, FlowState state1, Node node2, FlowState state2, string model
|
||||
) {
|
||||
getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and
|
||||
getConfig(state2) = getConfig(state1)
|
||||
getConfig(state2) = getConfig(state1) and
|
||||
model = ""
|
||||
or
|
||||
not singleConfiguration() and
|
||||
getConfig(state1).isAdditionalFlowStep(node1, node2) and
|
||||
state2 = state1
|
||||
state2 = state1 and
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate allowImplicitRead(Node node, ContentSet c) {
|
||||
|
||||
@@ -261,13 +261,17 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) {
|
||||
predicate isAdditionalFlowStep(
|
||||
Node node1, FlowState state1, Node node2, FlowState state2, string model
|
||||
) {
|
||||
getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and
|
||||
getConfig(state2) = getConfig(state1)
|
||||
getConfig(state2) = getConfig(state1) and
|
||||
model = ""
|
||||
or
|
||||
not singleConfiguration() and
|
||||
getConfig(state1).isAdditionalFlowStep(node1, node2) and
|
||||
state2 = state1
|
||||
state2 = state1 and
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate allowImplicitRead(Node node, ContentSet c) {
|
||||
|
||||
@@ -281,3 +281,9 @@ private predicate exprToPartialDefinitionStep(Expr exprIn, Expr exprOut) {
|
||||
}
|
||||
|
||||
private predicate iteratorDereference(Call c) { c.getTarget() instanceof IteratorReferenceFunction }
|
||||
|
||||
/**
|
||||
* Holds if the additional step from `src` to `sink` should be considered in
|
||||
* speculative taint flow exploration.
|
||||
*/
|
||||
predicate speculativeTaintStep(DataFlow::Node src, DataFlow::Node sink) { none() }
|
||||
|
||||
@@ -149,6 +149,11 @@ class Call extends Expr, NameQualifiableElement, TCall {
|
||||
variableAddressEscapesTreeNonConst(va, this.getQualifier().getFullyConverted()) and
|
||||
i = -1
|
||||
}
|
||||
|
||||
/** Holds if this expression could be the return value of an implicitly declared function. */
|
||||
predicate mayBeFromImplicitlyDeclaredFunction() {
|
||||
this.getTarget().getADeclarationEntry().isImplicit()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -181,12 +181,7 @@ class VariableDeclarationEntry extends @var_decl {
|
||||
string getName() { var_decls(this, _, _, result, _) and result != "" }
|
||||
}
|
||||
|
||||
class Parameter extends LocalScopeVariable, @parameter {
|
||||
@functionorblock function;
|
||||
int index;
|
||||
|
||||
Parameter() { params(this, function, index, _) }
|
||||
}
|
||||
class Parameter extends LocalScopeVariable, @parameter { }
|
||||
|
||||
class GlobalOrNamespaceVariable extends Variable, @globalvariable { }
|
||||
|
||||
|
||||
@@ -261,13 +261,17 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) {
|
||||
predicate isAdditionalFlowStep(
|
||||
Node node1, FlowState state1, Node node2, FlowState state2, string model
|
||||
) {
|
||||
getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and
|
||||
getConfig(state2) = getConfig(state1)
|
||||
getConfig(state2) = getConfig(state1) and
|
||||
model = ""
|
||||
or
|
||||
not singleConfiguration() and
|
||||
getConfig(state1).isAdditionalFlowStep(node1, node2) and
|
||||
state2 = state1
|
||||
state2 = state1 and
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate allowImplicitRead(Node node, ContentSet c) {
|
||||
|
||||
@@ -261,13 +261,17 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) {
|
||||
predicate isAdditionalFlowStep(
|
||||
Node node1, FlowState state1, Node node2, FlowState state2, string model
|
||||
) {
|
||||
getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and
|
||||
getConfig(state2) = getConfig(state1)
|
||||
getConfig(state2) = getConfig(state1) and
|
||||
model = ""
|
||||
or
|
||||
not singleConfiguration() and
|
||||
getConfig(state1).isAdditionalFlowStep(node1, node2) and
|
||||
state2 = state1
|
||||
state2 = state1 and
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate allowImplicitRead(Node node, ContentSet c) {
|
||||
|
||||
@@ -261,13 +261,17 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) {
|
||||
predicate isAdditionalFlowStep(
|
||||
Node node1, FlowState state1, Node node2, FlowState state2, string model
|
||||
) {
|
||||
getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and
|
||||
getConfig(state2) = getConfig(state1)
|
||||
getConfig(state2) = getConfig(state1) and
|
||||
model = ""
|
||||
or
|
||||
not singleConfiguration() and
|
||||
getConfig(state1).isAdditionalFlowStep(node1, node2) and
|
||||
state2 = state1
|
||||
state2 = state1 and
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate allowImplicitRead(Node node, ContentSet c) {
|
||||
|
||||
@@ -261,13 +261,17 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) {
|
||||
predicate isAdditionalFlowStep(
|
||||
Node node1, FlowState state1, Node node2, FlowState state2, string model
|
||||
) {
|
||||
getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and
|
||||
getConfig(state2) = getConfig(state1)
|
||||
getConfig(state2) = getConfig(state1) and
|
||||
model = ""
|
||||
or
|
||||
not singleConfiguration() and
|
||||
getConfig(state1).isAdditionalFlowStep(node1, node2) and
|
||||
state2 = state1
|
||||
state2 = state1 and
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate allowImplicitRead(Node node, ContentSet c) {
|
||||
|
||||
@@ -1364,7 +1364,10 @@ 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() and
|
||||
(
|
||||
call.(SummaryCall).getReceiver() = receiver.(FlowSummaryNode).getSummaryNode() or
|
||||
call.asCallInstruction().getCallTargetOperand() = receiver.asOperand()
|
||||
) and
|
||||
exists(kind)
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ private import SsaInternals as Ssa
|
||||
private import DataFlowImplCommon as DataFlowImplCommon
|
||||
private import codeql.util.Unit
|
||||
private import Node0ToString
|
||||
private import DataFlowDispatch as DataFlowDispatch
|
||||
import ExprNodes
|
||||
|
||||
/**
|
||||
@@ -2497,3 +2498,16 @@ class AdditionalCallTarget extends Unit {
|
||||
*/
|
||||
abstract Declaration viableTarget(Call call);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a function that may be called by `call`.
|
||||
*
|
||||
* Note that `call` may be a call to a function pointer expression.
|
||||
*/
|
||||
Function getARuntimeTarget(Call call) {
|
||||
exists(DataFlowCall dfCall | dfCall.asCallInstruction().getUnconvertedResultExpression() = call |
|
||||
result = DataFlowDispatch::viableCallable(dfCall).asSourceCallable()
|
||||
or
|
||||
result = DataFlowImplCommon::viableCallableLambda(dfCall, _).asSourceCallable()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -212,3 +212,30 @@ predicate modeledTaintStep(DataFlow::Node nodeIn, DataFlow::Node nodeOut, string
|
||||
nodeOut = callOutput(call, modelOut)
|
||||
)
|
||||
}
|
||||
|
||||
import SpeculativeTaintFlow
|
||||
|
||||
private module SpeculativeTaintFlow {
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowDispatch as DataFlowDispatch
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate as DataFlowPrivate
|
||||
|
||||
/**
|
||||
* Holds if the additional step from `src` to `sink` should be considered in
|
||||
* speculative taint flow exploration.
|
||||
*/
|
||||
predicate speculativeTaintStep(DataFlow::Node src, DataFlow::Node sink) {
|
||||
exists(DataFlowCall call, ArgumentPosition argpos |
|
||||
// TODO: exclude neutrals and anything that has QL modeling.
|
||||
not exists(DataFlowDispatch::viableCallable(call)) and
|
||||
src.(DataFlowPrivate::ArgumentNode).argumentOf(call, argpos)
|
||||
|
|
||||
not argpos.(DirectPosition).getIndex() = -1 and
|
||||
sink.(PostUpdateNode)
|
||||
.getPreUpdateNode()
|
||||
.(DataFlowPrivate::ArgumentNode)
|
||||
.argumentOf(call, any(DirectPosition qualpos | qualpos.getIndex() = -1))
|
||||
or
|
||||
sink.(DataFlowPrivate::OutNode).getCall() = call
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -683,8 +683,13 @@ private Overlap getExtentOverlap(MemoryLocation0 def, MemoryLocation0 use) {
|
||||
def.getVirtualVariable() = use.getVirtualVariable() and
|
||||
def instanceof EntireAllocationMemoryLocation and
|
||||
(
|
||||
// EntireAllocationMemoryLocation exactly overlaps itself.
|
||||
use instanceof EntireAllocationMemoryLocation and
|
||||
// EntireAllocationMemoryLocation exactly overlaps any EntireAllocationMemoryLocation for the
|
||||
// same allocation. Checking the allocation, rather than the memory location itself, ensures
|
||||
// that we get the right relationship between the "must" and "may" memory locations for that
|
||||
// allocation.
|
||||
// Note that if one of the locations is a "may" access, the overlap will be downgraded to
|
||||
// `MustTotallyOverlap` or `MayPartialOverlap` in `getOverlap()`.
|
||||
use.(EntireAllocationMemoryLocation).getAnAllocation() = def.getAnAllocation() and
|
||||
result instanceof MustExactlyOverlap
|
||||
or
|
||||
not use instanceof EntireAllocationMemoryLocation and
|
||||
|
||||
@@ -196,6 +196,8 @@ private predicate isInvalidFunction(Function func) {
|
||||
expr.getEnclosingFunction() = func and
|
||||
not exists(expr.getType())
|
||||
)
|
||||
or
|
||||
count(func.getEntryPoint().getLocation()) > 1
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -91,7 +91,7 @@ private class Sprintf extends FormattingFunction, NonThrowingFunction {
|
||||
override int getFirstFormatArgumentIndex() {
|
||||
if this.hasName("__builtin___sprintf_chk")
|
||||
then result = 4
|
||||
else result = this.getNumberOfParameters()
|
||||
else result = super.getFirstFormatArgumentIndex()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,21 @@ private Type getAFormatterWideTypeOrDefault() {
|
||||
* A standard library function that uses a `printf`-like formatting string.
|
||||
*/
|
||||
abstract class FormattingFunction extends ArrayFunction, TaintFunction {
|
||||
int firstFormatArgumentIndex;
|
||||
|
||||
FormattingFunction() {
|
||||
firstFormatArgumentIndex > 0 and
|
||||
if this.hasDefinition()
|
||||
then firstFormatArgumentIndex = this.getDefinition().getNumberOfParameters()
|
||||
else
|
||||
if this instanceof BuiltInFunction
|
||||
then firstFormatArgumentIndex = this.getNumberOfParameters()
|
||||
else
|
||||
forex(FunctionDeclarationEntry fde | fde = this.getAnExplicitDeclarationEntry() |
|
||||
firstFormatArgumentIndex = fde.getNumberOfParameters()
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the position at which the format parameter occurs. */
|
||||
abstract int getFormatParameterIndex();
|
||||
|
||||
@@ -121,33 +136,7 @@ abstract class FormattingFunction extends ArrayFunction, TaintFunction {
|
||||
* the first format specifier in the format string. We ignore all
|
||||
* implicit function definitions.
|
||||
*/
|
||||
int getFirstFormatArgumentIndex() {
|
||||
// The formatting function either has a definition in the snapshot, or all
|
||||
// `DeclarationEntry`s agree on the number of parameters (otherwise we don't
|
||||
// really know the correct number)
|
||||
if this.hasDefinition()
|
||||
then result = this.getDefinition().getNumberOfParameters()
|
||||
else result = this.getNumberOfExplicitParameters()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a non-implicit function declaration entry.
|
||||
*/
|
||||
private FunctionDeclarationEntry getAnExplicitDeclarationEntry() {
|
||||
result = this.getADeclarationEntry() and
|
||||
not result.isImplicit()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of parameters, excluding any parameters that have been defined
|
||||
* from implicit function declarations. If there is some inconsistency in the number
|
||||
* of parameters, then don't return anything.
|
||||
*/
|
||||
private int getNumberOfExplicitParameters() {
|
||||
forex(FunctionDeclarationEntry fde | fde = this.getAnExplicitDeclarationEntry() |
|
||||
result = fde.getNumberOfParameters()
|
||||
)
|
||||
}
|
||||
int getFirstFormatArgumentIndex() { result = firstFormatArgumentIndex }
|
||||
|
||||
/**
|
||||
* Gets the position of the buffer size argument, if any.
|
||||
|
||||
@@ -534,7 +534,7 @@ static_asserts(
|
||||
#keyset[function, index, type_id]
|
||||
params(
|
||||
int id: @parameter,
|
||||
int function: @functionorblock ref,
|
||||
int function: @parameterized_element ref,
|
||||
int index: int ref,
|
||||
int type_id: @type ref
|
||||
);
|
||||
@@ -1791,6 +1791,9 @@ case @expr.kind of
|
||||
| 388 = @datasizeof
|
||||
| 389 = @c11_generic
|
||||
| 390 = @requires_expr
|
||||
| 391 = @nested_requirement
|
||||
| 392 = @compound_requirement
|
||||
| 393 = @concept_id
|
||||
;
|
||||
|
||||
@var_args_expr = @vastartexpr
|
||||
@@ -1909,6 +1912,10 @@ case @expr.kind of
|
||||
| @istriviallyrelocatable
|
||||
;
|
||||
|
||||
compound_requirement_is_noexcept(
|
||||
int expr: @compound_requirement ref
|
||||
);
|
||||
|
||||
new_allocated_type(
|
||||
unique int expr: @new_expr ref,
|
||||
int type_id: @type ref
|
||||
@@ -2168,11 +2175,11 @@ stmt_decl_entry_bind(
|
||||
int decl_entry: @element ref
|
||||
);
|
||||
|
||||
@functionorblock = @function | @stmt_block;
|
||||
@parameterized_element = @function | @stmt_block | @requires_expr;
|
||||
|
||||
blockscope(
|
||||
unique int block: @stmt_block ref,
|
||||
int enclosing: @functionorblock ref
|
||||
int enclosing: @parameterized_element ref
|
||||
);
|
||||
|
||||
@jump = @stmt_goto | @stmt_break | @stmt_continue;
|
||||
|
||||
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
@@ -0,0 +1,2 @@
|
||||
description: Support C++20 requires expressions
|
||||
compatibility: backwards
|
||||
@@ -1,3 +1,9 @@
|
||||
## 1.2.6
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Remove results from the `cpp/wrong-type-format-argument` ("Wrong type of arguments to formatting function") query if the argument is the return value of an implicitly declared function.
|
||||
|
||||
## 1.2.5
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
@@ -170,7 +170,8 @@ where
|
||||
) and
|
||||
not arg.isAffectedByMacro() and
|
||||
not arg.isFromUninstantiatedTemplate(_) and
|
||||
not actual.getUnspecifiedType() instanceof ErroneousType
|
||||
not actual.getUnspecifiedType() instanceof ErroneousType and
|
||||
not arg.(Call).mayBeFromImplicitlyDeclaredFunction()
|
||||
select arg,
|
||||
"This format specifier for type '" + expected.getName() + "' does not match the argument type '" +
|
||||
actual.getUnspecifiedType().getName() + "'."
|
||||
|
||||
5
cpp/ql/src/change-notes/released/1.2.6.md
Normal file
5
cpp/ql/src/change-notes/released/1.2.6.md
Normal file
@@ -0,0 +1,5 @@
|
||||
## 1.2.6
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Remove results from the `cpp/wrong-type-format-argument` ("Wrong type of arguments to formatting function") query if the argument is the return value of an implicitly declared function.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 1.2.5
|
||||
lastReleaseVersion: 1.2.6
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-queries
|
||||
version: 1.2.5
|
||||
version: 1.2.6
|
||||
groups:
|
||||
- cpp
|
||||
- queries
|
||||
|
||||
@@ -5,31 +5,5 @@
|
||||
|
||||
import cpp as C
|
||||
private import codeql.util.test.InlineExpectationsTest
|
||||
|
||||
private module Impl implements InlineExpectationsTestSig {
|
||||
private newtype TExpectationComment = MkExpectationComment(C::CppStyleComment c)
|
||||
|
||||
/**
|
||||
* A class representing a line comment in the CPP style.
|
||||
* Unlike the `CppStyleComment` class, however, the string returned by `getContents` does _not_
|
||||
* include the preceding comment marker (`//`).
|
||||
*/
|
||||
class ExpectationComment extends TExpectationComment {
|
||||
C::CppStyleComment comment;
|
||||
|
||||
ExpectationComment() { this = MkExpectationComment(comment) }
|
||||
|
||||
/** Returns the contents of the given comment, _without_ the preceding comment marker (`//`). */
|
||||
string getContents() { result = comment.getContents().suffix(2) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = comment.toString() }
|
||||
|
||||
/** Gets the location of this comment. */
|
||||
Location getLocation() { result = comment.getLocation() }
|
||||
}
|
||||
|
||||
class Location = C::Location;
|
||||
}
|
||||
|
||||
private import internal.InlineExpectationsTestImpl
|
||||
import Make<Impl>
|
||||
|
||||
21
cpp/ql/test/TestUtilities/InlineExpectationsTestQuery.ql
Normal file
21
cpp/ql/test/TestUtilities/InlineExpectationsTestQuery.ql
Normal file
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* @kind test-postprocess
|
||||
*/
|
||||
|
||||
private import cpp
|
||||
private import codeql.util.test.InlineExpectationsTest as T
|
||||
private import internal.InlineExpectationsTestImpl
|
||||
import T::TestPostProcessing
|
||||
import T::TestPostProcessing::Make<Impl, Input>
|
||||
|
||||
private module Input implements T::TestPostProcessing::InputSig<Impl> {
|
||||
string getRelativeUrl(Location location) {
|
||||
exists(File f, int startline, int startcolumn, int endline, int endcolumn |
|
||||
location.hasLocationInfo(_, startline, startcolumn, endline, endcolumn) and
|
||||
f = location.getFile()
|
||||
|
|
||||
result =
|
||||
f.getRelativePath() + ":" + startline + ":" + startcolumn + ":" + endline + ":" + endcolumn
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import cpp as C
|
||||
private import codeql.util.test.InlineExpectationsTest
|
||||
|
||||
module Impl implements InlineExpectationsTestSig {
|
||||
private newtype TExpectationComment = MkExpectationComment(C::CppStyleComment c)
|
||||
|
||||
/**
|
||||
* A class representing a line comment in the CPP style.
|
||||
* Unlike the `CppStyleComment` class, however, the string returned by `getContents` does _not_
|
||||
* include the preceding comment marker (`//`).
|
||||
*/
|
||||
class ExpectationComment extends TExpectationComment {
|
||||
C::CppStyleComment comment;
|
||||
|
||||
ExpectationComment() { this = MkExpectationComment(comment) }
|
||||
|
||||
/** Returns the contents of the given comment, _without_ the preceding comment marker (`//`). */
|
||||
string getContents() { result = comment.getContents().suffix(2) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = comment.toString() }
|
||||
|
||||
/** Gets the location of this comment. */
|
||||
Location getLocation() { result = comment.getLocation() }
|
||||
}
|
||||
|
||||
class Location = C::Location;
|
||||
}
|
||||
@@ -1,4 +1,9 @@
|
||||
// query-type: graph
|
||||
/**
|
||||
* query-type: graph
|
||||
*
|
||||
* @kind graph-equivalence-test
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
class DestructorCallEnhanced extends DestructorCall {
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
// query-type: graph
|
||||
/**
|
||||
* query-type: graph
|
||||
*
|
||||
* @kind graph-equivalence-test
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
class DestructorCallEnhanced extends DestructorCall {
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
// query-type: graph
|
||||
/**
|
||||
* query-type: graph
|
||||
*
|
||||
* @kind graph-equivalence-test
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
class DestructorCallEnhanced extends DestructorCall {
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
// query-type: graph
|
||||
/**
|
||||
* query-type: graph
|
||||
*
|
||||
* @kind graph-equivalence-test
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
class DestructorCallEnhanced extends DestructorCall {
|
||||
|
||||
@@ -3,6 +3,9 @@ uniqueEnclosingCallable
|
||||
| test.cpp:864:47:864:54 | call to source | Node should have one enclosing callable but has 0. |
|
||||
| test.cpp:872:46:872:51 | call to source | Node should have one enclosing callable but has 0. |
|
||||
| test.cpp:872:53:872:56 | 1 | Node should have one enclosing callable but has 0. |
|
||||
| test.cpp:1126:33:1129:1 | {...} | Node should have one enclosing callable but has 0. |
|
||||
| test.cpp:1127:3:1127:13 | reads_input | Node should have one enclosing callable but has 0. |
|
||||
| test.cpp:1128:3:1128:21 | not_does_read_input | Node should have one enclosing callable but has 0. |
|
||||
uniqueCallEnclosingCallable
|
||||
| test.cpp:864:47:864:54 | call to source | Call should have one enclosing callable but has 0. |
|
||||
| test.cpp:872:46:872:51 | call to source | Call should have one enclosing callable but has 0. |
|
||||
@@ -186,3 +189,4 @@ identityLocalStep
|
||||
missingArgumentCall
|
||||
multipleArgumentCall
|
||||
lambdaCallEnclosingCallableMismatch
|
||||
speculativeStepAlreadyHasModel
|
||||
|
||||
@@ -38,3 +38,4 @@ identityLocalStep
|
||||
missingArgumentCall
|
||||
multipleArgumentCall
|
||||
lambdaCallEnclosingCallableMismatch
|
||||
speculativeStepAlreadyHasModel
|
||||
|
||||
@@ -323,6 +323,7 @@ irFlow
|
||||
| test.cpp:1069:9:1069:14 | call to source | test.cpp:1074:10:1074:10 | i |
|
||||
| test.cpp:1069:9:1069:14 | call to source | test.cpp:1081:10:1081:10 | i |
|
||||
| test.cpp:1117:27:1117:34 | call to source | test.cpp:1117:27:1117:34 | call to source |
|
||||
| test.cpp:1132:11:1132:16 | call to source | test.cpp:1121:8:1121:8 | x |
|
||||
| true_upon_entry.cpp:9:11:9:16 | call to source | true_upon_entry.cpp:13:8:13:8 | x |
|
||||
| true_upon_entry.cpp:17:11:17:16 | call to source | true_upon_entry.cpp:21:8:21:8 | x |
|
||||
| true_upon_entry.cpp:27:9:27:14 | call to source | true_upon_entry.cpp:29:8:29:8 | x |
|
||||
|
||||
@@ -1115,4 +1115,20 @@ void indirect_sink_const_ref(const T&);
|
||||
|
||||
void test_temp_with_conversion_from_materialization() {
|
||||
indirect_sink_const_ref(source()); // $ ir MISSING: ast
|
||||
}
|
||||
|
||||
void reads_input(int x) {
|
||||
sink(x); // $ ir MISSING: ast
|
||||
}
|
||||
|
||||
void not_does_read_input(int x);
|
||||
|
||||
void (*dispatch_table[])(int) = {
|
||||
reads_input,
|
||||
not_does_read_input
|
||||
};
|
||||
|
||||
void test_dispatch_table(int i) {
|
||||
int x = source();
|
||||
dispatch_table[i](x);
|
||||
}
|
||||
@@ -185,6 +185,8 @@ postWithInFlow
|
||||
| simple.cpp:83:12:83:13 | f1 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| simple.cpp:92:7:92:7 | i [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| simple.cpp:118:7:118:7 | i [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| simple.cpp:124:5:124:6 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| simple.cpp:124:6:124:6 | p [inner post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| struct_init.c:24:11:24:12 | ab [inner post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| struct_init.c:36:17:36:24 | nestedAB [inner post update] | PostUpdateNode should not be the target of local flow. |
|
||||
viableImplInCallContextTooLarge
|
||||
@@ -195,3 +197,4 @@ identityLocalStep
|
||||
missingArgumentCall
|
||||
multipleArgumentCall
|
||||
lambdaCallEnclosingCallableMismatch
|
||||
speculativeStepAlreadyHasModel
|
||||
|
||||
@@ -28,3 +28,4 @@ identityLocalStep
|
||||
missingArgumentCall
|
||||
multipleArgumentCall
|
||||
lambdaCallEnclosingCallableMismatch
|
||||
speculativeStepAlreadyHasModel
|
||||
|
||||
@@ -291,3 +291,6 @@ WARNING: module 'DataFlow' has been deprecated and may be removed in future (par
|
||||
| simple.cpp:94:10:94:11 | a2 | IR only |
|
||||
| simple.cpp:118:7:118:7 | i | AST only |
|
||||
| simple.cpp:120:8:120:8 | a | IR only |
|
||||
| simple.cpp:124:5:124:6 | * ... | AST only |
|
||||
| simple.cpp:131:14:131:14 | a | IR only |
|
||||
| simple.cpp:136:10:136:10 | a | IR only |
|
||||
|
||||
@@ -651,6 +651,9 @@
|
||||
| simple.cpp:94:10:94:11 | a2 |
|
||||
| simple.cpp:118:5:118:5 | a |
|
||||
| simple.cpp:120:8:120:8 | a |
|
||||
| simple.cpp:131:14:131:14 | a |
|
||||
| simple.cpp:135:20:135:20 | q |
|
||||
| simple.cpp:136:10:136:10 | a |
|
||||
| struct_init.c:15:8:15:9 | ab |
|
||||
| struct_init.c:15:12:15:12 | a |
|
||||
| struct_init.c:16:8:16:9 | ab |
|
||||
|
||||
@@ -581,6 +581,8 @@ WARNING: module 'DataFlow' has been deprecated and may be removed in future (par
|
||||
| simple.cpp:92:7:92:7 | i |
|
||||
| simple.cpp:118:5:118:5 | a |
|
||||
| simple.cpp:118:7:118:7 | i |
|
||||
| simple.cpp:124:5:124:6 | * ... |
|
||||
| simple.cpp:135:20:135:20 | q |
|
||||
| struct_init.c:15:8:15:9 | ab |
|
||||
| struct_init.c:15:12:15:12 | a |
|
||||
| struct_init.c:16:8:16:9 | ab |
|
||||
|
||||
@@ -120,4 +120,20 @@ void post_update_to_phi_input(bool b)
|
||||
sink(a.i); // $ ast,ir
|
||||
}
|
||||
|
||||
} // namespace Simple
|
||||
void write_to_param(int* p) {
|
||||
*p = user_input();
|
||||
}
|
||||
|
||||
void alias_with_fields(bool b) {
|
||||
A a;
|
||||
int* q;
|
||||
if(b) {
|
||||
q = &a.i;
|
||||
} else {
|
||||
q = nullptr;
|
||||
}
|
||||
write_to_param(q);
|
||||
sink(a.i); // $ MISSING: ast,ir
|
||||
}
|
||||
|
||||
} // namespace Simple
|
||||
@@ -25,8 +25,8 @@
|
||||
| declarationEntry.cpp:39:7:39:7 | declaration of operator= | declarationEntry.cpp:39:7:39:7 | operator= | yes |
|
||||
| declarationEntry.cpp:39:7:39:13 | definition of myClass | declarationEntry.cpp:39:7:39:13 | myClass | yes |
|
||||
| declarationEntry.cpp:42:6:42:21 | definition of myMemberVariable | declarationEntry.cpp:42:6:42:21 | myMemberVariable | yes |
|
||||
| file://:0:0:0:0 | declaration of 1st parameter | file://:0:0:0:0 | (unnamed parameter 0) | yes |
|
||||
| file://:0:0:0:0 | declaration of 1st parameter | file://:0:0:0:0 | (unnamed parameter 0) | yes |
|
||||
| file://:0:0:0:0 | declaration of (unnamed parameter 0) | file://:0:0:0:0 | (unnamed parameter 0) | yes |
|
||||
| file://:0:0:0:0 | declaration of (unnamed parameter 0) | file://:0:0:0:0 | (unnamed parameter 0) | yes |
|
||||
| file://:0:0:0:0 | definition of fp_offset | file://:0:0:0:0 | fp_offset | yes |
|
||||
| file://:0:0:0:0 | definition of gp_offset | file://:0:0:0:0 | gp_offset | yes |
|
||||
| file://:0:0:0:0 | definition of overflow_arg_area | file://:0:0:0:0 | overflow_arg_area | yes |
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
| file://:0:0:0:0 | declaration of 1st parameter |
|
||||
| file://:0:0:0:0 | declaration of 1st parameter |
|
||||
| file://:0:0:0:0 | declaration of 1st parameter |
|
||||
| file://:0:0:0:0 | declaration of 1st parameter |
|
||||
| file://:0:0:0:0 | declaration of (unnamed parameter 0) |
|
||||
| file://:0:0:0:0 | declaration of (unnamed parameter 0) |
|
||||
| file://:0:0:0:0 | declaration of (unnamed parameter 0) |
|
||||
| file://:0:0:0:0 | declaration of (unnamed parameter 0) |
|
||||
| file://:0:0:0:0 | definition of fp_offset |
|
||||
| file://:0:0:0:0 | definition of gp_offset |
|
||||
| file://:0:0:0:0 | definition of overflow_arg_area |
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
// query-type: graph
|
||||
/**
|
||||
* query-type: graph
|
||||
*
|
||||
* @kind graph-equivalence-test
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
class DestructorCallEnhanced extends DestructorCall {
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
| file://:0:0:0:0 | <error expr> |
|
||||
@@ -0,0 +1,5 @@
|
||||
import cpp
|
||||
|
||||
from Expr e
|
||||
where e.getType() instanceof ErroneousType
|
||||
select e
|
||||
@@ -0,0 +1,2 @@
|
||||
| file://:0:0:0:0 | There was an error during this compilation |
|
||||
| implicit.cpp:5:5:5:5 | identifier 'g' is undefined |
|
||||
@@ -0,0 +1,4 @@
|
||||
import cpp
|
||||
|
||||
from Diagnostic d
|
||||
select d
|
||||
@@ -0,0 +1,6 @@
|
||||
| implicit2.c:1:7:1:7 | g | file://:0:0:0:0 | float |
|
||||
| implicit2.c:1:7:1:7 | g | file://:0:0:0:0 | int |
|
||||
| implicit.c:1:6:1:6 | f | file://:0:0:0:0 | void |
|
||||
| implicit.c:3:5:3:5 | g | file://:0:0:0:0 | float |
|
||||
| implicit.c:3:5:3:5 | g | file://:0:0:0:0 | int |
|
||||
| implicit.cpp:3:6:3:6 | f | file://:0:0:0:0 | void |
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user