mirror of
https://github.com/github/codeql.git
synced 2026-05-17 20:57:07 +02:00
Compare commits
122 Commits
codeql-cli
...
nickrolfe/
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
740fd27707 | ||
|
|
d813590780 | ||
|
|
4411852e59 | ||
|
|
e00585ca24 | ||
|
|
d1848194eb | ||
|
|
38abd389eb | ||
|
|
0d4a2239fc | ||
|
|
072edad0fd | ||
|
|
c82410fd16 | ||
|
|
21adcca065 | ||
|
|
8c8f1418d5 | ||
|
|
03aa8df8e2 | ||
|
|
d392cdaab6 | ||
|
|
ef967b6a21 | ||
|
|
c6c4a7b14f | ||
|
|
3f871a08e2 | ||
|
|
ed305d2699 | ||
|
|
5766ff21d0 | ||
|
|
577f1a588b | ||
|
|
d67235b3c1 | ||
|
|
69df9f9daa | ||
|
|
82277d8f56 | ||
|
|
268a990aa6 | ||
|
|
a1e0bf022e | ||
|
|
be808deb59 | ||
|
|
eb365c1d24 | ||
|
|
830be92f1d | ||
|
|
f8e80f96ff | ||
|
|
1756feae71 | ||
|
|
b30a6d36b5 | ||
|
|
b94066acd8 | ||
|
|
7b62bed9db | ||
|
|
e877967a62 | ||
|
|
d999c1d3dd | ||
|
|
1cd30847f6 | ||
|
|
68face8d46 | ||
|
|
d62e3f6bc2 | ||
|
|
99ca28ea9b | ||
|
|
587aa93f6d | ||
|
|
4e8d8a4de1 | ||
|
|
7d927a7396 | ||
|
|
fb5b344427 | ||
|
|
44e70afa85 | ||
|
|
291027ad82 | ||
|
|
3b1feeef6d | ||
|
|
b8e1aa67d8 | ||
|
|
fca754bddd | ||
|
|
60ac031db4 | ||
|
|
5198ad7612 | ||
|
|
b32f4b844a | ||
|
|
833041c62e | ||
|
|
2aa4651534 | ||
|
|
74c8bfff4f | ||
|
|
e60c016fc6 | ||
|
|
cbf81b8839 | ||
|
|
300456cd3e | ||
|
|
c0cc754fb5 | ||
|
|
a4939b91e7 | ||
|
|
08bbe596a2 | ||
|
|
c07db098a7 | ||
|
|
8fd4041511 | ||
|
|
cbbff0c401 | ||
|
|
87f7b65052 | ||
|
|
a1dba82360 | ||
|
|
828d187198 | ||
|
|
ca04779dfc | ||
|
|
fe27e09a07 | ||
|
|
05dd161d76 | ||
|
|
7976d746b6 | ||
|
|
35a4d31519 | ||
|
|
f558e858e7 | ||
|
|
3a8efb3db1 | ||
|
|
d69d289020 | ||
|
|
e0eb820ef9 | ||
|
|
a1d798b817 | ||
|
|
cc9dafffde | ||
|
|
7c9fffc201 | ||
|
|
75f30a8f9c | ||
|
|
a6b1806e66 | ||
|
|
c8cb30f76e | ||
|
|
faf10294ed | ||
|
|
4702271102 | ||
|
|
1ea87020c4 | ||
|
|
f3741ff1e4 | ||
|
|
e48dfcc5b1 | ||
|
|
a7cc8fced5 | ||
|
|
ec5ac17f87 | ||
|
|
556c199a89 | ||
|
|
85e99feb49 | ||
|
|
d87117f623 | ||
|
|
c15f63ce62 | ||
|
|
15416a9c86 | ||
|
|
78e35e2f29 | ||
|
|
04a47093ee | ||
|
|
3911f3b202 | ||
|
|
76a330d4b9 | ||
|
|
723ca8ed88 | ||
|
|
0dd63c007e | ||
|
|
fd61a5253d | ||
|
|
840b74dbb5 | ||
|
|
420c35d4a2 | ||
|
|
18dd0f650c | ||
|
|
408c7bebe5 | ||
|
|
e8f55b9f0d | ||
|
|
c0ac29db16 | ||
|
|
4b7cb706f6 | ||
|
|
0d2e7d43b9 | ||
|
|
5179a99abb | ||
|
|
c4b2519e6c | ||
|
|
7797211118 | ||
|
|
0678b06a9b | ||
|
|
25241276b0 | ||
|
|
429bd5fbd8 | ||
|
|
0220f0aa5c | ||
|
|
b64a1b7c42 | ||
|
|
cadb948d57 | ||
|
|
d427e55507 | ||
|
|
557dd10896 | ||
|
|
0d5da42ddd | ||
|
|
75422dfa72 | ||
|
|
99b90789e5 | ||
|
|
b16b3c0394 |
56
.github/workflows/atm-check-queries-run.yml
vendored
56
.github/workflows/atm-check-queries-run.yml
vendored
@@ -1,56 +0,0 @@
|
||||
name: ATM Check Queries Run
|
||||
|
||||
env:
|
||||
DB_PATH: test_db
|
||||
ATM_MODEL_PACK: javascript/ql/experimental/adaptivethreatmodeling/src
|
||||
QUERY_SUITE: codeql-suites/javascript-atm-code-scanning.qls
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- ".github/workflows/atm-check-queries-run.yml"
|
||||
- "javascript/ql/experimental/adaptivethreatmodeling/**"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
run-atm-queries:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install CodeQL CLI
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
gh extensions install github/gh-codeql
|
||||
gh codeql download
|
||||
|
||||
- name: Install ATM model pack
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
set -exu
|
||||
|
||||
# Install ATM model pack
|
||||
gh codeql pack install ${ATM_MODEL_PACK}
|
||||
|
||||
# Retrieve model checksum
|
||||
model_checksum=$(gh codeql resolve extensions ${ATM_MODEL_PACK}/${QUERY_SUITE} | jq -r '.models[0].checksum')
|
||||
|
||||
# Trust the model so that we can use it in the ATM boosted queries
|
||||
mkdir -p "$HOME/.config/codeql"
|
||||
echo "--insecurely-execute-ml-model-checksums ${model_checksum}" >> "$HOME/.config/codeql/config"
|
||||
|
||||
- name: Create test DB
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
gh codeql database create ${RUNNER_TEMP}/${DB_PATH} --source-root config/atm/ --language javascript
|
||||
|
||||
- name: Run ATM query suite
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
gh codeql database run-queries -vv -- ${RUNNER_TEMP}/${DB_PATH} ${ATM_MODEL_PACK}/${QUERY_SUITE}
|
||||
|
||||
93
.github/workflows/atm-check-query-suite.yml
vendored
Normal file
93
.github/workflows/atm-check-query-suite.yml
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
name: "ATM - Check query suite"
|
||||
|
||||
env:
|
||||
QUERY_PACK: javascript/ql/experimental/adaptivethreatmodeling/src
|
||||
QUERY_SUITE: codeql-suites/javascript-atm-code-scanning.qls
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- ".github/workflows/atm-check-query-suite.yml"
|
||||
- "javascript/ql/experimental/adaptivethreatmodeling/**"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
atm-check-query-suite:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup CodeQL
|
||||
uses: ./.github/actions/fetch-codeql
|
||||
with:
|
||||
channel: release
|
||||
|
||||
- name: Install ATM model
|
||||
run: |
|
||||
set -exu
|
||||
|
||||
# Install dependencies of ATM query pack, i.e. the ATM model
|
||||
codeql pack install "${QUERY_PACK}"
|
||||
|
||||
# Retrieve model checksum
|
||||
model_checksum=$(codeql resolve extensions "${QUERY_PACK}/${QUERY_SUITE}" | jq -r '.models[0].checksum')
|
||||
|
||||
# Trust the model so that we can use it in the ATM boosted queries
|
||||
mkdir -p "$HOME/.config/codeql"
|
||||
echo "--insecurely-execute-ml-model-checksums ${model_checksum}" >> "$HOME/.config/codeql/config"
|
||||
|
||||
- name: Create test DB
|
||||
run: |
|
||||
DB_PATH="${RUNNER_TEMP}/db"
|
||||
echo "DB_PATH=${DB_PATH}" >> "${GITHUB_ENV}"
|
||||
|
||||
codeql database create "${DB_PATH}" --source-root config/atm --language javascript
|
||||
|
||||
- name: Run ATM query suite
|
||||
run: |
|
||||
SARIF_PATH="${RUNNER_TEMP}/sarif.json"
|
||||
echo "SARIF_PATH=${SARIF_PATH}" >> "${GITHUB_ENV}"
|
||||
|
||||
codeql database analyze \
|
||||
--format sarif-latest \
|
||||
--output "${SARIF_PATH}" \
|
||||
--sarif-group-rules-by-pack \
|
||||
-vv \
|
||||
-- \
|
||||
"${DB_PATH}" \
|
||||
"${QUERY_PACK}/${QUERY_SUITE}"
|
||||
|
||||
- name: Upload SARIF
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: javascript-ml-powered-queries.sarif
|
||||
path: "${{ env.SARIF_PATH }}"
|
||||
retention-days: 5
|
||||
|
||||
- name: Check results
|
||||
run: |
|
||||
# We should run at least the ML-powered queries in `expected_rules`.
|
||||
expected_rules="js/ml-powered/nosql-injection js/ml-powered/path-injection js/ml-powered/sql-injection js/ml-powered/xss"
|
||||
|
||||
for rule in ${expected_rules}; do
|
||||
found_rule=$(jq --arg rule "${rule}" '[.runs[0].tool.extensions[].rules | select(. != null) |
|
||||
flatten | .[].id] | any(. == $rule)' "${SARIF_PATH}")
|
||||
if [[ "${found_rule}" != "true" ]]; then
|
||||
echo "Expected SARIF output to contain rule '${rule}', but found no such rule."
|
||||
exit 1
|
||||
else
|
||||
echo "Found rule '${rule}'."
|
||||
fi
|
||||
done
|
||||
|
||||
# We should have at least one alert from an ML-powered query.
|
||||
num_alerts=$(jq '[.runs[0].results[] |
|
||||
select(.properties.score != null and (.rule.id | startswith("js/ml-powered/")))] | length' \
|
||||
"${SARIF_PATH}")
|
||||
if [[ "${num_alerts}" -eq 0 ]]; then
|
||||
echo "Expected to find at least one alert from an ML-powered query but found ${num_alerts}."
|
||||
exit 1
|
||||
else
|
||||
echo "Found ${num_alerts} alerts from ML-powered queries.";
|
||||
fi
|
||||
@@ -31,7 +31,7 @@ repos:
|
||||
|
||||
- id: sync-files
|
||||
name: Fix files required to be identical
|
||||
files: \.(qll?|qhelp|swift)$
|
||||
files: \.(qll?|qhelp|swift)$|^config/identical-files\.json$
|
||||
language: system
|
||||
entry: python3 config/sync-files.py --latest
|
||||
pass_filenames: false
|
||||
|
||||
@@ -40,6 +40,7 @@ WORKSPACE.bazel @github/codeql-ci-reviewers
|
||||
|
||||
# Workflows
|
||||
/.github/workflows/ @github/codeql-ci-reviewers
|
||||
/.github/workflows/atm-* @github/codeql-ml-powered-queries-reviewers
|
||||
/.github/workflows/go-* @github/codeql-go
|
||||
/.github/workflows/js-ml-tests.yml @github/codeql-ml-powered-queries-reviewers
|
||||
/.github/workflows/ql-for-ql-* @github/codeql-ql-for-ql-reviewers
|
||||
|
||||
@@ -600,8 +600,12 @@
|
||||
"swift/ql/test/extractor-tests/patterns/patterns.swift",
|
||||
"swift/ql/test/library-tests/ast/patterns.swift"
|
||||
],
|
||||
"Swift control flow test file": [
|
||||
"swift/ql/test/library-tests/controlflow/graph/cfg.swift",
|
||||
"swift/ql/test/library-tests/ast/cfg.swift"
|
||||
],
|
||||
"IncompleteMultiCharacterSanitization JS/Ruby": [
|
||||
"javascript/ql/lib/semmle/javascript/security/IncompleteMultiCharacterSanitizationQuery.qll",
|
||||
"ruby/ql/lib/codeql/ruby/security/IncompleteMultiCharacterSanitizationQuery.qll"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
|
||||
/**
|
||||
* Gets the number of `AccessPath`s that correspond to `apa`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
evalUnfold(apa, false, config) and
|
||||
result = 1 and
|
||||
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
* that it is expanded to a precise head-tail representation.
|
||||
*/
|
||||
language[monotonicAggregates]
|
||||
pragma[assume_small_delta]
|
||||
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
|
||||
apa instanceof AccessPathApproxNil and result = 1
|
||||
or
|
||||
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
|
||||
}
|
||||
|
||||
private newtype TPathNode =
|
||||
pragma[assume_small_delta]
|
||||
TPathNodeMid(
|
||||
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
|
||||
) {
|
||||
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
|
||||
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override AccessPathApproxCons getApprox() {
|
||||
result = TConsNil(head, tail.(AccessPathNil).getType())
|
||||
or
|
||||
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
result = TCons1(head, this.length())
|
||||
}
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override int length() { result = 1 + tail.length() }
|
||||
|
||||
private string toStringImpl(boolean needsSuffix) {
|
||||
@@ -3155,6 +3160,7 @@ private predicate pathNode(
|
||||
* Holds if data may flow from `mid` to `node`. The last step in or out of
|
||||
* a callable is recorded by `cc`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
pragma[nomagic]
|
||||
private predicate pathStep(
|
||||
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
|
||||
|
||||
@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
|
||||
/**
|
||||
* Gets the number of `AccessPath`s that correspond to `apa`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
evalUnfold(apa, false, config) and
|
||||
result = 1 and
|
||||
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
* that it is expanded to a precise head-tail representation.
|
||||
*/
|
||||
language[monotonicAggregates]
|
||||
pragma[assume_small_delta]
|
||||
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
|
||||
apa instanceof AccessPathApproxNil and result = 1
|
||||
or
|
||||
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
|
||||
}
|
||||
|
||||
private newtype TPathNode =
|
||||
pragma[assume_small_delta]
|
||||
TPathNodeMid(
|
||||
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
|
||||
) {
|
||||
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
|
||||
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override AccessPathApproxCons getApprox() {
|
||||
result = TConsNil(head, tail.(AccessPathNil).getType())
|
||||
or
|
||||
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
result = TCons1(head, this.length())
|
||||
}
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override int length() { result = 1 + tail.length() }
|
||||
|
||||
private string toStringImpl(boolean needsSuffix) {
|
||||
@@ -3155,6 +3160,7 @@ private predicate pathNode(
|
||||
* Holds if data may flow from `mid` to `node`. The last step in or out of
|
||||
* a callable is recorded by `cc`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
pragma[nomagic]
|
||||
private predicate pathStep(
|
||||
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
|
||||
|
||||
@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
|
||||
/**
|
||||
* Gets the number of `AccessPath`s that correspond to `apa`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
evalUnfold(apa, false, config) and
|
||||
result = 1 and
|
||||
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
* that it is expanded to a precise head-tail representation.
|
||||
*/
|
||||
language[monotonicAggregates]
|
||||
pragma[assume_small_delta]
|
||||
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
|
||||
apa instanceof AccessPathApproxNil and result = 1
|
||||
or
|
||||
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
|
||||
}
|
||||
|
||||
private newtype TPathNode =
|
||||
pragma[assume_small_delta]
|
||||
TPathNodeMid(
|
||||
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
|
||||
) {
|
||||
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
|
||||
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override AccessPathApproxCons getApprox() {
|
||||
result = TConsNil(head, tail.(AccessPathNil).getType())
|
||||
or
|
||||
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
result = TCons1(head, this.length())
|
||||
}
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override int length() { result = 1 + tail.length() }
|
||||
|
||||
private string toStringImpl(boolean needsSuffix) {
|
||||
@@ -3155,6 +3160,7 @@ private predicate pathNode(
|
||||
* Holds if data may flow from `mid` to `node`. The last step in or out of
|
||||
* a callable is recorded by `cc`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
pragma[nomagic]
|
||||
private predicate pathStep(
|
||||
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
|
||||
|
||||
@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
|
||||
/**
|
||||
* Gets the number of `AccessPath`s that correspond to `apa`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
evalUnfold(apa, false, config) and
|
||||
result = 1 and
|
||||
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
* that it is expanded to a precise head-tail representation.
|
||||
*/
|
||||
language[monotonicAggregates]
|
||||
pragma[assume_small_delta]
|
||||
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
|
||||
apa instanceof AccessPathApproxNil and result = 1
|
||||
or
|
||||
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
|
||||
}
|
||||
|
||||
private newtype TPathNode =
|
||||
pragma[assume_small_delta]
|
||||
TPathNodeMid(
|
||||
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
|
||||
) {
|
||||
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
|
||||
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override AccessPathApproxCons getApprox() {
|
||||
result = TConsNil(head, tail.(AccessPathNil).getType())
|
||||
or
|
||||
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
result = TCons1(head, this.length())
|
||||
}
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override int length() { result = 1 + tail.length() }
|
||||
|
||||
private string toStringImpl(boolean needsSuffix) {
|
||||
@@ -3155,6 +3160,7 @@ private predicate pathNode(
|
||||
* Holds if data may flow from `mid` to `node`. The last step in or out of
|
||||
* a callable is recorded by `cc`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
pragma[nomagic]
|
||||
private predicate pathStep(
|
||||
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-all
|
||||
version: 0.4.3
|
||||
version: 0.4.4-dev
|
||||
groups: cpp
|
||||
dbscheme: semmlecode.cpp.dbscheme
|
||||
extractor: cpp
|
||||
|
||||
@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
|
||||
/**
|
||||
* Gets the number of `AccessPath`s that correspond to `apa`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
evalUnfold(apa, false, config) and
|
||||
result = 1 and
|
||||
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
* that it is expanded to a precise head-tail representation.
|
||||
*/
|
||||
language[monotonicAggregates]
|
||||
pragma[assume_small_delta]
|
||||
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
|
||||
apa instanceof AccessPathApproxNil and result = 1
|
||||
or
|
||||
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
|
||||
}
|
||||
|
||||
private newtype TPathNode =
|
||||
pragma[assume_small_delta]
|
||||
TPathNodeMid(
|
||||
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
|
||||
) {
|
||||
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
|
||||
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override AccessPathApproxCons getApprox() {
|
||||
result = TConsNil(head, tail.(AccessPathNil).getType())
|
||||
or
|
||||
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
result = TCons1(head, this.length())
|
||||
}
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override int length() { result = 1 + tail.length() }
|
||||
|
||||
private string toStringImpl(boolean needsSuffix) {
|
||||
@@ -3155,6 +3160,7 @@ private predicate pathNode(
|
||||
* Holds if data may flow from `mid` to `node`. The last step in or out of
|
||||
* a callable is recorded by `cc`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
pragma[nomagic]
|
||||
private predicate pathStep(
|
||||
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
|
||||
|
||||
@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
|
||||
/**
|
||||
* Gets the number of `AccessPath`s that correspond to `apa`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
evalUnfold(apa, false, config) and
|
||||
result = 1 and
|
||||
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
* that it is expanded to a precise head-tail representation.
|
||||
*/
|
||||
language[monotonicAggregates]
|
||||
pragma[assume_small_delta]
|
||||
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
|
||||
apa instanceof AccessPathApproxNil and result = 1
|
||||
or
|
||||
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
|
||||
}
|
||||
|
||||
private newtype TPathNode =
|
||||
pragma[assume_small_delta]
|
||||
TPathNodeMid(
|
||||
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
|
||||
) {
|
||||
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
|
||||
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override AccessPathApproxCons getApprox() {
|
||||
result = TConsNil(head, tail.(AccessPathNil).getType())
|
||||
or
|
||||
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
result = TCons1(head, this.length())
|
||||
}
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override int length() { result = 1 + tail.length() }
|
||||
|
||||
private string toStringImpl(boolean needsSuffix) {
|
||||
@@ -3155,6 +3160,7 @@ private predicate pathNode(
|
||||
* Holds if data may flow from `mid` to `node`. The last step in or out of
|
||||
* a callable is recorded by `cc`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
pragma[nomagic]
|
||||
private predicate pathStep(
|
||||
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
|
||||
|
||||
@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
|
||||
/**
|
||||
* Gets the number of `AccessPath`s that correspond to `apa`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
evalUnfold(apa, false, config) and
|
||||
result = 1 and
|
||||
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
* that it is expanded to a precise head-tail representation.
|
||||
*/
|
||||
language[monotonicAggregates]
|
||||
pragma[assume_small_delta]
|
||||
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
|
||||
apa instanceof AccessPathApproxNil and result = 1
|
||||
or
|
||||
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
|
||||
}
|
||||
|
||||
private newtype TPathNode =
|
||||
pragma[assume_small_delta]
|
||||
TPathNodeMid(
|
||||
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
|
||||
) {
|
||||
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
|
||||
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override AccessPathApproxCons getApprox() {
|
||||
result = TConsNil(head, tail.(AccessPathNil).getType())
|
||||
or
|
||||
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
result = TCons1(head, this.length())
|
||||
}
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override int length() { result = 1 + tail.length() }
|
||||
|
||||
private string toStringImpl(boolean needsSuffix) {
|
||||
@@ -3155,6 +3160,7 @@ private predicate pathNode(
|
||||
* Holds if data may flow from `mid` to `node`. The last step in or out of
|
||||
* a callable is recorded by `cc`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
pragma[nomagic]
|
||||
private predicate pathStep(
|
||||
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
|
||||
|
||||
@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
|
||||
/**
|
||||
* Gets the number of `AccessPath`s that correspond to `apa`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
evalUnfold(apa, false, config) and
|
||||
result = 1 and
|
||||
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
* that it is expanded to a precise head-tail representation.
|
||||
*/
|
||||
language[monotonicAggregates]
|
||||
pragma[assume_small_delta]
|
||||
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
|
||||
apa instanceof AccessPathApproxNil and result = 1
|
||||
or
|
||||
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
|
||||
}
|
||||
|
||||
private newtype TPathNode =
|
||||
pragma[assume_small_delta]
|
||||
TPathNodeMid(
|
||||
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
|
||||
) {
|
||||
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
|
||||
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override AccessPathApproxCons getApprox() {
|
||||
result = TConsNil(head, tail.(AccessPathNil).getType())
|
||||
or
|
||||
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
result = TCons1(head, this.length())
|
||||
}
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override int length() { result = 1 + tail.length() }
|
||||
|
||||
private string toStringImpl(boolean needsSuffix) {
|
||||
@@ -3155,6 +3160,7 @@ private predicate pathNode(
|
||||
* Holds if data may flow from `mid` to `node`. The last step in or out of
|
||||
* a callable is recorded by `cc`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
pragma[nomagic]
|
||||
private predicate pathStep(
|
||||
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
|
||||
|
||||
@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
|
||||
/**
|
||||
* Gets the number of `AccessPath`s that correspond to `apa`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
evalUnfold(apa, false, config) and
|
||||
result = 1 and
|
||||
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
* that it is expanded to a precise head-tail representation.
|
||||
*/
|
||||
language[monotonicAggregates]
|
||||
pragma[assume_small_delta]
|
||||
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
|
||||
apa instanceof AccessPathApproxNil and result = 1
|
||||
or
|
||||
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
|
||||
}
|
||||
|
||||
private newtype TPathNode =
|
||||
pragma[assume_small_delta]
|
||||
TPathNodeMid(
|
||||
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
|
||||
) {
|
||||
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
|
||||
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override AccessPathApproxCons getApprox() {
|
||||
result = TConsNil(head, tail.(AccessPathNil).getType())
|
||||
or
|
||||
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
result = TCons1(head, this.length())
|
||||
}
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override int length() { result = 1 + tail.length() }
|
||||
|
||||
private string toStringImpl(boolean needsSuffix) {
|
||||
@@ -3155,6 +3160,7 @@ private predicate pathNode(
|
||||
* Holds if data may flow from `mid` to `node`. The last step in or out of
|
||||
* a callable is recorded by `cc`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
pragma[nomagic]
|
||||
private predicate pathStep(
|
||||
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
|
||||
|
||||
@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
|
||||
/**
|
||||
* Gets the number of `AccessPath`s that correspond to `apa`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
evalUnfold(apa, false, config) and
|
||||
result = 1 and
|
||||
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
* that it is expanded to a precise head-tail representation.
|
||||
*/
|
||||
language[monotonicAggregates]
|
||||
pragma[assume_small_delta]
|
||||
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
|
||||
apa instanceof AccessPathApproxNil and result = 1
|
||||
or
|
||||
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
|
||||
}
|
||||
|
||||
private newtype TPathNode =
|
||||
pragma[assume_small_delta]
|
||||
TPathNodeMid(
|
||||
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
|
||||
) {
|
||||
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
|
||||
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override AccessPathApproxCons getApprox() {
|
||||
result = TConsNil(head, tail.(AccessPathNil).getType())
|
||||
or
|
||||
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
result = TCons1(head, this.length())
|
||||
}
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override int length() { result = 1 + tail.length() }
|
||||
|
||||
private string toStringImpl(boolean needsSuffix) {
|
||||
@@ -3155,6 +3160,7 @@ private predicate pathNode(
|
||||
* Holds if data may flow from `mid` to `node`. The last step in or out of
|
||||
* a callable is recorded by `cc`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
pragma[nomagic]
|
||||
private predicate pathStep(
|
||||
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
|
||||
|
||||
@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
|
||||
/**
|
||||
* Gets the number of `AccessPath`s that correspond to `apa`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
evalUnfold(apa, false, config) and
|
||||
result = 1 and
|
||||
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
* that it is expanded to a precise head-tail representation.
|
||||
*/
|
||||
language[monotonicAggregates]
|
||||
pragma[assume_small_delta]
|
||||
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
|
||||
apa instanceof AccessPathApproxNil and result = 1
|
||||
or
|
||||
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
|
||||
}
|
||||
|
||||
private newtype TPathNode =
|
||||
pragma[assume_small_delta]
|
||||
TPathNodeMid(
|
||||
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
|
||||
) {
|
||||
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
|
||||
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override AccessPathApproxCons getApprox() {
|
||||
result = TConsNil(head, tail.(AccessPathNil).getType())
|
||||
or
|
||||
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
result = TCons1(head, this.length())
|
||||
}
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override int length() { result = 1 + tail.length() }
|
||||
|
||||
private string toStringImpl(boolean needsSuffix) {
|
||||
@@ -3155,6 +3160,7 @@ private predicate pathNode(
|
||||
* Holds if data may flow from `mid` to `node`. The last step in or out of
|
||||
* a callable is recorded by `cc`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
pragma[nomagic]
|
||||
private predicate pathStep(
|
||||
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
|
||||
|
||||
@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
|
||||
/**
|
||||
* Gets the number of `AccessPath`s that correspond to `apa`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
evalUnfold(apa, false, config) and
|
||||
result = 1 and
|
||||
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
* that it is expanded to a precise head-tail representation.
|
||||
*/
|
||||
language[monotonicAggregates]
|
||||
pragma[assume_small_delta]
|
||||
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
|
||||
apa instanceof AccessPathApproxNil and result = 1
|
||||
or
|
||||
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
|
||||
}
|
||||
|
||||
private newtype TPathNode =
|
||||
pragma[assume_small_delta]
|
||||
TPathNodeMid(
|
||||
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
|
||||
) {
|
||||
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
|
||||
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override AccessPathApproxCons getApprox() {
|
||||
result = TConsNil(head, tail.(AccessPathNil).getType())
|
||||
or
|
||||
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
result = TCons1(head, this.length())
|
||||
}
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override int length() { result = 1 + tail.length() }
|
||||
|
||||
private string toStringImpl(boolean needsSuffix) {
|
||||
@@ -3155,6 +3160,7 @@ private predicate pathNode(
|
||||
* Holds if data may flow from `mid` to `node`. The last step in or out of
|
||||
* a callable is recorded by `cc`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
pragma[nomagic]
|
||||
private predicate pathStep(
|
||||
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
|
||||
|
||||
@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
|
||||
/**
|
||||
* Gets the number of `AccessPath`s that correspond to `apa`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
evalUnfold(apa, false, config) and
|
||||
result = 1 and
|
||||
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
* that it is expanded to a precise head-tail representation.
|
||||
*/
|
||||
language[monotonicAggregates]
|
||||
pragma[assume_small_delta]
|
||||
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
|
||||
apa instanceof AccessPathApproxNil and result = 1
|
||||
or
|
||||
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
|
||||
}
|
||||
|
||||
private newtype TPathNode =
|
||||
pragma[assume_small_delta]
|
||||
TPathNodeMid(
|
||||
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
|
||||
) {
|
||||
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
|
||||
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override AccessPathApproxCons getApprox() {
|
||||
result = TConsNil(head, tail.(AccessPathNil).getType())
|
||||
or
|
||||
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
result = TCons1(head, this.length())
|
||||
}
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override int length() { result = 1 + tail.length() }
|
||||
|
||||
private string toStringImpl(boolean needsSuffix) {
|
||||
@@ -3155,6 +3160,7 @@ private predicate pathNode(
|
||||
* Holds if data may flow from `mid` to `node`. The last step in or out of
|
||||
* a callable is recorded by `cc`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
pragma[nomagic]
|
||||
private predicate pathStep(
|
||||
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-queries
|
||||
version: 0.4.3
|
||||
version: 0.4.4-dev
|
||||
groups:
|
||||
- cpp
|
||||
- queries
|
||||
|
||||
@@ -329,21 +329,21 @@ namespace NestedTests {
|
||||
namespace FlowThroughGlobals {
|
||||
int globalVar;
|
||||
|
||||
int taintGlobal() {
|
||||
void taintGlobal() {
|
||||
globalVar = source();
|
||||
}
|
||||
|
||||
int f() {
|
||||
void f() {
|
||||
sink(globalVar); // $ ir=333:17 ir=347:17 // tainted or clean? Not sure.
|
||||
taintGlobal();
|
||||
sink(globalVar); // $ ir=333:17 ir=347:17 MISSING: ast
|
||||
}
|
||||
|
||||
int calledAfterTaint() {
|
||||
void calledAfterTaint() {
|
||||
sink(globalVar); // $ ir=333:17 ir=347:17 MISSING: ast
|
||||
}
|
||||
|
||||
int taintAndCall() {
|
||||
void taintAndCall() {
|
||||
globalVar = source();
|
||||
calledAfterTaint();
|
||||
sink(globalVar); // $ ast ir=333:17 ir=347:17
|
||||
|
||||
@@ -77,27 +77,9 @@ module IRTest {
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) {
|
||||
exists(GlobalOrNamespaceVariable var | var.getName().matches("flowTestGlobal%") |
|
||||
writesVariable(n1.asInstruction(), var) and
|
||||
var = n2.asVariable()
|
||||
or
|
||||
readsVariable(n2.asInstruction(), var) and
|
||||
var = n1.asVariable()
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isBarrier(DataFlow::Node barrier) {
|
||||
barrier.asExpr().(VariableAccess).getTarget().hasName("barrier") or
|
||||
barrier = DataFlow::InstructionBarrierGuard<testBarrierGuard/3>::getABarrierNode()
|
||||
}
|
||||
}
|
||||
|
||||
private predicate readsVariable(LoadInstruction load, Variable var) {
|
||||
load.getSourceAddress().(VariableAddressInstruction).getAstVariable() = var
|
||||
}
|
||||
|
||||
private predicate writesVariable(StoreInstruction store, Variable var) {
|
||||
store.getDestinationAddress().(VariableAddressInstruction).getAstVariable() = var
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ int source();
|
||||
void sink(...);
|
||||
bool random();
|
||||
|
||||
int test1() {
|
||||
void test1() {
|
||||
int x = source();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
x = 0;
|
||||
@@ -13,7 +13,7 @@ int test1() {
|
||||
sink(x); // $ SPURIOUS: ir
|
||||
}
|
||||
|
||||
int test2(int iterations) {
|
||||
void test2(int iterations) {
|
||||
int x = source();
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
x = 0;
|
||||
@@ -21,7 +21,7 @@ int test2(int iterations) {
|
||||
sink(x); // $ ast,ir
|
||||
}
|
||||
|
||||
int test3() {
|
||||
void test3() {
|
||||
int x = 0;
|
||||
for (int i = 0; i < 10; i++) {
|
||||
x = source();
|
||||
@@ -29,7 +29,7 @@ int test3() {
|
||||
sink(x); // $ ast,ir
|
||||
}
|
||||
|
||||
int test4() {
|
||||
void test4() {
|
||||
int x = source();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
if (random())
|
||||
@@ -39,7 +39,7 @@ int test4() {
|
||||
sink(x); // $ ast,ir
|
||||
}
|
||||
|
||||
int test5() {
|
||||
void test5() {
|
||||
int x = source();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
if (random())
|
||||
@@ -49,7 +49,7 @@ int test5() {
|
||||
sink(x); // $ ast,ir
|
||||
}
|
||||
|
||||
int test6() {
|
||||
void test6() {
|
||||
int y;
|
||||
int x = source();
|
||||
for (int i = 0; i < 10 && (y = 1); i++) {
|
||||
@@ -57,7 +57,7 @@ int test6() {
|
||||
sink(x); // $ ast,ir
|
||||
}
|
||||
|
||||
int test7() {
|
||||
void test7() {
|
||||
int y;
|
||||
int x = source();
|
||||
for (int i = 0; i < 10 && (y = 1); i++) {
|
||||
@@ -66,7 +66,7 @@ int test7() {
|
||||
sink(x); // $ SPURIOUS: ir
|
||||
}
|
||||
|
||||
int test8() {
|
||||
void test8() {
|
||||
int x = source();
|
||||
// It appears to the analysis that the condition can exit after `i < 10`
|
||||
// without having assigned to `x`. That is an effect of how the
|
||||
@@ -78,7 +78,7 @@ int test8() {
|
||||
sink(x); // $ SPURIOUS: ast,ir
|
||||
}
|
||||
|
||||
int test9() {
|
||||
void test9() {
|
||||
int y;
|
||||
int x = source();
|
||||
for (int i = 0; (y = 1) && i < 10; i++) {
|
||||
@@ -86,21 +86,21 @@ int test9() {
|
||||
sink(x); // $ ast,ir
|
||||
}
|
||||
|
||||
int test10() {
|
||||
void test10() {
|
||||
int x = source();
|
||||
for (int i = 0; (x = 1) && i < 10; i++) {
|
||||
}
|
||||
sink(x); // no flow
|
||||
}
|
||||
|
||||
int test10(int b, int d) {
|
||||
void test10(int b, int d) {
|
||||
int i = 0;
|
||||
int x = source();
|
||||
if (b)
|
||||
goto L;
|
||||
for (; i < 10; i += d) {
|
||||
x = 0;
|
||||
L:
|
||||
L: ;
|
||||
}
|
||||
sink(x); // $ ir MISSING: ast
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/csharp-solorigate-all
|
||||
version: 1.3.3
|
||||
version: 1.3.4-dev
|
||||
groups:
|
||||
- csharp
|
||||
- solorigate
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/csharp-solorigate-queries
|
||||
version: 1.3.3
|
||||
version: 1.3.4-dev
|
||||
groups:
|
||||
- csharp
|
||||
- solorigate
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/csharp-all
|
||||
version: 0.4.3
|
||||
version: 0.4.4-dev
|
||||
groups: csharp
|
||||
dbscheme: semmlecode.csharp.dbscheme
|
||||
extractor: csharp
|
||||
|
||||
@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
|
||||
/**
|
||||
* Gets the number of `AccessPath`s that correspond to `apa`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
evalUnfold(apa, false, config) and
|
||||
result = 1 and
|
||||
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
* that it is expanded to a precise head-tail representation.
|
||||
*/
|
||||
language[monotonicAggregates]
|
||||
pragma[assume_small_delta]
|
||||
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
|
||||
apa instanceof AccessPathApproxNil and result = 1
|
||||
or
|
||||
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
|
||||
}
|
||||
|
||||
private newtype TPathNode =
|
||||
pragma[assume_small_delta]
|
||||
TPathNodeMid(
|
||||
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
|
||||
) {
|
||||
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
|
||||
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override AccessPathApproxCons getApprox() {
|
||||
result = TConsNil(head, tail.(AccessPathNil).getType())
|
||||
or
|
||||
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
result = TCons1(head, this.length())
|
||||
}
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override int length() { result = 1 + tail.length() }
|
||||
|
||||
private string toStringImpl(boolean needsSuffix) {
|
||||
@@ -3155,6 +3160,7 @@ private predicate pathNode(
|
||||
* Holds if data may flow from `mid` to `node`. The last step in or out of
|
||||
* a callable is recorded by `cc`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
pragma[nomagic]
|
||||
private predicate pathStep(
|
||||
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
|
||||
|
||||
@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
|
||||
/**
|
||||
* Gets the number of `AccessPath`s that correspond to `apa`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
evalUnfold(apa, false, config) and
|
||||
result = 1 and
|
||||
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
* that it is expanded to a precise head-tail representation.
|
||||
*/
|
||||
language[monotonicAggregates]
|
||||
pragma[assume_small_delta]
|
||||
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
|
||||
apa instanceof AccessPathApproxNil and result = 1
|
||||
or
|
||||
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
|
||||
}
|
||||
|
||||
private newtype TPathNode =
|
||||
pragma[assume_small_delta]
|
||||
TPathNodeMid(
|
||||
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
|
||||
) {
|
||||
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
|
||||
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override AccessPathApproxCons getApprox() {
|
||||
result = TConsNil(head, tail.(AccessPathNil).getType())
|
||||
or
|
||||
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
result = TCons1(head, this.length())
|
||||
}
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override int length() { result = 1 + tail.length() }
|
||||
|
||||
private string toStringImpl(boolean needsSuffix) {
|
||||
@@ -3155,6 +3160,7 @@ private predicate pathNode(
|
||||
* Holds if data may flow from `mid` to `node`. The last step in or out of
|
||||
* a callable is recorded by `cc`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
pragma[nomagic]
|
||||
private predicate pathStep(
|
||||
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
|
||||
|
||||
@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
|
||||
/**
|
||||
* Gets the number of `AccessPath`s that correspond to `apa`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
evalUnfold(apa, false, config) and
|
||||
result = 1 and
|
||||
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
* that it is expanded to a precise head-tail representation.
|
||||
*/
|
||||
language[monotonicAggregates]
|
||||
pragma[assume_small_delta]
|
||||
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
|
||||
apa instanceof AccessPathApproxNil and result = 1
|
||||
or
|
||||
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
|
||||
}
|
||||
|
||||
private newtype TPathNode =
|
||||
pragma[assume_small_delta]
|
||||
TPathNodeMid(
|
||||
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
|
||||
) {
|
||||
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
|
||||
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override AccessPathApproxCons getApprox() {
|
||||
result = TConsNil(head, tail.(AccessPathNil).getType())
|
||||
or
|
||||
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
result = TCons1(head, this.length())
|
||||
}
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override int length() { result = 1 + tail.length() }
|
||||
|
||||
private string toStringImpl(boolean needsSuffix) {
|
||||
@@ -3155,6 +3160,7 @@ private predicate pathNode(
|
||||
* Holds if data may flow from `mid` to `node`. The last step in or out of
|
||||
* a callable is recorded by `cc`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
pragma[nomagic]
|
||||
private predicate pathStep(
|
||||
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
|
||||
|
||||
@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
|
||||
/**
|
||||
* Gets the number of `AccessPath`s that correspond to `apa`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
evalUnfold(apa, false, config) and
|
||||
result = 1 and
|
||||
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
* that it is expanded to a precise head-tail representation.
|
||||
*/
|
||||
language[monotonicAggregates]
|
||||
pragma[assume_small_delta]
|
||||
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
|
||||
apa instanceof AccessPathApproxNil and result = 1
|
||||
or
|
||||
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
|
||||
}
|
||||
|
||||
private newtype TPathNode =
|
||||
pragma[assume_small_delta]
|
||||
TPathNodeMid(
|
||||
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
|
||||
) {
|
||||
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
|
||||
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override AccessPathApproxCons getApprox() {
|
||||
result = TConsNil(head, tail.(AccessPathNil).getType())
|
||||
or
|
||||
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
result = TCons1(head, this.length())
|
||||
}
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override int length() { result = 1 + tail.length() }
|
||||
|
||||
private string toStringImpl(boolean needsSuffix) {
|
||||
@@ -3155,6 +3160,7 @@ private predicate pathNode(
|
||||
* Holds if data may flow from `mid` to `node`. The last step in or out of
|
||||
* a callable is recorded by `cc`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
pragma[nomagic]
|
||||
private predicate pathStep(
|
||||
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
|
||||
|
||||
@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
|
||||
/**
|
||||
* Gets the number of `AccessPath`s that correspond to `apa`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
evalUnfold(apa, false, config) and
|
||||
result = 1 and
|
||||
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
* that it is expanded to a precise head-tail representation.
|
||||
*/
|
||||
language[monotonicAggregates]
|
||||
pragma[assume_small_delta]
|
||||
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
|
||||
apa instanceof AccessPathApproxNil and result = 1
|
||||
or
|
||||
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
|
||||
}
|
||||
|
||||
private newtype TPathNode =
|
||||
pragma[assume_small_delta]
|
||||
TPathNodeMid(
|
||||
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
|
||||
) {
|
||||
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
|
||||
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override AccessPathApproxCons getApprox() {
|
||||
result = TConsNil(head, tail.(AccessPathNil).getType())
|
||||
or
|
||||
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
result = TCons1(head, this.length())
|
||||
}
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override int length() { result = 1 + tail.length() }
|
||||
|
||||
private string toStringImpl(boolean needsSuffix) {
|
||||
@@ -3155,6 +3160,7 @@ private predicate pathNode(
|
||||
* Holds if data may flow from `mid` to `node`. The last step in or out of
|
||||
* a callable is recorded by `cc`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
pragma[nomagic]
|
||||
private predicate pathStep(
|
||||
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
|
||||
|
||||
@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
|
||||
/**
|
||||
* Gets the number of `AccessPath`s that correspond to `apa`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
evalUnfold(apa, false, config) and
|
||||
result = 1 and
|
||||
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
* that it is expanded to a precise head-tail representation.
|
||||
*/
|
||||
language[monotonicAggregates]
|
||||
pragma[assume_small_delta]
|
||||
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
|
||||
apa instanceof AccessPathApproxNil and result = 1
|
||||
or
|
||||
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
|
||||
}
|
||||
|
||||
private newtype TPathNode =
|
||||
pragma[assume_small_delta]
|
||||
TPathNodeMid(
|
||||
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
|
||||
) {
|
||||
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
|
||||
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override AccessPathApproxCons getApprox() {
|
||||
result = TConsNil(head, tail.(AccessPathNil).getType())
|
||||
or
|
||||
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
result = TCons1(head, this.length())
|
||||
}
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override int length() { result = 1 + tail.length() }
|
||||
|
||||
private string toStringImpl(boolean needsSuffix) {
|
||||
@@ -3155,6 +3160,7 @@ private predicate pathNode(
|
||||
* Holds if data may flow from `mid` to `node`. The last step in or out of
|
||||
* a callable is recorded by `cc`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
pragma[nomagic]
|
||||
private predicate pathStep(
|
||||
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/csharp-queries
|
||||
version: 0.4.3
|
||||
version: 0.4.4-dev
|
||||
groups:
|
||||
- csharp
|
||||
- queries
|
||||
|
||||
@@ -819,13 +819,15 @@ A class definition has the following syntax:
|
||||
|
||||
::
|
||||
|
||||
class ::= qldoc? annotations "class" classname "extends" type ("," type)* "{" member* "}"
|
||||
class ::= qldoc? annotations "class" classname ("extends" type ("," type)*)? ("instanceof" type ("," type)*)? "{" member* "}"
|
||||
|
||||
The identifier following the ``class`` keyword is the name of the class.
|
||||
|
||||
The types specified after the ``extends`` keyword are the *base types* of the class.
|
||||
|
||||
A class domain type is said to *inherit* from the base types of the associated class type, a character type is said to *inherit* from its associated class domain type and a class type is said to *inherit* from its associated character type. In addition, inheritance is transitive: If a type ``A`` inherits from a type ``B``, and ``B`` inherits from a type ``C``, then ``A`` inherits from ``C``.
|
||||
The types specified after the ``instanceof`` keyword are the *instanceof types* of the class.
|
||||
|
||||
A class type is said to *inherit* from the base types. In addition, inheritance is transitive: If a type ``A`` inherits from a type ``B``, and ``B`` inherits from a type ``C``, then ``A`` inherits from ``C``.
|
||||
|
||||
A class adds a mapping from the class name to the class declaration to the current module's declared type environment.
|
||||
|
||||
@@ -833,6 +835,20 @@ A valid class can be annotated with ``abstract``, ``final``, ``library``, and ``
|
||||
|
||||
A valid class may not inherit from a final class, from itself, or from more than one primitive type.
|
||||
|
||||
A valid class must have at least one base type or instanceof type.
|
||||
|
||||
Class dependencies
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The program is invalid if there is a cycle of class dependencies.
|
||||
|
||||
The following are class dependencies:
|
||||
- ``C`` depends on ``C.C``
|
||||
- ``C.C`` depends on ``C.extends``
|
||||
- If ``C`` is abstract then it depends on all classes ``D`` such that ``C`` is a base type of ``D``.
|
||||
- ``C.extends`` depends on ``D.D`` for each base type ``D`` of ``C``.
|
||||
- ``C.extends`` depends on ``D`` for each instanceof type ``D`` of ``C``.
|
||||
|
||||
Class environments
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@@ -848,7 +864,9 @@ For each of member predicates and fields a class *inherits* and *declares*, and
|
||||
|
||||
The program is invalid if any of these environments is not definite.
|
||||
|
||||
For each of member predicates and fields a domain type *exports* an environment. This is the union of the exported ``X`` environments of types the class inherits from, excluding any elements that are ``overridden`` by another element.
|
||||
For each of member predicates and fields a domain type *exports* an environment. We say the *exported X extends environment* is the union of the exported ``X`` environments of types the class inherits from, excluding any elements that are ``overridden`` by another element.
|
||||
We say the *exported X instanceof environement* is the union of the exported ``X`` environments of types that a instanceof type inherits from, excluding any elements that are ``overridden`` by another element.
|
||||
The *exported X environment* of the domain type is the union of the exported ``X`` extends environment and the exported ``X`` instanceof environement.
|
||||
|
||||
Members
|
||||
~~~~~~~
|
||||
@@ -1090,11 +1108,7 @@ A super expression has the following syntax:
|
||||
|
||||
super_expr ::= "super" | type "." "super"
|
||||
|
||||
For a super expression to be valid, the ``this`` keyword must have a type and value in the typing environment. The type of the expression is the same as the type of ``this`` in the typing environment.
|
||||
|
||||
A super expression may only occur in a QL program as the receiver expression for a predicate call.
|
||||
|
||||
If a super expression includes a ``type``, then that type must be a class that the enclosing class inherits from.
|
||||
For a super expression to be valid, the ``this`` keyword must have a type and value in the typing environment. The type of the expression is the same as the domain type of the type of ``this`` in the typing environment.
|
||||
|
||||
The value of a super expression is the same as the value of ``this`` in the named tuple.
|
||||
|
||||
@@ -1147,13 +1161,6 @@ A valid call with results *resolves* to a set of predicates. The ways a call can
|
||||
|
||||
- If the call has no receiver and the predicate name is a selection identifier, then the qualifier is resolved as a module (see "`Module resolution <#module-resolution>`__"). The identifier is then resolved in the exported predicate environment of the qualifier module.
|
||||
|
||||
- If the call has a super expression as the receiver, then it resolves to a member predicate in a class that the enclosing class inherits from:
|
||||
- If the super expression is unqualified and there is a single class that the current class inherits from, then the super-class is that class.
|
||||
- If the super expression is unqualified and there are multiple classes that the current class inherits from, then the super-class is the domain type.
|
||||
- Otherwise, the super-class is the class named by the qualifier of the super expression.
|
||||
|
||||
The predicate is resolved by looking up its name and arity in the exported predicate environment of the super-class.
|
||||
|
||||
- If the type of the receiver is the same as the enclosing class, the predicate is resolved by looking up its name and arity in the visible predicate environment of the class.
|
||||
|
||||
- If the type of the receiver is not the same as the enclosing class, the predicate is resolved by looking up its name and arity in the exported predicate environment of the class or domain type.
|
||||
@@ -1177,11 +1184,20 @@ If the resolved predicate is built in, then the call may not include a closure.
|
||||
|
||||
If the call includes a closure, then all declared predicate arguments, the enclosing type of the declaration (if it exists), and the result type of the declaration (if it exists) must be compatible. If one of those types is a subtype of ``int``, then all the other arguments must be a subtype of ``int``.
|
||||
|
||||
A call to a member predicate may be a *direct* call:
|
||||
- If the receiver is not a super expression it is not direct.
|
||||
- If the receiver is ``A.super`` and ``A`` is an instanceof type and not a base type then it is not direct.
|
||||
- If the receiver is ``A.super`` and ``A`` is a base type type and not an instanceof type then it is direct.
|
||||
- If the receiver is ``A.super`` and ``A`` is a base type and an instanceof type then the call is not valid.
|
||||
- If the receiver is ``super`` and the member predicate is in the exported member predicate environment of an instanceof type and not in the exported member predicate environment of a base type then it isn't direct.
|
||||
- If the receiver is ``super`` and the member predicate is in the exported member predicate environment of a base type and not in the exported member predicate environment of an instanceof type then it is direct.
|
||||
- If the receiver is ``super`` and the member predicate is in the exported member predicate environment of a base type and in the exported member predicate environment of an instanceof type then the call is not valid.
|
||||
|
||||
If the call resolves to a member predicate, then the *receiver values* are as follows. If the call has a receiver, then the receiver values are the values of that receiver. If the call does not have a receiver, then the single receiver value is the value of ``this`` in the contextual named tuple.
|
||||
|
||||
The *tuple prefixes* of a call with results include one value from each of the argument expressions' values, in the same order as the order of the arguments. If the call resolves to a non-member predicate, then those values are exactly the tuple prefixes of the call. If the call instead resolves to a member predicate, then the tuple prefixes additionally include a receiver value, ordered before the argument values.
|
||||
|
||||
The *matching tuples* of a call with results are all ordered tuples that are one of the tuple prefixes followed by any value of the same type as the call. If the call has no closure, then all matching tuples must additionally satisfy the resolved predicate of the call, unless the receiver is a super expression, in which case they must *directly* satisfy the resolved predicate of the call. If the call has a ``*`` or ``+`` closure, then the matching tuples must satisfy or directly satisfy the associated closure of the resolved predicate.
|
||||
The *matching tuples* of a call with results are all ordered tuples that are one of the tuple prefixes followed by any value of the same type as the call. If the call has no closure, then all matching tuples must additionally satisfy the resolved predicate of the call, unless the call is direct in which case they must *directly* satisfy the resolved predicate of the call. If the call has a ``*`` or ``+`` closure, then the matching tuples must satisfy or directly satisfy the associated closure of the resolved predicate.
|
||||
|
||||
The values of a call with results are the final elements of each of the call's matching tuples.
|
||||
|
||||
@@ -1534,13 +1550,15 @@ The identifier is called the *predicate name* of the call.
|
||||
|
||||
A call must resolve to a predicate, using the same definition of resolve as for calls with results (see "`Calls with results <#calls-with-results>`__").
|
||||
|
||||
A call may be direct using the same definition of direct as for calls with results (see "`Calls with results <#calls-with-results>`__").
|
||||
|
||||
The resolved predicate must not have a result type.
|
||||
|
||||
If the resolved predicate is a built-in member predicate of a primitive type, then the call may not include a closure. If the call does have a closure, then the call must resolve to a predicate with relational arity of 2.
|
||||
|
||||
The *candidate tuples* of a call are the ordered tuples formed by selecting a value from each of the arguments of the call.
|
||||
|
||||
If the call has no closure, then it matches whenever one of the candidate tuples satisfies the resolved predicate of the call, unless the call has a super expression as a receiver, in which case the candidate tuple must *directly* satisfy the resolved predicate. If the call has ``*`` or ``+`` closure, then the call matches whenever one of the candidate tuples satisfies or directly satisfies the associated closure of the resolved predicate.
|
||||
If the call has no closure, then it matches whenever one of the candidate tuples satisfies the resolved predicate of the call, unless the call is direct, in which case the candidate tuple must *directly* satisfy the resolved predicate. If the call has ``*`` or ``+`` closure, then the call matches whenever one of the candidate tuples satisfies or directly satisfies the associated closure of the resolved predicate.
|
||||
|
||||
Disambiguation of formulas
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@@ -1926,10 +1944,12 @@ Predicates, and types can *depend* and *strictly depend* on each other. Such dep
|
||||
|
||||
- A predicate containing a predicate call depends on the predicate to which the call resolves. If the call has negative or zero polarity then the dependency is strict.
|
||||
|
||||
- A predicate containing a predicate call, which resolves to a member predicate and does not have a ``super`` expression as a qualifier, depends on the dispatch dependencies of the root definitions of the target of the call. If the call has negative or zero polarity then the dependencies are strict. The predicate strictly depends on the strict dispatch dependencies of the root definitions.
|
||||
- A predicate containing a predicate call, which resolves to a member predicate, where the call is not direct, depends on the dispatch dependencies of the root definitions of the target of the call. If the call has negative or zero polarity then the dependencies are strict. The predicate strictly depends on the strict dispatch dependencies of the root definitions.
|
||||
|
||||
- For each class ``C`` in the program, for each base class ``B`` of ``C``, ``C.extends`` depends on ``B.B``.
|
||||
|
||||
- For each class ``C`` in the program, for each instanceof type ``B`` of ``C``, ``C.extends`` depends on ``B``.
|
||||
|
||||
- For each class ``C`` in the program, for each base type ``B`` of ``C`` that is not a class type, ``C.extends`` depends on ``B``.
|
||||
|
||||
- For each class ``C`` in the program, ``C.class`` depends on ``C.C``.
|
||||
@@ -1976,6 +1996,7 @@ Each layer of the stratification is *populated* in order. To populate a layer, e
|
||||
- To populate the type ``C.extends`` for a class ``C``, identify each named tuple that has the following properties:
|
||||
|
||||
- The value of ``this`` is in all non-class base types of ``C``.
|
||||
- The value of ``this`` is in all instanceof types of ``C``.
|
||||
- The keys of the tuple are ``this`` and the union of the public fields from each base type.
|
||||
- For each class base type ``B`` of ``C`` there is a named tuple with variables from the public fields of ``B`` and ``this`` that the given tuple and some tuple in ``B.B`` both extend.
|
||||
|
||||
@@ -2060,7 +2081,7 @@ The complete grammar for QL is as follows:
|
||||
| "{" formula "}"
|
||||
| "=" literalId "(" (predicateRef "/" int ("," predicateRef "/" int)*)? ")" "(" (exprs)? ")"
|
||||
|
||||
class ::= qldoc? annotations "class" classname "extends" type ("," type)* "{" member* "}"
|
||||
class ::= qldoc? annotations "class" classname ("extends" type ("," type)*)? ("instanceof" type ("," type)*)? "{" member* "}"
|
||||
|
||||
member ::= character | predicate | field
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/go-all
|
||||
version: 0.3.3
|
||||
version: 0.3.4-dev
|
||||
groups: go
|
||||
dbscheme: go.dbscheme
|
||||
extractor: go
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/go-queries
|
||||
version: 0.3.3
|
||||
version: 0.3.4-dev
|
||||
groups:
|
||||
- go
|
||||
- queries
|
||||
|
||||
@@ -80,7 +80,7 @@ class ExternalDeclExtractor(val logger: FileLogger, val invocationTrapFile: Stri
|
||||
}
|
||||
// Now elevate to a SourceFileTrapWriter, and populate the
|
||||
// file information if needed:
|
||||
val ftw = tw.makeFileTrapWriter(binaryPath, irDecl is IrClass)
|
||||
val ftw = tw.makeFileTrapWriter(binaryPath, true)
|
||||
|
||||
val fileExtractor = KotlinFileExtractor(logger, ftw, null, binaryPath, manager, this, primitiveTypeMapping, pluginContext, KotlinFileExtractor.DeclarationStack(), globalExtensionState)
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyFunction
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
@@ -1051,8 +1052,8 @@ open class KotlinFileExtractor(
|
||||
if (!f.hasAnnotation(jvmOverloadsFqName))
|
||||
return
|
||||
|
||||
fun extractGeneratedOverload(paramList: List<IrElement>) {
|
||||
val overloadParameters = paramList.filterIsInstance<IrValueParameter>()
|
||||
fun extractGeneratedOverload(paramList: List<IrValueParameter?>) {
|
||||
val overloadParameters = paramList.filterNotNull()
|
||||
// Note `overloadParameters` have incorrect parents and indices, since there is no actual IrFunction describing the required synthetic overload.
|
||||
// We have to use the `overriddenAttributes` element of `DeclarationStackAdjuster` to fix up references to these parameters while we're extracting
|
||||
// these synthetic overloads.
|
||||
@@ -1072,67 +1073,33 @@ open class KotlinFileExtractor(
|
||||
|
||||
DeclarationStackAdjuster(f, overriddenAttributes).use {
|
||||
|
||||
fun extractNormalArgs(argParentId: Label<out DbExprparent>, idxOffset: Int, enclosingStmtId: Label<out DbStmt>) {
|
||||
paramList.forEachIndexed { idx, param ->
|
||||
when(param) {
|
||||
is IrValueParameter -> {
|
||||
// Forward a parameter:
|
||||
val syntheticParamId = useValueParameter(param, overloadId)
|
||||
extractVariableAccess(syntheticParamId, param.type, realFunctionLocId, argParentId, idxOffset + idx, overloadId, enclosingStmtId)
|
||||
}
|
||||
is IrExpression -> {
|
||||
// Supply a default argument:
|
||||
extractExpressionExpr(param, overloadId, argParentId, idxOffset + idx, enclosingStmtId)
|
||||
}
|
||||
else -> {
|
||||
logger.errorElement("Unexpected parameter list entry", param)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Create a synthetic function body that calls the corresponding $default function:
|
||||
val regularArgs = paramList.map { it?.let { p -> IrGetValueImpl(-1, -1, p.symbol) } }
|
||||
|
||||
// Create a synthetic function body that calls the real function supplying default arguments where required:
|
||||
if (f is IrConstructor) {
|
||||
val blockId = extractBlockBody(overloadId, realFunctionLocId)
|
||||
val constructorCallId = tw.getFreshIdLabel<DbConstructorinvocationstmt>()
|
||||
tw.writeStmts_constructorinvocationstmt(constructorCallId, blockId, 0, overloadId)
|
||||
tw.writeHasLocation(constructorCallId, realFunctionLocId)
|
||||
tw.writeCallableBinding(constructorCallId, useFunction(f))
|
||||
tw.writeCallableBinding(constructorCallId, getDefaultsMethodLabel(f))
|
||||
|
||||
extractNormalArgs(constructorCallId, 0, constructorCallId)
|
||||
extractDefaultsCallArguments(constructorCallId, f, overloadId, constructorCallId, regularArgs, null, null)
|
||||
} else {
|
||||
val dispatchReceiver = f.dispatchReceiverParameter?.let { IrGetValueImpl(-1, -1, it.symbol) }
|
||||
val extensionReceiver = f.extensionReceiverParameter?.let { IrGetValueImpl(-1, -1, it.symbol) }
|
||||
|
||||
extractExpressionBody(overloadId, realFunctionLocId).also { returnId ->
|
||||
extractRawMethodAccess(
|
||||
f,
|
||||
realFunctionLocId,
|
||||
f.returnType,
|
||||
overloadId,
|
||||
returnId,
|
||||
0,
|
||||
returnId,
|
||||
f.valueParameters.size,
|
||||
{ argParentId, idxOffset ->
|
||||
extractNormalArgs(argParentId, idxOffset, returnId)
|
||||
},
|
||||
f.dispatchReceiverParameter?.type,
|
||||
f.dispatchReceiverParameter?.let { { callId ->
|
||||
extractThisAccess(it.type, overloadId, callId, -1, returnId, realFunctionLocId)
|
||||
} },
|
||||
f.extensionReceiverParameter?.let { { argParentId ->
|
||||
val syntheticParamId = useValueParameter(it, overloadId)
|
||||
extractVariableAccess(syntheticParamId, it.type, realFunctionLocId, argParentId, 0, overloadId, returnId)
|
||||
} }
|
||||
)
|
||||
extractsDefaultsCall(f, realFunctionLocId, f.returnType, overloadId, returnId, 0, returnId, regularArgs, dispatchReceiver, extensionReceiver)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val paramList: MutableList<IrElement> = f.valueParameters.toMutableList()
|
||||
for (n in (paramList.size - 1) downTo 0) {
|
||||
(paramList[n] as? IrValueParameter)?.defaultValue?.expression?.let {
|
||||
paramList[n] = it // Replace the last parameter that has a default with that default value.
|
||||
val paramList: MutableList<IrValueParameter?> = f.valueParameters.toMutableList()
|
||||
for (n in (f.valueParameters.size - 1) downTo 0) {
|
||||
if (f.valueParameters[n].defaultValue != null) {
|
||||
paramList[n] = null // Remove this parameter, to be replaced by a default value
|
||||
extractGeneratedOverload(paramList)
|
||||
}
|
||||
}
|
||||
@@ -2122,7 +2089,7 @@ open class KotlinFileExtractor(
|
||||
private fun extractCallValueArguments(callId: Label<out DbExprparent>, valueArguments: List<IrExpression?>, enclosingStmt: Label<out DbStmt>, enclosingCallable: Label<out DbCallable>, idxOffset: Int, extractVarargAsArray: Boolean = false) {
|
||||
var i = 0
|
||||
valueArguments.forEach { arg ->
|
||||
if(arg != null) {
|
||||
if (arg != null) {
|
||||
if (arg is IrVararg && !extractVarargAsArray) {
|
||||
arg.elements.forEachIndexed { varargNo, vararg -> extractVarargElement(vararg, enclosingCallable, callId, i + idxOffset + varargNo, enclosingStmt) }
|
||||
i += arg.elements.size
|
||||
@@ -3063,15 +3030,31 @@ open class KotlinFileExtractor(
|
||||
val isAnonymous = eType.isAnonymous
|
||||
val locId = tw.getLocation(e)
|
||||
val valueArgs = (0 until e.valueArgumentsCount).map { e.getValueArgument(it) }
|
||||
// For now, don't try to use default methods for enum constructor calls,
|
||||
// which have null arguments even though the parameters don't give default values.
|
||||
|
||||
val id = if (e !is IrEnumConstructorCall && callUsesDefaultArguments(e.symbol.owner, valueArgs)) {
|
||||
extractNewExpr(getDefaultsMethodLabel(e.symbol.owner).cast(), type, locId, parent, idx, callable, enclosingStmt).also {
|
||||
extractDefaultsCallArguments(it, e.symbol.owner, callable, enclosingStmt, valueArgs, null, null)
|
||||
}
|
||||
} else {
|
||||
extractNewExpr(e.symbol.owner, eType.arguments, type, locId, parent, idx, callable, enclosingStmt).also {
|
||||
extractCallValueArguments(it, e, enclosingStmt, callable, 0)
|
||||
|
||||
val realCallTarget = e.symbol.owner.realOverrideTarget
|
||||
// Generated constructor calls to kotlin.Enum have no arguments in IR, but the constructor takes two parameters.
|
||||
if (e is IrEnumConstructorCall &&
|
||||
realCallTarget is IrConstructor &&
|
||||
realCallTarget.parentClassOrNull?.fqNameWhenAvailable?.asString() == "kotlin.Enum" &&
|
||||
realCallTarget.valueParameters.size == 2 &&
|
||||
realCallTarget.valueParameters[0].type == pluginContext.irBuiltIns.stringType &&
|
||||
realCallTarget.valueParameters[1].type == pluginContext.irBuiltIns.intType) {
|
||||
|
||||
val id0 = extractNull(pluginContext.irBuiltIns.stringType, locId, it, 0, callable, enclosingStmt)
|
||||
tw.writeCompiler_generated(id0, CompilerGeneratedKinds.ENUM_CONSTRUCTOR_ARGUMENT.kind)
|
||||
|
||||
val id1 = extractConstantInteger(0, locId, it, 1, callable, enclosingStmt)
|
||||
tw.writeCompiler_generated(id1, CompilerGeneratedKinds.ENUM_CONSTRUCTOR_ARGUMENT.kind)
|
||||
} else {
|
||||
extractCallValueArguments(it, e, enclosingStmt, callable, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3396,6 +3379,14 @@ open class KotlinFileExtractor(
|
||||
extractExprContext(it, locId, callable, enclosingStmt)
|
||||
}
|
||||
|
||||
private fun extractNull(t: IrType, locId: Label<DbLocation>, parent: Label<out DbExprparent>, idx: Int, callable: Label<out DbCallable>, enclosingStmt: Label<out DbStmt>) =
|
||||
tw.getFreshIdLabel<DbNullliteral>().also {
|
||||
val type = useType(t)
|
||||
tw.writeExprs_nullliteral(it, type.javaResult.id, parent, idx)
|
||||
tw.writeExprsKotlinType(it, type.kotlinResult.id)
|
||||
extractExprContext(it, locId, callable, enclosingStmt)
|
||||
}
|
||||
|
||||
private fun extractAssignExpr(type: IrType, locId: Label<DbLocation>, parent: Label<out DbExprparent>, idx: Int, callable: Label<out DbCallable>, enclosingStmt: Label<out DbStmt>) =
|
||||
tw.getFreshIdLabel<DbAssignexpr>().also {
|
||||
val typeResults = useType(type)
|
||||
@@ -3614,12 +3605,7 @@ open class KotlinFileExtractor(
|
||||
tw.writeNamestrings(v.toString(), v.toString(), id)
|
||||
}
|
||||
v == null -> {
|
||||
val id = tw.getFreshIdLabel<DbNullliteral>()
|
||||
val type = useType(e.type) // class;kotlin.Nothing
|
||||
val locId = tw.getLocation(e)
|
||||
tw.writeExprs_nullliteral(id, type.javaResult.id, exprParent.parent, exprParent.idx)
|
||||
tw.writeExprsKotlinType(id, type.kotlinResult.id)
|
||||
extractExprContext(id, locId, callable, exprParent.enclosingStmt)
|
||||
extractNull(e.type, tw.getLocation(e), exprParent.parent, exprParent.idx, callable, exprParent.enclosingStmt)
|
||||
}
|
||||
else -> {
|
||||
logger.errorElement("Unrecognised IrConst: " + v.javaClass, e)
|
||||
@@ -5516,5 +5502,6 @@ open class KotlinFileExtractor(
|
||||
JVMOVERLOADS_METHOD(9),
|
||||
DEFAULT_ARGUMENTS_METHOD(10),
|
||||
INTERFACE_FORWARDER(11),
|
||||
ENUM_CONSTRUCTOR_ARGUMENT(12),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -963,9 +963,9 @@ open class KotlinUsesExtractor(
|
||||
private fun wildcardAdditionAllowed(v: Variance, t: IrType, addByDefault: Boolean, javaVariance: Variance?) =
|
||||
when {
|
||||
t.hasAnnotation(jvmWildcardAnnotation) -> true
|
||||
!addByDefault -> false
|
||||
// If a Java declaration specifies a variance, introduce it even if it's pointless (e.g. ? extends FinalClass, or ? super Object)
|
||||
javaVariance == v -> true
|
||||
!addByDefault -> false
|
||||
v == Variance.IN_VARIANCE -> !(t.isNullableAny() || t.isAny())
|
||||
v == Variance.OUT_VARIANCE -> extendsAdditionAllowed(t)
|
||||
else -> false
|
||||
@@ -1006,8 +1006,9 @@ open class KotlinUsesExtractor(
|
||||
null
|
||||
} ?: t
|
||||
|
||||
private fun getJavaTypeArgument(jt: JavaType, idx: Int) =
|
||||
private fun getJavaTypeArgument(jt: JavaType, idx: Int): JavaType? =
|
||||
when(jt) {
|
||||
is JavaWildcardType -> jt.bound?.let { getJavaTypeArgument(it, idx) }
|
||||
is JavaClassifierType -> jt.typeArguments.getOrNull(idx)
|
||||
is JavaArrayType -> if (idx == 0) jt.componentType else null
|
||||
else -> null
|
||||
|
||||
9
java/ql/consistency-queries/callArgs.ql
Normal file
9
java/ql/consistency-queries/callArgs.ql
Normal file
@@ -0,0 +1,9 @@
|
||||
import java
|
||||
|
||||
from Call call, Callable c
|
||||
where
|
||||
count(call.getAnArgument()) != c.getNumberOfParameters() and
|
||||
call.getCallee() = c and
|
||||
not exists(Parameter p | c.getAParameter() = p and p.isVarargs()) and
|
||||
call.getFile().isKotlinSourceFile()
|
||||
select call, c, count(call.getAnArgument()), c.getNumberOfParameters()
|
||||
@@ -0,0 +1,18 @@
|
||||
public class JavaDefns2 {
|
||||
|
||||
// Currently known not to work: the Comparable<? extends X> case, which Kotlin sees as Comparable<*> because the
|
||||
// wildcard goes the opposite direction to the variance declared on Comparable's type parameter.
|
||||
|
||||
public static void takesComparable(Comparable<CharSequence> invar, Comparable<? super CharSequence> contravar) { }
|
||||
|
||||
public static void takesNestedComparable(Comparable<Comparable<? super CharSequence>> innerContravar, Comparable<? super Comparable<CharSequence>> outerContravar) { }
|
||||
|
||||
public static void takesArrayOfComparable(Comparable<CharSequence>[] invar, Comparable<? super CharSequence>[] contravar) { }
|
||||
|
||||
public static Comparable<? super CharSequence> returnsWildcard() { return null; }
|
||||
|
||||
public static Comparable<CharSequence> returnsInvariant() { return null; }
|
||||
|
||||
public JavaDefns2(Comparable<CharSequence> invar, Comparable<? super CharSequence> contravar) { }
|
||||
|
||||
}
|
||||
@@ -7,4 +7,6 @@ fun user() {
|
||||
JavaDefns.takesArrayOfComparable(acs, acs)
|
||||
|
||||
val constructed = JavaDefns(cs, cs)
|
||||
|
||||
JavaDefns2.takesComparable(cs, cs)
|
||||
}
|
||||
|
||||
@@ -8,6 +8,16 @@
|
||||
| JavaDefns | takesComparable | invar | Comparable<CharSequence> |
|
||||
| JavaDefns | takesNestedComparable | innerContravar | Comparable<Comparable<? super CharSequence>> |
|
||||
| JavaDefns | takesNestedComparable | outerContravar | Comparable<? super Comparable<CharSequence>> |
|
||||
| JavaDefns2 | JavaDefns2 | p0 | Comparable<CharSequence> |
|
||||
| JavaDefns2 | JavaDefns2 | p1 | Comparable<? super CharSequence> |
|
||||
| JavaDefns2 | returnsInvariant | return | Comparable<CharSequence> |
|
||||
| JavaDefns2 | returnsWildcard | return | Comparable<? super CharSequence> |
|
||||
| JavaDefns2 | takesArrayOfComparable | p0 | Comparable<CharSequence>[] |
|
||||
| JavaDefns2 | takesArrayOfComparable | p1 | Comparable<? super CharSequence>[] |
|
||||
| JavaDefns2 | takesComparable | p0 | Comparable<CharSequence> |
|
||||
| JavaDefns2 | takesComparable | p1 | Comparable<? super CharSequence> |
|
||||
| JavaDefns2 | takesNestedComparable | p0 | Comparable<Comparable<? super CharSequence>> |
|
||||
| JavaDefns2 | takesNestedComparable | p1 | Comparable<? super Comparable<CharSequence>> |
|
||||
| KotlinDefns | returnsContravar | return | Comparable<CharSequence> |
|
||||
| KotlinDefns | returnsContravarForced | return | Comparable<? super CharSequence> |
|
||||
| KotlinDefns | returnsCovar | return | List<CharSequence> |
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
from create_database_utils import *
|
||||
|
||||
# Compile the JavaDefns2 copy outside tracing, to make sure the Kotlin view of it matches the Java view seen by the traced javac compilation of JavaDefns.java below.
|
||||
runSuccessfully(["javac", "JavaDefns2.java"])
|
||||
run_codeql_database_create(["kotlinc kotlindefns.kt", "javac JavaUser.java JavaDefns.java -cp .", "kotlinc -cp . kotlinuser.kt"], lang="java")
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import java
|
||||
|
||||
predicate isInterestingClass(Class c) {
|
||||
[c, c.(NestedType).getEnclosingType()].getName().matches(["KotlinDefns%", "JavaDefns"])
|
||||
[c, c.(NestedType).getEnclosingType()].getName().matches(["KotlinDefns%", "JavaDefns%"])
|
||||
}
|
||||
|
||||
from Callable c, string paramOrReturnName, Type paramOrReturnType
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added data flow summaries for tainted Android intents sent to activities via `Activity.startActivities`.
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/java-all
|
||||
version: 0.4.3
|
||||
version: 0.4.4-dev
|
||||
groups: java
|
||||
dbscheme: config/semmlecode.dbscheme
|
||||
extractor: java
|
||||
|
||||
@@ -69,6 +69,8 @@ class Element extends @element, Top {
|
||||
i = 10 and result = "Forwarder for Kotlin calls that need default arguments filling in"
|
||||
or
|
||||
i = 11 and result = "Forwarder for a Kotlin class inheriting an interface default method"
|
||||
or
|
||||
i = 12 and result = "Argument for enum constructor call"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,9 @@ module SummaryComponent {
|
||||
/** Gets a summary component for `Element`. */
|
||||
SummaryComponent element() { result = content(any(CollectionContent c)) }
|
||||
|
||||
/** Gets a summary component for `ArrayElement`. */
|
||||
SummaryComponent arrayElement() { result = content(any(ArrayContent c)) }
|
||||
|
||||
/** Gets a summary component for `MapValue`. */
|
||||
SummaryComponent mapValue() { result = content(any(MapValueContent c)) }
|
||||
|
||||
@@ -52,6 +55,11 @@ module SummaryComponentStack {
|
||||
result = push(SummaryComponent::element(), object)
|
||||
}
|
||||
|
||||
/** Gets a stack representing `ArrayElement` of `object`. */
|
||||
SummaryComponentStack arrayElementOf(SummaryComponentStack object) {
|
||||
result = push(SummaryComponent::arrayElement(), object)
|
||||
}
|
||||
|
||||
/** Gets a stack representing `MapValue` of `object`. */
|
||||
SummaryComponentStack mapValueOf(SummaryComponentStack object) {
|
||||
result = push(SummaryComponent::mapValue(), object)
|
||||
|
||||
@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
|
||||
/**
|
||||
* Gets the number of `AccessPath`s that correspond to `apa`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
evalUnfold(apa, false, config) and
|
||||
result = 1 and
|
||||
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
* that it is expanded to a precise head-tail representation.
|
||||
*/
|
||||
language[monotonicAggregates]
|
||||
pragma[assume_small_delta]
|
||||
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
|
||||
apa instanceof AccessPathApproxNil and result = 1
|
||||
or
|
||||
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
|
||||
}
|
||||
|
||||
private newtype TPathNode =
|
||||
pragma[assume_small_delta]
|
||||
TPathNodeMid(
|
||||
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
|
||||
) {
|
||||
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
|
||||
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override AccessPathApproxCons getApprox() {
|
||||
result = TConsNil(head, tail.(AccessPathNil).getType())
|
||||
or
|
||||
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
result = TCons1(head, this.length())
|
||||
}
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override int length() { result = 1 + tail.length() }
|
||||
|
||||
private string toStringImpl(boolean needsSuffix) {
|
||||
@@ -3155,6 +3160,7 @@ private predicate pathNode(
|
||||
* Holds if data may flow from `mid` to `node`. The last step in or out of
|
||||
* a callable is recorded by `cc`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
pragma[nomagic]
|
||||
private predicate pathStep(
|
||||
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
|
||||
|
||||
@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
|
||||
/**
|
||||
* Gets the number of `AccessPath`s that correspond to `apa`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
evalUnfold(apa, false, config) and
|
||||
result = 1 and
|
||||
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
* that it is expanded to a precise head-tail representation.
|
||||
*/
|
||||
language[monotonicAggregates]
|
||||
pragma[assume_small_delta]
|
||||
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
|
||||
apa instanceof AccessPathApproxNil and result = 1
|
||||
or
|
||||
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
|
||||
}
|
||||
|
||||
private newtype TPathNode =
|
||||
pragma[assume_small_delta]
|
||||
TPathNodeMid(
|
||||
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
|
||||
) {
|
||||
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
|
||||
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override AccessPathApproxCons getApprox() {
|
||||
result = TConsNil(head, tail.(AccessPathNil).getType())
|
||||
or
|
||||
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
result = TCons1(head, this.length())
|
||||
}
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override int length() { result = 1 + tail.length() }
|
||||
|
||||
private string toStringImpl(boolean needsSuffix) {
|
||||
@@ -3155,6 +3160,7 @@ private predicate pathNode(
|
||||
* Holds if data may flow from `mid` to `node`. The last step in or out of
|
||||
* a callable is recorded by `cc`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
pragma[nomagic]
|
||||
private predicate pathStep(
|
||||
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
|
||||
|
||||
@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
|
||||
/**
|
||||
* Gets the number of `AccessPath`s that correspond to `apa`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
evalUnfold(apa, false, config) and
|
||||
result = 1 and
|
||||
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
* that it is expanded to a precise head-tail representation.
|
||||
*/
|
||||
language[monotonicAggregates]
|
||||
pragma[assume_small_delta]
|
||||
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
|
||||
apa instanceof AccessPathApproxNil and result = 1
|
||||
or
|
||||
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
|
||||
}
|
||||
|
||||
private newtype TPathNode =
|
||||
pragma[assume_small_delta]
|
||||
TPathNodeMid(
|
||||
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
|
||||
) {
|
||||
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
|
||||
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override AccessPathApproxCons getApprox() {
|
||||
result = TConsNil(head, tail.(AccessPathNil).getType())
|
||||
or
|
||||
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
result = TCons1(head, this.length())
|
||||
}
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override int length() { result = 1 + tail.length() }
|
||||
|
||||
private string toStringImpl(boolean needsSuffix) {
|
||||
@@ -3155,6 +3160,7 @@ private predicate pathNode(
|
||||
* Holds if data may flow from `mid` to `node`. The last step in or out of
|
||||
* a callable is recorded by `cc`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
pragma[nomagic]
|
||||
private predicate pathStep(
|
||||
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
|
||||
|
||||
@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
|
||||
/**
|
||||
* Gets the number of `AccessPath`s that correspond to `apa`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
evalUnfold(apa, false, config) and
|
||||
result = 1 and
|
||||
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
* that it is expanded to a precise head-tail representation.
|
||||
*/
|
||||
language[monotonicAggregates]
|
||||
pragma[assume_small_delta]
|
||||
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
|
||||
apa instanceof AccessPathApproxNil and result = 1
|
||||
or
|
||||
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
|
||||
}
|
||||
|
||||
private newtype TPathNode =
|
||||
pragma[assume_small_delta]
|
||||
TPathNodeMid(
|
||||
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
|
||||
) {
|
||||
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
|
||||
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override AccessPathApproxCons getApprox() {
|
||||
result = TConsNil(head, tail.(AccessPathNil).getType())
|
||||
or
|
||||
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
result = TCons1(head, this.length())
|
||||
}
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override int length() { result = 1 + tail.length() }
|
||||
|
||||
private string toStringImpl(boolean needsSuffix) {
|
||||
@@ -3155,6 +3160,7 @@ private predicate pathNode(
|
||||
* Holds if data may flow from `mid` to `node`. The last step in or out of
|
||||
* a callable is recorded by `cc`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
pragma[nomagic]
|
||||
private predicate pathStep(
|
||||
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
|
||||
|
||||
@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
|
||||
/**
|
||||
* Gets the number of `AccessPath`s that correspond to `apa`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
evalUnfold(apa, false, config) and
|
||||
result = 1 and
|
||||
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
* that it is expanded to a precise head-tail representation.
|
||||
*/
|
||||
language[monotonicAggregates]
|
||||
pragma[assume_small_delta]
|
||||
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
|
||||
apa instanceof AccessPathApproxNil and result = 1
|
||||
or
|
||||
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
|
||||
}
|
||||
|
||||
private newtype TPathNode =
|
||||
pragma[assume_small_delta]
|
||||
TPathNodeMid(
|
||||
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
|
||||
) {
|
||||
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
|
||||
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override AccessPathApproxCons getApprox() {
|
||||
result = TConsNil(head, tail.(AccessPathNil).getType())
|
||||
or
|
||||
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
result = TCons1(head, this.length())
|
||||
}
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override int length() { result = 1 + tail.length() }
|
||||
|
||||
private string toStringImpl(boolean needsSuffix) {
|
||||
@@ -3155,6 +3160,7 @@ private predicate pathNode(
|
||||
* Holds if data may flow from `mid` to `node`. The last step in or out of
|
||||
* a callable is recorded by `cc`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
pragma[nomagic]
|
||||
private predicate pathStep(
|
||||
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
|
||||
|
||||
@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
|
||||
/**
|
||||
* Gets the number of `AccessPath`s that correspond to `apa`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
evalUnfold(apa, false, config) and
|
||||
result = 1 and
|
||||
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
* that it is expanded to a precise head-tail representation.
|
||||
*/
|
||||
language[monotonicAggregates]
|
||||
pragma[assume_small_delta]
|
||||
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
|
||||
apa instanceof AccessPathApproxNil and result = 1
|
||||
or
|
||||
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
|
||||
}
|
||||
|
||||
private newtype TPathNode =
|
||||
pragma[assume_small_delta]
|
||||
TPathNodeMid(
|
||||
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
|
||||
) {
|
||||
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
|
||||
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override AccessPathApproxCons getApprox() {
|
||||
result = TConsNil(head, tail.(AccessPathNil).getType())
|
||||
or
|
||||
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
result = TCons1(head, this.length())
|
||||
}
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override int length() { result = 1 + tail.length() }
|
||||
|
||||
private string toStringImpl(boolean needsSuffix) {
|
||||
@@ -3155,6 +3160,7 @@ private predicate pathNode(
|
||||
* Holds if data may flow from `mid` to `node`. The last step in or out of
|
||||
* a callable is recorded by `cc`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
pragma[nomagic]
|
||||
private predicate pathStep(
|
||||
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
|
||||
|
||||
@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
|
||||
/**
|
||||
* Gets the number of `AccessPath`s that correspond to `apa`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
evalUnfold(apa, false, config) and
|
||||
result = 1 and
|
||||
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
* that it is expanded to a precise head-tail representation.
|
||||
*/
|
||||
language[monotonicAggregates]
|
||||
pragma[assume_small_delta]
|
||||
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
|
||||
apa instanceof AccessPathApproxNil and result = 1
|
||||
or
|
||||
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
|
||||
}
|
||||
|
||||
private newtype TPathNode =
|
||||
pragma[assume_small_delta]
|
||||
TPathNodeMid(
|
||||
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
|
||||
) {
|
||||
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
|
||||
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override AccessPathApproxCons getApprox() {
|
||||
result = TConsNil(head, tail.(AccessPathNil).getType())
|
||||
or
|
||||
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
result = TCons1(head, this.length())
|
||||
}
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override int length() { result = 1 + tail.length() }
|
||||
|
||||
private string toStringImpl(boolean needsSuffix) {
|
||||
@@ -3155,6 +3160,7 @@ private predicate pathNode(
|
||||
* Holds if data may flow from `mid` to `node`. The last step in or out of
|
||||
* a callable is recorded by `cc`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
pragma[nomagic]
|
||||
private predicate pathStep(
|
||||
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
|
||||
|
||||
@@ -2629,6 +2629,7 @@ private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration
|
||||
/**
|
||||
* Gets the number of `AccessPath`s that correspond to `apa`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
evalUnfold(apa, false, config) and
|
||||
result = 1 and
|
||||
@@ -2647,6 +2648,7 @@ private int countAps(AccessPathApprox apa, Configuration config) {
|
||||
* that it is expanded to a precise head-tail representation.
|
||||
*/
|
||||
language[monotonicAggregates]
|
||||
pragma[assume_small_delta]
|
||||
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
|
||||
apa instanceof AccessPathApproxNil and result = 1
|
||||
or
|
||||
@@ -2681,6 +2683,7 @@ private newtype TAccessPath =
|
||||
}
|
||||
|
||||
private newtype TPathNode =
|
||||
pragma[assume_small_delta]
|
||||
TPathNodeMid(
|
||||
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
|
||||
) {
|
||||
@@ -2778,6 +2781,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
|
||||
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override AccessPathApproxCons getApprox() {
|
||||
result = TConsNil(head, tail.(AccessPathNil).getType())
|
||||
or
|
||||
@@ -2786,6 +2790,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
result = TCons1(head, this.length())
|
||||
}
|
||||
|
||||
pragma[assume_small_delta]
|
||||
override int length() { result = 1 + tail.length() }
|
||||
|
||||
private string toStringImpl(boolean needsSuffix) {
|
||||
@@ -3155,6 +3160,7 @@ private predicate pathNode(
|
||||
* Holds if data may flow from `mid` to `node`. The last step in or out of
|
||||
* a callable is recorded by `cc`.
|
||||
*/
|
||||
pragma[assume_small_delta]
|
||||
pragma[nomagic]
|
||||
private predicate pathStep(
|
||||
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import java
|
||||
private import semmle.code.java.frameworks.android.Android
|
||||
private import semmle.code.java.dataflow.DataFlow
|
||||
private import semmle.code.java.dataflow.ExternalFlow
|
||||
private import semmle.code.java.dataflow.FlowSteps
|
||||
private import semmle.code.java.dataflow.FlowSummary
|
||||
private import semmle.code.java.dataflow.internal.BaseSSA as BaseSsa
|
||||
|
||||
/** The class `android.content.Intent`. */
|
||||
class TypeIntent extends Class {
|
||||
@@ -242,19 +245,52 @@ private class StartComponentMethodAccess extends MethodAccess {
|
||||
|
||||
/** Gets the intent argument of this call. */
|
||||
Argument getIntentArg() {
|
||||
result.getType() instanceof TypeIntent and
|
||||
(
|
||||
result.getType() instanceof TypeIntent or
|
||||
result.getType().(Array).getElementType() instanceof TypeIntent
|
||||
) and
|
||||
result = this.getAnArgument()
|
||||
}
|
||||
|
||||
/** Holds if this targets a component of type `targetType`. */
|
||||
predicate targetsComponentType(RefType targetType) {
|
||||
predicate targetsComponentType(AndroidComponent targetType) {
|
||||
exists(NewIntent newIntent |
|
||||
DataFlow::localExprFlow(newIntent, this.getIntentArg()) and
|
||||
reaches(newIntent, this.getIntentArg()) and
|
||||
newIntent.getClassArg().getType().(ParameterizedType).getATypeArgument() = targetType
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `src` reaches the intent argument `arg` of `StartComponentMethodAccess`
|
||||
* through intra-procedural steps.
|
||||
*/
|
||||
private predicate reaches(Expr src, Argument arg) {
|
||||
any(StartComponentMethodAccess ma).getIntentArg() = arg and
|
||||
src = arg
|
||||
or
|
||||
exists(Expr mid, BaseSsa::BaseSsaVariable ssa, BaseSsa::BaseSsaUpdate upd |
|
||||
reaches(mid, arg) and
|
||||
mid = ssa.getAUse() and
|
||||
upd = ssa.getAnUltimateLocalDefinition() and
|
||||
src = upd.getDefiningExpr().(VariableAssign).getSource()
|
||||
)
|
||||
or
|
||||
exists(CastingExpr e | e.getExpr() = src | reaches(e, arg))
|
||||
or
|
||||
exists(ChooseExpr e | e.getAResultExpr() = src | reaches(e, arg))
|
||||
or
|
||||
exists(AssignExpr e | e.getSource() = src | reaches(e, arg))
|
||||
or
|
||||
exists(ArrayCreationExpr e | e.getInit().getAnInit() = src | reaches(e, arg))
|
||||
or
|
||||
exists(StmtExpr e | e.getResultExpr() = src | reaches(e, arg))
|
||||
or
|
||||
exists(NotNullExpr e | e.getExpr() = src | reaches(e, arg))
|
||||
or
|
||||
exists(WhenExpr e | e.getBranch(_).getAResult() = src | reaches(e, arg))
|
||||
}
|
||||
|
||||
/**
|
||||
* A value-preserving step from the intent argument of a `startActivity` call to
|
||||
* a `getIntent` call in the activity the intent targeted in its constructor.
|
||||
@@ -271,6 +307,87 @@ private class StartActivityIntentStep extends AdditionalValueStep {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `targetType` is targeted by an existing `StartComponentMethodAccess` call
|
||||
* and it's identified by `id`.
|
||||
*/
|
||||
private predicate isTargetableType(AndroidComponent targetType, string id) {
|
||||
exists(StartComponentMethodAccess ma | ma.targetsComponentType(targetType)) and
|
||||
targetType.getQualifiedName() = id
|
||||
}
|
||||
|
||||
private class StartActivitiesSyntheticCallable extends SyntheticCallable {
|
||||
AndroidComponent targetType;
|
||||
|
||||
StartActivitiesSyntheticCallable() {
|
||||
exists(string id |
|
||||
this = "android.content.Activity.startActivities()+" + id and
|
||||
isTargetableType(targetType, id)
|
||||
)
|
||||
}
|
||||
|
||||
override StartComponentMethodAccess getACall() {
|
||||
result.getMethod().hasName("startActivities") and
|
||||
result.targetsComponentType(targetType)
|
||||
}
|
||||
|
||||
override predicate propagatesFlow(
|
||||
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue
|
||||
) {
|
||||
exists(ActivityIntentSyntheticGlobal glob | glob.getTargetType() = targetType |
|
||||
input = SummaryComponentStack::arrayElementOf(SummaryComponentStack::argument(0)) and
|
||||
output = SummaryComponentStack::singleton(SummaryComponent::syntheticGlobal(glob)) and
|
||||
preservesValue = true
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class GetIntentSyntheticCallable extends SyntheticCallable {
|
||||
AndroidComponent targetType;
|
||||
|
||||
GetIntentSyntheticCallable() {
|
||||
exists(string id |
|
||||
this = "android.content.Activity.getIntent()+" + id and
|
||||
isTargetableType(targetType, id)
|
||||
)
|
||||
}
|
||||
|
||||
override Call getACall() {
|
||||
result.getCallee() instanceof AndroidGetIntentMethod and
|
||||
result.getEnclosingCallable().getDeclaringType() = targetType
|
||||
}
|
||||
|
||||
override predicate propagatesFlow(
|
||||
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue
|
||||
) {
|
||||
exists(ActivityIntentSyntheticGlobal glob | glob.getTargetType() = targetType |
|
||||
input = SummaryComponentStack::singleton(SummaryComponent::syntheticGlobal(glob)) and
|
||||
output = SummaryComponentStack::return() and
|
||||
preservesValue = true
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class ActivityIntentSyntheticGlobal extends SummaryComponent::SyntheticGlobal {
|
||||
AndroidComponent targetType;
|
||||
|
||||
ActivityIntentSyntheticGlobal() {
|
||||
exists(string id |
|
||||
this = "ActivityIntentSyntheticGlobal+" + id and
|
||||
isTargetableType(targetType, id)
|
||||
)
|
||||
}
|
||||
|
||||
AndroidComponent getTargetType() { result = targetType }
|
||||
}
|
||||
|
||||
private class RequiredComponentStackForStartActivities extends RequiredSummaryComponentStack {
|
||||
override predicate required(SummaryComponent head, SummaryComponentStack tail) {
|
||||
head = SummaryComponent::arrayElement() and
|
||||
tail = SummaryComponentStack::argument(0)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A value-preserving step from the intent argument of a `sendBroadcast` call to
|
||||
* the intent parameter in the `onReceive` method of the receiver the
|
||||
|
||||
@@ -129,19 +129,20 @@ private predicate isCanonicalTerm(RelevantRegExpTerm term, string str) {
|
||||
min(RelevantRegExpTerm t, Location loc, File file |
|
||||
loc = t.getLocation() and
|
||||
file = t.getFile() and
|
||||
str = t.getRawValue() + "|" + getCanonicalizationFlags(t.getRootTerm())
|
||||
str = getCanonicalizationString(t)
|
||||
|
|
||||
t order by t.getFile().getRelativePath(), loc.getStartLine(), loc.getStartColumn()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a string representation of the flags used with the regular expression.
|
||||
* Only the flags that are relevant for the canonicalization are included.
|
||||
* Gets a string representation of `term` that is used for canonicalization.
|
||||
*/
|
||||
string getCanonicalizationFlags(RegExpTerm root) {
|
||||
root.isRootTerm() and
|
||||
(if RegExpFlags::isIgnoreCase(root) then result = "i" else result = "")
|
||||
private string getCanonicalizationString(RelevantRegExpTerm term) {
|
||||
exists(string ignoreCase |
|
||||
(if RegExpFlags::isIgnoreCase(term.getRootTerm()) then ignoreCase = "i" else ignoreCase = "") and
|
||||
result = term.getRawValue() + "|" + ignoreCase
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -186,12 +187,19 @@ private newtype TInputSymbol =
|
||||
Epsilon()
|
||||
|
||||
/**
|
||||
* Gets the canonical CharClass for `term`.
|
||||
* Gets the the CharClass corresponding to the canonical representative `term`.
|
||||
*/
|
||||
CharClass getCanonicalCharClass(RegExpTerm term) {
|
||||
private CharClass getCharClassForCanonicalTerm(RegExpTerm term) {
|
||||
exists(string str | isCanonicalTerm(term, str) | result = CharClass(str))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a char class that represents `term`, even when `term` is not the canonical representative.
|
||||
*/
|
||||
CharacterClass getCanonicalCharClass(RegExpTerm term) {
|
||||
exists(string str | str = getCanonicalizationString(term) and result = CharClass(str))
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `a` and `b` are input symbols from the same regexp.
|
||||
*/
|
||||
@@ -284,7 +292,7 @@ private module CharacterClasses {
|
||||
*/
|
||||
pragma[noinline]
|
||||
predicate hasChildThatMatchesIgnoringCasingFlags(RegExpCharacterClass cc, string char) {
|
||||
exists(getCanonicalCharClass(cc)) and
|
||||
exists(getCharClassForCanonicalTerm(cc)) and
|
||||
exists(RegExpTerm child | child = cc.getAChild() |
|
||||
char = child.(RegexpCharacterConstant).getValue()
|
||||
or
|
||||
@@ -387,7 +395,7 @@ private module CharacterClasses {
|
||||
private class PositiveCharacterClass extends CharacterClass {
|
||||
RegExpCharacterClass cc;
|
||||
|
||||
PositiveCharacterClass() { this = getCanonicalCharClass(cc) and not cc.isInverted() }
|
||||
PositiveCharacterClass() { this = getCharClassForCanonicalTerm(cc) and not cc.isInverted() }
|
||||
|
||||
override string getARelevantChar() { result = caseNormalize(getAMentionedChar(cc), cc) }
|
||||
|
||||
@@ -400,7 +408,7 @@ private module CharacterClasses {
|
||||
private class InvertedCharacterClass extends CharacterClass {
|
||||
RegExpCharacterClass cc;
|
||||
|
||||
InvertedCharacterClass() { this = getCanonicalCharClass(cc) and cc.isInverted() }
|
||||
InvertedCharacterClass() { this = getCharClassForCanonicalTerm(cc) and cc.isInverted() }
|
||||
|
||||
override string getARelevantChar() {
|
||||
result = nextChar(caseNormalize(getAMentionedChar(cc), cc)) or
|
||||
@@ -435,7 +443,7 @@ private module CharacterClasses {
|
||||
|
||||
PositiveCharacterClassEscape() {
|
||||
isEscapeClass(cc, charClass) and
|
||||
this = getCanonicalCharClass(cc) and
|
||||
this = getCharClassForCanonicalTerm(cc) and
|
||||
charClass = ["d", "s", "w"]
|
||||
}
|
||||
|
||||
@@ -475,7 +483,7 @@ private module CharacterClasses {
|
||||
NegativeCharacterClassEscape() {
|
||||
exists(RegExpTerm cc |
|
||||
isEscapeClass(cc, charClass) and
|
||||
this = getCanonicalCharClass(cc) and
|
||||
this = getCharClassForCanonicalTerm(cc) and
|
||||
charClass = ["D", "S", "W"]
|
||||
)
|
||||
}
|
||||
@@ -652,17 +660,13 @@ predicate delta(State q1, EdgeLabel lbl, State q2) {
|
||||
cc.isUniversalClass() and q1 = before(cc) and lbl = Any() and q2 = after(cc)
|
||||
or
|
||||
q1 = before(cc) and
|
||||
lbl =
|
||||
CharacterClasses::normalize(CharClass(cc.getRawValue() + "|" +
|
||||
getCanonicalizationFlags(cc.getRootTerm()))) and
|
||||
lbl = CharacterClasses::normalize(CharClass(getCanonicalizationString(cc))) and
|
||||
q2 = after(cc)
|
||||
)
|
||||
or
|
||||
exists(RegExpTerm cc | isEscapeClass(cc, _) |
|
||||
q1 = before(cc) and
|
||||
lbl =
|
||||
CharacterClasses::normalize(CharClass(cc.getRawValue() + "|" +
|
||||
getCanonicalizationFlags(cc.getRootTerm()))) and
|
||||
lbl = CharacterClasses::normalize(CharClass(getCanonicalizationString(cc))) and
|
||||
q2 = after(cc)
|
||||
)
|
||||
or
|
||||
|
||||
@@ -26,5 +26,10 @@ where
|
||||
not exists(getARead(v)) and
|
||||
// Discarded exceptions are covered by another query.
|
||||
not exists(CatchClause cc | cc.getVariable().getVariable() = v) and
|
||||
// Exclude common Kotlin pattern to do something n times: `for(i in 1..n) { doSomething() }
|
||||
not exists(EnhancedForStmt f |
|
||||
f.getVariable().getVariable() = v and
|
||||
f.getExpr().getType().(RefType).hasQualifiedName("kotlin.ranges", ["IntRange", "LongRange"])
|
||||
) and
|
||||
not readImplicitly(v)
|
||||
select v, "Variable '" + v + "' is never read."
|
||||
|
||||
@@ -57,6 +57,8 @@ private predicate candidateMethod(RefType t, Method m, string name, int numParam
|
||||
m.getNumberOfParameters() = numParam and
|
||||
m = m.getSourceDeclaration() and
|
||||
not m.getAnAnnotation() instanceof DeprecatedAnnotation and
|
||||
// Exclude compiler generated methods, such as Kotlin `$default` methods:
|
||||
not m.isCompilerGenerated() and
|
||||
not whitelist(name)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/java-queries
|
||||
version: 0.4.3
|
||||
version: 0.4.4-dev
|
||||
groups:
|
||||
- java
|
||||
- queries
|
||||
|
||||
@@ -174,6 +174,8 @@ classes.kt:
|
||||
# 49| 0: [ClassInstanceExpr] new Enum(...)
|
||||
# 49| -3: [TypeAccess] Enum<Direction>
|
||||
# 49| 0: [TypeAccess] Direction
|
||||
# 49| 0: [NullLiteral] null
|
||||
# 49| 1: [IntegerLiteral] 0
|
||||
# 49| 1: [BlockStmt] { ... }
|
||||
# 50| 5: [FieldDeclaration] Direction NORTH;
|
||||
# 50| -1: [TypeAccess] Direction
|
||||
@@ -209,6 +211,8 @@ classes.kt:
|
||||
# 53| 0: [ClassInstanceExpr] new Enum(...)
|
||||
# 53| -3: [TypeAccess] Enum<Color>
|
||||
# 53| 0: [TypeAccess] Color
|
||||
# 53| 0: [NullLiteral] null
|
||||
# 53| 1: [IntegerLiteral] 0
|
||||
# 53| 1: [BlockStmt] { ... }
|
||||
# 53| 0: [ExprStmt] <Expr>;
|
||||
# 53| 0: [KtInitializerAssignExpr] ...=...
|
||||
|
||||
@@ -3358,6 +3358,8 @@ exprs.kt:
|
||||
# 174| 0: [ClassInstanceExpr] new Enum(...)
|
||||
# 174| -3: [TypeAccess] Enum<Direction>
|
||||
# 174| 0: [TypeAccess] Direction
|
||||
# 174| 0: [NullLiteral] null
|
||||
# 174| 1: [IntegerLiteral] 0
|
||||
# 174| 1: [BlockStmt] { ... }
|
||||
# 175| 5: [FieldDeclaration] Direction NORTH;
|
||||
# 175| -1: [TypeAccess] Direction
|
||||
@@ -3393,6 +3395,8 @@ exprs.kt:
|
||||
# 178| 0: [ClassInstanceExpr] new Enum(...)
|
||||
# 178| -3: [TypeAccess] Enum<Color>
|
||||
# 178| 0: [TypeAccess] Color
|
||||
# 178| 0: [NullLiteral] null
|
||||
# 178| 1: [IntegerLiteral] 0
|
||||
# 178| 1: [BlockStmt] { ... }
|
||||
# 178| 0: [ExprStmt] <Expr>;
|
||||
# 178| 0: [KtInitializerAssignExpr] ...=...
|
||||
|
||||
@@ -1470,9 +1470,11 @@
|
||||
| exprs.kt:170:9:170:17 | r2.height | exprs.kt:165:1:172:1 | foo | VarAccess |
|
||||
| exprs.kt:170:9:170:21 | ...=... | exprs.kt:165:1:172:1 | foo | AssignExpr |
|
||||
| exprs.kt:170:21:170:21 | 3 | exprs.kt:165:1:172:1 | foo | IntegerLiteral |
|
||||
| exprs.kt:174:1:176:1 | 0 | exprs.kt:174:6:176:1 | Direction | IntegerLiteral |
|
||||
| exprs.kt:174:1:176:1 | Direction | exprs.kt:174:6:176:1 | Direction | TypeAccess |
|
||||
| exprs.kt:174:1:176:1 | Enum<Direction> | exprs.kt:174:6:176:1 | Direction | TypeAccess |
|
||||
| exprs.kt:174:1:176:1 | new Enum(...) | exprs.kt:174:6:176:1 | Direction | ClassInstanceExpr |
|
||||
| exprs.kt:174:1:176:1 | null | exprs.kt:174:6:176:1 | Direction | NullLiteral |
|
||||
| exprs.kt:175:5:175:10 | ...=... | exprs.kt:0:0:0:0 | <clinit> | KtInitializerAssignExpr |
|
||||
| exprs.kt:175:5:175:10 | Direction | exprs.kt:0:0:0:0 | <clinit> | TypeAccess |
|
||||
| exprs.kt:175:5:175:10 | Direction | exprs.kt:0:0:0:0 | <clinit> | TypeAccess |
|
||||
@@ -1497,9 +1499,11 @@
|
||||
| exprs.kt:175:25:175:28 | Direction | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| exprs.kt:175:25:175:28 | Direction.EAST | exprs.kt:0:0:0:0 | <clinit> | VarAccess |
|
||||
| exprs.kt:175:25:175:28 | new Direction(...) | exprs.kt:0:0:0:0 | <clinit> | ClassInstanceExpr |
|
||||
| exprs.kt:178:1:182:1 | 0 | exprs.kt:178:6:182:1 | Color | IntegerLiteral |
|
||||
| exprs.kt:178:1:182:1 | Color | exprs.kt:178:6:182:1 | Color | TypeAccess |
|
||||
| exprs.kt:178:1:182:1 | Enum<Color> | exprs.kt:178:6:182:1 | Color | TypeAccess |
|
||||
| exprs.kt:178:1:182:1 | new Enum(...) | exprs.kt:178:6:182:1 | Color | ClassInstanceExpr |
|
||||
| exprs.kt:178:1:182:1 | null | exprs.kt:178:6:182:1 | Color | NullLiteral |
|
||||
| exprs.kt:178:18:178:29 | ...=... | exprs.kt:178:6:182:1 | Color | KtInitializerAssignExpr |
|
||||
| exprs.kt:178:18:178:29 | int | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| exprs.kt:178:18:178:29 | int | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
|
||||
@@ -88,6 +88,8 @@ A.kt:
|
||||
# 23| 0: [ClassInstanceExpr] new Enum(...)
|
||||
# 23| -3: [TypeAccess] Enum<Enu>
|
||||
# 23| 0: [TypeAccess] Enu
|
||||
# 23| 0: [NullLiteral] null
|
||||
# 23| 1: [IntegerLiteral] 0
|
||||
# 23| 1: [BlockStmt] { ... }
|
||||
# 24| 5: [FieldDeclaration] Enu A;
|
||||
# 24| -1: [TypeAccess] Enu
|
||||
|
||||
@@ -19,15 +19,16 @@ test.kt:
|
||||
# 45| 0: [TypeAccess] boolean
|
||||
# 45| 5: [BlockStmt] { ... }
|
||||
# 45| 0: [ReturnStmt] return ...
|
||||
# 45| 0: [MethodAccess] testExtensionFunction(...)
|
||||
# 45| 0: [MethodAccess] testExtensionFunction$default(...)
|
||||
# 45| -1: [TypeAccess] TestKt
|
||||
# 45| 0: [ExtensionReceiverAccess] this
|
||||
# 45| 1: [VarAccess] a
|
||||
# 45| 2: [MethodAccess] getString(...)
|
||||
# 45| -1: [TypeAccess] TestKt
|
||||
# 45| 3: [VarAccess] c
|
||||
# 45| 4: [FloatLiteral] 1.0
|
||||
# 45| 5: [VarAccess] e
|
||||
# 0| 0: [ExtensionReceiverAccess] this
|
||||
# 0| 1: [VarAccess] a
|
||||
# 1| 2: [NullLiteral] null
|
||||
# 0| 3: [VarAccess] c
|
||||
# 1| 4: [FloatLiteral] 0.0
|
||||
# 0| 5: [VarAccess] e
|
||||
# 1| 6: [IntegerLiteral] 21
|
||||
# 1| 7: [NullLiteral] null
|
||||
# 45| 3: [ExtensionMethod] testExtensionFunction
|
||||
# 45| 3: [TypeAccess] int
|
||||
#-----| 4: (Parameters)
|
||||
@@ -43,14 +44,16 @@ test.kt:
|
||||
# 45| 0: [TypeAccess] boolean
|
||||
# 45| 5: [BlockStmt] { ... }
|
||||
# 45| 0: [ReturnStmt] return ...
|
||||
# 45| 0: [MethodAccess] testExtensionFunction(...)
|
||||
# 45| 0: [MethodAccess] testExtensionFunction$default(...)
|
||||
# 45| -1: [TypeAccess] TestKt
|
||||
# 45| 0: [ExtensionReceiverAccess] this
|
||||
# 45| 1: [VarAccess] a
|
||||
# 45| 2: [VarAccess] b
|
||||
# 45| 3: [VarAccess] c
|
||||
# 45| 4: [FloatLiteral] 1.0
|
||||
# 45| 5: [VarAccess] e
|
||||
# 0| 0: [ExtensionReceiverAccess] this
|
||||
# 0| 1: [VarAccess] a
|
||||
# 0| 2: [VarAccess] b
|
||||
# 0| 3: [VarAccess] c
|
||||
# 1| 4: [FloatLiteral] 0.0
|
||||
# 0| 5: [VarAccess] e
|
||||
# 1| 6: [IntegerLiteral] 23
|
||||
# 1| 7: [NullLiteral] null
|
||||
# 45| 4: [ExtensionMethod] testExtensionFunction
|
||||
# 45| 3: [TypeAccess] int
|
||||
#-----| 4: (Parameters)
|
||||
@@ -135,14 +138,15 @@ test.kt:
|
||||
# 6| 0: [TypeAccess] boolean
|
||||
# 6| 5: [BlockStmt] { ... }
|
||||
# 6| 0: [ReturnStmt] return ...
|
||||
# 6| 0: [MethodAccess] testStaticFunction(...)
|
||||
# 6| 0: [MethodAccess] testStaticFunction$default(...)
|
||||
# 6| -1: [TypeAccess] Test
|
||||
# 6| 0: [VarAccess] a
|
||||
# 6| 1: [MethodAccess] getString(...)
|
||||
# 6| -1: [TypeAccess] TestKt
|
||||
# 6| 2: [VarAccess] c
|
||||
# 6| 3: [FloatLiteral] 1.0
|
||||
# 6| 4: [VarAccess] e
|
||||
# 0| 0: [VarAccess] a
|
||||
# 1| 1: [NullLiteral] null
|
||||
# 0| 2: [VarAccess] c
|
||||
# 1| 3: [FloatLiteral] 0.0
|
||||
# 0| 4: [VarAccess] e
|
||||
# 1| 5: [IntegerLiteral] 21
|
||||
# 1| 6: [NullLiteral] null
|
||||
# 6| 3: [Method] testStaticFunction
|
||||
# 6| 3: [TypeAccess] int
|
||||
#-----| 4: (Parameters)
|
||||
@@ -156,13 +160,15 @@ test.kt:
|
||||
# 6| 0: [TypeAccess] boolean
|
||||
# 6| 5: [BlockStmt] { ... }
|
||||
# 6| 0: [ReturnStmt] return ...
|
||||
# 6| 0: [MethodAccess] testStaticFunction(...)
|
||||
# 6| 0: [MethodAccess] testStaticFunction$default(...)
|
||||
# 6| -1: [TypeAccess] Test
|
||||
# 6| 0: [VarAccess] a
|
||||
# 6| 1: [VarAccess] b
|
||||
# 6| 2: [VarAccess] c
|
||||
# 6| 3: [FloatLiteral] 1.0
|
||||
# 6| 4: [VarAccess] e
|
||||
# 0| 0: [VarAccess] a
|
||||
# 0| 1: [VarAccess] b
|
||||
# 0| 2: [VarAccess] c
|
||||
# 1| 3: [FloatLiteral] 0.0
|
||||
# 0| 4: [VarAccess] e
|
||||
# 1| 5: [IntegerLiteral] 23
|
||||
# 1| 6: [NullLiteral] null
|
||||
# 6| 4: [Method] testStaticFunction
|
||||
# 6| 3: [TypeAccess] int
|
||||
#-----| 4: (Parameters)
|
||||
@@ -237,14 +243,16 @@ test.kt:
|
||||
# 9| 0: [TypeAccess] boolean
|
||||
# 9| 5: [BlockStmt] { ... }
|
||||
# 9| 0: [ReturnStmt] return ...
|
||||
# 9| 0: [MethodAccess] testMemberFunction(...)
|
||||
# 9| -1: [ThisAccess] this
|
||||
# 9| 0: [VarAccess] a
|
||||
# 9| 1: [MethodAccess] getString(...)
|
||||
# 9| -1: [TypeAccess] TestKt
|
||||
# 9| 2: [VarAccess] c
|
||||
# 9| 3: [FloatLiteral] 1.0
|
||||
# 9| 4: [VarAccess] e
|
||||
# 9| 0: [MethodAccess] testMemberFunction$default(...)
|
||||
# 9| -1: [TypeAccess] Test
|
||||
# 0| 0: [ThisAccess] this
|
||||
# 0| 1: [VarAccess] a
|
||||
# 1| 2: [NullLiteral] null
|
||||
# 0| 3: [VarAccess] c
|
||||
# 1| 4: [FloatLiteral] 0.0
|
||||
# 0| 5: [VarAccess] e
|
||||
# 1| 6: [IntegerLiteral] 21
|
||||
# 1| 7: [NullLiteral] null
|
||||
# 9| 7: [Method] testMemberFunction
|
||||
# 9| 3: [TypeAccess] int
|
||||
#-----| 4: (Parameters)
|
||||
@@ -258,13 +266,16 @@ test.kt:
|
||||
# 9| 0: [TypeAccess] boolean
|
||||
# 9| 5: [BlockStmt] { ... }
|
||||
# 9| 0: [ReturnStmt] return ...
|
||||
# 9| 0: [MethodAccess] testMemberFunction(...)
|
||||
# 9| -1: [ThisAccess] this
|
||||
# 9| 0: [VarAccess] a
|
||||
# 9| 1: [VarAccess] b
|
||||
# 9| 2: [VarAccess] c
|
||||
# 9| 3: [FloatLiteral] 1.0
|
||||
# 9| 4: [VarAccess] e
|
||||
# 9| 0: [MethodAccess] testMemberFunction$default(...)
|
||||
# 9| -1: [TypeAccess] Test
|
||||
# 0| 0: [ThisAccess] this
|
||||
# 0| 1: [VarAccess] a
|
||||
# 0| 2: [VarAccess] b
|
||||
# 0| 3: [VarAccess] c
|
||||
# 1| 4: [FloatLiteral] 0.0
|
||||
# 0| 5: [VarAccess] e
|
||||
# 1| 6: [IntegerLiteral] 23
|
||||
# 1| 7: [NullLiteral] null
|
||||
# 9| 8: [Method] testMemberFunction
|
||||
# 9| 3: [TypeAccess] int
|
||||
#-----| 4: (Parameters)
|
||||
@@ -343,15 +354,18 @@ test.kt:
|
||||
# 12| 0: [TypeAccess] boolean
|
||||
# 12| 5: [BlockStmt] { ... }
|
||||
# 12| 0: [ReturnStmt] return ...
|
||||
# 12| 0: [MethodAccess] testMemberExtensionFunction(...)
|
||||
# 12| -1: [ThisAccess] this
|
||||
# 12| 0: [ExtensionReceiverAccess] this
|
||||
# 12| 1: [VarAccess] a
|
||||
# 12| 2: [MethodAccess] getString(...)
|
||||
# 12| -1: [TypeAccess] TestKt
|
||||
# 12| 3: [VarAccess] c
|
||||
# 12| 4: [FloatLiteral] 1.0
|
||||
# 12| 5: [VarAccess] e
|
||||
# 12| 0: [MethodAccess] testMemberExtensionFunction$default(...)
|
||||
# 12| -1: [TypeAccess] Test
|
||||
# 0| 0: [ExtensionReceiverAccess] this
|
||||
# 0| 1: [ThisAccess] Test.this
|
||||
# 0| 0: [TypeAccess] Test
|
||||
# 0| 2: [VarAccess] a
|
||||
# 1| 3: [NullLiteral] null
|
||||
# 0| 4: [VarAccess] c
|
||||
# 1| 5: [FloatLiteral] 0.0
|
||||
# 0| 6: [VarAccess] e
|
||||
# 1| 7: [IntegerLiteral] 21
|
||||
# 1| 8: [NullLiteral] null
|
||||
# 12| 11: [ExtensionMethod] testMemberExtensionFunction
|
||||
# 12| 3: [TypeAccess] int
|
||||
#-----| 4: (Parameters)
|
||||
@@ -367,14 +381,18 @@ test.kt:
|
||||
# 12| 0: [TypeAccess] boolean
|
||||
# 12| 5: [BlockStmt] { ... }
|
||||
# 12| 0: [ReturnStmt] return ...
|
||||
# 12| 0: [MethodAccess] testMemberExtensionFunction(...)
|
||||
# 12| -1: [ThisAccess] this
|
||||
# 12| 0: [ExtensionReceiverAccess] this
|
||||
# 12| 1: [VarAccess] a
|
||||
# 12| 2: [VarAccess] b
|
||||
# 12| 3: [VarAccess] c
|
||||
# 12| 4: [FloatLiteral] 1.0
|
||||
# 12| 5: [VarAccess] e
|
||||
# 12| 0: [MethodAccess] testMemberExtensionFunction$default(...)
|
||||
# 12| -1: [TypeAccess] Test
|
||||
# 0| 0: [ExtensionReceiverAccess] this
|
||||
# 0| 1: [ThisAccess] Test.this
|
||||
# 0| 0: [TypeAccess] Test
|
||||
# 0| 2: [VarAccess] a
|
||||
# 0| 3: [VarAccess] b
|
||||
# 0| 4: [VarAccess] c
|
||||
# 1| 5: [FloatLiteral] 0.0
|
||||
# 0| 6: [VarAccess] e
|
||||
# 1| 7: [IntegerLiteral] 23
|
||||
# 1| 8: [NullLiteral] null
|
||||
# 12| 12: [ExtensionMethod] testMemberExtensionFunction
|
||||
# 12| 3: [TypeAccess] int
|
||||
#-----| 4: (Parameters)
|
||||
@@ -456,12 +474,13 @@ test.kt:
|
||||
# 16| 0: [TypeAccess] boolean
|
||||
# 16| 5: [BlockStmt] { ... }
|
||||
# 16| 0: [ThisConstructorInvocationStmt] this(...)
|
||||
# 16| 0: [VarAccess] a
|
||||
# 16| 1: [MethodAccess] getString(...)
|
||||
# 16| -1: [TypeAccess] TestKt
|
||||
# 16| 2: [VarAccess] c
|
||||
# 16| 3: [FloatLiteral] 1.0
|
||||
# 16| 4: [VarAccess] e
|
||||
# 0| 0: [VarAccess] a
|
||||
# 1| 1: [NullLiteral] null
|
||||
# 0| 2: [VarAccess] c
|
||||
# 1| 3: [FloatLiteral] 0.0
|
||||
# 0| 4: [VarAccess] e
|
||||
# 1| 5: [IntegerLiteral] 21
|
||||
# 1| 6: [NullLiteral] null
|
||||
# 16| 2: [Constructor] Test2
|
||||
#-----| 4: (Parameters)
|
||||
# 16| 0: [Parameter] a
|
||||
@@ -474,11 +493,13 @@ test.kt:
|
||||
# 16| 0: [TypeAccess] boolean
|
||||
# 16| 5: [BlockStmt] { ... }
|
||||
# 16| 0: [ThisConstructorInvocationStmt] this(...)
|
||||
# 16| 0: [VarAccess] a
|
||||
# 16| 1: [VarAccess] b
|
||||
# 16| 2: [VarAccess] c
|
||||
# 16| 3: [FloatLiteral] 1.0
|
||||
# 16| 4: [VarAccess] e
|
||||
# 0| 0: [VarAccess] a
|
||||
# 0| 1: [VarAccess] b
|
||||
# 0| 2: [VarAccess] c
|
||||
# 1| 3: [FloatLiteral] 0.0
|
||||
# 0| 4: [VarAccess] e
|
||||
# 1| 5: [IntegerLiteral] 23
|
||||
# 1| 6: [NullLiteral] null
|
||||
# 16| 3: [Constructor] Test2
|
||||
#-----| 4: (Parameters)
|
||||
# 16| 0: [Parameter] a
|
||||
@@ -554,14 +575,16 @@ test.kt:
|
||||
# 21| 0: [TypeAccess] boolean
|
||||
# 21| 5: [BlockStmt] { ... }
|
||||
# 21| 0: [ReturnStmt] return ...
|
||||
# 21| 0: [MethodAccess] testCompanionFunction(...)
|
||||
# 21| -1: [ThisAccess] this
|
||||
# 21| 0: [VarAccess] a
|
||||
# 21| 1: [MethodAccess] getString(...)
|
||||
# 21| -1: [TypeAccess] TestKt
|
||||
# 21| 2: [VarAccess] c
|
||||
# 21| 3: [FloatLiteral] 1.0
|
||||
# 21| 4: [VarAccess] e
|
||||
# 21| 0: [MethodAccess] testCompanionFunction$default(...)
|
||||
# 21| -1: [TypeAccess] Companion
|
||||
# 0| 0: [ThisAccess] this
|
||||
# 0| 1: [VarAccess] a
|
||||
# 1| 2: [NullLiteral] null
|
||||
# 0| 3: [VarAccess] c
|
||||
# 1| 4: [FloatLiteral] 0.0
|
||||
# 0| 5: [VarAccess] e
|
||||
# 1| 6: [IntegerLiteral] 21
|
||||
# 1| 7: [NullLiteral] null
|
||||
# 21| 3: [Method] testCompanionFunction
|
||||
# 21| 3: [TypeAccess] int
|
||||
#-----| 4: (Parameters)
|
||||
@@ -575,13 +598,16 @@ test.kt:
|
||||
# 21| 0: [TypeAccess] boolean
|
||||
# 21| 5: [BlockStmt] { ... }
|
||||
# 21| 0: [ReturnStmt] return ...
|
||||
# 21| 0: [MethodAccess] testCompanionFunction(...)
|
||||
# 21| -1: [ThisAccess] this
|
||||
# 21| 0: [VarAccess] a
|
||||
# 21| 1: [VarAccess] b
|
||||
# 21| 2: [VarAccess] c
|
||||
# 21| 3: [FloatLiteral] 1.0
|
||||
# 21| 4: [VarAccess] e
|
||||
# 21| 0: [MethodAccess] testCompanionFunction$default(...)
|
||||
# 21| -1: [TypeAccess] Companion
|
||||
# 0| 0: [ThisAccess] this
|
||||
# 0| 1: [VarAccess] a
|
||||
# 0| 2: [VarAccess] b
|
||||
# 0| 3: [VarAccess] c
|
||||
# 1| 4: [FloatLiteral] 0.0
|
||||
# 0| 5: [VarAccess] e
|
||||
# 1| 6: [IntegerLiteral] 23
|
||||
# 1| 7: [NullLiteral] null
|
||||
# 21| 4: [Method] testCompanionFunction
|
||||
# 21| 3: [TypeAccess] int
|
||||
#-----| 4: (Parameters)
|
||||
@@ -658,14 +684,16 @@ test.kt:
|
||||
# 24| 0: [TypeAccess] boolean
|
||||
# 24| 5: [BlockStmt] { ... }
|
||||
# 24| 0: [ReturnStmt] return ...
|
||||
# 24| 0: [MethodAccess] testStaticCompanionFunction(...)
|
||||
# 24| -1: [ThisAccess] this
|
||||
# 24| 0: [VarAccess] a
|
||||
# 24| 1: [MethodAccess] getString(...)
|
||||
# 24| -1: [TypeAccess] TestKt
|
||||
# 24| 2: [VarAccess] c
|
||||
# 24| 3: [FloatLiteral] 1.0
|
||||
# 24| 4: [VarAccess] e
|
||||
# 24| 0: [MethodAccess] testStaticCompanionFunction$default(...)
|
||||
# 24| -1: [TypeAccess] Companion
|
||||
# 0| 0: [ThisAccess] this
|
||||
# 0| 1: [VarAccess] a
|
||||
# 1| 2: [NullLiteral] null
|
||||
# 0| 3: [VarAccess] c
|
||||
# 1| 4: [FloatLiteral] 0.0
|
||||
# 0| 5: [VarAccess] e
|
||||
# 1| 6: [IntegerLiteral] 21
|
||||
# 1| 7: [NullLiteral] null
|
||||
# 24| 7: [Method] testStaticCompanionFunction
|
||||
# 24| 3: [TypeAccess] int
|
||||
#-----| 4: (Parameters)
|
||||
@@ -679,13 +707,16 @@ test.kt:
|
||||
# 24| 0: [TypeAccess] boolean
|
||||
# 24| 5: [BlockStmt] { ... }
|
||||
# 24| 0: [ReturnStmt] return ...
|
||||
# 24| 0: [MethodAccess] testStaticCompanionFunction(...)
|
||||
# 24| -1: [ThisAccess] this
|
||||
# 24| 0: [VarAccess] a
|
||||
# 24| 1: [VarAccess] b
|
||||
# 24| 2: [VarAccess] c
|
||||
# 24| 3: [FloatLiteral] 1.0
|
||||
# 24| 4: [VarAccess] e
|
||||
# 24| 0: [MethodAccess] testStaticCompanionFunction$default(...)
|
||||
# 24| -1: [TypeAccess] Companion
|
||||
# 0| 0: [ThisAccess] this
|
||||
# 0| 1: [VarAccess] a
|
||||
# 0| 2: [VarAccess] b
|
||||
# 0| 3: [VarAccess] c
|
||||
# 1| 4: [FloatLiteral] 0.0
|
||||
# 0| 5: [VarAccess] e
|
||||
# 1| 6: [IntegerLiteral] 23
|
||||
# 1| 7: [NullLiteral] null
|
||||
# 24| 8: [Method] testStaticCompanionFunction
|
||||
# 24| 3: [TypeAccess] int
|
||||
#-----| 4: (Parameters)
|
||||
@@ -762,14 +793,16 @@ test.kt:
|
||||
# 24| 0: [TypeAccess] boolean
|
||||
# 24| 5: [BlockStmt] { ... }
|
||||
# 24| 0: [ReturnStmt] return ...
|
||||
# 24| 0: [MethodAccess] testStaticCompanionFunction(...)
|
||||
# 24| -1: [ThisAccess] this
|
||||
# 24| 0: [VarAccess] a
|
||||
# 24| 1: [MethodAccess] getString(...)
|
||||
# 24| -1: [TypeAccess] TestKt
|
||||
# 24| 2: [VarAccess] c
|
||||
# 24| 3: [FloatLiteral] 1.0
|
||||
# 24| 4: [VarAccess] e
|
||||
# 24| 0: [MethodAccess] testStaticCompanionFunction$default(...)
|
||||
# 24| -1: [TypeAccess] Companion
|
||||
# 0| 0: [ThisAccess] this
|
||||
# 0| 1: [VarAccess] a
|
||||
# 1| 2: [NullLiteral] null
|
||||
# 0| 3: [VarAccess] c
|
||||
# 1| 4: [FloatLiteral] 0.0
|
||||
# 0| 5: [VarAccess] e
|
||||
# 1| 6: [IntegerLiteral] 21
|
||||
# 1| 7: [NullLiteral] null
|
||||
# 24| 7: [Method] testStaticCompanionFunction
|
||||
# 24| 3: [TypeAccess] int
|
||||
#-----| 4: (Parameters)
|
||||
@@ -783,13 +816,16 @@ test.kt:
|
||||
# 24| 0: [TypeAccess] boolean
|
||||
# 24| 5: [BlockStmt] { ... }
|
||||
# 24| 0: [ReturnStmt] return ...
|
||||
# 24| 0: [MethodAccess] testStaticCompanionFunction(...)
|
||||
# 24| -1: [ThisAccess] this
|
||||
# 24| 0: [VarAccess] a
|
||||
# 24| 1: [VarAccess] b
|
||||
# 24| 2: [VarAccess] c
|
||||
# 24| 3: [FloatLiteral] 1.0
|
||||
# 24| 4: [VarAccess] e
|
||||
# 24| 0: [MethodAccess] testStaticCompanionFunction$default(...)
|
||||
# 24| -1: [TypeAccess] Companion
|
||||
# 0| 0: [ThisAccess] this
|
||||
# 0| 1: [VarAccess] a
|
||||
# 0| 2: [VarAccess] b
|
||||
# 0| 3: [VarAccess] c
|
||||
# 1| 4: [FloatLiteral] 0.0
|
||||
# 0| 5: [VarAccess] e
|
||||
# 1| 6: [IntegerLiteral] 23
|
||||
# 1| 7: [NullLiteral] null
|
||||
# 24| 8: [Method] testStaticCompanionFunction
|
||||
# 24| 3: [TypeAccess] int
|
||||
#-----| 4: (Parameters)
|
||||
@@ -824,10 +860,12 @@ test.kt:
|
||||
# 30| 0: [TypeAccess] T
|
||||
# 30| 5: [BlockStmt] { ... }
|
||||
# 30| 0: [ThisConstructorInvocationStmt] this(...)
|
||||
# 30| 0: [IntegerLiteral] 1
|
||||
# 30| 1: [VarAccess] b
|
||||
# 30| 2: [StringLiteral] Hello world
|
||||
# 30| 3: [VarAccess] d
|
||||
# 1| 0: [IntegerLiteral] 0
|
||||
# 0| 1: [VarAccess] b
|
||||
# 1| 2: [NullLiteral] null
|
||||
# 0| 3: [VarAccess] d
|
||||
# 1| 4: [IntegerLiteral] 10
|
||||
# 1| 5: [NullLiteral] null
|
||||
# 30| 2: [Constructor] GenericTest
|
||||
#-----| 4: (Parameters)
|
||||
# 30| 0: [Parameter] a
|
||||
@@ -838,10 +876,12 @@ test.kt:
|
||||
# 30| 0: [TypeAccess] T
|
||||
# 30| 5: [BlockStmt] { ... }
|
||||
# 30| 0: [ThisConstructorInvocationStmt] this(...)
|
||||
# 30| 0: [VarAccess] a
|
||||
# 30| 1: [VarAccess] b
|
||||
# 30| 2: [StringLiteral] Hello world
|
||||
# 30| 3: [VarAccess] d
|
||||
# 0| 0: [VarAccess] a
|
||||
# 0| 1: [VarAccess] b
|
||||
# 1| 2: [NullLiteral] null
|
||||
# 0| 3: [VarAccess] d
|
||||
# 1| 4: [IntegerLiteral] 11
|
||||
# 1| 5: [NullLiteral] null
|
||||
# 30| 3: [Constructor] GenericTest
|
||||
#-----| 4: (Parameters)
|
||||
# 30| 0: [Parameter] a
|
||||
@@ -904,12 +944,15 @@ test.kt:
|
||||
# 33| 0: [TypeAccess] T
|
||||
# 33| 5: [BlockStmt] { ... }
|
||||
# 33| 0: [ReturnStmt] return ...
|
||||
# 33| 0: [MethodAccess] testMemberFunction(...)
|
||||
# 33| -1: [ThisAccess] this
|
||||
# 33| 0: [IntegerLiteral] 1
|
||||
# 33| 1: [VarAccess] b
|
||||
# 33| 2: [StringLiteral] Hello world
|
||||
# 33| 3: [VarAccess] d
|
||||
# 33| 0: [MethodAccess] testMemberFunction$default(...)
|
||||
# 33| -1: [TypeAccess] GenericTest<>
|
||||
# 0| 0: [ThisAccess] this
|
||||
# 1| 1: [IntegerLiteral] 0
|
||||
# 0| 2: [VarAccess] b
|
||||
# 1| 3: [NullLiteral] null
|
||||
# 0| 4: [VarAccess] d
|
||||
# 1| 5: [IntegerLiteral] 10
|
||||
# 1| 6: [NullLiteral] null
|
||||
# 33| 6: [Method] testMemberFunction
|
||||
# 33| 3: [TypeAccess] int
|
||||
#-----| 4: (Parameters)
|
||||
@@ -921,12 +964,15 @@ test.kt:
|
||||
# 33| 0: [TypeAccess] T
|
||||
# 33| 5: [BlockStmt] { ... }
|
||||
# 33| 0: [ReturnStmt] return ...
|
||||
# 33| 0: [MethodAccess] testMemberFunction(...)
|
||||
# 33| -1: [ThisAccess] this
|
||||
# 33| 0: [VarAccess] a
|
||||
# 33| 1: [VarAccess] b
|
||||
# 33| 2: [StringLiteral] Hello world
|
||||
# 33| 3: [VarAccess] d
|
||||
# 33| 0: [MethodAccess] testMemberFunction$default(...)
|
||||
# 33| -1: [TypeAccess] GenericTest<>
|
||||
# 0| 0: [ThisAccess] this
|
||||
# 0| 1: [VarAccess] a
|
||||
# 0| 2: [VarAccess] b
|
||||
# 1| 3: [NullLiteral] null
|
||||
# 0| 4: [VarAccess] d
|
||||
# 1| 5: [IntegerLiteral] 11
|
||||
# 1| 6: [NullLiteral] null
|
||||
# 33| 7: [Method] testMemberFunction
|
||||
# 33| 3: [TypeAccess] int
|
||||
#-----| 4: (Parameters)
|
||||
|
||||
@@ -12,16 +12,9 @@
|
||||
| User.java:35:61:35:68 | source(...) | test.kt:74:10:74:10 | s | User.java:5:22:5:25 | test |
|
||||
| User.java:38:28:38:35 | source(...) | test.kt:84:10:84:10 | y | User.java:5:22:5:25 | test |
|
||||
| User.java:39:20:39:27 | source(...) | test.kt:84:10:84:10 | y | User.java:5:22:5:25 | test |
|
||||
| test.kt:10:55:10:62 | source(...) | test.kt:10:84:10:84 | s | test.kt:10:3:10:87 | taintSuppliedAsDefault |
|
||||
| test.kt:10:55:10:62 | source(...) | test.kt:10:84:10:84 | s | test.kt:10:3:10:87 | taintSuppliedAsDefault$default |
|
||||
| test.kt:22:63:22:70 | source(...) | test.kt:22:92:22:92 | s | test.kt:22:5:22:95 | taintSuppliedAsDefaultStatic |
|
||||
| test.kt:22:63:22:70 | source(...) | test.kt:22:92:22:92 | s | test.kt:22:5:22:95 | taintSuppliedAsDefaultStatic |
|
||||
| test.kt:22:63:22:70 | source(...) | test.kt:22:92:22:92 | s | test.kt:22:5:22:95 | taintSuppliedAsDefaultStatic$default |
|
||||
| test.kt:30:55:30:62 | source(...) | test.kt:30:84:30:84 | s | test.kt:30:3:30:87 | taintSuppliedAsDefault |
|
||||
| test.kt:30:55:30:62 | source(...) | test.kt:30:84:30:84 | s | test.kt:30:3:30:87 | taintSuppliedAsDefault$default |
|
||||
| test.kt:40:53:40:60 | source(...) | test.kt:40:80:40:80 | s | test.kt:40:3:40:83 | taintSuppliedAsDefault |
|
||||
| test.kt:40:53:40:60 | source(...) | test.kt:40:80:40:80 | s | test.kt:40:3:40:83 | taintSuppliedAsDefault$default |
|
||||
| test.kt:47:92:47:99 | source(...) | test.kt:50:10:50:10 | s | test.kt:47:55:53:1 | ConstructorTaintsByDefault |
|
||||
| test.kt:47:92:47:99 | source(...) | test.kt:50:10:50:10 | s | test.kt:47:55:53:1 | ConstructorTaintsByDefault |
|
||||
| test.kt:63:100:63:107 | source(...) | test.kt:66:10:66:10 | s | test.kt:63:65:69:1 | GenericConstructorTaintsByDefault |
|
||||
| test.kt:63:100:63:107 | source(...) | test.kt:66:10:66:10 | s | test.kt:63:65:69:1 | GenericConstructorTaintsByDefault |
|
||||
|
||||
@@ -231,9 +231,11 @@
|
||||
| enumClass.kt:0:0:0:0 | EnumWithFunctions[] | TypeAccess |
|
||||
| enumClass.kt:0:0:0:0 | String | TypeAccess |
|
||||
| enumClass.kt:0:0:0:0 | String | TypeAccess |
|
||||
| enumClass.kt:1:1:4:1 | 0 | IntegerLiteral |
|
||||
| enumClass.kt:1:1:4:1 | Enum<EnumClass> | TypeAccess |
|
||||
| enumClass.kt:1:1:4:1 | EnumClass | TypeAccess |
|
||||
| enumClass.kt:1:1:4:1 | new Enum(...) | ClassInstanceExpr |
|
||||
| enumClass.kt:1:1:4:1 | null | NullLiteral |
|
||||
| enumClass.kt:1:22:1:31 | ...=... | KtInitializerAssignExpr |
|
||||
| enumClass.kt:1:22:1:31 | int | TypeAccess |
|
||||
| enumClass.kt:1:22:1:31 | int | TypeAccess |
|
||||
@@ -256,9 +258,11 @@
|
||||
| enumClass.kt:3:5:3:12 | EnumClass.enum2 | VarAccess |
|
||||
| enumClass.kt:3:5:3:12 | new EnumClass(...) | ClassInstanceExpr |
|
||||
| enumClass.kt:3:11:3:11 | 1 | IntegerLiteral |
|
||||
| enumClass.kt:6:1:16:1 | 0 | IntegerLiteral |
|
||||
| enumClass.kt:6:1:16:1 | Enum<EnumWithFunctions> | TypeAccess |
|
||||
| enumClass.kt:6:1:16:1 | EnumWithFunctions | TypeAccess |
|
||||
| enumClass.kt:6:1:16:1 | new Enum(...) | ClassInstanceExpr |
|
||||
| enumClass.kt:6:1:16:1 | null | NullLiteral |
|
||||
| enumClass.kt:8:3:11:4 | ...=... | KtInitializerAssignExpr |
|
||||
| enumClass.kt:8:3:11:4 | <implicit coercion to unit> | ImplicitCoercionToUnitExpr |
|
||||
| enumClass.kt:8:3:11:4 | EnumWithFunctions | TypeAccess |
|
||||
|
||||
@@ -7,3 +7,8 @@ class C {
|
||||
prop(this)
|
||||
}
|
||||
}
|
||||
|
||||
class A {
|
||||
fun <T : Any> fn(value: T, i: Int = 1) {}
|
||||
fun fn(value: String, i: Int = 1) {}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
| test.kt:8:10:8:10 | int e | Variable 'int e' is never read. |
|
||||
| test.kt:14:11:14:13 | int idx | Variable 'int idx' is never read. |
|
||||
| test.kt:14:16:14:16 | int e | Variable 'int e' is never read. |
|
||||
@@ -0,0 +1 @@
|
||||
Violations of Best Practice/Dead Code/UnreadLocal.ql
|
||||
25
java/ql/test/kotlin/query-tests/UnreadLocal/test.kt
Normal file
25
java/ql/test/kotlin/query-tests/UnreadLocal/test.kt
Normal file
@@ -0,0 +1,25 @@
|
||||
fun fn0(size: Int) {
|
||||
for (idx in 1..size) {
|
||||
println()
|
||||
}
|
||||
}
|
||||
|
||||
fun fn1(a: Array<Int>) {
|
||||
for (e in a) {
|
||||
println()
|
||||
}
|
||||
}
|
||||
|
||||
fun fn2(a: Array<Int>) {
|
||||
for ((idx, e) in a.withIndex()) {
|
||||
println()
|
||||
}
|
||||
}
|
||||
|
||||
fun fn3() {
|
||||
for (i in 1 until 10) {
|
||||
println()
|
||||
}
|
||||
}
|
||||
|
||||
// Diagnostic Matches: % Couldn't find a Java equivalent function to kotlin.Int.rangeTo in java.lang.Integer%
|
||||
@@ -24,6 +24,12 @@ public class TestStartActivityToGetIntent {
|
||||
Intent[] intents = new Intent[] {intent};
|
||||
ctx.startActivities(intents);
|
||||
}
|
||||
{
|
||||
Intent intent = new Intent(null, AnotherActivity.class);
|
||||
intent.putExtra("data", (String) source("ctx-start-acts-2"));
|
||||
Intent[] intents = new Intent[] {intent};
|
||||
ctx.startActivities(intents);
|
||||
}
|
||||
{
|
||||
Intent intent = new Intent(null, SomeActivity.class);
|
||||
intent.putExtra("data", (String) source("act-start"));
|
||||
@@ -35,6 +41,12 @@ public class TestStartActivityToGetIntent {
|
||||
Intent[] intents = new Intent[] {intent};
|
||||
act.startActivities(intents);
|
||||
}
|
||||
{
|
||||
Intent intent = new Intent(null, Object.class);
|
||||
intent.putExtra("data", (String) source("start-activities-should-not-reach"));
|
||||
Intent[] intents = new Intent[] {intent};
|
||||
act.startActivities(intents);
|
||||
}
|
||||
{
|
||||
Intent intent = new Intent(null, SomeActivity.class);
|
||||
intent.putExtra("data", (String) source("start-for-result"));
|
||||
@@ -79,9 +91,16 @@ public class TestStartActivityToGetIntent {
|
||||
static class SomeActivity extends Activity {
|
||||
|
||||
public void test() {
|
||||
sink(getIntent().getStringExtra("data")); // $ hasValueFlow=ctx-start hasValueFlow=act-start hasValueFlow=start-for-result hasValueFlow=start-if-needed hasValueFlow=start-matching hasValueFlow=start-from-child hasValueFlow=start-from-frag hasValueFlow=4-arg MISSING: hasValueFlow=ctx-start-acts hasValueFlow=act-start-acts
|
||||
// @formatter:off
|
||||
sink(getIntent().getStringExtra("data")); // $ hasValueFlow=ctx-start hasValueFlow=act-start hasValueFlow=start-for-result hasValueFlow=start-if-needed hasValueFlow=start-matching hasValueFlow=start-from-child hasValueFlow=start-from-frag hasValueFlow=4-arg hasValueFlow=ctx-start-acts hasValueFlow=act-start-acts
|
||||
// @formatter:on
|
||||
}
|
||||
}
|
||||
|
||||
static class AnotherActivity extends Activity {
|
||||
public void test() {
|
||||
sink(getIntent().getStringExtra("data")); // $ hasValueFlow=ctx-start-acts-2
|
||||
}
|
||||
}
|
||||
|
||||
static class SafeActivity extends Activity {
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
public class Test {
|
||||
|
||||
static class BoundedGeneric<T extends CharSequence> {
|
||||
public T getter(int unused) { return null; }
|
||||
public void setter(T t) { }
|
||||
}
|
||||
|
||||
public static BoundedGeneric<?> getUnbounded() { return null; }
|
||||
|
||||
public static BoundedGeneric<? super String> getLowerBounded() { return null; }
|
||||
|
||||
public static void test() {
|
||||
CharSequence cs = getUnbounded().getter(0);
|
||||
Object o = getLowerBounded().getter(0);
|
||||
getUnbounded().setter(null);
|
||||
getLowerBounded().setter(null);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
| Test$BoundedGeneric.class:0:0:0:0 | getter | Test$BoundedGeneric.class:0:0:0:0 | BoundedGeneric<? super String> | CharSequence | int |
|
||||
| Test$BoundedGeneric.class:0:0:0:0 | getter | Test$BoundedGeneric.class:0:0:0:0 | BoundedGeneric<?> | CharSequence | int |
|
||||
| Test$BoundedGeneric.class:0:0:0:0 | setter | Test$BoundedGeneric.class:0:0:0:0 | BoundedGeneric<? super String> | void | String |
|
||||
| Test$BoundedGeneric.class:0:0:0:0 | setter | Test$BoundedGeneric.class:0:0:0:0 | BoundedGeneric<?> | void | <nulltype> |
|
||||
@@ -0,0 +1,5 @@
|
||||
import java
|
||||
|
||||
from MethodAccess ma
|
||||
select ma.getCallee(), ma.getCallee().getDeclaringType(), ma.getCallee().getReturnType().toString(),
|
||||
ma.getCallee().getAParamType().toString()
|
||||
@@ -0,0 +1,13 @@
|
||||
import java.util.Collection;
|
||||
|
||||
public class Test {
|
||||
|
||||
public Collection<? extends CharSequence> getCollection() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void test() {
|
||||
this.getCollection().isEmpty();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import java
|
||||
|
||||
from Method m, Type t
|
||||
where m.getAParamType() = t and t.toString().matches("%? super ? extends%")
|
||||
select m, t
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
private import javascript as JS
|
||||
import EndpointTypes
|
||||
import EndpointCharacteristics
|
||||
|
||||
/**
|
||||
* EXPERIMENTAL. This API may change in the future.
|
||||
@@ -44,7 +45,14 @@ abstract class AtmConfig extends string {
|
||||
*
|
||||
* Holds if `sink` is a known sink of flow.
|
||||
*/
|
||||
predicate isKnownSink(JS::DataFlow::Node sink) { none() }
|
||||
final predicate isKnownSink(JS::DataFlow::Node sink) {
|
||||
// If the list of characteristics includes positive indicators with maximal confidence for this class, then it's a
|
||||
// known sink for the class.
|
||||
exists(EndpointCharacteristic characteristic |
|
||||
characteristic.getEndpoints(sink) and
|
||||
characteristic.getImplications(this.getASinkEndpointType(), true, 1.0)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* EXPERIMENTAL. This API may change in the future.
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
/**
|
||||
* For internal use only.
|
||||
*/
|
||||
|
||||
import experimental.adaptivethreatmodeling.EndpointTypes
|
||||
private import semmle.javascript.security.dataflow.SqlInjectionCustomizations
|
||||
private import semmle.javascript.security.dataflow.DomBasedXssCustomizations
|
||||
private import semmle.javascript.security.dataflow.NosqlInjectionCustomizations
|
||||
private import semmle.javascript.security.dataflow.TaintedPathCustomizations
|
||||
|
||||
/**
|
||||
* A set of characteristics that a particular endpoint might have. This set of characteristics is used to make decisions
|
||||
* about whether to include the endpoint in the training set and with what label, as well as whether to score the
|
||||
* endpoint at inference time.
|
||||
*/
|
||||
abstract class EndpointCharacteristic extends string {
|
||||
/**
|
||||
* Holds when the string matches the name of the characteristic, which should describe some characteristic of the
|
||||
* endpoint that is meaningful for determining whether it's a sink and if so of which type
|
||||
*/
|
||||
bindingset[this]
|
||||
EndpointCharacteristic() { any() }
|
||||
|
||||
/**
|
||||
* Holds for endpoints that have this characteristic. This predicate contains the logic that applies characteristics
|
||||
* to the appropriate set of dataflow nodes.
|
||||
*/
|
||||
abstract predicate getEndpoints(DataFlow::Node n);
|
||||
|
||||
/**
|
||||
* This predicate describes what the characteristic tells us about an endpoint.
|
||||
*
|
||||
* Params:
|
||||
* endpointClass: Class 0 is the negative class. Each positive int corresponds to a single sink type.
|
||||
* isPositiveIndicator: Does this characteristic indicate this endpoint _is_ a member of the class, or that it
|
||||
* _isn't_ a member of the class?
|
||||
* confidence: A number in [0, 1], which tells us how strong an indicator this characteristic is for the endpoint
|
||||
* belonging / not belonging to the given class.
|
||||
*/
|
||||
abstract predicate getImplications(
|
||||
EndpointType endpointClass, boolean isPositiveIndicator, float confidence
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Endpoints identified as "DomBasedXssSink" by the standard JavaScript libraries are XSS sinks with maximal confidence.
|
||||
*/
|
||||
private class DomBasedXssSinkCharacteristic extends EndpointCharacteristic {
|
||||
DomBasedXssSinkCharacteristic() { this = "DomBasedXssSink" }
|
||||
|
||||
override predicate getEndpoints(DataFlow::Node n) { n instanceof DomBasedXss::Sink }
|
||||
|
||||
override predicate getImplications(
|
||||
EndpointType endpointClass, boolean isPositiveIndicator, float confidence
|
||||
) {
|
||||
endpointClass instanceof XssSinkType and isPositiveIndicator = true and confidence = 1.0
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Endpoints identified as "TaintedPathSink" by the standard JavaScript libraries are path injection sinks with maximal
|
||||
* confidence.
|
||||
*/
|
||||
private class TaintedPathSinkCharacteristic extends EndpointCharacteristic {
|
||||
TaintedPathSinkCharacteristic() { this = "TaintedPathSink" }
|
||||
|
||||
override predicate getEndpoints(DataFlow::Node n) { n instanceof TaintedPath::Sink }
|
||||
|
||||
override predicate getImplications(
|
||||
EndpointType endpointClass, boolean isPositiveIndicator, float confidence
|
||||
) {
|
||||
endpointClass instanceof TaintedPathSinkType and isPositiveIndicator = true and confidence = 1.0
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Endpoints identified as "SqlInjectionSink" by the standard JavaScript libraries are SQL injection sinks with maximal
|
||||
* confidence.
|
||||
*/
|
||||
private class SqlInjectionSinkCharacteristic extends EndpointCharacteristic {
|
||||
SqlInjectionSinkCharacteristic() { this = "SqlInjectionSink" }
|
||||
|
||||
override predicate getEndpoints(DataFlow::Node n) { n instanceof SqlInjection::Sink }
|
||||
|
||||
override predicate getImplications(
|
||||
EndpointType endpointClass, boolean isPositiveIndicator, float confidence
|
||||
) {
|
||||
endpointClass instanceof SqlInjectionSinkType and
|
||||
isPositiveIndicator = true and
|
||||
confidence = 1.0
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Endpoints identified as "NosqlInjectionSink" by the standard JavaScript libraries are NoSQL injection sinks with
|
||||
* maximal confidence.
|
||||
*/
|
||||
private class NosqlInjectionSinkCharacteristic extends EndpointCharacteristic {
|
||||
NosqlInjectionSinkCharacteristic() { this = "NosqlInjectionSink" }
|
||||
|
||||
override predicate getEndpoints(DataFlow::Node n) { n instanceof NosqlInjection::Sink }
|
||||
|
||||
override predicate getImplications(
|
||||
EndpointType endpointClass, boolean isPositiveIndicator, float confidence
|
||||
) {
|
||||
endpointClass instanceof NosqlInjectionSinkType and
|
||||
isPositiveIndicator = true and
|
||||
confidence = 1.0
|
||||
}
|
||||
}
|
||||
@@ -93,8 +93,6 @@ class NosqlInjectionAtmConfig extends AtmConfig {
|
||||
source instanceof NosqlInjection::Source or TaintedObject::isSource(source, _)
|
||||
}
|
||||
|
||||
override predicate isKnownSink(DataFlow::Node sink) { sink instanceof NosqlInjection::Sink }
|
||||
|
||||
override predicate isEffectiveSink(DataFlow::Node sinkCandidate) {
|
||||
not exists(SinkEndpointFilter::getAReasonSinkExcluded(sinkCandidate))
|
||||
}
|
||||
|
||||
@@ -65,8 +65,6 @@ class SqlInjectionAtmConfig extends AtmConfig {
|
||||
|
||||
override predicate isKnownSource(DataFlow::Node source) { source instanceof SqlInjection::Source }
|
||||
|
||||
override predicate isKnownSink(DataFlow::Node sink) { sink instanceof SqlInjection::Sink }
|
||||
|
||||
override predicate isEffectiveSink(DataFlow::Node sinkCandidate) {
|
||||
not exists(SinkEndpointFilter::getAReasonSinkExcluded(sinkCandidate))
|
||||
}
|
||||
|
||||
@@ -64,8 +64,6 @@ class TaintedPathAtmConfig extends AtmConfig {
|
||||
|
||||
override predicate isKnownSource(DataFlow::Node source) { source instanceof TaintedPath::Source }
|
||||
|
||||
override predicate isKnownSink(DataFlow::Node sink) { sink instanceof TaintedPath::Sink }
|
||||
|
||||
override predicate isEffectiveSink(DataFlow::Node sinkCandidate) {
|
||||
not exists(SinkEndpointFilter::getAReasonSinkExcluded(sinkCandidate))
|
||||
}
|
||||
|
||||
@@ -65,8 +65,6 @@ class DomBasedXssAtmConfig extends AtmConfig {
|
||||
|
||||
override predicate isKnownSource(DataFlow::Node source) { source instanceof DomBasedXss::Source }
|
||||
|
||||
override predicate isKnownSink(DataFlow::Node sink) { sink instanceof DomBasedXss::Sink }
|
||||
|
||||
override predicate isEffectiveSink(DataFlow::Node sinkCandidate) {
|
||||
not exists(SinkEndpointFilter::getAReasonSinkExcluded(sinkCandidate))
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/javascript-experimental-atm-lib
|
||||
version: 0.3.7
|
||||
version: 0.4.1
|
||||
extractor: javascript
|
||||
library: true
|
||||
groups:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/javascript-experimental-atm-model
|
||||
version: 0.2.1
|
||||
version: 0.3.1
|
||||
groups:
|
||||
- javascript
|
||||
- experimental
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
dependencies:
|
||||
codeql/javascript-experimental-atm-model:
|
||||
version: 0.2.1-2022-09-06-08h55m54s.bubbly-basin-xpztl8fh.f3c3c9360a727959e428ecc6932257e6a546dc65d8a9baac525a49247123822d
|
||||
version: 0.3.0
|
||||
compiled: false
|
||||
lockVersion: 1.0.0
|
||||
|
||||
@@ -6,4 +6,4 @@ groups:
|
||||
- experimental
|
||||
dependencies:
|
||||
codeql/javascript-experimental-atm-lib: ${workspace}
|
||||
codeql/javascript-experimental-atm-model: "0.2.1-2022-09-06-08h55m54s.bubbly-basin-xpztl8fh.f3c3c9360a727959e428ecc6932257e6a546dc65d8a9baac525a49247123822d"
|
||||
codeql/javascript-experimental-atm-model: "0.3.0"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
dependencies:
|
||||
codeql/javascript-experimental-atm-model:
|
||||
version: 0.2.1-2022-09-06-08h55m54s.bubbly-basin-xpztl8fh.f3c3c9360a727959e428ecc6932257e6a546dc65d8a9baac525a49247123822d
|
||||
version: 0.3.0
|
||||
compiled: false
|
||||
lockVersion: 1.0.0
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: codeql/javascript-experimental-atm-queries
|
||||
language: javascript
|
||||
version: 0.3.7
|
||||
version: 0.4.1
|
||||
suites: codeql-suites
|
||||
defaultSuiteFile: codeql-suites/javascript-atm-code-scanning.qls
|
||||
groups:
|
||||
@@ -8,4 +8,4 @@ groups:
|
||||
- experimental
|
||||
dependencies:
|
||||
codeql/javascript-experimental-atm-lib: ${workspace}
|
||||
codeql/javascript-experimental-atm-model: "0.2.1-2022-09-06-08h55m54s.bubbly-basin-xpztl8fh.f3c3c9360a727959e428ecc6932257e6a546dc65d8a9baac525a49247123822d"
|
||||
codeql/javascript-experimental-atm-model: "0.3.0"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
dependencies:
|
||||
codeql/javascript-experimental-atm-model:
|
||||
version: 0.2.1-2022-09-06-08h55m54s.bubbly-basin-xpztl8fh.f3c3c9360a727959e428ecc6932257e6a546dc65d8a9baac525a49247123822d
|
||||
version: 0.3.0
|
||||
compiled: false
|
||||
lockVersion: 1.0.0
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/javascript-all
|
||||
version: 0.3.3
|
||||
version: 0.3.4-dev
|
||||
groups: javascript
|
||||
dbscheme: semmlecode.javascript.dbscheme
|
||||
extractor: javascript
|
||||
|
||||
@@ -129,19 +129,20 @@ private predicate isCanonicalTerm(RelevantRegExpTerm term, string str) {
|
||||
min(RelevantRegExpTerm t, Location loc, File file |
|
||||
loc = t.getLocation() and
|
||||
file = t.getFile() and
|
||||
str = t.getRawValue() + "|" + getCanonicalizationFlags(t.getRootTerm())
|
||||
str = getCanonicalizationString(t)
|
||||
|
|
||||
t order by t.getFile().getRelativePath(), loc.getStartLine(), loc.getStartColumn()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a string representation of the flags used with the regular expression.
|
||||
* Only the flags that are relevant for the canonicalization are included.
|
||||
* Gets a string representation of `term` that is used for canonicalization.
|
||||
*/
|
||||
string getCanonicalizationFlags(RegExpTerm root) {
|
||||
root.isRootTerm() and
|
||||
(if RegExpFlags::isIgnoreCase(root) then result = "i" else result = "")
|
||||
private string getCanonicalizationString(RelevantRegExpTerm term) {
|
||||
exists(string ignoreCase |
|
||||
(if RegExpFlags::isIgnoreCase(term.getRootTerm()) then ignoreCase = "i" else ignoreCase = "") and
|
||||
result = term.getRawValue() + "|" + ignoreCase
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -186,12 +187,19 @@ private newtype TInputSymbol =
|
||||
Epsilon()
|
||||
|
||||
/**
|
||||
* Gets the canonical CharClass for `term`.
|
||||
* Gets the the CharClass corresponding to the canonical representative `term`.
|
||||
*/
|
||||
CharClass getCanonicalCharClass(RegExpTerm term) {
|
||||
private CharClass getCharClassForCanonicalTerm(RegExpTerm term) {
|
||||
exists(string str | isCanonicalTerm(term, str) | result = CharClass(str))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a char class that represents `term`, even when `term` is not the canonical representative.
|
||||
*/
|
||||
CharacterClass getCanonicalCharClass(RegExpTerm term) {
|
||||
exists(string str | str = getCanonicalizationString(term) and result = CharClass(str))
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `a` and `b` are input symbols from the same regexp.
|
||||
*/
|
||||
@@ -284,7 +292,7 @@ private module CharacterClasses {
|
||||
*/
|
||||
pragma[noinline]
|
||||
predicate hasChildThatMatchesIgnoringCasingFlags(RegExpCharacterClass cc, string char) {
|
||||
exists(getCanonicalCharClass(cc)) and
|
||||
exists(getCharClassForCanonicalTerm(cc)) and
|
||||
exists(RegExpTerm child | child = cc.getAChild() |
|
||||
char = child.(RegexpCharacterConstant).getValue()
|
||||
or
|
||||
@@ -387,7 +395,7 @@ private module CharacterClasses {
|
||||
private class PositiveCharacterClass extends CharacterClass {
|
||||
RegExpCharacterClass cc;
|
||||
|
||||
PositiveCharacterClass() { this = getCanonicalCharClass(cc) and not cc.isInverted() }
|
||||
PositiveCharacterClass() { this = getCharClassForCanonicalTerm(cc) and not cc.isInverted() }
|
||||
|
||||
override string getARelevantChar() { result = caseNormalize(getAMentionedChar(cc), cc) }
|
||||
|
||||
@@ -400,7 +408,7 @@ private module CharacterClasses {
|
||||
private class InvertedCharacterClass extends CharacterClass {
|
||||
RegExpCharacterClass cc;
|
||||
|
||||
InvertedCharacterClass() { this = getCanonicalCharClass(cc) and cc.isInverted() }
|
||||
InvertedCharacterClass() { this = getCharClassForCanonicalTerm(cc) and cc.isInverted() }
|
||||
|
||||
override string getARelevantChar() {
|
||||
result = nextChar(caseNormalize(getAMentionedChar(cc), cc)) or
|
||||
@@ -435,7 +443,7 @@ private module CharacterClasses {
|
||||
|
||||
PositiveCharacterClassEscape() {
|
||||
isEscapeClass(cc, charClass) and
|
||||
this = getCanonicalCharClass(cc) and
|
||||
this = getCharClassForCanonicalTerm(cc) and
|
||||
charClass = ["d", "s", "w"]
|
||||
}
|
||||
|
||||
@@ -475,7 +483,7 @@ private module CharacterClasses {
|
||||
NegativeCharacterClassEscape() {
|
||||
exists(RegExpTerm cc |
|
||||
isEscapeClass(cc, charClass) and
|
||||
this = getCanonicalCharClass(cc) and
|
||||
this = getCharClassForCanonicalTerm(cc) and
|
||||
charClass = ["D", "S", "W"]
|
||||
)
|
||||
}
|
||||
@@ -652,17 +660,13 @@ predicate delta(State q1, EdgeLabel lbl, State q2) {
|
||||
cc.isUniversalClass() and q1 = before(cc) and lbl = Any() and q2 = after(cc)
|
||||
or
|
||||
q1 = before(cc) and
|
||||
lbl =
|
||||
CharacterClasses::normalize(CharClass(cc.getRawValue() + "|" +
|
||||
getCanonicalizationFlags(cc.getRootTerm()))) and
|
||||
lbl = CharacterClasses::normalize(CharClass(getCanonicalizationString(cc))) and
|
||||
q2 = after(cc)
|
||||
)
|
||||
or
|
||||
exists(RegExpTerm cc | isEscapeClass(cc, _) |
|
||||
q1 = before(cc) and
|
||||
lbl =
|
||||
CharacterClasses::normalize(CharClass(cc.getRawValue() + "|" +
|
||||
getCanonicalizationFlags(cc.getRootTerm()))) and
|
||||
lbl = CharacterClasses::normalize(CharClass(getCanonicalizationString(cc))) and
|
||||
q2 = after(cc)
|
||||
)
|
||||
or
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/javascript-queries
|
||||
version: 0.4.3
|
||||
version: 0.4.4-dev
|
||||
groups:
|
||||
- javascript
|
||||
- queries
|
||||
|
||||
@@ -37,3 +37,5 @@
|
||||
| tst-multi-character-sanitization.js:143:13:143:56 | content ... /g, '') | This string may still contain $@, which may cause an HTML element injection vulnerability. | tst-multi-character-sanitization.js:143:30:143:30 | < | <script |
|
||||
| tst-multi-character-sanitization.js:144:13:144:91 | content ... /g, '') | This string may still contain $@, which may cause an HTML element injection vulnerability. | tst-multi-character-sanitization.js:144:30:144:30 | < | <script |
|
||||
| tst-multi-character-sanitization.js:145:13:145:90 | content ... /g, '') | This string may still contain $@, which may cause an HTML element injection vulnerability. | tst-multi-character-sanitization.js:145:30:145:30 | < | <script |
|
||||
| tst-multi-character-sanitization.js:148:3:148:99 | n.clone ... gi, '') | This string may still contain $@, which may cause an HTML element injection vulnerability. | tst-multi-character-sanitization.js:148:41:148:41 | < | <script |
|
||||
| tst-multi-character-sanitization.js:152:3:152:99 | n.clone ... gi, '') | This string may still contain $@, which may cause an HTML element injection vulnerability. | tst-multi-character-sanitization.js:152:41:152:41 | < | <script |
|
||||
|
||||
@@ -144,4 +144,12 @@
|
||||
content = content.replace(/<(script|iframe|video)[\s\S]*?<\/(script|iframe|video)>/g, '') // NOT OK
|
||||
content = content.replace(/<(script|iframe|video)(.|\s)*?\/(script|iframe|video)>/g, '') // NOT OK
|
||||
content = content.replace(/<[^<]*>/g, ""); // OK
|
||||
|
||||
n.cloneNode(false).outerHTML.replace(/<\/?[\w:\-]+ ?|=[\"][^\"]+\"|=\'[^\']+\'|=[\w\-]+|>/gi, '').replace(/[\w:\-]+/gi, function(a) { // NOT OK
|
||||
o.push({specified : 1, nodeName : a});
|
||||
});
|
||||
|
||||
n.cloneNode(false).outerHTML.replace(/<\/?[\w:\-]+ ?|=[\"][^\"]+\"|=\'[^\']+\'|=[\w\-]+|>/gi, '').replace(/[\w:\-]+/gi, function(a) { // NOT OK
|
||||
o.push({specified : 1, nodeName : a});
|
||||
});
|
||||
});
|
||||
@@ -1,3 +1,3 @@
|
||||
name: codeql/suite-helpers
|
||||
version: 0.3.3
|
||||
version: 0.3.4-dev
|
||||
groups: shared
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/python-all
|
||||
version: 0.6.3
|
||||
version: 0.6.4-dev
|
||||
groups: python
|
||||
dbscheme: semmlecode.python.dbscheme
|
||||
extractor: python
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user