mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Merge branch 'main' into redsun82/rust-has-implementation
This commit is contained in:
2
.github/workflows/validate-change-notes.yml
vendored
2
.github/workflows/validate-change-notes.yml
vendored
@@ -31,4 +31,4 @@ jobs:
|
|||||||
- name: Fail if there are any errors with existing change notes
|
- name: Fail if there are any errors with existing change notes
|
||||||
|
|
||||||
run: |
|
run: |
|
||||||
codeql pack release --groups cpp,csharp,java,javascript,python,ruby,-examples,-test,-experimental
|
codeql pack release --groups actions,cpp,csharp,go,java,javascript,python,ruby,shared,swift -examples,-test,-experimental
|
||||||
|
|||||||
20
MODULE.bazel
20
MODULE.bazel
@@ -239,24 +239,24 @@ go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps")
|
|||||||
go_deps.from_file(go_mod = "//go/extractor:go.mod")
|
go_deps.from_file(go_mod = "//go/extractor:go.mod")
|
||||||
use_repo(go_deps, "org_golang_x_mod", "org_golang_x_tools")
|
use_repo(go_deps, "org_golang_x_mod", "org_golang_x_tools")
|
||||||
|
|
||||||
lfs_files = use_repo_rule("//misc/bazel:lfs.bzl", "lfs_files")
|
lfs_archive = use_repo_rule("//misc/bazel:lfs.bzl", "lfs_archive")
|
||||||
|
|
||||||
lfs_files(
|
lfs_archive(
|
||||||
name = "ripunzip-linux",
|
name = "ripunzip-linux",
|
||||||
srcs = ["//misc/ripunzip:ripunzip-linux"],
|
src = "//misc/ripunzip:ripunzip-Linux.zip",
|
||||||
executable = True,
|
build_file = "//misc/ripunzip:BUILD.ripunzip.bazel",
|
||||||
)
|
)
|
||||||
|
|
||||||
lfs_files(
|
lfs_archive(
|
||||||
name = "ripunzip-windows",
|
name = "ripunzip-windows",
|
||||||
srcs = ["//misc/ripunzip:ripunzip-windows.exe"],
|
src = "//misc/ripunzip:ripunzip-Windows.zip",
|
||||||
executable = True,
|
build_file = "//misc/ripunzip:BUILD.ripunzip.bazel",
|
||||||
)
|
)
|
||||||
|
|
||||||
lfs_files(
|
lfs_archive(
|
||||||
name = "ripunzip-macos",
|
name = "ripunzip-macos",
|
||||||
srcs = ["//misc/ripunzip:ripunzip-macos"],
|
src = "//misc/ripunzip:ripunzip-macOS.zip",
|
||||||
executable = True,
|
build_file = "//misc/ripunzip:BUILD.ripunzip.bazel",
|
||||||
)
|
)
|
||||||
|
|
||||||
register_toolchains(
|
register_toolchains(
|
||||||
|
|||||||
@@ -1,3 +1,11 @@
|
|||||||
|
## 0.4.11
|
||||||
|
|
||||||
|
No user-facing changes.
|
||||||
|
|
||||||
|
## 0.4.10
|
||||||
|
|
||||||
|
No user-facing changes.
|
||||||
|
|
||||||
## 0.4.9
|
## 0.4.9
|
||||||
|
|
||||||
No user-facing changes.
|
No user-facing changes.
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
category: minorAnalysis
|
||||||
|
---
|
||||||
|
* Fixed performance issues in the parsing of Bash scripts in workflow files,
|
||||||
|
which led to out-of-disk errors when analysing certain workflow files with
|
||||||
|
complex interpolations of shell commands or quoted strings.
|
||||||
3
actions/ql/lib/change-notes/released/0.4.10.md
Normal file
3
actions/ql/lib/change-notes/released/0.4.10.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
## 0.4.10
|
||||||
|
|
||||||
|
No user-facing changes.
|
||||||
3
actions/ql/lib/change-notes/released/0.4.11.md
Normal file
3
actions/ql/lib/change-notes/released/0.4.11.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
## 0.4.11
|
||||||
|
|
||||||
|
No user-facing changes.
|
||||||
@@ -1,2 +1,2 @@
|
|||||||
---
|
---
|
||||||
lastReleaseVersion: 0.4.9
|
lastReleaseVersion: 0.4.11
|
||||||
|
|||||||
@@ -50,8 +50,8 @@ class Expression extends AstNode instanceof ExpressionImpl {
|
|||||||
string getNormalizedExpression() { result = normalizeExpr(expression) }
|
string getNormalizedExpression() { result = normalizeExpr(expression) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A common class for `env` in workflow, job or step. */
|
/** An `env` in workflow, job or step. */
|
||||||
abstract class Env extends AstNode instanceof EnvImpl {
|
class Env extends AstNode instanceof EnvImpl {
|
||||||
/** Gets an environment variable value given its name. */
|
/** Gets an environment variable value given its name. */
|
||||||
ScalarValueImpl getEnvVarValue(string name) { result = super.getEnvVarValue(name) }
|
ScalarValueImpl getEnvVarValue(string name) { result = super.getEnvVarValue(name) }
|
||||||
|
|
||||||
|
|||||||
@@ -8,35 +8,64 @@ class BashShellScript extends ShellScript {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private string lineProducer(int i) {
|
/**
|
||||||
result = this.getRawScript().regexpReplaceAll("\\\\\\s*\n", "").splitAt("\n", i)
|
* Gets the line at 0-based index `lineIndex` within this shell script,
|
||||||
|
* assuming newlines as separators.
|
||||||
|
*/
|
||||||
|
private string lineProducer(int lineIndex) {
|
||||||
|
result = this.getRawScript().regexpReplaceAll("\\\\\\s*\n", "").splitAt("\n", lineIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
private predicate cmdSubstitutionReplacement(string cmdSubs, string id, int k) {
|
private predicate cmdSubstitutionReplacement(string command, string id, int lineIndex) {
|
||||||
exists(string line | line = this.lineProducer(k) |
|
this.commandInSubstitution(lineIndex, command, id)
|
||||||
exists(int i, int j |
|
or
|
||||||
cmdSubs =
|
this.commandInBackticks(lineIndex, command, id)
|
||||||
// $() cmd substitution
|
}
|
||||||
line.regexpFind("\\$\\((?:[^()]+|\\((?:[^()]+|\\([^()]*\\))*\\))*\\)", i, j)
|
|
||||||
.regexpReplaceAll("^\\$\\(", "")
|
/**
|
||||||
.regexpReplaceAll("\\)$", "") and
|
* Holds if there is a command substitution `$(command)` in
|
||||||
id = "cmdsubs:" + k + ":" + i + ":" + j
|
* the line at `lineIndex` in the shell script,
|
||||||
)
|
* and `id` is a unique identifier for this command.
|
||||||
or
|
*/
|
||||||
exists(int i, int j |
|
private predicate commandInSubstitution(int lineIndex, string command, string id) {
|
||||||
// `...` cmd substitution
|
exists(int occurrenceIndex, int occurrenceOffset |
|
||||||
cmdSubs =
|
command =
|
||||||
line.regexpFind("\\`[^\\`]+\\`", i, j)
|
// Look for the command inside a $(...) command substitution
|
||||||
.regexpReplaceAll("^\\`", "")
|
this.lineProducer(lineIndex)
|
||||||
.regexpReplaceAll("\\`$", "") and
|
.regexpFind("\\$\\((?:[^()]+|\\((?:[^()]+|\\([^()]*\\))*\\))*\\)", occurrenceIndex,
|
||||||
id = "cmd:" + k + ":" + i + ":" + j
|
occurrenceOffset)
|
||||||
)
|
// trim starting $( - TODO do this in first regex
|
||||||
|
.regexpReplaceAll("^\\$\\(", "")
|
||||||
|
// trim ending ) - TODO do this in first regex
|
||||||
|
.regexpReplaceAll("\\)$", "") and
|
||||||
|
id = "cmdsubs:" + lineIndex + ":" + occurrenceIndex + ":" + occurrenceOffset
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private predicate rankedCmdSubstitutionReplacements(int i, string old, string new) {
|
/**
|
||||||
old = rank[i](string old2 | this.cmdSubstitutionReplacement(old2, _, _) | old2) and
|
* Holds if `command` is a command in backticks `` `...` `` in
|
||||||
this.cmdSubstitutionReplacement(old, new, _)
|
* the line at `lineIndex` in the shell script,
|
||||||
|
* and `id` is a unique identifier for this command.
|
||||||
|
*/
|
||||||
|
private predicate commandInBackticks(int lineIndex, string command, string id) {
|
||||||
|
exists(int occurrenceIndex, int occurrenceOffset |
|
||||||
|
command =
|
||||||
|
this.lineProducer(lineIndex)
|
||||||
|
.regexpFind("\\`[^\\`]+\\`", occurrenceIndex, occurrenceOffset)
|
||||||
|
// trim leading backtick - TODO do this in first regex
|
||||||
|
.regexpReplaceAll("^\\`", "")
|
||||||
|
// trim trailing backtick - TODO do this in first regex
|
||||||
|
.regexpReplaceAll("\\`$", "") and
|
||||||
|
id = "cmd:" + lineIndex + ":" + occurrenceIndex + ":" + occurrenceOffset
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private predicate rankedCmdSubstitutionReplacements(int i, string command, string commandId) {
|
||||||
|
// rank commands by their unique IDs
|
||||||
|
commandId = rank[i](string c, string id | this.cmdSubstitutionReplacement(c, id, _) | id) and
|
||||||
|
// since we cannot output (command, ID) tuples from the rank operation,
|
||||||
|
// we need to work out the specific command associated with the resulting ID
|
||||||
|
this.cmdSubstitutionReplacement(command, commandId, _)
|
||||||
}
|
}
|
||||||
|
|
||||||
private predicate doReplaceCmdSubstitutions(int line, int round, string old, string new) {
|
private predicate doReplaceCmdSubstitutions(int line, int round, string old, string new) {
|
||||||
@@ -64,31 +93,56 @@ class BashShellScript extends ShellScript {
|
|||||||
this.cmdSubstitutionReplacement(result, _, i)
|
this.cmdSubstitutionReplacement(result, _, i)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if `quotedStr` is a string in double quotes in
|
||||||
|
* the line at `lineIndex` in the shell script,
|
||||||
|
* and `id` is a unique identifier for this quoted string.
|
||||||
|
*/
|
||||||
|
private predicate doubleQuotedString(int lineIndex, string quotedStr, string id) {
|
||||||
|
exists(int occurrenceIndex, int occurrenceOffset |
|
||||||
|
// double quoted string
|
||||||
|
quotedStr =
|
||||||
|
this.cmdSubstitutedLineProducer(lineIndex)
|
||||||
|
.regexpFind("\"((?:[^\"\\\\]|\\\\.)*)\"", occurrenceIndex, occurrenceOffset) and
|
||||||
|
id =
|
||||||
|
"qstr:" + lineIndex + ":" + occurrenceIndex + ":" + occurrenceOffset + ":" +
|
||||||
|
quotedStr.length() + ":" + quotedStr.regexpReplaceAll("[^a-zA-Z0-9]", "")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if `quotedStr` is a string in single quotes in
|
||||||
|
* the line at `lineIndex` in the shell script,
|
||||||
|
* and `id` is a unique identifier for this quoted string.
|
||||||
|
*/
|
||||||
|
private predicate singleQuotedString(int lineIndex, string quotedStr, string id) {
|
||||||
|
exists(int occurrenceIndex, int occurrenceOffset |
|
||||||
|
// single quoted string
|
||||||
|
quotedStr =
|
||||||
|
this.cmdSubstitutedLineProducer(lineIndex)
|
||||||
|
.regexpFind("'((?:\\\\.|[^'\\\\])*)'", occurrenceIndex, occurrenceOffset) and
|
||||||
|
id =
|
||||||
|
"qstr:" + lineIndex + ":" + occurrenceIndex + ":" + occurrenceOffset + ":" +
|
||||||
|
quotedStr.length() + ":" + quotedStr.regexpReplaceAll("[^a-zA-Z0-9]", "")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private predicate quotedStringReplacement(string quotedStr, string id) {
|
private predicate quotedStringReplacement(string quotedStr, string id) {
|
||||||
exists(string line, int k | line = this.cmdSubstitutedLineProducer(k) |
|
exists(int lineIndex |
|
||||||
exists(int i, int j |
|
this.doubleQuotedString(lineIndex, quotedStr, id)
|
||||||
// double quoted string
|
|
||||||
quotedStr = line.regexpFind("\"((?:[^\"\\\\]|\\\\.)*)\"", i, j) and
|
|
||||||
id =
|
|
||||||
"qstr:" + k + ":" + i + ":" + j + ":" + quotedStr.length() + ":" +
|
|
||||||
quotedStr.regexpReplaceAll("[^a-zA-Z0-9]", "")
|
|
||||||
)
|
|
||||||
or
|
or
|
||||||
exists(int i, int j |
|
this.singleQuotedString(lineIndex, quotedStr, id)
|
||||||
// single quoted string
|
|
||||||
quotedStr = line.regexpFind("'((?:\\\\.|[^'\\\\])*)'", i, j) and
|
|
||||||
id =
|
|
||||||
"qstr:" + k + ":" + i + ":" + j + ":" + quotedStr.length() + ":" +
|
|
||||||
quotedStr.regexpReplaceAll("[^a-zA-Z0-9]", "")
|
|
||||||
)
|
|
||||||
) and
|
) and
|
||||||
// Only do this for strings that might otherwise disrupt subsequent parsing
|
// Only do this for strings that might otherwise disrupt subsequent parsing
|
||||||
quotedStr.regexpMatch("[\"'].*[$\n\r'\"" + Bash::separator() + "].*[\"']")
|
quotedStr.regexpMatch("[\"'].*[$\n\r'\"" + Bash::separator() + "].*[\"']")
|
||||||
}
|
}
|
||||||
|
|
||||||
private predicate rankedQuotedStringReplacements(int i, string old, string new) {
|
private predicate rankedQuotedStringReplacements(int i, string quotedString, string quotedStringId) {
|
||||||
old = rank[i](string old2 | this.quotedStringReplacement(old2, _) | old2) and
|
// rank quoted strings by their nearly-unique IDs
|
||||||
this.quotedStringReplacement(old, new)
|
quotedStringId = rank[i](string s, string id | this.quotedStringReplacement(s, id) | id) and
|
||||||
|
// since we cannot output (string, ID) tuples from the rank operation,
|
||||||
|
// we need to work out the specific string associated with the resulting ID
|
||||||
|
this.quotedStringReplacement(quotedString, quotedStringId)
|
||||||
}
|
}
|
||||||
|
|
||||||
private predicate doReplaceQuotedStrings(int line, int round, string old, string new) {
|
private predicate doReplaceQuotedStrings(int line, int round, string old, string new) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
name: codeql/actions-all
|
name: codeql/actions-all
|
||||||
version: 0.4.10-dev
|
version: 0.4.12-dev
|
||||||
library: true
|
library: true
|
||||||
warnOnImplicitThis: true
|
warnOnImplicitThis: true
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|||||||
@@ -1,3 +1,13 @@
|
|||||||
|
## 0.6.3
|
||||||
|
|
||||||
|
No user-facing changes.
|
||||||
|
|
||||||
|
## 0.6.2
|
||||||
|
|
||||||
|
### Minor Analysis Improvements
|
||||||
|
|
||||||
|
* The query `actions/missing-workflow-permissions` is now aware of the minimal permissions needed for the actions `deploy-pages`, `delete-package-versions`, `ai-inference`. This should lead to better alert messages and better fix suggestions.
|
||||||
|
|
||||||
## 0.6.1
|
## 0.6.1
|
||||||
|
|
||||||
No user-facing changes.
|
No user-facing changes.
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
---
|
## 0.6.2
|
||||||
category: minorAnalysis
|
|
||||||
---
|
### Minor Analysis Improvements
|
||||||
|
|
||||||
* The query `actions/missing-workflow-permissions` is now aware of the minimal permissions needed for the actions `deploy-pages`, `delete-package-versions`, `ai-inference`. This should lead to better alert messages and better fix suggestions.
|
* The query `actions/missing-workflow-permissions` is now aware of the minimal permissions needed for the actions `deploy-pages`, `delete-package-versions`, `ai-inference`. This should lead to better alert messages and better fix suggestions.
|
||||||
3
actions/ql/src/change-notes/released/0.6.3.md
Normal file
3
actions/ql/src/change-notes/released/0.6.3.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
## 0.6.3
|
||||||
|
|
||||||
|
No user-facing changes.
|
||||||
@@ -1,2 +1,2 @@
|
|||||||
---
|
---
|
||||||
lastReleaseVersion: 0.6.1
|
lastReleaseVersion: 0.6.3
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
name: codeql/actions-queries
|
name: codeql/actions-queries
|
||||||
version: 0.6.2-dev
|
version: 0.6.4-dev
|
||||||
library: false
|
library: false
|
||||||
warnOnImplicitThis: true
|
warnOnImplicitThis: true
|
||||||
groups: [actions, queries]
|
groups: [actions, queries]
|
||||||
|
|||||||
81
actions/ql/test/query-tests/Security/CWE-094/.github/workflows/interpolation.yml
vendored
Normal file
81
actions/ql/test/query-tests/Security/CWE-094/.github/workflows/interpolation.yml
vendored
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
name: Workflow with complex interpolation
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
choice-a:
|
||||||
|
required: true
|
||||||
|
type: choice
|
||||||
|
description: choice-a
|
||||||
|
default: a1
|
||||||
|
options:
|
||||||
|
- a1
|
||||||
|
- a2
|
||||||
|
- a3
|
||||||
|
string-b:
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
description: string-b
|
||||||
|
string-c:
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
description: string-c
|
||||||
|
list-d:
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
default: d1 d2
|
||||||
|
description: list-d whitespace separated
|
||||||
|
list-e:
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
description: list-e whitespace separated
|
||||||
|
choice-f:
|
||||||
|
required: true
|
||||||
|
type: choice
|
||||||
|
description: choice-f
|
||||||
|
options:
|
||||||
|
- false
|
||||||
|
- true
|
||||||
|
|
||||||
|
env:
|
||||||
|
DRY_TEST: false
|
||||||
|
B: ${{ github.event.inputs.string-b }}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
job:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Produce values
|
||||||
|
id: produce-values
|
||||||
|
run: |
|
||||||
|
echo "region=region" >> $GITHUB_OUTPUT
|
||||||
|
echo "zone=zone" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Step with complex interpolation
|
||||||
|
id: complex
|
||||||
|
env:
|
||||||
|
CHOICE_A: ${{ github.event.inputs.choice-a }}
|
||||||
|
STRING_B: ${{ github.event.inputs.string-b }}
|
||||||
|
STRING_C: ${{ github.event.inputs.string-c }}
|
||||||
|
LIST_D: ${{ github.event.inputs.list-d }}
|
||||||
|
LIST_E: ${{ github.event.inputs.list-e }}
|
||||||
|
CHOICE_F: ${{ github.event.inputs.choice-f }}
|
||||||
|
REGION: ${{ steps.produce-values.outputs.region }}
|
||||||
|
ZONE: ${{ steps.produce-values.outputs.zone }}
|
||||||
|
DRY_TEST_JSON: ${{ fromJSON(env.DRY_TEST) }}
|
||||||
|
FUNCTION_NAME: my-function
|
||||||
|
USER_EMAIL: 'example@example.com'
|
||||||
|
TYPE: type
|
||||||
|
RANGE: '0-100'
|
||||||
|
|
||||||
|
run: |
|
||||||
|
comma_separated_list_d=$(echo "${LIST_D}" | sed "s/ /\",\"/g")
|
||||||
|
comma_separated_list_e=$(echo "${LIST_E}" | sed "s/ /\",\"/g")
|
||||||
|
c1=$(echo "${STRING_C}" | cut -d "-" -f 1)
|
||||||
|
c2=$(echo "${STRING_C}" | cut -d "-" -f 2)
|
||||||
|
# Similar commands that use JSON payloads with string interpolation.
|
||||||
|
response=$(aws lambda invoke --invocation-type RequestResponse --function-name "${FUNCTION_NAME}" --region "${REGION}" --cli-read-timeout 0 --cli-binary-format raw-in-base64-out --payload '{"appName":"my-app","chA":"'"${CHOICE_A}"'","c1":"'"${c1}"'","c2":"'"${c2}"'","a":"${CHOICE_A}","bValue":"${B}","zone":"${ZONE}","userEmail":"'"${USER_EMAIL}"'","region":"${REGION}","range":"${RANGE}","type":"${TYPE}","b":"${STRING_B}","listD":"","listE":"","dryTest":'"${DRY_TEST_JSON}"',"f":"${CHOICE_F}"}' ./config.json --log-type Tail)
|
||||||
|
response=$(aws lambda invoke --invocation-type RequestResponse --function-name "${FUNCTION_NAME}" --region "${REGION}" --cli-read-timeout 0 --cli-binary-format raw-in-base64-out --payload '{"appName":"my-app","chA":"'"${CHOICE_A}"'","c1":"'"${c1}"'","c2":"'"${c2}"'","a":"${CHOICE_A}","bValue":"${B}","zone":"${ZONE}","userEmail":"'"${USER_EMAIL}"'","region":"${REGION}","range":"${RANGE}","type":"${TYPE}","b":"${STRING_B}","listD":["'"${comma_separated_list_d}"'"],"listE":"","dryTest":'"${DRY_TEST_JSON}"',"f":"${CHOICE_F}"}' ./config.json --log-type Tail)
|
||||||
|
response=$(aws lambda invoke --invocation-type RequestResponse --function-name "${FUNCTION_NAME}" --region "${REGION}" --cli-read-timeout 0 --cli-binary-format raw-in-base64-out --payload '{"appName":"my-app","chA":"'"${CHOICE_A}"'","c1":"'"${c1}"'","c2":"'"${c2}"'","a":"${CHOICE_A}","bValue":"${B}","zone":"${ZONE}","userEmail":"'"${USER_EMAIL}"'","region":"${REGION}","range":"${RANGE}","type":"${TYPE}","b":"${STRING_B}","listD":["'"${comma_separated_list_d}"'"],"listE":"","dryTest":'"${DRY_TEST_JSON}"',"f":"${CHOICE_F}"}' ./config.json --log-type Tail)
|
||||||
|
response=$(aws lambda invoke --invocation-type RequestResponse --function-name "${FUNCTION_NAME}" --region "${REGION}" --cli-read-timeout 0 --cli-binary-format raw-in-base64-out --payload '{"appName":"my-app","chA":"'"${CHOICE_A}"'","c1":"'"${c1}"'","c2":"'"${c2}"'","a":"${CHOICE_A}","bValue":"${B}","zone":"${ZONE}","userEmail":"'"${USER_EMAIL}"'","region":"${REGION}","range":"${RANGE}","type":"${TYPE}","b":"${STRING_B}","listD":["'"${comma_separated_list_d}"'"],"listE":"","dryTest":'"${DRY_TEST_JSON}"',"f":"${CHOICE_F}"}' ./config.json --log-type Tail)
|
||||||
|
response=$(aws lambda invoke --invocation-type RequestResponse --function-name "${FUNCTION_NAME}" --region "${REGION}" --cli-read-timeout 0 --cli-binary-format raw-in-base64-out --payload '{"appName":"my-app","chA":"'"${CHOICE_A}"'","c1":"'"${c1}"'","c2":"'"${c2}"'","a":"${CHOICE_A}","bValue":"${B}","zone":"${ZONE}","userEmail":"'"${USER_EMAIL}"'","region":"${REGION}","range":"${RANGE}","type":"${TYPE}","b":"${STRING_B}","listD":"","listE":["'"${comma_separated_list_e}"'"],"dryTest":'"${DRY_TEST_JSON}"',"f":"${CHOICE_F}"}' ./config.json --log-type Tail)
|
||||||
|
shell: bash
|
||||||
10
cpp/bulk_generation_targets.yml
Normal file
10
cpp/bulk_generation_targets.yml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
language: cpp
|
||||||
|
strategy: dca
|
||||||
|
destination: cpp/ql/lib/ext/generated
|
||||||
|
targets:
|
||||||
|
- name: openssl
|
||||||
|
with-sinks: false
|
||||||
|
with-sources: false
|
||||||
|
- name: sqlite
|
||||||
|
with-sinks: false
|
||||||
|
with-sources: false
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
class LambdaExpr extends @lambdaexpr {
|
||||||
|
string toString() { none() }
|
||||||
|
}
|
||||||
|
|
||||||
|
from LambdaExpr lambda, string default_capture, boolean has_explicit_return_type
|
||||||
|
where lambdas(lambda, default_capture, has_explicit_return_type, _)
|
||||||
|
select lambda, default_capture, has_explicit_return_type
|
||||||
2493
cpp/downgrades/3c45f8b9e71ec723bf50c40581e1f18f4f25e290/old.dbscheme
Normal file
2493
cpp/downgrades/3c45f8b9e71ec723bf50c40581e1f18f4f25e290/old.dbscheme
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,3 @@
|
|||||||
|
description: capture whether a lambda has an explicitly specified parameter list.
|
||||||
|
compatibility: full
|
||||||
|
lambdas.rel: run lambdas.qlo
|
||||||
@@ -11,7 +11,7 @@ int getKind(int kind) {
|
|||||||
if kind = 14
|
if kind = 14
|
||||||
then result = 6 // Represent MSFT #import as #include
|
then result = 6 // Represent MSFT #import as #include
|
||||||
else
|
else
|
||||||
if kind = 15 or kind = 6
|
if kind = 15 or kind = 16
|
||||||
then result = 3 // Represent #elifdef and #elifndef as #elif
|
then result = 3 // Represent #elifdef and #elifndef as #elif
|
||||||
else result = kind
|
else result = kind
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
class BuiltinType extends @builtintype {
|
||||||
|
string toString() { none() }
|
||||||
|
}
|
||||||
|
|
||||||
|
from BuiltinType id, string name, int kind, int new_kind, int size, int sign, int alignment
|
||||||
|
where
|
||||||
|
builtintypes(id, name, kind, size, sign, alignment) and
|
||||||
|
if kind = 62 then new_kind = 1 else new_kind = kind
|
||||||
|
select id, name, new_kind, size, sign, alignment
|
||||||
2492
cpp/downgrades/af887e83a815a9cefe774ffa80e2493a1365b9e2/old.dbscheme
Normal file
2492
cpp/downgrades/af887e83a815a9cefe774ffa80e2493a1365b9e2/old.dbscheme
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,3 @@
|
|||||||
|
description: Support __mfp8 type
|
||||||
|
compatibility: backwards
|
||||||
|
builtintypes.rel: run builtintypes.qlo
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy": "dca",
|
|
||||||
"language": "cpp",
|
|
||||||
"targets": [
|
|
||||||
{ "name": "openssl", "with-sources": false, "with-sinks": false },
|
|
||||||
{ "name": "sqlite", "with-sources": false, "with-sinks": false }
|
|
||||||
],
|
|
||||||
"destination": "cpp/ql/lib/ext/generated"
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,33 @@
|
|||||||
|
## 5.1.0
|
||||||
|
|
||||||
|
### New Features
|
||||||
|
|
||||||
|
* Added a predicate `getReferencedMember` to `UsingDeclarationEntry`, which yields a member depending on a type template parameter.
|
||||||
|
|
||||||
|
## 5.0.0
|
||||||
|
|
||||||
|
### Breaking Changes
|
||||||
|
|
||||||
|
* Deleted the deprecated `userInputArgument` predicate and its convenience accessor from the `Security.qll`.
|
||||||
|
* Deleted the deprecated `userInputReturned` predicate and its convenience accessor from the `Security.qll`.
|
||||||
|
* Deleted the deprecated `userInputReturn` predicate from the `Security.qll`.
|
||||||
|
* Deleted the deprecated `isUserInput` predicate and its convenience accessor from the `Security.qll`.
|
||||||
|
* Deleted the deprecated `userInputArgument` predicate from the `SecurityOptions.qll`.
|
||||||
|
* Deleted the deprecated `userInputReturned` predicate from the `SecurityOptions.qll`.
|
||||||
|
|
||||||
|
### New Features
|
||||||
|
|
||||||
|
* Added local flow source models for `ReadFile`, `ReadFileEx`, `MapViewOfFile`, `MapViewOfFile2`, `MapViewOfFile3`, `MapViewOfFile3FromApp`, `MapViewOfFileEx`, `MapViewOfFileFromApp`, `MapViewOfFileNuma2`, and `NtReadFile`.
|
||||||
|
* Added the `pCmdLine` arguments of `WinMain` and `wWinMain` as local flow sources.
|
||||||
|
* Added source models for `GetCommandLineA`, `GetCommandLineW`, `GetEnvironmentStringsA`, `GetEnvironmentStringsW`, `GetEnvironmentVariableA`, and `GetEnvironmentVariableW`.
|
||||||
|
* Added summary models for `CommandLineToArgvA` and `CommandLineToArgvW`.
|
||||||
|
* Added support for `wmain` as part of the ArgvSource model.
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* Fixed a problem where `asExpr()` on `DataFlow::Node` would never return `ArrayAggregateLiteral`s.
|
||||||
|
* Fixed a problem where `asExpr()` on `DataFlow::Node` would never return `ClassAggregateLiteral`s.
|
||||||
|
|
||||||
## 4.3.1
|
## 4.3.1
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
category: fix
|
|
||||||
---
|
|
||||||
* Fixed a problem where `asExpr()` on `DataFlow::Node` would never return `ClassAggregateLiteral`s.
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
category: fix
|
|
||||||
---
|
|
||||||
* Fixed a problem where `asExpr()` on `DataFlow::Node` would never return `ArrayAggregateLiteral`s.
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
category: feature
|
|
||||||
---
|
|
||||||
* Added support for `wmain` as part of the ArgvSource model.
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
---
|
|
||||||
category: breaking
|
|
||||||
---
|
|
||||||
* Deleted the deprecated `userInputArgument` predicate and its convenience accessor from the `Security.qll`.
|
|
||||||
* Deleted the deprecated `userInputReturned` predicate and its convenience accessor from the `Security.qll`.
|
|
||||||
* Deleted the deprecated `userInputReturn` predicate from the `Security.qll`.
|
|
||||||
* Deleted the deprecated `isUserInput` predicate and its convenience accessor from the `Security.qll`.
|
|
||||||
* Deleted the deprecated `userInputArgument` predicate from the `SecurityOptions.qll`.
|
|
||||||
* Deleted the deprecated `userInputReturned` predicate from the `SecurityOptions.qll`.
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
---
|
|
||||||
category: feature
|
|
||||||
---
|
|
||||||
* Added the `pCmdLine` arguments of `WinMain` and `wWinMain` as local flow sources.
|
|
||||||
* Added source models for `GetCommandLineA`, `GetCommandLineW`, `GetEnvironmentStringsA`, `GetEnvironmentStringsW`, `GetEnvironmentVariableA`, and `GetEnvironmentVariableW`.
|
|
||||||
* Added summary models for `CommandLineToArgvA` and `CommandLineToArgvW`.
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
category: feature
|
|
||||||
---
|
|
||||||
* Added local flow source models for `ReadFile`, `ReadFileEx`, `MapViewOfFile`, `MapViewOfFile2`, `MapViewOfFile3`, `MapViewOfFile3FromApp`, `MapViewOfFileEx`, `MapViewOfFileFromApp`, `MapViewOfFileNuma2`, and `NtReadFile`.
|
|
||||||
4
cpp/ql/lib/change-notes/2025-06-06-lambda-parameters.md
Normal file
4
cpp/ql/lib/change-notes/2025-06-06-lambda-parameters.md
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
category: feature
|
||||||
|
---
|
||||||
|
* Added a predicate `hasParameterList` to `LambdaExpression` to capture whether a lambda has an explicitly specified parameter list.
|
||||||
23
cpp/ql/lib/change-notes/released/5.0.0.md
Normal file
23
cpp/ql/lib/change-notes/released/5.0.0.md
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
## 5.0.0
|
||||||
|
|
||||||
|
### Breaking Changes
|
||||||
|
|
||||||
|
* Deleted the deprecated `userInputArgument` predicate and its convenience accessor from the `Security.qll`.
|
||||||
|
* Deleted the deprecated `userInputReturned` predicate and its convenience accessor from the `Security.qll`.
|
||||||
|
* Deleted the deprecated `userInputReturn` predicate from the `Security.qll`.
|
||||||
|
* Deleted the deprecated `isUserInput` predicate and its convenience accessor from the `Security.qll`.
|
||||||
|
* Deleted the deprecated `userInputArgument` predicate from the `SecurityOptions.qll`.
|
||||||
|
* Deleted the deprecated `userInputReturned` predicate from the `SecurityOptions.qll`.
|
||||||
|
|
||||||
|
### New Features
|
||||||
|
|
||||||
|
* Added local flow source models for `ReadFile`, `ReadFileEx`, `MapViewOfFile`, `MapViewOfFile2`, `MapViewOfFile3`, `MapViewOfFile3FromApp`, `MapViewOfFileEx`, `MapViewOfFileFromApp`, `MapViewOfFileNuma2`, and `NtReadFile`.
|
||||||
|
* Added the `pCmdLine` arguments of `WinMain` and `wWinMain` as local flow sources.
|
||||||
|
* Added source models for `GetCommandLineA`, `GetCommandLineW`, `GetEnvironmentStringsA`, `GetEnvironmentStringsW`, `GetEnvironmentVariableA`, and `GetEnvironmentVariableW`.
|
||||||
|
* Added summary models for `CommandLineToArgvA` and `CommandLineToArgvW`.
|
||||||
|
* Added support for `wmain` as part of the ArgvSource model.
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* Fixed a problem where `asExpr()` on `DataFlow::Node` would never return `ArrayAggregateLiteral`s.
|
||||||
|
* Fixed a problem where `asExpr()` on `DataFlow::Node` would never return `ClassAggregateLiteral`s.
|
||||||
5
cpp/ql/lib/change-notes/released/5.1.0.md
Normal file
5
cpp/ql/lib/change-notes/released/5.1.0.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
## 5.1.0
|
||||||
|
|
||||||
|
### New Features
|
||||||
|
|
||||||
|
* Added a predicate `getReferencedMember` to `UsingDeclarationEntry`, which yields a member depending on a type template parameter.
|
||||||
@@ -1,2 +1,2 @@
|
|||||||
---
|
---
|
||||||
lastReleaseVersion: 4.3.1
|
lastReleaseVersion: 5.1.0
|
||||||
|
|||||||
@@ -4,42 +4,15 @@ private import OpenSSLOperationBase
|
|||||||
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers
|
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers
|
||||||
private import semmle.code.cpp.dataflow.new.DataFlow
|
private import semmle.code.cpp.dataflow.new.DataFlow
|
||||||
|
|
||||||
private module AlgGetterToAlgConsumerConfig implements DataFlow::ConfigSig {
|
|
||||||
predicate isSource(DataFlow::Node source) {
|
|
||||||
exists(OpenSSLAlgorithmValueConsumer c | c.getResultNode() = source)
|
|
||||||
}
|
|
||||||
|
|
||||||
predicate isSink(DataFlow::Node sink) {
|
|
||||||
exists(ECKeyGenOperation c | c.getAlgorithmArg() = sink.asExpr())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private module AlgGetterToAlgConsumerFlow = DataFlow::Global<AlgGetterToAlgConsumerConfig>;
|
|
||||||
|
|
||||||
class ECKeyGenOperation extends OpenSSLOperation, Crypto::KeyGenerationOperationInstance {
|
class ECKeyGenOperation extends OpenSSLOperation, Crypto::KeyGenerationOperationInstance {
|
||||||
ECKeyGenOperation() { this.(Call).getTarget().getName() = "EC_KEY_generate_key" }
|
ECKeyGenOperation() { this.(Call).getTarget().getName() = "EC_KEY_generate_key" }
|
||||||
|
|
||||||
override Expr getOutputArg() {
|
override Expr getAlgorithmArg() { result = this.(Call).getArgument(0) }
|
||||||
result = this.(Call) // return value of call
|
|
||||||
}
|
|
||||||
|
|
||||||
Expr getAlgorithmArg() { result = this.(Call).getArgument(0) }
|
|
||||||
|
|
||||||
override Expr getInputArg() {
|
|
||||||
// there is no 'input', in the sense that no data is being manipulated by the operation.
|
|
||||||
// There is an input of an algorithm, but that is not the intention of the operation input arg.
|
|
||||||
none()
|
|
||||||
}
|
|
||||||
|
|
||||||
override Crypto::KeyArtifactType getOutputKeyType() { result = Crypto::TAsymmetricKeyType() }
|
override Crypto::KeyArtifactType getOutputKeyType() { result = Crypto::TAsymmetricKeyType() }
|
||||||
|
|
||||||
override Crypto::ArtifactOutputDataFlowNode getOutputKeyArtifact() {
|
override Crypto::ArtifactOutputDataFlowNode getOutputKeyArtifact() {
|
||||||
result = this.getOutputNode()
|
result.asExpr() = this.(Call).getArgument(0)
|
||||||
}
|
|
||||||
|
|
||||||
override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() {
|
|
||||||
AlgGetterToAlgConsumerFlow::flow(result.(OpenSSLAlgorithmValueConsumer).getResultNode(),
|
|
||||||
DataFlow::exprNode(this.getAlgorithmArg()))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override Crypto::ConsumerInputDataFlowNode getKeySizeConsumer() {
|
override Crypto::ConsumerInputDataFlowNode getKeySizeConsumer() {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
private import experimental.quantum.Language
|
private import experimental.quantum.Language
|
||||||
private import experimental.quantum.OpenSSL.CtxFlow as CTXFlow
|
private import experimental.quantum.OpenSSL.CtxFlow as CTXFlow
|
||||||
|
private import OpenSSLOperationBase
|
||||||
|
|
||||||
module EncValToInitEncArgConfig implements DataFlow::ConfigSig {
|
module EncValToInitEncArgConfig implements DataFlow::ConfigSig {
|
||||||
predicate isSource(DataFlow::Node source) { source.asExpr().getValue().toInt() in [0, 1] }
|
predicate isSource(DataFlow::Node source) { source.asExpr().getValue().toInt() in [0, 1] }
|
||||||
@@ -34,19 +35,12 @@ Crypto::KeyOperationSubtype intToCipherOperationSubtype(int i) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: need to add key consumer
|
// TODO: need to add key consumer
|
||||||
abstract class EVP_Cipher_Initializer extends Call {
|
abstract class EVP_Cipher_Initializer extends EVPInitialize {
|
||||||
Expr getContextArg() { result = this.(Call).getArgument(0) }
|
override Expr getAlgorithmArg() { result = this.(Call).getArgument(1) }
|
||||||
|
|
||||||
Expr getAlgorithmArg() { result = this.(Call).getArgument(1) }
|
|
||||||
|
|
||||||
abstract Expr getKeyArg();
|
|
||||||
|
|
||||||
abstract Expr getIVArg();
|
|
||||||
|
|
||||||
// abstract Crypto::CipherOperationSubtype getCipherOperationSubtype();
|
|
||||||
abstract Expr getOperationSubtypeArg();
|
abstract Expr getOperationSubtypeArg();
|
||||||
|
|
||||||
Crypto::KeyOperationSubtype getCipherOperationSubtype() {
|
override Crypto::KeyOperationSubtype getKeyOperationSubtype() {
|
||||||
if this.(Call).getTarget().getName().toLowerCase().matches("%encrypt%")
|
if this.(Call).getTarget().getName().toLowerCase().matches("%encrypt%")
|
||||||
then result instanceof Crypto::TEncryptMode
|
then result instanceof Crypto::TEncryptMode
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -4,36 +4,23 @@ private import EVPCipherInitializer
|
|||||||
private import OpenSSLOperationBase
|
private import OpenSSLOperationBase
|
||||||
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers
|
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers
|
||||||
|
|
||||||
private module AlgGetterToAlgConsumerConfig implements DataFlow::ConfigSig {
|
class EVP_Cipher_Update_Call extends EVPUpdate {
|
||||||
predicate isSource(DataFlow::Node source) {
|
EVP_Cipher_Update_Call() {
|
||||||
exists(OpenSSLAlgorithmValueConsumer c | c.getResultNode() = source)
|
this.(Call).getTarget().getName() in [
|
||||||
|
"EVP_EncryptUpdate", "EVP_DecryptUpdate", "EVP_CipherUpdate"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate isSink(DataFlow::Node sink) {
|
override Expr getInputArg() { result = this.(Call).getArgument(3) }
|
||||||
exists(EVP_Cipher_Operation c | c.getAlgorithmArg() = sink.asExpr())
|
|
||||||
}
|
override Expr getOutputArg() { result = this.(Call).getArgument(1) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private module AlgGetterToAlgConsumerFlow = DataFlow::Global<AlgGetterToAlgConsumerConfig>;
|
|
||||||
|
|
||||||
// import experimental.quantum.OpenSSL.AlgorithmValueConsumers.AlgorithmValueConsumers
|
|
||||||
// import OpenSSLOperation
|
|
||||||
// class EVPCipherOutput extends CipherOutputArtifact {
|
|
||||||
// EVPCipherOutput() { exists(EVP_Cipher_Operation op | op.getOutputArg() = this) }
|
|
||||||
// override DataFlow::Node getOutputNode() { result.asDefiningArgument() = this }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
/**
|
/**
|
||||||
* see: https://docs.openssl.org/master/man3/EVP_EncryptInit/#synopsis
|
* see: https://docs.openssl.org/master/man3/EVP_EncryptInit/#synopsis
|
||||||
* Base configuration for all EVP cipher operations.
|
* Base configuration for all EVP cipher operations.
|
||||||
* NOTE: cannot extend instance of OpenSSLOperation, as we need to override
|
|
||||||
* elements of OpenSSLOperation (i.e., we are creating an instance)
|
|
||||||
*/
|
*/
|
||||||
abstract class EVP_Cipher_Operation extends OpenSSLOperation, Crypto::KeyOperationInstance {
|
abstract class EVP_Cipher_Operation extends EVPOperation, Crypto::KeyOperationInstance {
|
||||||
Expr getContextArg() { result = this.(Call).getArgument(0) }
|
|
||||||
|
|
||||||
Expr getAlgorithmArg() { this.getInitCall().getAlgorithmArg() = result }
|
|
||||||
|
|
||||||
override Expr getOutputArg() { result = this.(Call).getArgument(1) }
|
override Expr getOutputArg() { result = this.(Call).getArgument(1) }
|
||||||
|
|
||||||
override Crypto::KeyOperationSubtype getKeyOperationSubtype() {
|
override Crypto::KeyOperationSubtype getKeyOperationSubtype() {
|
||||||
@@ -43,54 +30,35 @@ abstract class EVP_Cipher_Operation extends OpenSSLOperation, Crypto::KeyOperati
|
|||||||
result instanceof Crypto::TDecryptMode and
|
result instanceof Crypto::TDecryptMode and
|
||||||
this.(Call).getTarget().getName().toLowerCase().matches("%decrypt%")
|
this.(Call).getTarget().getName().toLowerCase().matches("%decrypt%")
|
||||||
or
|
or
|
||||||
result = this.getInitCall().getCipherOperationSubtype() and
|
result = this.getInitCall().getKeyOperationSubtype() and
|
||||||
this.(Call).getTarget().getName().toLowerCase().matches("%cipher%")
|
this.(Call).getTarget().getName().toLowerCase().matches("%cipher%")
|
||||||
}
|
}
|
||||||
|
|
||||||
EVP_Cipher_Initializer getInitCall() {
|
|
||||||
CTXFlow::ctxArgFlowsToCtxArg(result.getContextArg(), this.getContextArg())
|
|
||||||
}
|
|
||||||
|
|
||||||
override Crypto::ConsumerInputDataFlowNode getNonceConsumer() {
|
override Crypto::ConsumerInputDataFlowNode getNonceConsumer() {
|
||||||
this.getInitCall().getIVArg() = result.asExpr()
|
this.getInitCall().getIVArg() = result.asExpr()
|
||||||
}
|
}
|
||||||
|
|
||||||
override Crypto::ConsumerInputDataFlowNode getInputConsumer() { result = this.getInputNode() }
|
|
||||||
|
|
||||||
override Crypto::ConsumerInputDataFlowNode getKeyConsumer() {
|
override Crypto::ConsumerInputDataFlowNode getKeyConsumer() {
|
||||||
this.getInitCall().getKeyArg() = result.asExpr()
|
this.getInitCall().getKeyArg() = result.asExpr()
|
||||||
|
// todo: or track to the EVP_PKEY_CTX_new
|
||||||
}
|
}
|
||||||
|
|
||||||
override Crypto::ArtifactOutputDataFlowNode getOutputArtifact() { result = this.getOutputNode() }
|
override Crypto::ArtifactOutputDataFlowNode getOutputArtifact() {
|
||||||
|
result = EVPOperation.super.getOutputArtifact()
|
||||||
|
}
|
||||||
|
|
||||||
override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() {
|
override Crypto::ConsumerInputDataFlowNode getInputConsumer() {
|
||||||
AlgGetterToAlgConsumerFlow::flow(result.(OpenSSLAlgorithmValueConsumer).getResultNode(),
|
result = EVPOperation.super.getInputConsumer()
|
||||||
DataFlow::exprNode(this.getInitCall().getAlgorithmArg()))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class EVP_Cipher_Call extends EVP_Cipher_Operation {
|
class EVP_Cipher_Call extends EVPOperation, EVP_Cipher_Operation {
|
||||||
EVP_Cipher_Call() { this.(Call).getTarget().getName() = "EVP_Cipher" }
|
EVP_Cipher_Call() { this.(Call).getTarget().getName() = "EVP_Cipher" }
|
||||||
|
|
||||||
override Expr getInputArg() { result = this.(Call).getArgument(2) }
|
override Expr getInputArg() { result = this.(Call).getArgument(2) }
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: not modeled as cipher operations, these are intermediate calls
|
class EVP_Cipher_Final_Call extends EVPFinal, EVP_Cipher_Operation {
|
||||||
class EVP_Cipher_Update_Call extends Call {
|
|
||||||
EVP_Cipher_Update_Call() {
|
|
||||||
this.(Call).getTarget().getName() in [
|
|
||||||
"EVP_EncryptUpdate", "EVP_DecryptUpdate", "EVP_CipherUpdate"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
Expr getInputArg() { result = this.(Call).getArgument(3) }
|
|
||||||
|
|
||||||
DataFlow::Node getInputNode() { result.asExpr() = this.getInputArg() }
|
|
||||||
|
|
||||||
Expr getContextArg() { result = this.(Call).getArgument(0) }
|
|
||||||
}
|
|
||||||
|
|
||||||
class EVP_Cipher_Final_Call extends EVP_Cipher_Operation {
|
|
||||||
EVP_Cipher_Final_Call() {
|
EVP_Cipher_Final_Call() {
|
||||||
this.(Call).getTarget().getName() in [
|
this.(Call).getTarget().getName() in [
|
||||||
"EVP_EncryptFinal_ex", "EVP_DecryptFinal_ex", "EVP_CipherFinal_ex", "EVP_EncryptFinal",
|
"EVP_EncryptFinal_ex", "EVP_DecryptFinal_ex", "EVP_CipherFinal_ex", "EVP_EncryptFinal",
|
||||||
@@ -98,26 +66,12 @@ class EVP_Cipher_Final_Call extends EVP_Cipher_Operation {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
EVP_Cipher_Update_Call getUpdateCalls() {
|
/**
|
||||||
CTXFlow::ctxArgFlowsToCtxArg(result.getContextArg(), this.getContextArg())
|
* Output is both from update calls and from the final call.
|
||||||
|
*/
|
||||||
|
override Expr getOutputArg() {
|
||||||
|
result = EVPFinal.super.getOutputArg()
|
||||||
|
or
|
||||||
|
result = EVP_Cipher_Operation.super.getOutputArg()
|
||||||
}
|
}
|
||||||
|
|
||||||
override Expr getInputArg() { result = this.getUpdateCalls().getInputArg() }
|
|
||||||
|
|
||||||
override Crypto::ConsumerInputDataFlowNode getInputConsumer() { result = this.getInputNode() }
|
|
||||||
}
|
|
||||||
|
|
||||||
class EVP_PKEY_Operation extends EVP_Cipher_Operation {
|
|
||||||
EVP_PKEY_Operation() {
|
|
||||||
this.(Call).getTarget().getName() in ["EVP_PKEY_decrypt", "EVP_PKEY_encrypt"]
|
|
||||||
}
|
|
||||||
|
|
||||||
override Expr getInputArg() { result = this.(Call).getArgument(3) }
|
|
||||||
// TODO: how PKEY is initialized is different that symmetric cipher
|
|
||||||
// Consider making an entirely new class for this and specializing
|
|
||||||
// the get init call
|
|
||||||
}
|
|
||||||
|
|
||||||
class EVPCipherInputArgument extends Expr {
|
|
||||||
EVPCipherInputArgument() { exists(EVP_Cipher_Operation op | op.getInputArg() = this) }
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
import cpp
|
import cpp
|
||||||
|
private import OpenSSLOperationBase
|
||||||
|
|
||||||
abstract class EVP_Hash_Initializer extends Call {
|
abstract class EVP_Hash_Initializer extends EVPInitialize { }
|
||||||
Expr getContextArg() { result = this.(Call).getArgument(0) }
|
|
||||||
|
|
||||||
abstract Expr getAlgorithmArg();
|
|
||||||
}
|
|
||||||
|
|
||||||
class EVP_DigestInit_Variant_Calls extends EVP_Hash_Initializer {
|
class EVP_DigestInit_Variant_Calls extends EVP_Hash_Initializer {
|
||||||
EVP_DigestInit_Variant_Calls() {
|
EVP_DigestInit_Variant_Calls() {
|
||||||
|
|||||||
@@ -8,118 +8,78 @@ private import OpenSSLOperationBase
|
|||||||
private import EVPHashInitializer
|
private import EVPHashInitializer
|
||||||
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers
|
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers
|
||||||
|
|
||||||
// import EVPHashConsumers
|
class EVP_Digest_Update_Call extends EVPUpdate {
|
||||||
abstract class EVP_Hash_Operation extends OpenSSLOperation, Crypto::HashOperationInstance {
|
EVP_Digest_Update_Call() { this.(Call).getTarget().getName() = "EVP_DigestUpdate" }
|
||||||
Expr getContextArg() { result = this.(Call).getArgument(0) }
|
|
||||||
|
|
||||||
Expr getAlgorithmArg() { result = this.getInitCall().getAlgorithmArg() }
|
override Expr getInputArg() { result = this.(Call).getArgument(1) }
|
||||||
|
|
||||||
EVP_Hash_Initializer getInitCall() {
|
|
||||||
CTXFlow::ctxArgFlowsToCtxArg(result.getContextArg(), this.getContextArg())
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* By default, the algorithm value comes from the init call.
|
|
||||||
* There are variants where this isn't true, in which case the
|
|
||||||
* subclass should override this method.
|
|
||||||
*/
|
|
||||||
override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() {
|
|
||||||
AlgGetterToAlgConsumerFlow::flow(result.(OpenSSLAlgorithmValueConsumer).getResultNode(),
|
|
||||||
DataFlow::exprNode(this.getAlgorithmArg()))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private module AlgGetterToAlgConsumerConfig implements DataFlow::ConfigSig {
|
|
||||||
predicate isSource(DataFlow::Node source) {
|
|
||||||
exists(OpenSSLAlgorithmValueConsumer c | c.getResultNode() = source)
|
|
||||||
}
|
|
||||||
|
|
||||||
predicate isSink(DataFlow::Node sink) {
|
|
||||||
exists(EVP_Hash_Operation c | c.getAlgorithmArg() = sink.asExpr())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private module AlgGetterToAlgConsumerFlow = DataFlow::Global<AlgGetterToAlgConsumerConfig>;
|
|
||||||
|
|
||||||
//https://docs.openssl.org/3.0/man3/EVP_DigestInit/#synopsis
|
//https://docs.openssl.org/3.0/man3/EVP_DigestInit/#synopsis
|
||||||
class EVP_Q_Digest_Operation extends EVP_Hash_Operation {
|
class EVP_Q_Digest_Operation extends EVPOperation, Crypto::HashOperationInstance {
|
||||||
EVP_Q_Digest_Operation() { this.(Call).getTarget().getName() = "EVP_Q_digest" }
|
EVP_Q_Digest_Operation() { this.(Call).getTarget().getName() = "EVP_Q_digest" }
|
||||||
|
|
||||||
//override Crypto::AlgorithmConsumer getAlgorithmConsumer() { }
|
override Expr getAlgorithmArg() { result = this.(Call).getArgument(1) }
|
||||||
|
|
||||||
override EVP_Hash_Initializer getInitCall() {
|
override EVP_Hash_Initializer getInitCall() {
|
||||||
// This variant of digest does not use an init
|
// This variant of digest does not use an init
|
||||||
// and even if it were used, the init would be ignored/undefined
|
// and even if it were used, the init would be ignored/undefined
|
||||||
none()
|
none()
|
||||||
}
|
}
|
||||||
|
|
||||||
override Expr getOutputArg() { result = this.(Call).getArgument(5) }
|
|
||||||
|
|
||||||
override Expr getInputArg() { result = this.(Call).getArgument(3) }
|
override Expr getInputArg() { result = this.(Call).getArgument(3) }
|
||||||
|
|
||||||
override Crypto::ArtifactOutputDataFlowNode getOutputArtifact() { result = this.getOutputNode() }
|
override Expr getOutputArg() { result = this.(Call).getArgument(5) }
|
||||||
|
|
||||||
override Crypto::ConsumerInputDataFlowNode getInputConsumer() { result = this.getInputNode() }
|
override Crypto::ArtifactOutputDataFlowNode getOutputArtifact() {
|
||||||
|
result = EVPOperation.super.getOutputArtifact()
|
||||||
override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() {
|
|
||||||
// The operation is a direct algorithm consumer
|
|
||||||
// NOTE: the operation itself is already modeld as a value consumer, so we can
|
|
||||||
// simply return 'this', see modeled hash algorithm consuers for EVP_Q_Digest
|
|
||||||
this = result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override Expr getAlgorithmArg() { result = this.(Call).getArgument(1) }
|
override Crypto::ConsumerInputDataFlowNode getInputConsumer() {
|
||||||
|
result = EVPOperation.super.getInputConsumer()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class EVP_Digest_Operation extends EVP_Hash_Operation {
|
class EVP_Digest_Operation extends EVPOperation, Crypto::HashOperationInstance {
|
||||||
EVP_Digest_Operation() { this.(Call).getTarget().getName() = "EVP_Digest" }
|
EVP_Digest_Operation() { this.(Call).getTarget().getName() = "EVP_Digest" }
|
||||||
|
|
||||||
// There is no context argument for this function
|
// There is no context argument for this function
|
||||||
override Expr getContextArg() { none() }
|
override Expr getContextArg() { none() }
|
||||||
|
|
||||||
|
override Expr getAlgorithmArg() { result = this.(Call).getArgument(4) }
|
||||||
|
|
||||||
override EVP_Hash_Initializer getInitCall() {
|
override EVP_Hash_Initializer getInitCall() {
|
||||||
// This variant of digest does not use an init
|
// This variant of digest does not use an init
|
||||||
// and even if it were used, the init would be ignored/undefined
|
// and even if it were used, the init would be ignored/undefined
|
||||||
none()
|
none()
|
||||||
}
|
}
|
||||||
|
|
||||||
override Expr getAlgorithmArg() { result = this.(Call).getArgument(4) }
|
override Expr getInputArg() { result = this.(Call).getArgument(0) }
|
||||||
|
|
||||||
override Expr getOutputArg() { result = this.(Call).getArgument(2) }
|
override Expr getOutputArg() { result = this.(Call).getArgument(2) }
|
||||||
|
|
||||||
override Expr getInputArg() { result = this.(Call).getArgument(0) }
|
override Crypto::ArtifactOutputDataFlowNode getOutputArtifact() {
|
||||||
|
result = EVPOperation.super.getOutputArtifact()
|
||||||
|
}
|
||||||
|
|
||||||
override Crypto::ArtifactOutputDataFlowNode getOutputArtifact() { result = this.getOutputNode() }
|
override Crypto::ConsumerInputDataFlowNode getInputConsumer() {
|
||||||
|
result = EVPOperation.super.getInputConsumer()
|
||||||
override Crypto::ConsumerInputDataFlowNode getInputConsumer() { result = this.getInputNode() }
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: not modeled as hash operations, these are intermediate calls
|
class EVP_Digest_Final_Call extends EVPFinal, Crypto::HashOperationInstance {
|
||||||
class EVP_Digest_Update_Call extends Call {
|
|
||||||
EVP_Digest_Update_Call() { this.(Call).getTarget().getName() in ["EVP_DigestUpdate"] }
|
|
||||||
|
|
||||||
Expr getInputArg() { result = this.(Call).getArgument(1) }
|
|
||||||
|
|
||||||
DataFlow::Node getInputNode() { result.asExpr() = this.getInputArg() }
|
|
||||||
|
|
||||||
Expr getContextArg() { result = this.(Call).getArgument(0) }
|
|
||||||
}
|
|
||||||
|
|
||||||
class EVP_Digest_Final_Call extends EVP_Hash_Operation {
|
|
||||||
EVP_Digest_Final_Call() {
|
EVP_Digest_Final_Call() {
|
||||||
this.(Call).getTarget().getName() in [
|
this.(Call).getTarget().getName() in [
|
||||||
"EVP_DigestFinal", "EVP_DigestFinal_ex", "EVP_DigestFinalXOF"
|
"EVP_DigestFinal", "EVP_DigestFinal_ex", "EVP_DigestFinalXOF"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
EVP_Digest_Update_Call getUpdateCalls() {
|
|
||||||
CTXFlow::ctxArgFlowsToCtxArg(result.getContextArg(), this.getContextArg())
|
|
||||||
}
|
|
||||||
|
|
||||||
override Expr getInputArg() { result = this.getUpdateCalls().getInputArg() }
|
|
||||||
|
|
||||||
override Crypto::ConsumerInputDataFlowNode getInputConsumer() { result = this.getInputNode() }
|
|
||||||
|
|
||||||
override Expr getOutputArg() { result = this.(Call).getArgument(1) }
|
override Expr getOutputArg() { result = this.(Call).getArgument(1) }
|
||||||
|
|
||||||
override Crypto::ArtifactOutputDataFlowNode getOutputArtifact() { result = this.getOutputNode() }
|
override Crypto::ArtifactOutputDataFlowNode getOutputArtifact() {
|
||||||
|
result = EVPFinal.super.getOutputArtifact()
|
||||||
|
}
|
||||||
|
|
||||||
|
override Crypto::ConsumerInputDataFlowNode getInputConsumer() {
|
||||||
|
result = EVPFinal.super.getInputConsumer()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,162 @@
|
|||||||
private import experimental.quantum.Language
|
private import experimental.quantum.Language
|
||||||
|
private import experimental.quantum.OpenSSL.CtxFlow as CTXFlow
|
||||||
|
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class for all OpenSSL operations.
|
||||||
|
*/
|
||||||
abstract class OpenSSLOperation extends Crypto::OperationInstance instanceof Call {
|
abstract class OpenSSLOperation extends Crypto::OperationInstance instanceof Call {
|
||||||
|
/**
|
||||||
|
* Expression that specifies the algorithm for the operation.
|
||||||
|
* Will be an argument of the operation in the simplest case.
|
||||||
|
*/
|
||||||
|
abstract Expr getAlgorithmArg();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Algorithm is specified in initialization call or is implicitly established by the key.
|
||||||
|
*/
|
||||||
|
override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() {
|
||||||
|
AlgGetterToAlgConsumerFlow::flow(result.(OpenSSLAlgorithmValueConsumer).getResultNode(),
|
||||||
|
DataFlow::exprNode(this.getAlgorithmArg()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Call to initialization functions from the EVP API.
|
||||||
|
* These are not operations in the sense of Crypto::OperationInstance,
|
||||||
|
* but they are used to initialize the context for the operation.
|
||||||
|
*/
|
||||||
|
abstract class EVPInitialize extends Call {
|
||||||
|
/**
|
||||||
|
* Gets the context argument that ties together initialization, updates and/or final calls.
|
||||||
|
*/
|
||||||
|
Expr getContextArg() { result = this.(Call).getArgument(0) }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the type of key operation, none if not applicable.
|
||||||
|
*/
|
||||||
|
Crypto::KeyOperationSubtype getKeyOperationSubtype() { none() }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Explicitly specified algorithm or none if implicit (e.g., established by the key).
|
||||||
|
* None if not applicable.
|
||||||
|
*/
|
||||||
|
Expr getAlgorithmArg() { none() }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the key for the operation, none if not applicable.
|
||||||
|
*/
|
||||||
|
Expr getKeyArg() { none() }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the IV/nonce, none if not applicable.
|
||||||
|
*/
|
||||||
|
Expr getIVArg() { none() }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Call to update functions from the EVP API.
|
||||||
|
* These are not operations in the sense of Crypto::OperationInstance,
|
||||||
|
* but they are used to update the context for the operation.
|
||||||
|
*/
|
||||||
|
abstract class EVPUpdate extends Call {
|
||||||
|
/**
|
||||||
|
* Gets the context argument that ties together initialization, updates and/or final calls.
|
||||||
|
*/
|
||||||
|
Expr getContextArg() { result = this.(Call).getArgument(0) }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update calls always have some input data like plaintext or message digest.
|
||||||
|
*/
|
||||||
abstract Expr getInputArg();
|
abstract Expr getInputArg();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Can be an argument of a call or a return value of a function.
|
* Update calls sometimes have some output data like a plaintext.
|
||||||
|
*/
|
||||||
|
Expr getOutputArg() { none() }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flows from algorithm values to operations, specific to OpenSSL
|
||||||
|
*/
|
||||||
|
private module AlgGetterToAlgConsumerConfig implements DataFlow::ConfigSig {
|
||||||
|
predicate isSource(DataFlow::Node source) {
|
||||||
|
exists(OpenSSLAlgorithmValueConsumer c | c.getResultNode() = source)
|
||||||
|
}
|
||||||
|
|
||||||
|
predicate isSink(DataFlow::Node sink) {
|
||||||
|
exists(EVPOperation c | c.getAlgorithmArg() = sink.asExpr())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private module AlgGetterToAlgConsumerFlow = DataFlow::Global<AlgGetterToAlgConsumerConfig>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The base class for all operations of the EVP API.
|
||||||
|
* This captures one-shot APIs (with and without an initilizer call) and final calls.
|
||||||
|
* Provides some default methods for Crypto::KeyOperationInstance class
|
||||||
|
*/
|
||||||
|
abstract class EVPOperation extends OpenSSLOperation {
|
||||||
|
/**
|
||||||
|
* Gets the context argument that ties together initialization, updates and/or final calls.
|
||||||
|
*/
|
||||||
|
Expr getContextArg() { result = this.(Call).getArgument(0) }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Some input data like plaintext or message digest.
|
||||||
|
* Either argument provided direcly in the call or all arguments that were provided in update calls.
|
||||||
|
*/
|
||||||
|
abstract Expr getInputArg();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Some output data like ciphertext or signature.
|
||||||
*/
|
*/
|
||||||
abstract Expr getOutputArg();
|
abstract Expr getOutputArg();
|
||||||
|
|
||||||
DataFlow::Node getInputNode() {
|
/**
|
||||||
// Assumed to be default to asExpr
|
* Overwrite with an explicitly specified algorithm or leave base implementation to find it in the initialization call.
|
||||||
result.asExpr() = this.getInputArg()
|
*/
|
||||||
|
override Expr getAlgorithmArg() { result = this.getInitCall().getAlgorithmArg() }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the initialization call, may be none.
|
||||||
|
*/
|
||||||
|
EVPInitialize getInitCall() {
|
||||||
|
CTXFlow::ctxArgFlowsToCtxArg(result.getContextArg(), this.getContextArg())
|
||||||
}
|
}
|
||||||
|
|
||||||
DataFlow::Node getOutputNode() {
|
Crypto::ArtifactOutputDataFlowNode getOutputArtifact() {
|
||||||
if exists(Call c | c.getAnArgument() = this)
|
result = DataFlow::exprNode(this.getOutputArg())
|
||||||
then result.asDefiningArgument() = this
|
}
|
||||||
else result.asExpr() = this
|
|
||||||
|
/**
|
||||||
|
* Input consumer is the input argument of the call.
|
||||||
|
*/
|
||||||
|
Crypto::ConsumerInputDataFlowNode getInputConsumer() {
|
||||||
|
result = DataFlow::exprNode(this.getInputArg())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The final calls of the EVP API.
|
||||||
|
*/
|
||||||
|
abstract class EVPFinal extends EVPOperation {
|
||||||
|
/**
|
||||||
|
* All update calls that were executed before this final call.
|
||||||
|
*/
|
||||||
|
EVPUpdate getUpdateCalls() {
|
||||||
|
CTXFlow::ctxArgFlowsToCtxArg(result.getContextArg(), this.getContextArg())
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the input data provided to all update calls.
|
||||||
|
* If more input data was provided in the final call, override the method.
|
||||||
|
*/
|
||||||
|
override Expr getInputArg() { result = this.getUpdateCalls().getInputArg() }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the output data provided to all update calls.
|
||||||
|
* If more output data was provided in the final call, override the method.
|
||||||
|
*/
|
||||||
|
override Expr getOutputArg() { result = this.getUpdateCalls().getOutputArg() }
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
name: codeql/cpp-all
|
name: codeql/cpp-all
|
||||||
version: 4.3.2-dev
|
version: 5.1.1-dev
|
||||||
groups: cpp
|
groups: cpp
|
||||||
dbscheme: semmlecode.cpp.dbscheme
|
dbscheme: semmlecode.cpp.dbscheme
|
||||||
extractor: cpp
|
extractor: cpp
|
||||||
|
|||||||
@@ -174,7 +174,27 @@ class UsingDeclarationEntry extends UsingEntry {
|
|||||||
*/
|
*/
|
||||||
Declaration getDeclaration() { usings(underlyingElement(this), unresolveElement(result), _, _) }
|
Declaration getDeclaration() { usings(underlyingElement(this), unresolveElement(result), _, _) }
|
||||||
|
|
||||||
override string toString() { result = "using " + this.getDeclaration().getDescription() }
|
/**
|
||||||
|
* Gets the member that is referenced by this using declaration, where the member depends on a
|
||||||
|
* type template parameter.
|
||||||
|
*
|
||||||
|
* For example:
|
||||||
|
* ```
|
||||||
|
* template <typename T>
|
||||||
|
* class A {
|
||||||
|
* using T::m;
|
||||||
|
* };
|
||||||
|
* ```
|
||||||
|
* Here, `getReferencedMember()` yields the member `m` of `T`. Observe that,
|
||||||
|
* as `T` is not instantiated, `m` is represented by a `Literal` and not
|
||||||
|
* a `Declaration`.
|
||||||
|
*/
|
||||||
|
Literal getReferencedMember() { usings(underlyingElement(this), unresolveElement(result), _, _) }
|
||||||
|
|
||||||
|
override string toString() {
|
||||||
|
result = "using " + this.getDeclaration().getDescription() or
|
||||||
|
result = "using " + this.getReferencedMember()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -839,6 +839,9 @@ private predicate floatingPointTypeMapping(
|
|||||||
or
|
or
|
||||||
// _Complex _Float128
|
// _Complex _Float128
|
||||||
kind = 61 and base = 2 and domain = TComplexDomain() and realKind = 49 and extended = false
|
kind = 61 and base = 2 and domain = TComplexDomain() and realKind = 49 and extended = false
|
||||||
|
or
|
||||||
|
// __mfp8
|
||||||
|
kind = 62 and base = 2 and domain = TRealDomain() and realKind = 62 and extended = false
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -41,12 +41,17 @@ class LambdaExpression extends Expr, @lambdaexpr {
|
|||||||
* - "&" if capture-by-reference is the default for implicit captures.
|
* - "&" if capture-by-reference is the default for implicit captures.
|
||||||
* - "=" if capture-by-value is the default for implicit captures.
|
* - "=" if capture-by-value is the default for implicit captures.
|
||||||
*/
|
*/
|
||||||
string getDefaultCaptureMode() { lambdas(underlyingElement(this), result, _) }
|
string getDefaultCaptureMode() { lambdas(underlyingElement(this), result, _, _) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if the return type (of the call operator of the resulting object) was explicitly specified.
|
* Holds if the return type (of the call operator of the resulting object) was explicitly specified.
|
||||||
*/
|
*/
|
||||||
predicate returnTypeIsExplicit() { lambdas(underlyingElement(this), _, true) }
|
predicate returnTypeIsExplicit() { lambdas(underlyingElement(this), _, true, _) }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if the lambda has an explicitly specified parameter list, even when empty.
|
||||||
|
*/
|
||||||
|
predicate hasParameterList() { lambdas(underlyingElement(this), _, _, true) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the function which will be invoked when the resulting object is called.
|
* Gets the function which will be invoked when the resulting object is called.
|
||||||
|
|||||||
@@ -691,6 +691,7 @@ case @builtintype.kind of
|
|||||||
| 59 = @complex_std_float64 // _Complex _Float64
|
| 59 = @complex_std_float64 // _Complex _Float64
|
||||||
| 60 = @complex_float64x // _Complex _Float64x
|
| 60 = @complex_float64x // _Complex _Float64x
|
||||||
| 61 = @complex_std_float128 // _Complex _Float128
|
| 61 = @complex_std_float128 // _Complex _Float128
|
||||||
|
| 62 = @mfp8 // __mfp8
|
||||||
;
|
;
|
||||||
|
|
||||||
builtintypes(
|
builtintypes(
|
||||||
@@ -2138,7 +2139,8 @@ code_block(
|
|||||||
lambdas(
|
lambdas(
|
||||||
unique int expr: @lambdaexpr ref,
|
unique int expr: @lambdaexpr ref,
|
||||||
string default_capture: string ref,
|
string default_capture: string ref,
|
||||||
boolean has_explicit_return_type: boolean ref
|
boolean has_explicit_return_type: boolean ref,
|
||||||
|
boolean has_explicit_parameter_list: boolean ref
|
||||||
);
|
);
|
||||||
|
|
||||||
lambda_capture(
|
lambda_capture(
|
||||||
|
|||||||
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 __mfp8 type
|
||||||
|
compatibility: full
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
class LambdaExpr extends @lambdaexpr {
|
||||||
|
string toString() { none() }
|
||||||
|
}
|
||||||
|
|
||||||
|
from LambdaExpr lambda, string default_capture, boolean has_explicit_return_type
|
||||||
|
where lambdas(lambda, default_capture, has_explicit_return_type)
|
||||||
|
select lambda, default_capture, has_explicit_return_type, true
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,3 @@
|
|||||||
|
description: capture whether a lambda has an explicitly specified parameter list.
|
||||||
|
compatibility: backwards
|
||||||
|
lambdas.rel: run lambdas.qlo
|
||||||
@@ -1,3 +1,13 @@
|
|||||||
|
## 1.4.2
|
||||||
|
|
||||||
|
No user-facing changes.
|
||||||
|
|
||||||
|
## 1.4.1
|
||||||
|
|
||||||
|
### Minor Analysis Improvements
|
||||||
|
|
||||||
|
* Added flow model for the `SQLite` and `OpenSSL` libraries. This may result in more alerts when running queries on codebases that use these libraries.
|
||||||
|
|
||||||
## 1.4.0
|
## 1.4.0
|
||||||
|
|
||||||
### Query Metadata Changes
|
### Query Metadata Changes
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
---
|
## 1.4.1
|
||||||
category: minorAnalysis
|
|
||||||
---
|
### Minor Analysis Improvements
|
||||||
* Added flow model for the `SQLite` and `OpenSSL` libraries. This may result in more alerts when running queries on codebases that use these libraries.
|
|
||||||
|
* Added flow model for the `SQLite` and `OpenSSL` libraries. This may result in more alerts when running queries on codebases that use these libraries.
|
||||||
3
cpp/ql/src/change-notes/released/1.4.2.md
Normal file
3
cpp/ql/src/change-notes/released/1.4.2.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
## 1.4.2
|
||||||
|
|
||||||
|
No user-facing changes.
|
||||||
@@ -1,2 +1,2 @@
|
|||||||
---
|
---
|
||||||
lastReleaseVersion: 1.4.0
|
lastReleaseVersion: 1.4.2
|
||||||
|
|||||||
@@ -98,8 +98,8 @@ private predicate exprReleases(Expr e, Expr released, string kind) {
|
|||||||
e.(FunctionCall).getTarget() = f or
|
e.(FunctionCall).getTarget() = f or
|
||||||
e.(FunctionCall).getTarget().(MemberFunction).getAnOverridingFunction+() = f
|
e.(FunctionCall).getTarget().(MemberFunction).getAnOverridingFunction+() = f
|
||||||
) and
|
) and
|
||||||
access = f.getParameter(arg).getAnAccess() and
|
access = f.getParameter(pragma[only_bind_into](arg)).getAnAccess() and
|
||||||
e.(FunctionCall).getArgument(arg) = released and
|
e.(FunctionCall).getArgument(pragma[only_bind_into](arg)) = released and
|
||||||
exprReleases(_,
|
exprReleases(_,
|
||||||
pragma[only_bind_into](exprOrDereference(globalValueNumber(access).getAnExpr())), kind)
|
pragma[only_bind_into](exprOrDereference(globalValueNumber(access).getAnExpr())), kind)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
name: codeql/cpp-queries
|
name: codeql/cpp-queries
|
||||||
version: 1.4.1-dev
|
version: 1.4.3-dev
|
||||||
groups:
|
groups:
|
||||||
- cpp
|
- cpp
|
||||||
- queries
|
- queries
|
||||||
|
|||||||
@@ -324,7 +324,7 @@ Conversion3.cpp:
|
|||||||
# 2| getExpr(): [CStyleCast] (int)...
|
# 2| getExpr(): [CStyleCast] (int)...
|
||||||
# 2| Conversion = [IntegralConversion] integral conversion
|
# 2| Conversion = [IntegralConversion] integral conversion
|
||||||
# 2| Type = [IntType] int
|
# 2| Type = [IntType] int
|
||||||
# 2| Value = [CStyleCast] 1
|
# 2| Value = [CStyleCast] 5
|
||||||
# 2| ValueCategory = prvalue
|
# 2| ValueCategory = prvalue
|
||||||
# 2| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
|
# 2| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
|
||||||
# 2| Type = [IntType] int
|
# 2| Type = [IntType] int
|
||||||
|
|||||||
@@ -1,8 +1,16 @@
|
|||||||
| openssl_basic.c:40:13:40:31 | EncryptOperation | openssl_basic.c:35:54:35:62 | Message | openssl_basic.c:40:13:40:31 | KeyOperationOutput | openssl_basic.c:23:62:23:65 | Key | openssl_basic.c:23:68:23:71 | Nonce | openssl_basic.c:23:37:23:51 | KeyOperationAlgorithm | Encrypt |
|
| openssl_basic.c:40:13:40:31 | EncryptOperation | openssl_basic.c:35:54:35:62 | Message | openssl_basic.c:35:36:35:45 | KeyOperationOutput | openssl_basic.c:23:62:23:65 | Key | openssl_basic.c:23:68:23:71 | Nonce | openssl_basic.c:23:37:23:51 | KeyOperationAlgorithm | Encrypt |
|
||||||
| openssl_basic.c:40:13:40:31 | EncryptOperation | openssl_basic.c:35:54:35:62 | Message | openssl_basic.c:40:13:40:31 | KeyOperationOutput | openssl_basic.c:23:62:23:65 | Key | openssl_basic.c:31:54:31:55 | Nonce | openssl_basic.c:23:37:23:51 | KeyOperationAlgorithm | Encrypt |
|
| openssl_basic.c:40:13:40:31 | EncryptOperation | openssl_basic.c:35:54:35:62 | Message | openssl_basic.c:35:36:35:45 | KeyOperationOutput | openssl_basic.c:23:62:23:65 | Key | openssl_basic.c:31:54:31:55 | Nonce | openssl_basic.c:23:37:23:51 | KeyOperationAlgorithm | Encrypt |
|
||||||
| openssl_basic.c:40:13:40:31 | EncryptOperation | openssl_basic.c:35:54:35:62 | Message | openssl_basic.c:40:13:40:31 | KeyOperationOutput | openssl_basic.c:31:49:31:51 | Key | openssl_basic.c:23:68:23:71 | Nonce | openssl_basic.c:23:37:23:51 | KeyOperationAlgorithm | Encrypt |
|
| openssl_basic.c:40:13:40:31 | EncryptOperation | openssl_basic.c:35:54:35:62 | Message | openssl_basic.c:35:36:35:45 | KeyOperationOutput | openssl_basic.c:31:49:31:51 | Key | openssl_basic.c:23:68:23:71 | Nonce | openssl_basic.c:23:37:23:51 | KeyOperationAlgorithm | Encrypt |
|
||||||
| openssl_basic.c:40:13:40:31 | EncryptOperation | openssl_basic.c:35:54:35:62 | Message | openssl_basic.c:40:13:40:31 | KeyOperationOutput | openssl_basic.c:31:49:31:51 | Key | openssl_basic.c:31:54:31:55 | Nonce | openssl_basic.c:23:37:23:51 | KeyOperationAlgorithm | Encrypt |
|
| openssl_basic.c:40:13:40:31 | EncryptOperation | openssl_basic.c:35:54:35:62 | Message | openssl_basic.c:35:36:35:45 | KeyOperationOutput | openssl_basic.c:31:49:31:51 | Key | openssl_basic.c:31:54:31:55 | Nonce | openssl_basic.c:23:37:23:51 | KeyOperationAlgorithm | Encrypt |
|
||||||
| openssl_basic.c:90:11:90:29 | DecryptOperation | openssl_basic.c:81:49:81:58 | Message | openssl_basic.c:90:11:90:29 | KeyOperationOutput | openssl_basic.c:69:58:69:61 | Key | openssl_basic.c:69:64:69:67 | Nonce | openssl_basic.c:69:33:69:47 | KeyOperationAlgorithm | Decrypt |
|
| openssl_basic.c:40:13:40:31 | EncryptOperation | openssl_basic.c:35:54:35:62 | Message | openssl_basic.c:40:38:40:53 | KeyOperationOutput | openssl_basic.c:23:62:23:65 | Key | openssl_basic.c:23:68:23:71 | Nonce | openssl_basic.c:23:37:23:51 | KeyOperationAlgorithm | Encrypt |
|
||||||
| openssl_basic.c:90:11:90:29 | DecryptOperation | openssl_basic.c:81:49:81:58 | Message | openssl_basic.c:90:11:90:29 | KeyOperationOutput | openssl_basic.c:69:58:69:61 | Key | openssl_basic.c:77:50:77:51 | Nonce | openssl_basic.c:69:33:69:47 | KeyOperationAlgorithm | Decrypt |
|
| openssl_basic.c:40:13:40:31 | EncryptOperation | openssl_basic.c:35:54:35:62 | Message | openssl_basic.c:40:38:40:53 | KeyOperationOutput | openssl_basic.c:23:62:23:65 | Key | openssl_basic.c:31:54:31:55 | Nonce | openssl_basic.c:23:37:23:51 | KeyOperationAlgorithm | Encrypt |
|
||||||
| openssl_basic.c:90:11:90:29 | DecryptOperation | openssl_basic.c:81:49:81:58 | Message | openssl_basic.c:90:11:90:29 | KeyOperationOutput | openssl_basic.c:77:45:77:47 | Key | openssl_basic.c:69:64:69:67 | Nonce | openssl_basic.c:69:33:69:47 | KeyOperationAlgorithm | Decrypt |
|
| openssl_basic.c:40:13:40:31 | EncryptOperation | openssl_basic.c:35:54:35:62 | Message | openssl_basic.c:40:38:40:53 | KeyOperationOutput | openssl_basic.c:31:49:31:51 | Key | openssl_basic.c:23:68:23:71 | Nonce | openssl_basic.c:23:37:23:51 | KeyOperationAlgorithm | Encrypt |
|
||||||
| openssl_basic.c:90:11:90:29 | DecryptOperation | openssl_basic.c:81:49:81:58 | Message | openssl_basic.c:90:11:90:29 | KeyOperationOutput | openssl_basic.c:77:45:77:47 | Key | openssl_basic.c:77:50:77:51 | Nonce | openssl_basic.c:69:33:69:47 | KeyOperationAlgorithm | Decrypt |
|
| openssl_basic.c:40:13:40:31 | EncryptOperation | openssl_basic.c:35:54:35:62 | Message | openssl_basic.c:40:38:40:53 | KeyOperationOutput | openssl_basic.c:31:49:31:51 | Key | openssl_basic.c:31:54:31:55 | Nonce | openssl_basic.c:23:37:23:51 | KeyOperationAlgorithm | Encrypt |
|
||||||
|
| openssl_basic.c:90:11:90:29 | DecryptOperation | openssl_basic.c:81:49:81:58 | Message | openssl_basic.c:81:32:81:40 | KeyOperationOutput | openssl_basic.c:69:58:69:61 | Key | openssl_basic.c:69:64:69:67 | Nonce | openssl_basic.c:69:33:69:47 | KeyOperationAlgorithm | Decrypt |
|
||||||
|
| openssl_basic.c:90:11:90:29 | DecryptOperation | openssl_basic.c:81:49:81:58 | Message | openssl_basic.c:81:32:81:40 | KeyOperationOutput | openssl_basic.c:69:58:69:61 | Key | openssl_basic.c:77:50:77:51 | Nonce | openssl_basic.c:69:33:69:47 | KeyOperationAlgorithm | Decrypt |
|
||||||
|
| openssl_basic.c:90:11:90:29 | DecryptOperation | openssl_basic.c:81:49:81:58 | Message | openssl_basic.c:81:32:81:40 | KeyOperationOutput | openssl_basic.c:77:45:77:47 | Key | openssl_basic.c:69:64:69:67 | Nonce | openssl_basic.c:69:33:69:47 | KeyOperationAlgorithm | Decrypt |
|
||||||
|
| openssl_basic.c:90:11:90:29 | DecryptOperation | openssl_basic.c:81:49:81:58 | Message | openssl_basic.c:81:32:81:40 | KeyOperationOutput | openssl_basic.c:77:45:77:47 | Key | openssl_basic.c:77:50:77:51 | Nonce | openssl_basic.c:69:33:69:47 | KeyOperationAlgorithm | Decrypt |
|
||||||
|
| openssl_basic.c:90:11:90:29 | DecryptOperation | openssl_basic.c:81:49:81:58 | Message | openssl_basic.c:90:36:90:50 | KeyOperationOutput | openssl_basic.c:69:58:69:61 | Key | openssl_basic.c:69:64:69:67 | Nonce | openssl_basic.c:69:33:69:47 | KeyOperationAlgorithm | Decrypt |
|
||||||
|
| openssl_basic.c:90:11:90:29 | DecryptOperation | openssl_basic.c:81:49:81:58 | Message | openssl_basic.c:90:36:90:50 | KeyOperationOutput | openssl_basic.c:69:58:69:61 | Key | openssl_basic.c:77:50:77:51 | Nonce | openssl_basic.c:69:33:69:47 | KeyOperationAlgorithm | Decrypt |
|
||||||
|
| openssl_basic.c:90:11:90:29 | DecryptOperation | openssl_basic.c:81:49:81:58 | Message | openssl_basic.c:90:36:90:50 | KeyOperationOutput | openssl_basic.c:77:45:77:47 | Key | openssl_basic.c:69:64:69:67 | Nonce | openssl_basic.c:69:33:69:47 | KeyOperationAlgorithm | Decrypt |
|
||||||
|
| openssl_basic.c:90:11:90:29 | DecryptOperation | openssl_basic.c:81:49:81:58 | Message | openssl_basic.c:90:36:90:50 | KeyOperationOutput | openssl_basic.c:77:45:77:47 | Key | openssl_basic.c:77:50:77:51 | Nonce | openssl_basic.c:69:33:69:47 | KeyOperationAlgorithm | Decrypt |
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
| openssl_basic.c:124:13:124:30 | HashOperation | openssl_basic.c:124:13:124:30 | Digest | openssl_basic.c:116:38:116:47 | HashAlgorithm | openssl_basic.c:120:37:120:43 | Message |
|
| openssl_basic.c:124:13:124:30 | HashOperation | openssl_basic.c:124:39:124:44 | Digest | openssl_basic.c:116:38:116:47 | HashAlgorithm | openssl_basic.c:120:37:120:43 | Message |
|
||||||
| openssl_basic.c:144:13:144:22 | HashOperation | openssl_basic.c:144:13:144:22 | Digest | openssl_basic.c:144:67:144:73 | HashAlgorithm | openssl_basic.c:144:24:144:30 | Message |
|
| openssl_basic.c:144:13:144:22 | HashOperation | openssl_basic.c:144:46:144:51 | Digest | openssl_basic.c:144:67:144:73 | HashAlgorithm | openssl_basic.c:144:24:144:30 | Message |
|
||||||
|
|||||||
@@ -9,3 +9,6 @@
|
|||||||
| multi.c:5:27:5:36 | // Multi 3 | declaration of multi3 |
|
| multi.c:5:27:5:36 | // Multi 3 | declaration of multi3 |
|
||||||
| templates.cpp:3:3:3:8 | // Foo | declaration of foo |
|
| templates.cpp:3:3:3:8 | // Foo | declaration of foo |
|
||||||
| templates.cpp:7:3:7:8 | // Bar | definition of bar |
|
| templates.cpp:7:3:7:8 | // Bar | definition of bar |
|
||||||
|
| templates.cpp:16:3:16:20 | // using T::member | using member |
|
||||||
|
| templates.cpp:19:3:19:28 | // using T::nested::member | using member |
|
||||||
|
| templates.cpp:25:3:25:20 | // using T::member | using member |
|
||||||
|
|||||||
@@ -10,3 +10,18 @@ class Cl {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class Derived : public T {
|
||||||
|
// using T::member
|
||||||
|
using T::member;
|
||||||
|
|
||||||
|
// using T::nested::member
|
||||||
|
using T::nested::member;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class Base {
|
||||||
|
// using T::member
|
||||||
|
using T::member;
|
||||||
|
};
|
||||||
@@ -1,2 +1,2 @@
|
|||||||
| Bar::(unnamed namespace)::B | Bar::<unnamed>::B |
|
| Bar::(unnamed namespace)::B | Bar::<unnamed>::B |
|
||||||
| Foo::(unnamed namespace)::A | _ZN3Foo37_GLOBAL__N__13_funcdname_cpp_?AEv |
|
| Foo::(unnamed namespace)::A | _ZN35_INTERNAL_13_funcdname_cpp_?Foo37_GLOBAL__N__13_funcdname_cpp_?AEv |
|
||||||
|
|||||||
@@ -2,4 +2,8 @@ import cpp
|
|||||||
|
|
||||||
from Function f, ReturnStmt r
|
from Function f, ReturnStmt r
|
||||||
where r.getEnclosingFunction() = f
|
where r.getEnclosingFunction() = f
|
||||||
select f.getQualifiedName(), r.getExpr().getValue().regexpReplaceAll("_[0-9a-f]+AEv$", "_?AEv")
|
select f.getQualifiedName(),
|
||||||
|
r.getExpr()
|
||||||
|
.getValue()
|
||||||
|
.regexpReplaceAll("_[0-9a-f]+AEv$", "_?AEv")
|
||||||
|
.regexpReplaceAll("cpp_[0-9a-f]+Foo37_", "cpp_?Foo37_")
|
||||||
|
|||||||
@@ -58,6 +58,77 @@
|
|||||||
#-----| Type = [LongType] unsigned long
|
#-----| Type = [LongType] unsigned long
|
||||||
#-----| getParameter(1): [Parameter] (unnamed parameter 1)
|
#-----| getParameter(1): [Parameter] (unnamed parameter 1)
|
||||||
#-----| Type = [ScopedEnum] align_val_t
|
#-----| Type = [ScopedEnum] align_val_t
|
||||||
|
arm.cpp:
|
||||||
|
# 6| [TopLevelFunction] uint8x8_t vadd_u8(uint8x8_t, uint8x8_t)
|
||||||
|
# 6| <params>:
|
||||||
|
# 6| getParameter(0): [Parameter] a
|
||||||
|
# 6| Type = [CTypedefType] uint8x8_t
|
||||||
|
# 6| getParameter(1): [Parameter] b
|
||||||
|
# 6| Type = [CTypedefType] uint8x8_t
|
||||||
|
# 6| getEntryPoint(): [BlockStmt] { ... }
|
||||||
|
# 7| getStmt(0): [ReturnStmt] return ...
|
||||||
|
# 7| getExpr(): [AddExpr] ... + ...
|
||||||
|
# 7| Type = [GNUVectorType] __attribute((neon_vector_type(8))) unsigned char
|
||||||
|
# 7| ValueCategory = prvalue
|
||||||
|
# 7| getLeftOperand(): [VariableAccess] a
|
||||||
|
# 7| Type = [CTypedefType] uint8x8_t
|
||||||
|
# 7| ValueCategory = prvalue(load)
|
||||||
|
# 7| getRightOperand(): [VariableAccess] b
|
||||||
|
# 7| Type = [CTypedefType] uint8x8_t
|
||||||
|
# 7| ValueCategory = prvalue(load)
|
||||||
|
# 12| [TopLevelFunction] uint16x8_t __builtin_aarch64_uaddlv8qi_uuu(uint8x8_t, uint8x8_t)
|
||||||
|
# 12| <params>:
|
||||||
|
# 12| getParameter(0): [Parameter] (unnamed parameter 0)
|
||||||
|
# 12| Type = [CTypedefType] uint8x8_t
|
||||||
|
# 12| getParameter(1): [Parameter] (unnamed parameter 1)
|
||||||
|
# 12| Type = [CTypedefType] uint8x8_t
|
||||||
|
# 14| [TopLevelFunction] uint16x8_t vaddl_u8(uint8x8_t, uint8x8_t)
|
||||||
|
# 14| <params>:
|
||||||
|
# 14| getParameter(0): [Parameter] a
|
||||||
|
# 14| Type = [CTypedefType] uint8x8_t
|
||||||
|
# 14| getParameter(1): [Parameter] b
|
||||||
|
# 14| Type = [CTypedefType] uint8x8_t
|
||||||
|
# 14| getEntryPoint(): [BlockStmt] { ... }
|
||||||
|
# 15| getStmt(0): [ReturnStmt] return ...
|
||||||
|
# 15| getExpr(): [FunctionCall] call to __builtin_aarch64_uaddlv8qi_uuu
|
||||||
|
# 15| Type = [CTypedefType] uint16x8_t
|
||||||
|
# 15| ValueCategory = prvalue
|
||||||
|
# 15| getArgument(0): [VariableAccess] a
|
||||||
|
# 15| Type = [CTypedefType] uint8x8_t
|
||||||
|
# 15| ValueCategory = prvalue(load)
|
||||||
|
# 15| getArgument(1): [VariableAccess] b
|
||||||
|
# 15| Type = [CTypedefType] uint8x8_t
|
||||||
|
# 15| ValueCategory = prvalue(load)
|
||||||
|
# 18| [TopLevelFunction] uint16x8_t arm_add(uint8x8_t, uint8x8_t)
|
||||||
|
# 18| <params>:
|
||||||
|
# 18| getParameter(0): [Parameter] a
|
||||||
|
# 18| Type = [CTypedefType] uint8x8_t
|
||||||
|
# 18| getParameter(1): [Parameter] b
|
||||||
|
# 18| Type = [CTypedefType] uint8x8_t
|
||||||
|
# 18| getEntryPoint(): [BlockStmt] { ... }
|
||||||
|
# 19| getStmt(0): [DeclStmt] declaration
|
||||||
|
# 19| getDeclarationEntry(0): [VariableDeclarationEntry] definition of c
|
||||||
|
# 19| Type = [CTypedefType] uint8x8_t
|
||||||
|
# 19| getVariable().getInitializer(): [Initializer] initializer for c
|
||||||
|
# 19| getExpr(): [FunctionCall] call to vadd_u8
|
||||||
|
# 19| Type = [CTypedefType] uint8x8_t
|
||||||
|
# 19| ValueCategory = prvalue
|
||||||
|
# 19| getArgument(0): [VariableAccess] a
|
||||||
|
# 19| Type = [CTypedefType] uint8x8_t
|
||||||
|
# 19| ValueCategory = prvalue(load)
|
||||||
|
# 19| getArgument(1): [VariableAccess] b
|
||||||
|
# 19| Type = [CTypedefType] uint8x8_t
|
||||||
|
# 19| ValueCategory = prvalue(load)
|
||||||
|
# 20| getStmt(1): [ReturnStmt] return ...
|
||||||
|
# 20| getExpr(): [FunctionCall] call to vaddl_u8
|
||||||
|
# 20| Type = [CTypedefType] uint16x8_t
|
||||||
|
# 20| ValueCategory = prvalue
|
||||||
|
# 20| getArgument(0): [VariableAccess] a
|
||||||
|
# 20| Type = [CTypedefType] uint8x8_t
|
||||||
|
# 20| ValueCategory = prvalue(load)
|
||||||
|
# 20| getArgument(1): [VariableAccess] c
|
||||||
|
# 20| Type = [CTypedefType] uint8x8_t
|
||||||
|
# 20| ValueCategory = prvalue(load)
|
||||||
bad_asts.cpp:
|
bad_asts.cpp:
|
||||||
# 5| [CopyAssignmentOperator] Bad::S& Bad::S::operator=(Bad::S const&)
|
# 5| [CopyAssignmentOperator] Bad::S& Bad::S::operator=(Bad::S const&)
|
||||||
# 5| <params>:
|
# 5| <params>:
|
||||||
@@ -23814,11 +23885,11 @@ ir.cpp:
|
|||||||
# 2692| Conversion = [IntegralConversion] integral conversion
|
# 2692| Conversion = [IntegralConversion] integral conversion
|
||||||
# 2692| Type = [LongType] unsigned long
|
# 2692| Type = [LongType] unsigned long
|
||||||
# 2692| ValueCategory = prvalue
|
# 2692| ValueCategory = prvalue
|
||||||
#-----| getExpr().getFullyConverted(): [CStyleCast] (int)...
|
# 2692| getExpr().getFullyConverted(): [CStyleCast] (int)...
|
||||||
#-----| Conversion = [IntegralConversion] integral conversion
|
# 2692| Conversion = [IntegralConversion] integral conversion
|
||||||
#-----| Type = [IntType] int
|
# 2692| Type = [IntType] int
|
||||||
#-----| Value = [CStyleCast] 1
|
# 2692| Value = [CStyleCast] 1
|
||||||
#-----| ValueCategory = prvalue
|
# 2692| ValueCategory = prvalue
|
||||||
# 2693| getStmt(1): [ReturnStmt] return ...
|
# 2693| getStmt(1): [ReturnStmt] return ...
|
||||||
# 2693| getExpr(): [VariableAccess] y
|
# 2693| getExpr(): [VariableAccess] y
|
||||||
# 2693| Type = [IntType] int
|
# 2693| Type = [IntType] int
|
||||||
|
|||||||
@@ -1,3 +1,86 @@
|
|||||||
|
arm.cpp:
|
||||||
|
# 6| uint8x8_t vadd_u8(uint8x8_t, uint8x8_t)
|
||||||
|
# 6| Block 0
|
||||||
|
# 6| v6_1(void) = EnterFunction :
|
||||||
|
# 6| m6_2(unknown) = AliasedDefinition :
|
||||||
|
# 6| m6_3(unknown) = InitializeNonLocal :
|
||||||
|
# 6| m6_4(unknown) = Chi : total:m6_2, partial:m6_3
|
||||||
|
# 6| r6_5(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] :
|
||||||
|
# 6| m6_6(__attribute((neon_vector_type(8))) unsigned char) = InitializeParameter[a] : &:r6_5
|
||||||
|
# 6| r6_7(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[b] :
|
||||||
|
# 6| m6_8(__attribute((neon_vector_type(8))) unsigned char) = InitializeParameter[b] : &:r6_7
|
||||||
|
# 7| r7_1(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[#return] :
|
||||||
|
# 7| r7_2(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] :
|
||||||
|
# 7| r7_3(__attribute((neon_vector_type(8))) unsigned char) = Load[a] : &:r7_2, m6_6
|
||||||
|
# 7| r7_4(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[b] :
|
||||||
|
# 7| r7_5(__attribute((neon_vector_type(8))) unsigned char) = Load[b] : &:r7_4, m6_8
|
||||||
|
# 7| r7_6(__attribute((neon_vector_type(8))) unsigned char) = Add : r7_3, r7_5
|
||||||
|
# 7| m7_7(__attribute((neon_vector_type(8))) unsigned char) = Store[#return] : &:r7_1, r7_6
|
||||||
|
# 6| r6_9(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[#return] :
|
||||||
|
# 6| v6_10(void) = ReturnValue : &:r6_9, m7_7
|
||||||
|
# 6| v6_11(void) = AliasedUse : m6_3
|
||||||
|
# 6| v6_12(void) = ExitFunction :
|
||||||
|
|
||||||
|
# 14| uint16x8_t vaddl_u8(uint8x8_t, uint8x8_t)
|
||||||
|
# 14| Block 0
|
||||||
|
# 14| v14_1(void) = EnterFunction :
|
||||||
|
# 14| m14_2(unknown) = AliasedDefinition :
|
||||||
|
# 14| m14_3(unknown) = InitializeNonLocal :
|
||||||
|
# 14| m14_4(unknown) = Chi : total:m14_2, partial:m14_3
|
||||||
|
# 14| r14_5(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] :
|
||||||
|
# 14| m14_6(__attribute((neon_vector_type(8))) unsigned char) = InitializeParameter[a] : &:r14_5
|
||||||
|
# 14| r14_7(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[b] :
|
||||||
|
# 14| m14_8(__attribute((neon_vector_type(8))) unsigned char) = InitializeParameter[b] : &:r14_7
|
||||||
|
# 15| r15_1(glval<__attribute((neon_vector_type(8))) unsigned short>) = VariableAddress[#return] :
|
||||||
|
# 15| r15_2(glval<unknown>) = FunctionAddress[__builtin_aarch64_uaddlv8qi_uuu] :
|
||||||
|
# 15| r15_3(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] :
|
||||||
|
# 15| r15_4(__attribute((neon_vector_type(8))) unsigned char) = Load[a] : &:r15_3, m14_6
|
||||||
|
# 15| r15_5(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[b] :
|
||||||
|
# 15| r15_6(__attribute((neon_vector_type(8))) unsigned char) = Load[b] : &:r15_5, m14_8
|
||||||
|
# 15| r15_7(__attribute((neon_vector_type(8))) unsigned short) = Call[__builtin_aarch64_uaddlv8qi_uuu] : func:r15_2, 0:r15_4, 1:r15_6
|
||||||
|
# 15| m15_8(unknown) = ^CallSideEffect : ~m14_4
|
||||||
|
# 15| m15_9(unknown) = Chi : total:m14_4, partial:m15_8
|
||||||
|
# 15| m15_10(__attribute((neon_vector_type(8))) unsigned short) = Store[#return] : &:r15_1, r15_7
|
||||||
|
# 14| r14_9(glval<__attribute((neon_vector_type(8))) unsigned short>) = VariableAddress[#return] :
|
||||||
|
# 14| v14_10(void) = ReturnValue : &:r14_9, m15_10
|
||||||
|
# 14| v14_11(void) = AliasedUse : ~m15_9
|
||||||
|
# 14| v14_12(void) = ExitFunction :
|
||||||
|
|
||||||
|
# 18| uint16x8_t arm_add(uint8x8_t, uint8x8_t)
|
||||||
|
# 18| Block 0
|
||||||
|
# 18| v18_1(void) = EnterFunction :
|
||||||
|
# 18| m18_2(unknown) = AliasedDefinition :
|
||||||
|
# 18| m18_3(unknown) = InitializeNonLocal :
|
||||||
|
# 18| m18_4(unknown) = Chi : total:m18_2, partial:m18_3
|
||||||
|
# 18| r18_5(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] :
|
||||||
|
# 18| m18_6(__attribute((neon_vector_type(8))) unsigned char) = InitializeParameter[a] : &:r18_5
|
||||||
|
# 18| r18_7(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[b] :
|
||||||
|
# 18| m18_8(__attribute((neon_vector_type(8))) unsigned char) = InitializeParameter[b] : &:r18_7
|
||||||
|
# 19| r19_1(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[c] :
|
||||||
|
# 19| r19_2(glval<unknown>) = FunctionAddress[vadd_u8] :
|
||||||
|
# 19| r19_3(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] :
|
||||||
|
# 19| r19_4(__attribute((neon_vector_type(8))) unsigned char) = Load[a] : &:r19_3, m18_6
|
||||||
|
# 19| r19_5(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[b] :
|
||||||
|
# 19| r19_6(__attribute((neon_vector_type(8))) unsigned char) = Load[b] : &:r19_5, m18_8
|
||||||
|
# 19| r19_7(__attribute((neon_vector_type(8))) unsigned char) = Call[vadd_u8] : func:r19_2, 0:r19_4, 1:r19_6
|
||||||
|
# 19| m19_8(unknown) = ^CallSideEffect : ~m18_4
|
||||||
|
# 19| m19_9(unknown) = Chi : total:m18_4, partial:m19_8
|
||||||
|
# 19| m19_10(__attribute((neon_vector_type(8))) unsigned char) = Store[c] : &:r19_1, r19_7
|
||||||
|
# 20| r20_1(glval<__attribute((neon_vector_type(8))) unsigned short>) = VariableAddress[#return] :
|
||||||
|
# 20| r20_2(glval<unknown>) = FunctionAddress[vaddl_u8] :
|
||||||
|
# 20| r20_3(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] :
|
||||||
|
# 20| r20_4(__attribute((neon_vector_type(8))) unsigned char) = Load[a] : &:r20_3, m18_6
|
||||||
|
# 20| r20_5(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[c] :
|
||||||
|
# 20| r20_6(__attribute((neon_vector_type(8))) unsigned char) = Load[c] : &:r20_5, m19_10
|
||||||
|
# 20| r20_7(__attribute((neon_vector_type(8))) unsigned short) = Call[vaddl_u8] : func:r20_2, 0:r20_4, 1:r20_6
|
||||||
|
# 20| m20_8(unknown) = ^CallSideEffect : ~m19_9
|
||||||
|
# 20| m20_9(unknown) = Chi : total:m19_9, partial:m20_8
|
||||||
|
# 20| m20_10(__attribute((neon_vector_type(8))) unsigned short) = Store[#return] : &:r20_1, r20_7
|
||||||
|
# 18| r18_9(glval<__attribute((neon_vector_type(8))) unsigned short>) = VariableAddress[#return] :
|
||||||
|
# 18| v18_10(void) = ReturnValue : &:r18_9, m20_10
|
||||||
|
# 18| v18_11(void) = AliasedUse : ~m20_9
|
||||||
|
# 18| v18_12(void) = ExitFunction :
|
||||||
|
|
||||||
bad_asts.cpp:
|
bad_asts.cpp:
|
||||||
# 9| int Bad::S::MemberFunction<int 6>(int)
|
# 9| int Bad::S::MemberFunction<int 6>(int)
|
||||||
# 9| Block 0
|
# 9| Block 0
|
||||||
@@ -19457,11 +19540,11 @@ ir.cpp:
|
|||||||
# 2691| m2691_3(unknown) = InitializeNonLocal :
|
# 2691| m2691_3(unknown) = InitializeNonLocal :
|
||||||
# 2691| m2691_4(unknown) = Chi : total:m2691_2, partial:m2691_3
|
# 2691| m2691_4(unknown) = Chi : total:m2691_2, partial:m2691_3
|
||||||
# 2692| r2692_1(glval<int>) = VariableAddress[y] :
|
# 2692| r2692_1(glval<int>) = VariableAddress[y] :
|
||||||
#-----| r0_1(int) = Constant[1] :
|
# 2692| r2692_2(int) = Constant[1] :
|
||||||
#-----| m0_2(int) = Store[y] : &:r2692_1, r0_1
|
# 2692| m2692_3(int) = Store[y] : &:r2692_1, r2692_2
|
||||||
# 2693| r2693_1(glval<int>) = VariableAddress[#return] :
|
# 2693| r2693_1(glval<int>) = VariableAddress[#return] :
|
||||||
# 2693| r2693_2(glval<int>) = VariableAddress[y] :
|
# 2693| r2693_2(glval<int>) = VariableAddress[y] :
|
||||||
# 2693| r2693_3(int) = Load[y] : &:r2693_2, m0_2
|
# 2693| r2693_3(int) = Load[y] : &:r2693_2, m2692_3
|
||||||
# 2693| m2693_4(int) = Store[#return] : &:r2693_1, r2693_3
|
# 2693| m2693_4(int) = Store[#return] : &:r2693_1, r2693_3
|
||||||
# 2691| r2691_5(glval<int>) = VariableAddress[#return] :
|
# 2691| r2691_5(glval<int>) = VariableAddress[#return] :
|
||||||
# 2691| v2691_6(void) = ReturnValue : &:r2691_5, m2693_4
|
# 2691| v2691_6(void) = ReturnValue : &:r2691_5, m2693_4
|
||||||
|
|||||||
21
cpp/ql/test/library-tests/ir/ir/arm.cpp
Normal file
21
cpp/ql/test/library-tests/ir/ir/arm.cpp
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
// semmle-extractor-options: --edg --target --edg linux_arm64
|
||||||
|
|
||||||
|
typedef __Uint8x8_t uint8x8_t;
|
||||||
|
typedef __Uint16x8_t uint16x8_t;
|
||||||
|
|
||||||
|
uint8x8_t vadd_u8(uint8x8_t a, uint8x8_t b) {
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Workaround: the frontend only exposes this when the arm_neon.h
|
||||||
|
// header is encountered.
|
||||||
|
uint16x8_t __builtin_aarch64_uaddlv8qi_uuu(uint8x8_t, uint8x8_t);
|
||||||
|
|
||||||
|
uint16x8_t vaddl_u8(uint8x8_t a, uint8x8_t b) {
|
||||||
|
return __builtin_aarch64_uaddlv8qi_uuu (a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16x8_t arm_add(uint8x8_t a, uint8x8_t b) {
|
||||||
|
uint8x8_t c = vadd_u8(a, b);
|
||||||
|
return vaddl_u8(a, c);
|
||||||
|
}
|
||||||
@@ -1,3 +1,80 @@
|
|||||||
|
arm.cpp:
|
||||||
|
# 6| uint8x8_t vadd_u8(uint8x8_t, uint8x8_t)
|
||||||
|
# 6| Block 0
|
||||||
|
# 6| v6_1(void) = EnterFunction :
|
||||||
|
# 6| mu6_2(unknown) = AliasedDefinition :
|
||||||
|
# 6| mu6_3(unknown) = InitializeNonLocal :
|
||||||
|
# 6| r6_4(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] :
|
||||||
|
# 6| mu6_5(__attribute((neon_vector_type(8))) unsigned char) = InitializeParameter[a] : &:r6_4
|
||||||
|
# 6| r6_6(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[b] :
|
||||||
|
# 6| mu6_7(__attribute((neon_vector_type(8))) unsigned char) = InitializeParameter[b] : &:r6_6
|
||||||
|
# 7| r7_1(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[#return] :
|
||||||
|
# 7| r7_2(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] :
|
||||||
|
# 7| r7_3(__attribute((neon_vector_type(8))) unsigned char) = Load[a] : &:r7_2, ~m?
|
||||||
|
# 7| r7_4(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[b] :
|
||||||
|
# 7| r7_5(__attribute((neon_vector_type(8))) unsigned char) = Load[b] : &:r7_4, ~m?
|
||||||
|
# 7| r7_6(__attribute((neon_vector_type(8))) unsigned char) = Add : r7_3, r7_5
|
||||||
|
# 7| mu7_7(__attribute((neon_vector_type(8))) unsigned char) = Store[#return] : &:r7_1, r7_6
|
||||||
|
# 6| r6_8(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[#return] :
|
||||||
|
# 6| v6_9(void) = ReturnValue : &:r6_8, ~m?
|
||||||
|
# 6| v6_10(void) = AliasedUse : ~m?
|
||||||
|
# 6| v6_11(void) = ExitFunction :
|
||||||
|
|
||||||
|
# 14| uint16x8_t vaddl_u8(uint8x8_t, uint8x8_t)
|
||||||
|
# 14| Block 0
|
||||||
|
# 14| v14_1(void) = EnterFunction :
|
||||||
|
# 14| mu14_2(unknown) = AliasedDefinition :
|
||||||
|
# 14| mu14_3(unknown) = InitializeNonLocal :
|
||||||
|
# 14| r14_4(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] :
|
||||||
|
# 14| mu14_5(__attribute((neon_vector_type(8))) unsigned char) = InitializeParameter[a] : &:r14_4
|
||||||
|
# 14| r14_6(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[b] :
|
||||||
|
# 14| mu14_7(__attribute((neon_vector_type(8))) unsigned char) = InitializeParameter[b] : &:r14_6
|
||||||
|
# 15| r15_1(glval<__attribute((neon_vector_type(8))) unsigned short>) = VariableAddress[#return] :
|
||||||
|
# 15| r15_2(glval<unknown>) = FunctionAddress[__builtin_aarch64_uaddlv8qi_uuu] :
|
||||||
|
# 15| r15_3(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] :
|
||||||
|
# 15| r15_4(__attribute((neon_vector_type(8))) unsigned char) = Load[a] : &:r15_3, ~m?
|
||||||
|
# 15| r15_5(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[b] :
|
||||||
|
# 15| r15_6(__attribute((neon_vector_type(8))) unsigned char) = Load[b] : &:r15_5, ~m?
|
||||||
|
# 15| r15_7(__attribute((neon_vector_type(8))) unsigned short) = Call[__builtin_aarch64_uaddlv8qi_uuu] : func:r15_2, 0:r15_4, 1:r15_6
|
||||||
|
# 15| mu15_8(unknown) = ^CallSideEffect : ~m?
|
||||||
|
# 15| mu15_9(__attribute((neon_vector_type(8))) unsigned short) = Store[#return] : &:r15_1, r15_7
|
||||||
|
# 14| r14_8(glval<__attribute((neon_vector_type(8))) unsigned short>) = VariableAddress[#return] :
|
||||||
|
# 14| v14_9(void) = ReturnValue : &:r14_8, ~m?
|
||||||
|
# 14| v14_10(void) = AliasedUse : ~m?
|
||||||
|
# 14| v14_11(void) = ExitFunction :
|
||||||
|
|
||||||
|
# 18| uint16x8_t arm_add(uint8x8_t, uint8x8_t)
|
||||||
|
# 18| Block 0
|
||||||
|
# 18| v18_1(void) = EnterFunction :
|
||||||
|
# 18| mu18_2(unknown) = AliasedDefinition :
|
||||||
|
# 18| mu18_3(unknown) = InitializeNonLocal :
|
||||||
|
# 18| r18_4(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] :
|
||||||
|
# 18| mu18_5(__attribute((neon_vector_type(8))) unsigned char) = InitializeParameter[a] : &:r18_4
|
||||||
|
# 18| r18_6(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[b] :
|
||||||
|
# 18| mu18_7(__attribute((neon_vector_type(8))) unsigned char) = InitializeParameter[b] : &:r18_6
|
||||||
|
# 19| r19_1(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[c] :
|
||||||
|
# 19| r19_2(glval<unknown>) = FunctionAddress[vadd_u8] :
|
||||||
|
# 19| r19_3(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] :
|
||||||
|
# 19| r19_4(__attribute((neon_vector_type(8))) unsigned char) = Load[a] : &:r19_3, ~m?
|
||||||
|
# 19| r19_5(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[b] :
|
||||||
|
# 19| r19_6(__attribute((neon_vector_type(8))) unsigned char) = Load[b] : &:r19_5, ~m?
|
||||||
|
# 19| r19_7(__attribute((neon_vector_type(8))) unsigned char) = Call[vadd_u8] : func:r19_2, 0:r19_4, 1:r19_6
|
||||||
|
# 19| mu19_8(unknown) = ^CallSideEffect : ~m?
|
||||||
|
# 19| mu19_9(__attribute((neon_vector_type(8))) unsigned char) = Store[c] : &:r19_1, r19_7
|
||||||
|
# 20| r20_1(glval<__attribute((neon_vector_type(8))) unsigned short>) = VariableAddress[#return] :
|
||||||
|
# 20| r20_2(glval<unknown>) = FunctionAddress[vaddl_u8] :
|
||||||
|
# 20| r20_3(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] :
|
||||||
|
# 20| r20_4(__attribute((neon_vector_type(8))) unsigned char) = Load[a] : &:r20_3, ~m?
|
||||||
|
# 20| r20_5(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[c] :
|
||||||
|
# 20| r20_6(__attribute((neon_vector_type(8))) unsigned char) = Load[c] : &:r20_5, ~m?
|
||||||
|
# 20| r20_7(__attribute((neon_vector_type(8))) unsigned short) = Call[vaddl_u8] : func:r20_2, 0:r20_4, 1:r20_6
|
||||||
|
# 20| mu20_8(unknown) = ^CallSideEffect : ~m?
|
||||||
|
# 20| mu20_9(__attribute((neon_vector_type(8))) unsigned short) = Store[#return] : &:r20_1, r20_7
|
||||||
|
# 18| r18_8(glval<__attribute((neon_vector_type(8))) unsigned short>) = VariableAddress[#return] :
|
||||||
|
# 18| v18_9(void) = ReturnValue : &:r18_8, ~m?
|
||||||
|
# 18| v18_10(void) = AliasedUse : ~m?
|
||||||
|
# 18| v18_11(void) = ExitFunction :
|
||||||
|
|
||||||
bad_asts.cpp:
|
bad_asts.cpp:
|
||||||
# 9| int Bad::S::MemberFunction<int 6>(int)
|
# 9| int Bad::S::MemberFunction<int 6>(int)
|
||||||
# 9| Block 0
|
# 9| Block 0
|
||||||
@@ -17775,8 +17852,8 @@ ir.cpp:
|
|||||||
# 2691| mu2691_2(unknown) = AliasedDefinition :
|
# 2691| mu2691_2(unknown) = AliasedDefinition :
|
||||||
# 2691| mu2691_3(unknown) = InitializeNonLocal :
|
# 2691| mu2691_3(unknown) = InitializeNonLocal :
|
||||||
# 2692| r2692_1(glval<int>) = VariableAddress[y] :
|
# 2692| r2692_1(glval<int>) = VariableAddress[y] :
|
||||||
#-----| r0_1(int) = Constant[1] :
|
# 2692| r2692_2(int) = Constant[1] :
|
||||||
#-----| mu0_2(int) = Store[y] : &:r2692_1, r0_1
|
# 2692| mu2692_3(int) = Store[y] : &:r2692_1, r2692_2
|
||||||
# 2693| r2693_1(glval<int>) = VariableAddress[#return] :
|
# 2693| r2693_1(glval<int>) = VariableAddress[#return] :
|
||||||
# 2693| r2693_2(glval<int>) = VariableAddress[y] :
|
# 2693| r2693_2(glval<int>) = VariableAddress[y] :
|
||||||
# 2693| r2693_3(int) = Load[y] : &:r2693_2, ~m?
|
# 2693| r2693_3(int) = Load[y] : &:r2693_2, ~m?
|
||||||
|
|||||||
@@ -1011,10 +1011,10 @@ void test_overflow() {
|
|||||||
range(x); // $ range===2147483647
|
range(x); // $ range===2147483647
|
||||||
const int y = 256;
|
const int y = 256;
|
||||||
range(y); // $ range===256
|
range(y); // $ range===256
|
||||||
if ((x + y) <= 512) {
|
if ((x + y) <= 512) { // $ overflow=+
|
||||||
range(x); // $ range===2147483647
|
range(x); // $ range===2147483647
|
||||||
range(y); // $ range===256
|
range(y); // $ range===256
|
||||||
range(x + y); // $ range===-2147483393
|
range(x + y); // $ range=<=2147483903 overflow=+
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
| parameters.cpp:2:5:2:23 | [...](...){...} | with list | 2 |
|
||||||
|
| parameters.cpp:4:5:4:22 | [...](...){...} | with list | 1 |
|
||||||
|
| parameters.cpp:6:5:6:17 | [...](...){...} | with list | 1 |
|
||||||
|
| parameters.cpp:8:5:8:20 | [...](...){...} | with list | 0 |
|
||||||
|
| parameters.cpp:10:5:10:26 | [...](...){...} | with list | 0 |
|
||||||
|
| parameters.cpp:11:5:11:24 | [...](...){...} | without list | 0 |
|
||||||
|
| parameters.cpp:13:5:13:20 | [...](...){...} | with list | 0 |
|
||||||
|
| parameters.cpp:16:5:18:5 | [...](...){...} | with list | 0 |
|
||||||
|
| parameters.cpp:20:5:22:5 | [...](...){...} | without list | 0 |
|
||||||
|
| parameters.cpp:24:5:24:10 | [...](...){...} | without list | 0 |
|
||||||
|
| parameters.cpp:25:5:25:14 | [...](...){...} | with list | 0 |
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import cpp
|
||||||
|
|
||||||
|
from LambdaExpression e, string parameterList
|
||||||
|
where if e.hasParameterList() then parameterList = "with list" else parameterList = "without list"
|
||||||
|
select e, parameterList, e.getLambdaFunction().getNumberOfParameters()
|
||||||
26
cpp/ql/test/library-tests/lambdas/syntax/parameters.cpp
Normal file
26
cpp/ql/test/library-tests/lambdas/syntax/parameters.cpp
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
void test_lambda_declarator() {
|
||||||
|
[=](int, float) { };
|
||||||
|
|
||||||
|
[](int x = 42) { };
|
||||||
|
|
||||||
|
[](int x) { };
|
||||||
|
|
||||||
|
[]() mutable { };
|
||||||
|
|
||||||
|
[]() [[nodiscard]] { };
|
||||||
|
[] [[nodiscard]] { };
|
||||||
|
|
||||||
|
[]() -> void { };
|
||||||
|
|
||||||
|
int i;
|
||||||
|
[&i]() {
|
||||||
|
i += 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
[&i] {
|
||||||
|
i += 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
[] { };
|
||||||
|
[=] () { };
|
||||||
|
}
|
||||||
@@ -1,4 +1,10 @@
|
|||||||
uniqueEnclosingCallable
|
uniqueEnclosingCallable
|
||||||
|
| builtin.c:14:3:14:16 | ... * ... | Node should have one enclosing callable but has 0. |
|
||||||
|
| builtin.c:14:3:14:16 | sizeof(int) | Node should have one enclosing callable but has 0. |
|
||||||
|
| builtin.c:14:10:14:10 | 4 | Node should have one enclosing callable but has 0. |
|
||||||
|
| builtin.c:15:3:15:16 | ... * ... | Node should have one enclosing callable but has 0. |
|
||||||
|
| builtin.c:15:3:15:16 | sizeof(int) | Node should have one enclosing callable but has 0. |
|
||||||
|
| builtin.c:15:10:15:10 | 4 | Node should have one enclosing callable but has 0. |
|
||||||
| enum.c:2:6:2:6 | 1 | Node should have one enclosing callable but has 0. |
|
| enum.c:2:6:2:6 | 1 | Node should have one enclosing callable but has 0. |
|
||||||
| enum.c:2:6:2:10 | ... + ... | Node should have one enclosing callable but has 0. |
|
| enum.c:2:6:2:10 | ... + ... | Node should have one enclosing callable but has 0. |
|
||||||
| enum.c:2:10:2:10 | 1 | Node should have one enclosing callable but has 0. |
|
| enum.c:2:10:2:10 | 1 | Node should have one enclosing callable but has 0. |
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
| test.cpp:3:8:3:8 | C<1> | 0 | int | test.cpp:5:25:5:25 | 1 | 1 |
|
| test.cpp:3:8:3:8 | C<1> | 0 | int | test.cpp:6:3:6:6 | one1 | 1 |
|
||||||
| test.cpp:3:8:3:8 | C<2> | 0 | int | file://:0:0:0:0 | 2 | 2 |
|
| test.cpp:3:8:3:8 | C<2> | 0 | int | test.cpp:7:3:7:13 | ... + ... | 2 |
|
||||||
| test.cpp:3:8:3:8 | C<x> | 0 | int | file://:0:0:0:0 | x | x |
|
| test.cpp:3:8:3:8 | C<x> | 0 | int | file://:0:0:0:0 | x | x |
|
||||||
| test.cpp:10:8:10:8 | D<T, X> | 0 | <none> | test.cpp:9:19:9:19 | T | <none> |
|
| test.cpp:10:8:10:8 | D<T, X> | 0 | <none> | test.cpp:9:19:9:19 | T | <none> |
|
||||||
| test.cpp:10:8:10:8 | D<T, X> | 1 | T | file://:0:0:0:0 | X | X |
|
| test.cpp:10:8:10:8 | D<T, X> | 1 | T | file://:0:0:0:0 | X | X |
|
||||||
| test.cpp:10:8:10:8 | D<int, 2> | 0 | <none> | file://:0:0:0:0 | int | <none> |
|
| test.cpp:10:8:10:8 | D<int, 2> | 0 | <none> | file://:0:0:0:0 | int | <none> |
|
||||||
| test.cpp:10:8:10:8 | D<int, 2> | 1 | int | test.cpp:12:8:12:8 | 2 | 2 |
|
| test.cpp:10:8:10:8 | D<int, 2> | 1 | int | test.cpp:12:8:12:8 | 2 | 2 |
|
||||||
| test.cpp:10:8:10:8 | D<long, 2L> | 0 | <none> | file://:0:0:0:0 | long | <none> |
|
| test.cpp:10:8:10:8 | D<long, 2L> | 0 | <none> | file://:0:0:0:0 | long | <none> |
|
||||||
| test.cpp:10:8:10:8 | D<long, 2L> | 1 | long | file://:0:0:0:0 | 2 | 2 |
|
| test.cpp:10:8:10:8 | D<long, 2L> | 1 | long | test.cpp:13:9:13:9 | 2 | 2 |
|
||||||
| test.cpp:16:8:16:8 | E<T, X> | 0 | <none> | test.cpp:15:19:15:19 | T | <none> |
|
| test.cpp:16:8:16:8 | E<T, X> | 0 | <none> | test.cpp:15:19:15:19 | T | <none> |
|
||||||
| test.cpp:16:8:16:8 | E<T, X> | 1 | T * | file://:0:0:0:0 | X | X |
|
| test.cpp:16:8:16:8 | E<T, X> | 1 | T * | file://:0:0:0:0 | X | X |
|
||||||
| test.cpp:16:8:16:8 | E<int, (int *)nullptr> | 0 | <none> | file://:0:0:0:0 | int | <none> |
|
| test.cpp:16:8:16:8 | E<int, (int *)nullptr> | 0 | <none> | file://:0:0:0:0 | int | <none> |
|
||||||
| test.cpp:16:8:16:8 | E<int, (int *)nullptr> | 1 | int * | file://:0:0:0:0 | 0 | 0 |
|
| test.cpp:16:8:16:8 | E<int, (int *)nullptr> | 1 | int * | test.cpp:18:8:18:14 | 0 | 0 |
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
| file://:0:0:0:0 | __float128 |
|
| file://:0:0:0:0 | __float128 |
|
||||||
| file://:0:0:0:0 | __fp16 |
|
| file://:0:0:0:0 | __fp16 |
|
||||||
| file://:0:0:0:0 | __int128 |
|
| file://:0:0:0:0 | __int128 |
|
||||||
|
| file://:0:0:0:0 | __mfp8 |
|
||||||
| file://:0:0:0:0 | __va_list_tag |
|
| file://:0:0:0:0 | __va_list_tag |
|
||||||
| file://:0:0:0:0 | __va_list_tag & |
|
| file://:0:0:0:0 | __va_list_tag & |
|
||||||
| file://:0:0:0:0 | __va_list_tag && |
|
| file://:0:0:0:0 | __va_list_tag && |
|
||||||
|
|||||||
@@ -46,6 +46,7 @@
|
|||||||
| file://:0:0:0:0 | __float128 | 16 |
|
| file://:0:0:0:0 | __float128 | 16 |
|
||||||
| file://:0:0:0:0 | __fp16 | 2 |
|
| file://:0:0:0:0 | __fp16 | 2 |
|
||||||
| file://:0:0:0:0 | __int128 | 16 |
|
| file://:0:0:0:0 | __int128 | 16 |
|
||||||
|
| file://:0:0:0:0 | __mfp8 | 1 |
|
||||||
| file://:0:0:0:0 | __va_list_tag | 24 |
|
| file://:0:0:0:0 | __va_list_tag | 24 |
|
||||||
| file://:0:0:0:0 | __va_list_tag & | 8 |
|
| file://:0:0:0:0 | __va_list_tag & | 8 |
|
||||||
| file://:0:0:0:0 | __va_list_tag && | 8 |
|
| file://:0:0:0:0 | __va_list_tag && | 8 |
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
| file://:0:0:0:0 | __float128 | __float128 |
|
| file://:0:0:0:0 | __float128 | __float128 |
|
||||||
| file://:0:0:0:0 | __fp16 | __fp16 |
|
| file://:0:0:0:0 | __fp16 | __fp16 |
|
||||||
| file://:0:0:0:0 | __int128 | __int128 |
|
| file://:0:0:0:0 | __int128 | __int128 |
|
||||||
|
| file://:0:0:0:0 | __mfp8 | __mfp8 |
|
||||||
| file://:0:0:0:0 | __va_list_tag & | __va_list_tag & |
|
| file://:0:0:0:0 | __va_list_tag & | __va_list_tag & |
|
||||||
| file://:0:0:0:0 | __va_list_tag && | __va_list_tag && |
|
| file://:0:0:0:0 | __va_list_tag && | __va_list_tag && |
|
||||||
| file://:0:0:0:0 | auto | auto |
|
| file://:0:0:0:0 | auto | auto |
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
| __float128 | Float128Type | | | | |
|
| __float128 | Float128Type | | | | |
|
||||||
| __fp16 | BinaryFloatingPointType, RealNumberType | | | | |
|
| __fp16 | BinaryFloatingPointType, RealNumberType | | | | |
|
||||||
| __int128 | Int128Type | | | | |
|
| __int128 | Int128Type | | | | |
|
||||||
|
| __mfp8 | BinaryFloatingPointType, RealNumberType | | | | |
|
||||||
| __va_list_tag | DirectAccessHolder, MetricClass, Struct, StructLikeClass | | | | |
|
| __va_list_tag | DirectAccessHolder, MetricClass, Struct, StructLikeClass | | | | |
|
||||||
| __va_list_tag & | LValueReferenceType, PointerOrArrayOrReferenceType, PointerOrArrayOrReferenceTypeIndirection | | __va_list_tag | | |
|
| __va_list_tag & | LValueReferenceType, PointerOrArrayOrReferenceType, PointerOrArrayOrReferenceTypeIndirection | | __va_list_tag | | |
|
||||||
| __va_list_tag && | PointerOrArrayOrReferenceType, PointerOrArrayOrReferenceTypeIndirection, RValueReferenceType | | __va_list_tag | | |
|
| __va_list_tag && | PointerOrArrayOrReferenceType, PointerOrArrayOrReferenceTypeIndirection, RValueReferenceType | | __va_list_tag | | |
|
||||||
|
|||||||
@@ -1,3 +1,11 @@
|
|||||||
|
## 1.7.42
|
||||||
|
|
||||||
|
No user-facing changes.
|
||||||
|
|
||||||
|
## 1.7.41
|
||||||
|
|
||||||
|
No user-facing changes.
|
||||||
|
|
||||||
## 1.7.40
|
## 1.7.40
|
||||||
|
|
||||||
No user-facing changes.
|
No user-facing changes.
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
## 1.7.41
|
||||||
|
|
||||||
|
No user-facing changes.
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
## 1.7.42
|
||||||
|
|
||||||
|
No user-facing changes.
|
||||||
@@ -1,2 +1,2 @@
|
|||||||
---
|
---
|
||||||
lastReleaseVersion: 1.7.40
|
lastReleaseVersion: 1.7.42
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
name: codeql/csharp-solorigate-all
|
name: codeql/csharp-solorigate-all
|
||||||
version: 1.7.41-dev
|
version: 1.7.43-dev
|
||||||
groups:
|
groups:
|
||||||
- csharp
|
- csharp
|
||||||
- solorigate
|
- solorigate
|
||||||
|
|||||||
@@ -1,3 +1,11 @@
|
|||||||
|
## 1.7.42
|
||||||
|
|
||||||
|
No user-facing changes.
|
||||||
|
|
||||||
|
## 1.7.41
|
||||||
|
|
||||||
|
No user-facing changes.
|
||||||
|
|
||||||
## 1.7.40
|
## 1.7.40
|
||||||
|
|
||||||
No user-facing changes.
|
No user-facing changes.
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
## 1.7.41
|
||||||
|
|
||||||
|
No user-facing changes.
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
## 1.7.42
|
||||||
|
|
||||||
|
No user-facing changes.
|
||||||
@@ -1,2 +1,2 @@
|
|||||||
---
|
---
|
||||||
lastReleaseVersion: 1.7.40
|
lastReleaseVersion: 1.7.42
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
name: codeql/csharp-solorigate-queries
|
name: codeql/csharp-solorigate-queries
|
||||||
version: 1.7.41-dev
|
version: 1.7.43-dev
|
||||||
groups:
|
groups:
|
||||||
- csharp
|
- csharp
|
||||||
- solorigate
|
- solorigate
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ ql/csharp/ql/src/API Abuse/CallToGCCollect.ql
|
|||||||
ql/csharp/ql/src/API Abuse/FormatInvalid.ql
|
ql/csharp/ql/src/API Abuse/FormatInvalid.ql
|
||||||
ql/csharp/ql/src/API Abuse/NoDisposeCallOnLocalIDisposable.ql
|
ql/csharp/ql/src/API Abuse/NoDisposeCallOnLocalIDisposable.ql
|
||||||
ql/csharp/ql/src/Bad Practices/Control-Flow/ConstantCondition.ql
|
ql/csharp/ql/src/Bad Practices/Control-Flow/ConstantCondition.ql
|
||||||
|
ql/csharp/ql/src/CSI/NullAlways.ql
|
||||||
|
ql/csharp/ql/src/CSI/NullMaybe.ql
|
||||||
ql/csharp/ql/src/Dead Code/DeadStoreOfLocal.ql
|
ql/csharp/ql/src/Dead Code/DeadStoreOfLocal.ql
|
||||||
ql/csharp/ql/src/Language Abuse/MissedReadonlyOpportunity.ql
|
ql/csharp/ql/src/Language Abuse/MissedReadonlyOpportunity.ql
|
||||||
ql/csharp/ql/src/Likely Bugs/Collections/ContainerLengthCmpOffByOne.ql
|
ql/csharp/ql/src/Likely Bugs/Collections/ContainerLengthCmpOffByOne.ql
|
||||||
@@ -11,6 +13,7 @@ ql/csharp/ql/src/Likely Bugs/EqualityCheckOnFloats.ql
|
|||||||
ql/csharp/ql/src/Likely Bugs/ReferenceEqualsOnValueTypes.ql
|
ql/csharp/ql/src/Likely Bugs/ReferenceEqualsOnValueTypes.ql
|
||||||
ql/csharp/ql/src/Likely Bugs/SelfAssignment.ql
|
ql/csharp/ql/src/Likely Bugs/SelfAssignment.ql
|
||||||
ql/csharp/ql/src/Likely Bugs/UncheckedCastInEquals.ql
|
ql/csharp/ql/src/Likely Bugs/UncheckedCastInEquals.ql
|
||||||
|
ql/csharp/ql/src/Performance/StringConcatenationInLoop.ql
|
||||||
ql/csharp/ql/src/Performance/UseTryGetValue.ql
|
ql/csharp/ql/src/Performance/UseTryGetValue.ql
|
||||||
ql/csharp/ql/src/Useless code/DefaultToString.ql
|
ql/csharp/ql/src/Useless code/DefaultToString.ql
|
||||||
ql/csharp/ql/src/Useless code/IntGetHashCode.ql
|
ql/csharp/ql/src/Useless code/IntGetHashCode.ql
|
||||||
|
|||||||
@@ -1,3 +1,13 @@
|
|||||||
|
## 5.1.8
|
||||||
|
|
||||||
|
No user-facing changes.
|
||||||
|
|
||||||
|
## 5.1.7
|
||||||
|
|
||||||
|
### Minor Analysis Improvements
|
||||||
|
|
||||||
|
* The generated Models as Data (MaD) models for .NET 9 Runtime have been updated and are now more precise (due to a recent model generator improvement).
|
||||||
|
|
||||||
## 5.1.6
|
## 5.1.6
|
||||||
|
|
||||||
No user-facing changes.
|
No user-facing changes.
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
---
|
## 5.1.7
|
||||||
category: minorAnalysis
|
|
||||||
---
|
### Minor Analysis Improvements
|
||||||
|
|
||||||
* The generated Models as Data (MaD) models for .NET 9 Runtime have been updated and are now more precise (due to a recent model generator improvement).
|
* The generated Models as Data (MaD) models for .NET 9 Runtime have been updated and are now more precise (due to a recent model generator improvement).
|
||||||
3
csharp/ql/lib/change-notes/released/5.1.8.md
Normal file
3
csharp/ql/lib/change-notes/released/5.1.8.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
## 5.1.8
|
||||||
|
|
||||||
|
No user-facing changes.
|
||||||
@@ -1,2 +1,2 @@
|
|||||||
---
|
---
|
||||||
lastReleaseVersion: 5.1.6
|
lastReleaseVersion: 5.1.8
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
name: codeql/csharp-all
|
name: codeql/csharp-all
|
||||||
version: 5.1.7-dev
|
version: 5.1.9-dev
|
||||||
groups: csharp
|
groups: csharp
|
||||||
dbscheme: semmlecode.csharp.dbscheme
|
dbscheme: semmlecode.csharp.dbscheme
|
||||||
extractor: csharp
|
extractor: csharp
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user