upgrading to 2.16.3, resolving zipslip merge conflict

This commit is contained in:
Dilan Bhalla
2024-02-22 15:24:05 -08:00
1068 changed files with 71791 additions and 46445 deletions

View File

@@ -1,5 +1,8 @@
name: Check change note name: Check change note
permissions:
pull-requests: read
on: on:
pull_request_target: pull_request_target:
types: [labeled, unlabeled, opened, synchronize, reopened, ready_for_review] types: [labeled, unlabeled, opened, synchronize, reopened, ready_for_review]

View File

@@ -9,6 +9,9 @@ on:
- main - main
- "rc/*" - "rc/*"
permissions:
contents: read
jobs: jobs:
check: check:
runs-on: ubuntu-latest runs-on: ubuntu-latest

View File

@@ -10,6 +10,9 @@ on:
- main - main
- "rc/*" - "rc/*"
permissions:
contents: read
jobs: jobs:
qldoc: qldoc:
runs-on: ubuntu-latest runs-on: ubuntu-latest

View File

@@ -11,6 +11,9 @@ on:
- "rc/*" - "rc/*"
workflow_dispatch: workflow_dispatch:
permissions:
contents: read
jobs: jobs:
check: check:
name: Check query IDs name: Check query IDs

View File

@@ -5,6 +5,9 @@ on:
schedule: schedule:
- cron: "30 1 * * *" - cron: "30 1 * * *"
permissions:
issues: write
jobs: jobs:
stale: stale:
if: github.repository == 'github/codeql' if: github.repository == 'github/codeql'

View File

@@ -8,8 +8,12 @@ on:
- "codeql-cli-*" - "codeql-cli-*"
pull_request: pull_request:
permissions:
contents: read
jobs: jobs:
compile-queries: compile-queries:
if: github.repository_owner == 'github'
runs-on: ubuntu-latest-xl runs-on: ubuntu-latest-xl
steps: steps:

View File

@@ -25,6 +25,9 @@ defaults:
run: run:
working-directory: csharp working-directory: csharp
permissions:
contents: read
jobs: jobs:
qlupgrade: qlupgrade:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -46,6 +49,7 @@ jobs:
xargs codeql execute upgrades testdb xargs codeql execute upgrades testdb
diff -q testdb/semmlecode.csharp.dbscheme downgrades/initial/semmlecode.csharp.dbscheme diff -q testdb/semmlecode.csharp.dbscheme downgrades/initial/semmlecode.csharp.dbscheme
qltest: qltest:
if: github.repository_owner == 'github'
runs-on: ubuntu-latest-xl runs-on: ubuntu-latest-xl
strategy: strategy:
fail-fast: false fail-fast: false

View File

@@ -14,6 +14,10 @@ on:
- ".github/workflows/csv-coverage-metrics.yml" - ".github/workflows/csv-coverage-metrics.yml"
- ".github/actions/fetch-codeql/action.yml" - ".github/actions/fetch-codeql/action.yml"
permissions:
contents: read
security-events: write
jobs: jobs:
publish-java: publish-java:
runs-on: ubuntu-latest runs-on: ubuntu-latest

View File

@@ -19,6 +19,10 @@ on:
- main - main
- "rc/*" - "rc/*"
permissions:
contents: read
pull-requests: read
jobs: jobs:
generate: generate:
name: Generate framework coverage artifacts name: Generate framework coverage artifacts

View File

@@ -6,6 +6,10 @@ on:
types: types:
- completed - completed
permissions:
contents: read
pull-requests: write
jobs: jobs:
check: check:
name: Check framework coverage differences and comment name: Check framework coverage differences and comment

View File

@@ -3,6 +3,9 @@ name: Build framework coverage timeseries reports
on: on:
workflow_dispatch: workflow_dispatch:
permissions:
contents: read
jobs: jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest

View File

@@ -5,6 +5,10 @@ on:
schedule: schedule:
- cron: "0 0 * * *" - cron: "0 0 * * *"
permissions:
contents: write
pull-requests: write
jobs: jobs:
update: update:
name: Update framework coverage report name: Update framework coverage report

View File

@@ -7,6 +7,9 @@ on:
description: "github/codeql repo SHA used for looking up the CSV models" description: "github/codeql repo SHA used for looking up the CSV models"
required: false required: false
permissions:
contents: read
jobs: jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest

View File

@@ -7,13 +7,14 @@ name: Fast-forward tracking branch for selected CodeQL version
on: on:
workflow_dispatch: workflow_dispatch:
permissions:
contents: write
jobs: jobs:
fast-forward: fast-forward:
name: Fast-forward tracking branch for selected CodeQL version name: Fast-forward tracking branch for selected CodeQL version
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.repository == 'github/codeql' if: github.repository == 'github/codeql'
permissions:
contents: write
env: env:
BRANCH_NAME: 'lgtm.com' BRANCH_NAME: 'lgtm.com'
steps: steps:

View File

@@ -8,7 +8,11 @@ on:
- .github/actions/** - .github/actions/**
- codeql-workspace.yml - codeql-workspace.yml
env: env:
GO_VERSION: '~1.21.0' GO_VERSION: '~1.22.0'
permissions:
contents: read
jobs: jobs:
test-mac: test-mac:
name: Test MacOS name: Test MacOS
@@ -18,6 +22,7 @@ jobs:
uses: actions/setup-go@v5 uses: actions/setup-go@v5
with: with:
go-version: ${{ env.GO_VERSION }} go-version: ${{ env.GO_VERSION }}
cache: false
id: go id: go
- name: Check out code - name: Check out code
@@ -46,6 +51,7 @@ jobs:
make test cache="${{ steps.query-cache.outputs.cache-dir }}" make test cache="${{ steps.query-cache.outputs.cache-dir }}"
test-win: test-win:
if: github.repository_owner == 'github'
name: Test Windows name: Test Windows
runs-on: windows-latest-xl runs-on: windows-latest-xl
steps: steps:
@@ -53,6 +59,7 @@ jobs:
uses: actions/setup-go@v5 uses: actions/setup-go@v5
with: with:
go-version: ${{ env.GO_VERSION }} go-version: ${{ env.GO_VERSION }}
cache: false
id: go id: go
- name: Check out code - name: Check out code

View File

@@ -15,10 +15,16 @@ on:
- .github/workflows/go-tests.yml - .github/workflows/go-tests.yml
- .github/actions/** - .github/actions/**
- codeql-workspace.yml - codeql-workspace.yml
env: env:
GO_VERSION: '~1.21.0' GO_VERSION: '~1.22.0'
permissions:
contents: read
jobs: jobs:
test-linux: test-linux:
if: github.repository_owner == 'github'
name: Test Linux (Ubuntu) name: Test Linux (Ubuntu)
runs-on: ubuntu-latest-xl runs-on: ubuntu-latest-xl
steps: steps:
@@ -26,6 +32,7 @@ jobs:
uses: actions/setup-go@v5 uses: actions/setup-go@v5
with: with:
go-version: ${{ env.GO_VERSION }} go-version: ${{ env.GO_VERSION }}
cache: false
id: go id: go
- name: Check out code - name: Check out code

View File

@@ -2,11 +2,12 @@ name: "Pull Request Labeler"
on: on:
- pull_request_target - pull_request_target
jobs: permissions:
triage:
permissions:
contents: read contents: read
pull-requests: write pull-requests: write
jobs:
triage:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/labeler@v4 - uses: actions/labeler@v4

View File

@@ -11,6 +11,9 @@ on:
- ".github/workflows/mad_regenerate-models.yml" - ".github/workflows/mad_regenerate-models.yml"
- ".github/actions/fetch-codeql/action.yml" - ".github/actions/fetch-codeql/action.yml"
permissions:
contents: read
jobs: jobs:
regenerate-models: regenerate-models:
runs-on: ubuntu-latest runs-on: ubuntu-latest

View File

@@ -77,7 +77,7 @@ jobs:
done < "${RUNNER_TEMP}/paths.txt" >> comment_body.txt done < "${RUNNER_TEMP}/paths.txt" >> comment_body.txt
exit "${EXIT_CODE}" exit "${EXIT_CODE}"
- if: always() - if: ${{ !cancelled() }}
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
with: with:
name: comment name: comment

View File

@@ -9,8 +9,13 @@ on:
env: env:
CARGO_TERM_COLOR: always CARGO_TERM_COLOR: always
permissions:
contents: read
security-events: write
jobs: jobs:
analyze: analyze:
if: github.repository_owner == 'github'
runs-on: ubuntu-latest-xl runs-on: ubuntu-latest-xl
steps: steps:
### Build the queries ### ### Build the queries ###
@@ -19,7 +24,7 @@ jobs:
fetch-depth: 0 fetch-depth: 0
- name: Find codeql - name: Find codeql
id: find-codeql id: find-codeql
uses: github/codeql-action/init@v2 uses: github/codeql-action/init@main
with: with:
languages: javascript # does not matter languages: javascript # does not matter
- uses: ./.github/actions/os-version - uses: ./.github/actions/os-version
@@ -65,7 +70,7 @@ jobs:
exclude:*/ql/lib/upgrades/ exclude:*/ql/lib/upgrades/
exclude:java/ql/integration-tests exclude:java/ql/integration-tests
- name: Upload sarif to code-scanning - name: Upload sarif to code-scanning
uses: github/codeql-action/upload-sarif@v2 uses: github/codeql-action/upload-sarif@main
with: with:
sarif_file: ql-for-ql.sarif sarif_file: ql-for-ql.sarif
category: ql-for-ql category: ql-for-ql

View File

@@ -11,6 +11,10 @@ on:
- ql/ql/src/ql.dbscheme - ql/ql/src/ql.dbscheme
workflow_dispatch: workflow_dispatch:
permissions:
contents: read
security-events: read
jobs: jobs:
measure: measure:
env: env:
@@ -25,7 +29,7 @@ jobs:
- name: Find codeql - name: Find codeql
id: find-codeql id: find-codeql
uses: github/codeql-action/init@v2 uses: github/codeql-action/init@main
with: with:
languages: javascript # does not matter languages: javascript # does not matter
- uses: ./.github/actions/os-version - uses: ./.github/actions/os-version

View File

@@ -17,6 +17,9 @@ on:
env: env:
CARGO_TERM_COLOR: always CARGO_TERM_COLOR: always
permissions:
contents: read
jobs: jobs:
qltest: qltest:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -24,7 +27,7 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Find codeql - name: Find codeql
id: find-codeql id: find-codeql
uses: github/codeql-action/init@v2 uses: github/codeql-action/init@main
with: with:
languages: javascript # does not matter languages: javascript # does not matter
- uses: ./.github/actions/os-version - uses: ./.github/actions/os-version
@@ -69,7 +72,7 @@ jobs:
echo "/usr/local/opt/gnu-tar/libexec/gnubin" >> $GITHUB_PATH echo "/usr/local/opt/gnu-tar/libexec/gnubin" >> $GITHUB_PATH
- name: Find codeql - name: Find codeql
id: find-codeql id: find-codeql
uses: github/codeql-action/init@v2 uses: github/codeql-action/init@main
with: with:
languages: javascript # does not matter languages: javascript # does not matter
- uses: ./.github/actions/os-version - uses: ./.github/actions/os-version

View File

@@ -13,6 +13,9 @@ on:
- '.github/actions/fetch-codeql/action.yml' - '.github/actions/fetch-codeql/action.yml'
- 'misc/scripts/generate-code-scanning-query-list.py' - 'misc/scripts/generate-code-scanning-query-list.py'
permissions:
contents: read
jobs: jobs:
build: build:

View File

@@ -32,6 +32,9 @@ defaults:
run: run:
working-directory: ruby working-directory: ruby
permissions:
contents: read
jobs: jobs:
build: build:
strategy: strategy:
@@ -111,6 +114,7 @@ jobs:
ruby/extractor/target/release/codeql-extractor-ruby.exe ruby/extractor/target/release/codeql-extractor-ruby.exe
retention-days: 1 retention-days: 1
compile-queries: compile-queries:
if: github.repository_owner == 'github'
runs-on: ubuntu-latest-xl runs-on: ubuntu-latest-xl
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4

View File

@@ -17,6 +17,9 @@ on:
- .github/workflows/ruby-dataset-measure.yml - .github/workflows/ruby-dataset-measure.yml
workflow_dispatch: workflow_dispatch:
permissions:
contents: read
jobs: jobs:
measure: measure:
env: env:

View File

@@ -29,6 +29,9 @@ defaults:
run: run:
working-directory: ruby working-directory: ruby
permissions:
contents: read
jobs: jobs:
qlupgrade: qlupgrade:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -50,6 +53,7 @@ jobs:
xargs codeql execute upgrades testdb xargs codeql execute upgrades testdb
diff -q testdb/ruby.dbscheme downgrades/initial/ruby.dbscheme diff -q testdb/ruby.dbscheme downgrades/initial/ruby.dbscheme
qltest: qltest:
if: github.repository_owner == 'github'
runs-on: ubuntu-latest-xl runs-on: ubuntu-latest-xl
strategy: strategy:
fail-fast: false fail-fast: false

View File

@@ -33,40 +33,47 @@ on:
- rc/* - rc/*
- codeql-cli-* - codeql-cli-*
permissions:
contents: read
jobs: jobs:
# not using a matrix as you cannot depend on a specific job in a matrix, and we want to start linux checks # not using a matrix as you cannot depend on a specific job in a matrix, and we want to start linux checks
# without waiting for the macOS build # without waiting for the macOS build
build-and-test-macos: build-and-test-macos:
if: github.repository_owner == 'github'
runs-on: macos-12-xl runs-on: macos-12-xl
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: ./swift/actions/build-and-test - uses: ./swift/actions/build-and-test
build-and-test-linux: build-and-test-linux:
if: github.repository_owner == 'github'
runs-on: ubuntu-latest-xl runs-on: ubuntu-latest-xl
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: ./swift/actions/build-and-test - uses: ./swift/actions/build-and-test
qltests-linux: qltests-linux:
if: github.repository_owner == 'github'
needs: build-and-test-linux needs: build-and-test-linux
runs-on: ubuntu-latest-xl runs-on: ubuntu-latest-xl
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: ./swift/actions/run-ql-tests - uses: ./swift/actions/run-ql-tests
qltests-macos: qltests-macos:
if : ${{ github.event_name == 'pull_request' }} if: ${{ github.repository_owner == 'github' && github.event_name == 'pull_request' }}
needs: build-and-test-macos needs: build-and-test-macos
runs-on: macos-12-xl runs-on: macos-12-xl
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: ./swift/actions/run-ql-tests - uses: ./swift/actions/run-ql-tests
integration-tests-linux: integration-tests-linux:
if: github.repository_owner == 'github'
needs: build-and-test-linux needs: build-and-test-linux
runs-on: ubuntu-latest-xl runs-on: ubuntu-latest-xl
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: ./swift/actions/run-integration-tests - uses: ./swift/actions/run-integration-tests
integration-tests-macos: integration-tests-macos:
if : ${{ github.event_name == 'pull_request' }} if: ${{ github.repository_owner == 'github' && github.event_name == 'pull_request' }}
needs: build-and-test-macos needs: build-and-test-macos
runs-on: macos-12-xl runs-on: macos-12-xl
timeout-minutes: 60 timeout-minutes: 60

View File

@@ -10,6 +10,9 @@ on:
- main - main
- 'rc/*' - 'rc/*'
permissions:
contents: read
jobs: jobs:
sync: sync:
runs-on: ubuntu-latest runs-on: ubuntu-latest

View File

@@ -23,6 +23,9 @@ defaults:
run: run:
working-directory: shared/tree-sitter-extractor working-directory: shared/tree-sitter-extractor
permissions:
contents: read
jobs: jobs:
test: test:
runs-on: ubuntu-latest runs-on: ubuntu-latest

View File

@@ -15,6 +15,9 @@ on:
- ".github/workflows/validate-change-notes.yml" - ".github/workflows/validate-change-notes.yml"
- ".github/actions/fetch-codeql/action.yml" - ".github/actions/fetch-codeql/action.yml"
permissions:
contents: read
jobs: jobs:
check-change-note: check-change-note:
runs-on: ubuntu-latest runs-on: ubuntu-latest

View File

@@ -0,0 +1,19 @@
class Element extends @element {
string toString() { none() }
}
class Expr extends @expr {
string toString() { none() }
}
class Stmt extends @stmt {
string toString() { none() }
}
predicate isStmtWithInitializer(Stmt stmt) { exists(int kind | stmts(stmt, kind, _) | kind = 29) }
from Expr child, int index, int index_new, Element parent
where
exprparents(child, index, parent) and
if isStmtWithInitializer(parent) then index_new = index - 1 else index_new = index
select child, index_new, parent

View File

@@ -0,0 +1,9 @@
class Stmt extends @stmt {
string toString() { none() }
}
from Stmt f, Stmt i
where
for_initialization(f, i) and
f instanceof @stmt_for
select f, i

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,20 @@
class Element extends @element {
string toString() { none() }
}
class Stmt extends @stmt {
string toString() { none() }
}
predicate isStmtWithInitializer(Stmt stmt) { exists(int kind | stmts(stmt, kind, _) | kind = 29) }
from Stmt child, int index, int index_new, Element parent
where
stmtparents(child, index, parent) and
(
not isStmtWithInitializer(parent)
or
index > 0
) and
if isStmtWithInitializer(parent) then index_new = index - 1 else index_new = index
select child, index_new, parent

View File

@@ -0,0 +1,5 @@
description: Support C++20 range-based for initializers
compatibility: partial
exprparents.rel: run exprparents.qlo
stmtparents.rel: run stmtparents.qlo
for_initialization.rel: run for_initialization.qlo

View File

@@ -1,3 +1,9 @@
## 0.12.6
### New Features
* A `getInitialization` predicate was added to the `RangeBasedForStmt` class that yields the C++20-style initializer of the range-based `for` statement when it exists.
## 0.12.5 ## 0.12.5
### New Features ### New Features

View File

@@ -0,0 +1,5 @@
## 0.12.6
### New Features
* A `getInitialization` predicate was added to the `RangeBasedForStmt` class that yields the C++20-style initializer of the range-based `for` statement when it exists.

View File

@@ -1,2 +1,2 @@
--- ---
lastReleaseVersion: 0.12.5 lastReleaseVersion: 0.12.6

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-all name: codeql/cpp-all
version: 0.12.5 version: 0.12.6
groups: cpp groups: cpp
dbscheme: semmlecode.cpp.dbscheme dbscheme: semmlecode.cpp.dbscheme
extractor: cpp extractor: cpp

View File

@@ -735,7 +735,9 @@ private predicate namedStmtChildPredicates(Locatable s, Element e, string pred)
or or
s.(ForStmt).getStmt() = e and pred = "getStmt()" s.(ForStmt).getStmt() = e and pred = "getStmt()"
or or
s.(RangeBasedForStmt).getChild(0) = e and pred = "getChild(0)" s.(RangeBasedForStmt).getInitialization() = e and pred = "getInitialization()"
or
s.(RangeBasedForStmt).getChild(1) = e and pred = "getChild(1)"
or or
s.(RangeBasedForStmt).getBeginEndDeclaration() = e and pred = "getBeginEndDeclaration()" s.(RangeBasedForStmt).getBeginEndDeclaration() = e and pred = "getBeginEndDeclaration()"
or or
@@ -743,7 +745,7 @@ private predicate namedStmtChildPredicates(Locatable s, Element e, string pred)
or or
s.(RangeBasedForStmt).getUpdate() = e and pred = "getUpdate()" s.(RangeBasedForStmt).getUpdate() = e and pred = "getUpdate()"
or or
s.(RangeBasedForStmt).getChild(4) = e and pred = "getChild(4)" s.(RangeBasedForStmt).getChild(5) = e and pred = "getChild(5)"
or or
s.(RangeBasedForStmt).getStmt() = e and pred = "getStmt()" s.(RangeBasedForStmt).getStmt() = e and pred = "getStmt()"
or or
@@ -835,7 +837,11 @@ private predicate namedExprChildPredicates(Expr expr, Element ele, string pred)
or or
expr.(OverloadedArrayExpr).getArrayOffset() = ele and pred = "getArrayOffset()" expr.(OverloadedArrayExpr).getArrayOffset() = ele and pred = "getArrayOffset()"
or or
expr.(OverloadedPointerDereferenceExpr).getExpr() = ele and pred = "getExpr()" // OverloadedPointerDereferenceExpr::getExpr/0 also considers qualifiers, which are already handled above for all Call classes.
not expr.(OverloadedPointerDereferenceExpr).getQualifier() =
expr.(OverloadedPointerDereferenceExpr).getExpr() and
expr.(OverloadedPointerDereferenceExpr).getExpr() = ele and
pred = "getExpr()"
or or
expr.(CommaExpr).getLeftOperand() = ele and pred = "getLeftOperand()" expr.(CommaExpr).getLeftOperand() = ele and pred = "getLeftOperand()"
or or

View File

@@ -234,7 +234,16 @@ class VariableDeclarationEntry extends DeclarationEntry, @var_decl {
* int f(int y) { return y; } * int f(int y) { return y; }
* ``` * ```
*/ */
override string getName() { var_decls(underlyingElement(this), _, _, result, _) and result != "" } override string getName() {
exists(string name |
var_decls(underlyingElement(this), _, _, name, _) and
(
name != "" and result = name
or
name = "" and result = this.getVariable().(LocalVariable).getName()
)
)
}
/** /**
* Gets the type of the variable which is being declared or defined. * Gets the type of the variable which is being declared or defined.

View File

@@ -203,16 +203,15 @@ private class GuardConditionFromIR extends GuardCondition {
* `&&` and `||`. See the detailed explanation on predicate `controls`. * `&&` and `||`. See the detailed explanation on predicate `controls`.
*/ */
private predicate controlsBlock(BasicBlock controlled, boolean testIsTrue) { private predicate controlsBlock(BasicBlock controlled, boolean testIsTrue) {
exists(IRBlock irb, Instruction instr | exists(IRBlock irb |
ir.controls(irb, testIsTrue) and ir.controls(irb, testIsTrue) and
instr = irb.getAnInstruction() and nonExcludedIRAndBasicBlock(irb, controlled) and
instr.getAst().(ControlFlowNode).getBasicBlock() = controlled and not isUnreachedBlock(irb)
not isUnreachedBlock(irb) and
not this.excludeAsControlledInstruction(instr)
) )
} }
}
private predicate excludeAsControlledInstruction(Instruction instr) { private predicate excludeAsControlledInstruction(Instruction instr) {
// Exclude the temporaries generated by a ternary expression. // Exclude the temporaries generated by a ternary expression.
exists(TranslatedConditionalExpr tce | exists(TranslatedConditionalExpr tce |
instr = tce.getInstruction(ConditionValueFalseStoreTag()) instr = tce.getInstruction(ConditionValueFalseStoreTag())
@@ -226,7 +225,20 @@ private class GuardConditionFromIR extends GuardCondition {
or or
// Exclude unreached instructions, as their AST is the whole function and not a block. // Exclude unreached instructions, as their AST is the whole function and not a block.
instr instanceof UnreachedInstruction instr instanceof UnreachedInstruction
} }
/**
* Holds if `irb` is the `IRBlock` corresponding to the AST basic block
* `controlled`, and `irb` does not contain any instruction(s) that should make
* the `irb` be ignored.
*/
pragma[nomagic]
private predicate nonExcludedIRAndBasicBlock(IRBlock irb, BasicBlock controlled) {
exists(Instruction instr |
instr = irb.getAnInstruction() and
instr.getAst().(ControlFlowNode).getBasicBlock() = controlled and
not excludeAsControlledInstruction(instr)
)
} }
/** /**

View File

@@ -637,8 +637,10 @@ private predicate straightLineSparse(Node scope, int i, Node ni, Spec spec) {
any(RangeBasedForStmt for | any(RangeBasedForStmt for |
i = -1 and ni = for and spec.isAt() i = -1 and ni = for and spec.isAt()
or or
i = 0 and ni = for.getInitialization() and spec.isAround()
or
exists(DeclStmt s | s.getADeclaration() = for.getRangeVariable() | exists(DeclStmt s | s.getADeclaration() = for.getRangeVariable() |
i = 0 and ni = s and spec.isAround() i = 1 and ni = s and spec.isAround()
) )
or or
exists(DeclStmt s | exists(DeclStmt s |
@@ -649,22 +651,22 @@ private predicate straightLineSparse(Node scope, int i, Node ni, Spec spec) {
// DeclStmt in that case. // DeclStmt in that case.
exists(s.getADeclaration()) exists(s.getADeclaration())
| |
i = 1 and ni = s and spec.isAround() i = 2 and ni = s and spec.isAround()
) )
or or
i = 2 and ni = for.getCondition() and spec.isBefore() i = 3 and ni = for.getCondition() and spec.isBefore()
or or
i = 3 and /* BARRIER */ ni = for and spec.isBarrier() i = 4 and /* BARRIER */ ni = for and spec.isBarrier()
or or
exists(DeclStmt declStmt | declStmt.getADeclaration() = for.getVariable() | exists(DeclStmt declStmt | declStmt.getADeclaration() = for.getVariable() |
i = 4 and ni = declStmt and spec.isAfter() i = 5 and ni = declStmt and spec.isAfter()
) )
or or
i = 5 and ni = for.getStmt() and spec.isAround() i = 6 and ni = for.getStmt() and spec.isAround()
or or
i = 6 and ni = for.getUpdate() and spec.isAround() i = 7 and ni = for.getUpdate() and spec.isAround()
or or
i = 7 and ni = for.getCondition() and spec.isBefore() i = 8 and ni = for.getCondition() and spec.isBefore()
) )
or or
scope = scope =

View File

@@ -244,9 +244,15 @@ class ConditionDeclExpr extends Expr, @condition_decl {
/** /**
* Gets the compiler-generated variable access that conceptually occurs after * Gets the compiler-generated variable access that conceptually occurs after
* the initialization of the declared variable. * the initialization of the declared variable, if any.
*/ */
VariableAccess getVariableAccess() { result = this.getChild(0) } VariableAccess getVariableAccess() { result = this.getExpr() }
/**
* Gets the expression that is evaluated after the initialization of the declared
* variable.
*/
Expr getExpr() { result = this.getChild(0) }
/** /**
* Gets the expression that initializes the declared variable. This predicate * Gets the expression that initializes the declared variable. This predicate

View File

@@ -709,7 +709,7 @@ class FinalGlobalValue extends Node, TFinalGlobalValue {
override DataFlowType getType() { override DataFlowType getType() {
exists(int indirectionIndex | exists(int indirectionIndex |
indirectionIndex = globalUse.getIndirectionIndex() and indirectionIndex = globalUse.getIndirectionIndex() and
result = getTypeImpl(globalUse.getUnspecifiedType(), indirectionIndex - 1) result = getTypeImpl(globalUse.getUnderlyingType(), indirectionIndex - 1)
) )
} }
@@ -740,7 +740,7 @@ class InitialGlobalValue extends Node, TInitialGlobalValue {
override DataFlowType getType() { override DataFlowType getType() {
exists(DataFlowType type | exists(DataFlowType type |
type = globalDef.getUnspecifiedType() and type = globalDef.getUnderlyingType() and
if this.isGLValue() if this.isGLValue()
then result = type then result = type
else result = getTypeImpl(type, globalDef.getIndirectionIndex() - 1) else result = getTypeImpl(type, globalDef.getIndirectionIndex() - 1)
@@ -943,10 +943,13 @@ private Type getTypeImpl0(Type t, int indirectionIndex) {
indirectionIndex > 0 and indirectionIndex > 0 and
exists(Type stripped | exists(Type stripped |
stripped = stripPointer(t.stripTopLevelSpecifiers()) and stripped = stripPointer(t.stripTopLevelSpecifiers()) and
// We need to avoid the case where `stripPointer(t) = t` (which can happen on // We need to avoid the case where `stripPointer(t) = t` (which can happen
// iterators that specify a `value_type` that is the iterator itself). Such a type // on iterators that specify a `value_type` that is the iterator itself).
// would create an infinite loop otherwise. For these cases we simply don't produce // Such a type would create an infinite loop otherwise. For these cases we
// a result for `getTypeImpl`. // simply don't produce a result for `getTypeImpl`.
// To be on the safe side, we check whether the _unspecified_ type has
// changed since this also prevents an infinite loop when `stripped` and
// `t` only differ by const'ness or volatile'ness.
stripped.getUnspecifiedType() != t.getUnspecifiedType() and stripped.getUnspecifiedType() != t.getUnspecifiedType() and
result = getTypeImpl0(stripped, indirectionIndex - 1) result = getTypeImpl0(stripped, indirectionIndex - 1)
) )
@@ -996,12 +999,14 @@ private module RawIndirectNodes {
override Declaration getEnclosingCallable() { result = this.getFunction() } override Declaration getEnclosingCallable() { result = this.getFunction() }
override predicate isGLValue() { this.getOperand().isGLValue() }
override DataFlowType getType() { override DataFlowType getType() {
exists(int sub, DataFlowType type, boolean isGLValue | exists(int sub, DataFlowType type, boolean isGLValue |
type = getOperandType(this.getOperand(), isGLValue) and type = getOperandType(this.getOperand(), isGLValue) and
if isGLValue = true then sub = 1 else sub = 0 if isGLValue = true then sub = 1 else sub = 0
| |
result = getTypeImpl(type.getUnspecifiedType(), indirectionIndex - sub) result = getTypeImpl(type.getUnderlyingType(), indirectionIndex - sub)
) )
} }
@@ -1038,12 +1043,14 @@ private module RawIndirectNodes {
override Declaration getEnclosingCallable() { result = this.getFunction() } override Declaration getEnclosingCallable() { result = this.getFunction() }
override predicate isGLValue() { this.getInstruction().isGLValue() }
override DataFlowType getType() { override DataFlowType getType() {
exists(int sub, DataFlowType type, boolean isGLValue | exists(int sub, DataFlowType type, boolean isGLValue |
type = getInstructionType(this.getInstruction(), isGLValue) and type = getInstructionType(this.getInstruction(), isGLValue) and
if isGLValue = true then sub = 1 else sub = 0 if isGLValue = true then sub = 1 else sub = 0
| |
result = getTypeImpl(type.getUnspecifiedType(), indirectionIndex - sub) result = getTypeImpl(type.getUnderlyingType(), indirectionIndex - sub)
) )
} }
@@ -1136,7 +1143,7 @@ class FinalParameterNode extends Node, TFinalParameterNode {
override Declaration getEnclosingCallable() { result = this.getFunction() } override Declaration getEnclosingCallable() { result = this.getFunction() }
override DataFlowType getType() { result = getTypeImpl(p.getUnspecifiedType(), indirectionIndex) } override DataFlowType getType() { result = getTypeImpl(p.getUnderlyingType(), indirectionIndex) }
final override Location getLocationImpl() { final override Location getLocationImpl() {
// Parameters can have multiple locations. When there's a unique location we use // Parameters can have multiple locations. When there's a unique location we use
@@ -1789,7 +1796,7 @@ class VariableNode extends Node, TVariableNode {
} }
override DataFlowType getType() { override DataFlowType getType() {
result = getTypeImpl(v.getUnspecifiedType(), indirectionIndex - 1) result = getTypeImpl(v.getUnderlyingType(), indirectionIndex - 1)
} }
final override Location getLocationImpl() { final override Location getLocationImpl() {

View File

@@ -507,13 +507,13 @@ module ProductFlow {
private predicate pathSuccPlus(TNodePair n1, TNodePair n2) = fastTC(pathSucc/2)(n1, n2) private predicate pathSuccPlus(TNodePair n1, TNodePair n2) = fastTC(pathSucc/2)(n1, n2)
private predicate localPathStep1(Flow1::PathNode pred, Flow1::PathNode succ) { private predicate localPathStep1(Flow1::PathNode pred, Flow1::PathNode succ) {
Flow1::PathGraph::edges(pred, succ) and Flow1::PathGraph::edges(pred, succ, _, _) and
pragma[only_bind_out](pred.getNode().getEnclosingCallable()) = pragma[only_bind_out](pred.getNode().getEnclosingCallable()) =
pragma[only_bind_out](succ.getNode().getEnclosingCallable()) pragma[only_bind_out](succ.getNode().getEnclosingCallable())
} }
private predicate localPathStep2(Flow2::PathNode pred, Flow2::PathNode succ) { private predicate localPathStep2(Flow2::PathNode pred, Flow2::PathNode succ) {
Flow2::PathGraph::edges(pred, succ) and Flow2::PathGraph::edges(pred, succ, _, _) and
pragma[only_bind_out](pred.getNode().getEnclosingCallable()) = pragma[only_bind_out](pred.getNode().getEnclosingCallable()) =
pragma[only_bind_out](succ.getNode().getEnclosingCallable()) pragma[only_bind_out](succ.getNode().getEnclosingCallable())
} }
@@ -530,7 +530,7 @@ module ProductFlow {
TJump() TJump()
private predicate intoImpl1(Flow1::PathNode pred1, Flow1::PathNode succ1, DataFlowCall call) { private predicate intoImpl1(Flow1::PathNode pred1, Flow1::PathNode succ1, DataFlowCall call) {
Flow1::PathGraph::edges(pred1, succ1) and Flow1::PathGraph::edges(pred1, succ1, _, _) and
pred1.getNode().(ArgumentNode).getCall() = call and pred1.getNode().(ArgumentNode).getCall() = call and
succ1.getNode() instanceof ParameterNode succ1.getNode() instanceof ParameterNode
} }
@@ -543,7 +543,7 @@ module ProductFlow {
} }
private predicate outImpl1(Flow1::PathNode pred1, Flow1::PathNode succ1, DataFlowCall call) { private predicate outImpl1(Flow1::PathNode pred1, Flow1::PathNode succ1, DataFlowCall call) {
Flow1::PathGraph::edges(pred1, succ1) and Flow1::PathGraph::edges(pred1, succ1, _, _) and
exists(ReturnKindExt returnKind | exists(ReturnKindExt returnKind |
succ1.getNode() = returnKind.getAnOutNode(call) and succ1.getNode() = returnKind.getAnOutNode(call) and
pred1.getNode().(ReturnNodeExt).getKind() = returnKind pred1.getNode().(ReturnNodeExt).getKind() = returnKind
@@ -558,7 +558,7 @@ module ProductFlow {
} }
private predicate intoImpl2(Flow2::PathNode pred2, Flow2::PathNode succ2, DataFlowCall call) { private predicate intoImpl2(Flow2::PathNode pred2, Flow2::PathNode succ2, DataFlowCall call) {
Flow2::PathGraph::edges(pred2, succ2) and Flow2::PathGraph::edges(pred2, succ2, _, _) and
pred2.getNode().(ArgumentNode).getCall() = call and pred2.getNode().(ArgumentNode).getCall() = call and
succ2.getNode() instanceof ParameterNode succ2.getNode() instanceof ParameterNode
} }
@@ -571,7 +571,7 @@ module ProductFlow {
} }
private predicate outImpl2(Flow2::PathNode pred2, Flow2::PathNode succ2, DataFlowCall call) { private predicate outImpl2(Flow2::PathNode pred2, Flow2::PathNode succ2, DataFlowCall call) {
Flow2::PathGraph::edges(pred2, succ2) and Flow2::PathGraph::edges(pred2, succ2, _, _) and
exists(ReturnKindExt returnKind | exists(ReturnKindExt returnKind |
succ2.getNode() = returnKind.getAnOutNode(call) and succ2.getNode() = returnKind.getAnOutNode(call) and
pred2.getNode().(ReturnNodeExt).getKind() = returnKind pred2.getNode().(ReturnNodeExt).getKind() = returnKind
@@ -590,7 +590,7 @@ module ProductFlow {
Declaration predDecl, Declaration succDecl, Flow1::PathNode pred1, Flow1::PathNode succ1, Declaration predDecl, Declaration succDecl, Flow1::PathNode pred1, Flow1::PathNode succ1,
TKind kind TKind kind
) { ) {
Flow1::PathGraph::edges(pred1, succ1) and Flow1::PathGraph::edges(pred1, succ1, _, _) and
predDecl != succDecl and predDecl != succDecl and
pred1.getNode().getEnclosingCallable() = predDecl and pred1.getNode().getEnclosingCallable() = predDecl and
succ1.getNode().getEnclosingCallable() = succDecl and succ1.getNode().getEnclosingCallable() = succDecl and
@@ -610,7 +610,7 @@ module ProductFlow {
Declaration predDecl, Declaration succDecl, Flow2::PathNode pred2, Flow2::PathNode succ2, Declaration predDecl, Declaration succDecl, Flow2::PathNode pred2, Flow2::PathNode succ2,
TKind kind TKind kind
) { ) {
Flow2::PathGraph::edges(pred2, succ2) and Flow2::PathGraph::edges(pred2, succ2, _, _) and
predDecl != succDecl and predDecl != succDecl and
pred2.getNode().getEnclosingCallable() = predDecl and pred2.getNode().getEnclosingCallable() = predDecl and
succ2.getNode().getEnclosingCallable() = succDecl and succ2.getNode().getEnclosingCallable() = succDecl and

View File

@@ -142,7 +142,7 @@ private newtype TDefOrUseImpl =
exists(SsaInternals0::Def def | exists(SsaInternals0::Def def |
def.getSourceVariable().getBaseVariable().(BaseIRVariable).getIRVariable().getAst() = p and def.getSourceVariable().getBaseVariable().(BaseIRVariable).getIRVariable().getAst() = p and
not def.getValue().asInstruction() instanceof InitializeParameterInstruction and not def.getValue().asInstruction() instanceof InitializeParameterInstruction and
unspecifiedTypeIsModifiableAt(p.getUnspecifiedType(), indirectionIndex) underlyingTypeIsModifiableAt(p.getUnderlyingType(), indirectionIndex)
) )
} }
@@ -172,11 +172,13 @@ private predicate isGlobalDefImpl(
) )
} }
private predicate unspecifiedTypeIsModifiableAt(Type unspecified, int indirectionIndex) { private predicate underlyingTypeIsModifiableAt(Type underlying, int indirectionIndex) {
indirectionIndex = [1 .. getIndirectionForUnspecifiedType(unspecified).getNumberOfIndirections()] and indirectionIndex =
[1 .. getIndirectionForUnspecifiedType(underlying.getUnspecifiedType())
.getNumberOfIndirections()] and
exists(CppType cppType | exists(CppType cppType |
cppType.hasUnspecifiedType(unspecified, _) and cppType.hasUnderlyingType(underlying, false) and
isModifiableAt(cppType, indirectionIndex + 1) isModifiableAt(cppType, indirectionIndex)
) )
} }
@@ -545,6 +547,11 @@ class GlobalUse extends UseImpl, TGlobalUse {
*/ */
Type getUnspecifiedType() { result = global.getUnspecifiedType() } Type getUnspecifiedType() { result = global.getUnspecifiedType() }
/**
* Gets the type of this use, after typedefs have been resolved.
*/
Type getUnderlyingType() { result = global.getUnderlyingType() }
override predicate isCertain() { any() } override predicate isCertain() { any() }
override BaseSourceVariableInstruction getBase() { none() } override BaseSourceVariableInstruction getBase() { none() }
@@ -588,11 +595,16 @@ class GlobalDefImpl extends DefOrUseImpl, TGlobalDefImpl {
int getIndirection() { result = indirectionIndex } int getIndirection() { result = indirectionIndex }
/** /**
* Gets the type of this use after specifiers have been deeply stripped * Gets the type of this definition after specifiers have been deeply
* and typedefs have been resolved. * stripped and typedefs have been resolved.
*/ */
Type getUnspecifiedType() { result = global.getUnspecifiedType() } Type getUnspecifiedType() { result = global.getUnspecifiedType() }
/**
* Gets the type of this definition, after typedefs have been resolved.
*/
Type getUnderlyingType() { result = global.getUnderlyingType() }
override string toString() { result = "Def of " + this.getSourceVariable() } override string toString() { result = "Def of " + this.getSourceVariable() }
override Location getLocation() { result = f.getLocation() } override Location getLocation() { result = f.getLocation() }
@@ -1092,6 +1104,11 @@ class GlobalDef extends TGlobalDef, SsaDefOrUse {
*/ */
DataFlowType getUnspecifiedType() { result = global.getUnspecifiedType() } DataFlowType getUnspecifiedType() { result = global.getUnspecifiedType() }
/**
* Gets the type of this definition, after typedefs have been resolved.
*/
DataFlowType getUnderlyingType() { result = global.getUnderlyingType() }
/** Gets the `IRFunction` whose body is evaluated after this definition. */ /** Gets the `IRFunction` whose body is evaluated after this definition. */
IRFunction getIRFunction() { result = global.getIRFunction() } IRFunction getIRFunction() { result = global.getIRFunction() }

View File

@@ -452,7 +452,7 @@ private module IsModifiableAtImpl {
private predicate impl(CppType cppType, int indirectionIndex) { private predicate impl(CppType cppType, int indirectionIndex) {
exists(Type pointerType, Type base | exists(Type pointerType, Type base |
isUnderlyingIndirectionType(pointerType) and isUnderlyingIndirectionType(pointerType) and
cppType.hasUnderlyingType(pointerType, _) and cppType.hasUnderlyingType(pointerType, false) and
base = getTypeImpl(pointerType, indirectionIndex) base = getTypeImpl(pointerType, indirectionIndex)
| |
// The value cannot be modified if it has a const specifier, // The value cannot be modified if it has a const specifier,

View File

@@ -2125,13 +2125,6 @@ class ChiInstruction extends Instruction {
*/ */
final Instruction getPartial() { result = this.getPartialOperand().getDef() } final Instruction getPartial() { result = this.getPartialOperand().getDef() }
/**
* Gets the bit range `[startBit, endBit)` updated by the partial operand of this `ChiInstruction`, relative to the start address of the total operand.
*/
final predicate getUpdatedInterval(int startBit, int endBit) {
Construction::getIntervalUpdatedByChi(this, startBit, endBit)
}
/** /**
* Holds if the `ChiPartialOperand` totally, but not exactly, overlaps with the `ChiTotalOperand`. * Holds if the `ChiPartialOperand` totally, but not exactly, overlaps with the `ChiTotalOperand`.
* This means that the `ChiPartialOperand` will not override the entire memory associated with the * This means that the `ChiPartialOperand` will not override the entire memory associated with the

View File

@@ -233,20 +233,6 @@ private module Cached {
) )
} }
/**
* Holds if the partial operand of this `ChiInstruction` updates the bit range
* `[startBitOffset, endBitOffset)` of the total operand.
*/
cached
predicate getIntervalUpdatedByChi(ChiInstruction chi, int startBitOffset, int endBitOffset) {
exists(Alias::MemoryLocation location, OldInstruction oldInstruction |
oldInstruction = getOldInstruction(chi.getPartial()) and
location = Alias::getResultMemoryLocation(oldInstruction) and
startBitOffset = Alias::getStartBitOffset(location) and
endBitOffset = Alias::getEndBitOffset(location)
)
}
/** /**
* Holds if `operand` totally overlaps with its definition and consumes the bit range * Holds if `operand` totally overlaps with its definition and consumes the bit range
* `[startBitOffset, endBitOffset)`. * `[startBitOffset, endBitOffset)`.

View File

@@ -2125,13 +2125,6 @@ class ChiInstruction extends Instruction {
*/ */
final Instruction getPartial() { result = this.getPartialOperand().getDef() } final Instruction getPartial() { result = this.getPartialOperand().getDef() }
/**
* Gets the bit range `[startBit, endBit)` updated by the partial operand of this `ChiInstruction`, relative to the start address of the total operand.
*/
final predicate getUpdatedInterval(int startBit, int endBit) {
Construction::getIntervalUpdatedByChi(this, startBit, endBit)
}
/** /**
* Holds if the `ChiPartialOperand` totally, but not exactly, overlaps with the `ChiTotalOperand`. * Holds if the `ChiPartialOperand` totally, but not exactly, overlaps with the `ChiTotalOperand`.
* This means that the `ChiPartialOperand` will not override the entire memory associated with the * This means that the `ChiPartialOperand` will not override the entire memory associated with the

View File

@@ -202,12 +202,6 @@ Instruction getMemoryOperandDefinition(
none() none()
} }
/**
* Holds if the partial operand of this `ChiInstruction` updates the bit range
* `[startBitOffset, endBitOffset)` of the total operand.
*/
predicate getIntervalUpdatedByChi(ChiInstruction chi, int startBit, int endBit) { none() }
/** /**
* Holds if the operand totally overlaps with its definition and consumes the * Holds if the operand totally overlaps with its definition and consumes the
* bit range `[startBitOffset, endBitOffset)`. * bit range `[startBitOffset, endBitOffset)`.

View File

@@ -209,6 +209,8 @@ private predicate usedAsCondition(Expr expr) {
or or
exists(IfStmt ifStmt | ifStmt.getCondition().getFullyConverted() = expr) exists(IfStmt ifStmt | ifStmt.getCondition().getFullyConverted() = expr)
or or
exists(ConstexprIfStmt ifStmt | ifStmt.getCondition().getFullyConverted() = expr)
or
exists(ConditionalExpr condExpr | exists(ConditionalExpr condExpr |
// The two-operand form of `ConditionalExpr` treats its condition as a value, since it needs to // The two-operand form of `ConditionalExpr` treats its condition as a value, since it needs to
// be reused as a value if the condition is true. // be reused as a value if the condition is true.
@@ -474,7 +476,6 @@ private module IRDeclarationEntries {
* This class exists to work around the fact that `DeclStmt`s in some cases * This class exists to work around the fact that `DeclStmt`s in some cases
* do not have `DeclarationEntry`s. Currently, this is the case for: * do not have `DeclarationEntry`s. Currently, this is the case for:
* - `DeclStmt`s in template instantiations. * - `DeclStmt`s in template instantiations.
* - `DeclStmt`s that are generated by the desugaring of range-based for-loops.
* *
* So instead, the IR works with `IRDeclarationEntry`s that synthesize missing * So instead, the IR works with `IRDeclarationEntry`s that synthesize missing
* `DeclarationEntry`s when there is no result for `DeclStmt::getDeclarationEntry`. * `DeclarationEntry`s when there is no result for `DeclStmt::getDeclarationEntry`.

View File

@@ -3173,7 +3173,7 @@ class TranslatedConditionDeclExpr extends TranslatedNonConstantExpr {
private TranslatedConditionDecl getDecl() { result = getTranslatedConditionDecl(expr) } private TranslatedConditionDecl getDecl() { result = getTranslatedConditionDecl(expr) }
private TranslatedExpr getConditionExpr() { private TranslatedExpr getConditionExpr() {
result = getTranslatedExpr(expr.getVariableAccess().getFullyConverted()) result = getTranslatedExpr(expr.getExpr().getFullyConverted())
} }
} }

View File

@@ -774,6 +774,72 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext {
} }
} }
class TranslatedConstExprIfStmt extends TranslatedStmt, ConditionContext {
override ConstexprIfStmt stmt;
override Instruction getFirstInstruction(EdgeKind kind) {
if this.hasInitialization()
then result = this.getInitialization().getFirstInstruction(kind)
else result = this.getFirstConditionInstruction(kind)
}
override TranslatedElement getChild(int id) {
id = 0 and result = this.getInitialization()
or
id = 1 and result = this.getCondition()
or
id = 2 and result = this.getThen()
or
id = 3 and result = this.getElse()
}
private predicate hasInitialization() { exists(stmt.getInitialization()) }
private TranslatedStmt getInitialization() {
result = getTranslatedStmt(stmt.getInitialization())
}
private TranslatedCondition getCondition() {
result = getTranslatedCondition(stmt.getCondition().getFullyConverted())
}
private Instruction getFirstConditionInstruction(EdgeKind kind) {
result = this.getCondition().getFirstInstruction(kind)
}
private TranslatedStmt getThen() { result = getTranslatedStmt(stmt.getThen()) }
private TranslatedStmt getElse() { result = getTranslatedStmt(stmt.getElse()) }
private predicate hasElse() { exists(stmt.getElse()) }
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
override Instruction getChildTrueSuccessor(TranslatedCondition child, EdgeKind kind) {
child = this.getCondition() and
result = this.getThen().getFirstInstruction(kind)
}
override Instruction getChildFalseSuccessor(TranslatedCondition child, EdgeKind kind) {
child = this.getCondition() and
if this.hasElse()
then result = this.getElse().getFirstInstruction(kind)
else result = this.getParent().getChildSuccessor(this, kind)
}
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
child = this.getInitialization() and
result = this.getFirstConditionInstruction(kind)
or
(child = this.getThen() or child = this.getElse()) and
result = this.getParent().getChildSuccessor(this, kind)
}
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
none()
}
}
abstract class TranslatedLoop extends TranslatedStmt, ConditionContext { abstract class TranslatedLoop extends TranslatedStmt, ConditionContext {
override Loop stmt; override Loop stmt;
@@ -894,25 +960,38 @@ class TranslatedRangeBasedForStmt extends TranslatedStmt, ConditionContext {
override RangeBasedForStmt stmt; override RangeBasedForStmt stmt;
override TranslatedElement getChild(int id) { override TranslatedElement getChild(int id) {
id = 0 and result = this.getRangeVariableDeclStmt() id = 0 and result = this.getInitialization()
or
id = 1 and result = this.getRangeVariableDeclStmt()
or or
// Note: `__begin` and `__end` are declared by the same `DeclStmt` // Note: `__begin` and `__end` are declared by the same `DeclStmt`
id = 1 and result = this.getBeginEndVariableDeclStmt() id = 2 and result = this.getBeginEndVariableDeclStmt()
or or
id = 2 and result = this.getCondition() id = 3 and result = this.getCondition()
or or
id = 3 and result = this.getUpdate() id = 4 and result = this.getUpdate()
or or
id = 4 and result = this.getVariableDeclStmt() id = 5 and result = this.getVariableDeclStmt()
or or
id = 5 and result = this.getBody() id = 6 and result = this.getBody()
}
private predicate hasInitialization() { exists(stmt.getInitialization()) }
private TranslatedStmt getInitialization() {
result = getTranslatedStmt(stmt.getInitialization())
} }
override Instruction getFirstInstruction(EdgeKind kind) { override Instruction getFirstInstruction(EdgeKind kind) {
result = this.getRangeVariableDeclStmt().getFirstInstruction(kind) if this.hasInitialization()
then result = this.getInitialization().getFirstInstruction(kind)
else result = this.getFirstRangeVariableDeclStmtInstruction(kind)
} }
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
child = this.getInitialization() and
result = this.getFirstRangeVariableDeclStmtInstruction(kind)
or
child = this.getRangeVariableDeclStmt() and child = this.getRangeVariableDeclStmt() and
result = this.getBeginEndVariableDeclStmt().getFirstInstruction(kind) result = this.getBeginEndVariableDeclStmt().getFirstInstruction(kind)
or or
@@ -952,6 +1031,10 @@ class TranslatedRangeBasedForStmt extends TranslatedStmt, ConditionContext {
) )
} }
private Instruction getFirstRangeVariableDeclStmtInstruction(EdgeKind kind) {
result = this.getRangeVariableDeclStmt().getFirstInstruction(kind)
}
private TranslatedDeclStmt getBeginEndVariableDeclStmt() { private TranslatedDeclStmt getBeginEndVariableDeclStmt() {
exists(IRVariableDeclarationEntry entry | exists(IRVariableDeclarationEntry entry |
entry.getStmt() = stmt.getBeginEndDeclaration() and entry.getStmt() = stmt.getBeginEndDeclaration() and

View File

@@ -2125,13 +2125,6 @@ class ChiInstruction extends Instruction {
*/ */
final Instruction getPartial() { result = this.getPartialOperand().getDef() } final Instruction getPartial() { result = this.getPartialOperand().getDef() }
/**
* Gets the bit range `[startBit, endBit)` updated by the partial operand of this `ChiInstruction`, relative to the start address of the total operand.
*/
final predicate getUpdatedInterval(int startBit, int endBit) {
Construction::getIntervalUpdatedByChi(this, startBit, endBit)
}
/** /**
* Holds if the `ChiPartialOperand` totally, but not exactly, overlaps with the `ChiTotalOperand`. * Holds if the `ChiPartialOperand` totally, but not exactly, overlaps with the `ChiTotalOperand`.
* This means that the `ChiPartialOperand` will not override the entire memory associated with the * This means that the `ChiPartialOperand` will not override the entire memory associated with the

View File

@@ -233,20 +233,6 @@ private module Cached {
) )
} }
/**
* Holds if the partial operand of this `ChiInstruction` updates the bit range
* `[startBitOffset, endBitOffset)` of the total operand.
*/
cached
predicate getIntervalUpdatedByChi(ChiInstruction chi, int startBitOffset, int endBitOffset) {
exists(Alias::MemoryLocation location, OldInstruction oldInstruction |
oldInstruction = getOldInstruction(chi.getPartial()) and
location = Alias::getResultMemoryLocation(oldInstruction) and
startBitOffset = Alias::getStartBitOffset(location) and
endBitOffset = Alias::getEndBitOffset(location)
)
}
/** /**
* Holds if `operand` totally overlaps with its definition and consumes the bit range * Holds if `operand` totally overlaps with its definition and consumes the bit range
* `[startBitOffset, endBitOffset)`. * `[startBitOffset, endBitOffset)`.

View File

@@ -3,6 +3,7 @@ private import implementations.Deallocation
private import implementations.Fread private import implementations.Fread
private import implementations.Getenv private import implementations.Getenv
private import implementations.Gets private import implementations.Gets
private import implementations.GetText
private import implementations.IdentityFunction private import implementations.IdentityFunction
private import implementations.Inet private import implementations.Inet
private import implementations.Iterator private import implementations.Iterator

View File

@@ -0,0 +1,33 @@
import semmle.code.cpp.models.interfaces.DataFlow
/**
* Returns the transated text index for a given gettext function `f`
*/
private int getTextArg(Function f) {
// basic variations of gettext
f.hasGlobalOrStdName("gettext") and result = 0
or
f.hasGlobalOrStdName("dgettext") and result = 1
or
f.hasGlobalOrStdName("dcgettext") and result = 1
or
// plural variations of gettext that take one format string for singular and another for plural form
f.hasGlobalOrStdName("ngettext") and
(result = 0 or result = 1)
or
f.hasGlobalOrStdName("dngettext") and
(result = 1 or result = 2)
or
f.hasGlobalOrStdName("dcngettext") and
(result = 1 or result = 2)
}
class GetTextFunction extends DataFlowFunction {
int argInd;
GetTextFunction() { argInd = getTextArg(this) }
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
input.isParameterDeref(argInd) and output.isReturnValueDeref()
}
}

View File

@@ -22,11 +22,28 @@ private class MemsetFunctionModel extends ArrayFunction, DataFlowFunction, Alias
]) ])
} }
/**
* Gets the index of the parameter that specifies the fill character to insert, if any.
*/
private int getFillCharParameterIndex() {
(
this.hasGlobalOrStdOrBslName("memset")
or
this.hasGlobalOrStdName("wmemset")
or
this.hasGlobalName(["__builtin_memset", "__builtin_memset_chk"])
) and
result = 1
}
override predicate hasArrayOutput(int bufParam) { bufParam = 0 } override predicate hasArrayOutput(int bufParam) { bufParam = 0 }
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
input.isParameter(0) and input.isParameter(0) and
output.isReturnValue() output.isReturnValue()
or
input.isParameter(this.getFillCharParameterIndex()) and
(output.isParameterDeref(0) or output.isReturnValueDeref())
} }
override predicate hasArrayWithVariableSize(int bufParam, int countParam) { override predicate hasArrayWithVariableSize(int bufParam, int countParam) {

View File

@@ -892,6 +892,26 @@ class DoStmt extends Loop, @stmt_end_test_while {
class RangeBasedForStmt extends Loop, @stmt_range_based_for { class RangeBasedForStmt extends Loop, @stmt_range_based_for {
override string getAPrimaryQlClass() { result = "RangeBasedForStmt" } override string getAPrimaryQlClass() { result = "RangeBasedForStmt" }
/**
* Gets the initialization statement of this 'for' statement, if any.
*
* For example, for
* ```
* for (int x = y; auto z : ... ) { }
* ```
* the result is `int x = y;`.
*
* Does not hold if the initialization statement is missing or an empty statement, as in
* ```
* for (auto z : ...) { }
* ```
* or
* ```
* for (; auto z : ) { }
* ```
*/
Stmt getInitialization() { for_initialization(underlyingElement(this), unresolveElement(result)) }
/** /**
* Gets the 'body' statement of this range-based 'for' statement. * Gets the 'body' statement of this range-based 'for' statement.
* *
@@ -901,7 +921,7 @@ class RangeBasedForStmt extends Loop, @stmt_range_based_for {
* ``` * ```
* the result is the `BlockStmt` `{ y += x; }`. * the result is the `BlockStmt` `{ y += x; }`.
*/ */
override Stmt getStmt() { result = this.getChild(5) } override Stmt getStmt() { result = this.getChild(6) }
override string toString() { result = "for(...:...) ..." } override string toString() { result = "for(...:...) ..." }
@@ -914,7 +934,7 @@ class RangeBasedForStmt extends Loop, @stmt_range_based_for {
* ``` * ```
* the result is `int x`. * the result is `int x`.
*/ */
LocalVariable getVariable() { result = this.getChild(4).(DeclStmt).getADeclaration() } LocalVariable getVariable() { result = this.getChild(5).(DeclStmt).getADeclaration() }
/** /**
* Gets the expression giving the range to iterate over. * Gets the expression giving the range to iterate over.
@@ -928,7 +948,7 @@ class RangeBasedForStmt extends Loop, @stmt_range_based_for {
Expr getRange() { result = this.getRangeVariable().getInitializer().getExpr() } Expr getRange() { result = this.getRangeVariable().getInitializer().getExpr() }
/** Gets the compiler-generated `__range` variable after desugaring. */ /** Gets the compiler-generated `__range` variable after desugaring. */
LocalVariable getRangeVariable() { result = this.getChild(0).(DeclStmt).getADeclaration() } LocalVariable getRangeVariable() { result = this.getChild(1).(DeclStmt).getADeclaration() }
/** /**
* Gets the compiler-generated `__begin != __end` which is the * Gets the compiler-generated `__begin != __end` which is the
@@ -936,7 +956,7 @@ class RangeBasedForStmt extends Loop, @stmt_range_based_for {
* It will be either an `NEExpr` or a call to a user-defined * It will be either an `NEExpr` or a call to a user-defined
* `operator!=`. * `operator!=`.
*/ */
override Expr getCondition() { result = this.getChild(2) } override Expr getCondition() { result = this.getChild(3) }
override Expr getControllingExpr() { result = this.getCondition() } override Expr getControllingExpr() { result = this.getCondition() }
@@ -945,7 +965,7 @@ class RangeBasedForStmt extends Loop, @stmt_range_based_for {
* `__end`, initializing them to the values they have before entering the * `__end`, initializing them to the values they have before entering the
* desugared loop. * desugared loop.
*/ */
DeclStmt getBeginEndDeclaration() { result = this.getChild(1) } DeclStmt getBeginEndDeclaration() { result = this.getChild(2) }
/** Gets the compiler-generated `__begin` variable after desugaring. */ /** Gets the compiler-generated `__begin` variable after desugaring. */
LocalVariable getBeginVariable() { result = this.getBeginEndDeclaration().getDeclaration(0) } LocalVariable getBeginVariable() { result = this.getBeginEndDeclaration().getDeclaration(0) }
@@ -959,7 +979,7 @@ class RangeBasedForStmt extends Loop, @stmt_range_based_for {
* be either a `PrefixIncrExpr` or a call to a user-defined * be either a `PrefixIncrExpr` or a call to a user-defined
* `operator++`. * `operator++`.
*/ */
Expr getUpdate() { result = this.getChild(3) } Expr getUpdate() { result = this.getChild(4) }
/** Gets the compiler-generated `__begin` variable after desugaring. */ /** Gets the compiler-generated `__begin` variable after desugaring. */
LocalVariable getAnIterationVariable() { result = this.getBeginVariable() } LocalVariable getAnIterationVariable() { result = this.getBeginVariable() }

View File

@@ -2050,8 +2050,11 @@ switch_body(
int body_id: @stmt ref int body_id: @stmt ref
); );
@stmt_for_or_range_based_for = @stmt_for
| @stmt_range_based_for;
for_initialization( for_initialization(
unique int for_stmt: @stmt_for ref, unique int for_stmt: @stmt_for_or_range_based_for ref,
int init_id: @stmt ref int init_id: @stmt ref
); );

View File

@@ -0,0 +1,19 @@
class Element extends @element {
string toString() { none() }
}
class Expr extends @expr {
string toString() { none() }
}
class Stmt extends @stmt {
string toString() { none() }
}
predicate isStmtWithInitializer(Stmt stmt) { exists(int kind | stmts(stmt, kind, _) | kind = 29) }
from Expr child, int index, int index_new, Element parent
where
exprparents(child, index, parent) and
if isStmtWithInitializer(parent) then index_new = index + 1 else index_new = index
select child, index_new, parent

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,15 @@
class Element extends @element {
string toString() { none() }
}
class Stmt extends @stmt {
string toString() { none() }
}
predicate isStmtWithInitializer(Stmt stmt) { exists(int kind | stmts(stmt, kind, _) | kind = 29) }
from Stmt child, int index, int index_new, Element parent
where
stmtparents(child, index, parent) and
if isStmtWithInitializer(parent) then index_new = index + 1 else index_new = index
select child, index_new, parent

View File

@@ -0,0 +1,4 @@
description: Support C++20 range-based for initializers
compatibility: partial
exprparents.rel: run exprparents.qlo
stmtparents.rel: run stmtparents.qlo

View File

@@ -1,3 +1,10 @@
## 0.9.5
### Minor Analysis Improvements
* The "non-constant format string" query (`cpp/non-constant-format`) has been updated to produce fewer false positives.
* Added dataflow models for the `gettext` function variants.
## 0.9.4 ## 0.9.4
### Minor Analysis Improvements ### Minor Analysis Improvements
@@ -6,7 +13,6 @@
* The "Incorrect return-value check for a 'scanf'-like function" query (`cpp/incorrectly-checked-scanf`) no longer reports an alert when an explicit check for EOF is added. * The "Incorrect return-value check for a 'scanf'-like function" query (`cpp/incorrectly-checked-scanf`) no longer reports an alert when an explicit check for EOF is added.
* The "Incorrect return-value check for a 'scanf'-like function" query (`cpp/incorrectly-checked-scanf`) now recognizes more EOF checks. * The "Incorrect return-value check for a 'scanf'-like function" query (`cpp/incorrectly-checked-scanf`) now recognizes more EOF checks.
* The "Potentially uninitialized local variable" query (`cpp/uninitialized-local`) no longer reports an alert when the local variable is used as a qualifier to a static member function call. * The "Potentially uninitialized local variable" query (`cpp/uninitialized-local`) no longer reports an alert when the local variable is used as a qualifier to a static member function call.
* ```
* The diagnostic query `cpp/diagnostics/successfully-extracted-files` now considers any C/C++ file seen during extraction, even one with some errors, to be extracted / scanned. This affects the Code Scanning UI measure of scanned C/C++ files. * The diagnostic query `cpp/diagnostics/successfully-extracted-files` now considers any C/C++ file seen during extraction, even one with some errors, to be extracted / scanned. This affects the Code Scanning UI measure of scanned C/C++ files.
## 0.9.3 ## 0.9.3

View File

@@ -1,9 +1,13 @@
/** /**
* @name Non-constant format string * @name Non-constant format string
* @description Passing a non-constant 'format' string to a printf-like function can lead * @description Passing a value that is not a string literal 'format' string to a printf-like function can lead
* to a mismatch between the number of arguments defined by the 'format' and the number * to a mismatch between the number of arguments defined by the 'format' and the number
* of arguments actually passed to the function. If the format string ultimately stems * of arguments actually passed to the function. If the format string ultimately stems
* from an untrusted source, this can be used for exploits. * from an untrusted source, this can be used for exploits.
* This query finds format strings coming from non-literal sources. Note that format strings of
* type `const char*` it is still considered non-constant if the value is not coming from a string
* literal. For example, for a parameter with type `const char*` of an exported function that is
* used as a format string, there is no way to ensure the originating value was a string literal.
* @kind problem * @kind problem
* @problem.severity recommendation * @problem.severity recommendation
* @security-severity 9.3 * @security-severity 9.3
@@ -17,142 +21,117 @@
import semmle.code.cpp.ir.dataflow.TaintTracking import semmle.code.cpp.ir.dataflow.TaintTracking
import semmle.code.cpp.commons.Printf import semmle.code.cpp.commons.Printf
import semmle.code.cpp.security.FlowSources
import semmle.code.cpp.ir.dataflow.internal.ModelUtil
import semmle.code.cpp.models.interfaces.DataFlow
import semmle.code.cpp.models.interfaces.Taint
import semmle.code.cpp.ir.IR
// For the following `...gettext` functions, we assume that class UncalledFunction extends Function {
// all translations preserve the type and order of `%` specifiers UncalledFunction() {
// (and hence are safe to use as format strings). This not exists(Call c | c.getTarget() = this) and
// assumption is hard-coded into the query. // Ignore functions that appear to be function pointers
predicate whitelistFunction(Function f, int arg) { // function pointers may be seen as uncalled statically
// basic variations of gettext not exists(FunctionAccess fa | fa.getTarget() = this)
f.getName() = "_" and arg = 0 }
or
f.getName() = "gettext" and arg = 0
or
f.getName() = "dgettext" and arg = 1
or
f.getName() = "dcgettext" and arg = 1
or
// plural variations of gettext that take one format string for singular and another for plural form
f.getName() = "ngettext" and
(arg = 0 or arg = 1)
or
f.getName() = "dngettext" and
(arg = 1 or arg = 2)
or
f.getName() = "dcngettext" and
(arg = 1 or arg = 2)
} }
// we assume that ALL uses of the `_` macro /**
// return constant string literals * Holds if `node` is a non-constant source of data flow for non-const format string detection.
predicate underscoreMacro(Expr e) { * This is defined as either:
exists(MacroInvocation mi | * 1) a `FlowSource`
mi.getMacroName() = "_" and * 2) a parameter of an 'uncalled' function
mi.getExpr() = e * 3) an argument to a function with no definition that is not known to define the output through its input
* 4) an out arg of a function with no definition that is not known to define the output through its input
*
* The latter two cases address identifying standard string manipulation libraries as input sources
* e.g., strcpy. More simply, functions without definitions that are known to manipulate the
* input to produce an output are not sources. Instead the ultimate source of input to these functions
* should be considered as the source.
*
* False Negative Implication: This approach has false negatives (fails to identify non-const sources)
* when the source is a field of a struct or object and the initialization is not observed statically.
* There are 3 general cases where this can occur:
* 1) Parameters of uncalled functions that are structs/objects and a field is accessed for a format string.
* 2) A local variable that is a struct/object and initialization of the field occurs in code that is unseen statically.
* e.g., an object constructor isn't known statically, or a function sets fields
* of a struct, but the function is not known statically.
* 3) A function meeting cases (3) and (4) above returns (through an out argument or return value)
* a struct or object where a field containing a format string has been initialized.
*
* Note, uninitialized variables used as format strings are never detected by design.
* Uninitialized variables are a separate vulnerability concern and should be addressed by a separate query.
*/
predicate isNonConst(DataFlow::Node node) {
node instanceof FlowSource
or
// Parameters of uncalled functions that aren't const
exists(UncalledFunction f, Parameter p |
f.getAParameter() = p and
p = node.asParameter()
)
or
// Consider as an input any out arg of a function or a function's return where the function is not:
// 1. a function with a known dataflow or taintflow from input to output and the `node` is the output
// 2. a function where there is a known definition
// i.e., functions that with unknown bodies and are not known to define the output through its input
// are considered as possible non-const sources
// The function's output must also not be const to be considered a non-const source
exists(Function func, CallInstruction call |
// NOTE: could use `Call` getAnArgument() instead of `CallInstruction` but requires two
// variables representing the same call in ordoer to use `callOutput` below.
exists(Expr arg |
call.getPositionalArgumentOperand(_).getDef().getUnconvertedResultExpression() = arg and
arg = node.asDefiningArgument()
)
or
call.getUnconvertedResultExpression() = node.asIndirectExpr()
|
func = call.getStaticCallTarget() and
not exists(FunctionOutput output |
// NOTE: we must include dataflow and taintflow. e.g., including only dataflow we will find sprintf
// variant function's output are now possible non-const sources
pragma[only_bind_out](func).(DataFlowFunction).hasDataFlow(_, output) or
pragma[only_bind_out](func).(TaintFunction).hasTaintFlow(_, output)
|
node = callOutput(call, output)
)
) and
not exists(Call c |
c.getTarget().hasDefinition() and
if node instanceof DataFlow::DefinitionByReferenceNode
then c.getAnArgument() = node.asDefiningArgument()
else c = [node.asExpr(), node.asIndirectExpr()]
) )
} }
/** /**
* Holds if `t` cannot hold a character array, directly or indirectly. * Holds if `sink` is a sink is a format string of any
* `FormattingFunctionCall`.
*/ */
predicate cannotContainString(Type t, boolean isIndirect) {
isIndirect = false and
exists(Type unspecified |
unspecified = t.getUnspecifiedType() and
not unspecified instanceof UnknownType
|
unspecified instanceof BuiltInType or
unspecified instanceof IntegralOrEnumType
)
}
predicate isNonConst(DataFlow::Node node, boolean isIndirect) {
exists(Expr e |
e = node.asExpr() and isIndirect = false
or
e = node.asIndirectExpr() and isIndirect = true
|
exists(FunctionCall fc | fc = e |
not (
whitelistFunction(fc.getTarget(), _) or
fc.getTarget().hasDefinition()
)
)
or
exists(Parameter p | p = e.(VariableAccess).getTarget() |
p.getFunction().getName() = "main" and p.getType() instanceof PointerType
)
or
e instanceof CrementOperation
or
e instanceof AddressOfExpr
or
e instanceof ReferenceToExpr
or
e instanceof AssignPointerAddExpr
or
e instanceof AssignPointerSubExpr
or
e instanceof PointerArithmeticOperation
or
e instanceof FieldAccess
or
e instanceof PointerDereferenceExpr
or
e instanceof AddressOfExpr
or
e instanceof ExprCall
or
e instanceof NewArrayExpr
or
exists(Variable v | v = e.(VariableAccess).getTarget() |
v.getType().(ArrayType).getBaseType() instanceof CharType and
exists(AssignExpr ae |
ae.getLValue().(ArrayExpr).getArrayBase().(VariableAccess).getTarget() = v
)
)
)
or
node instanceof DataFlow::DefinitionByReferenceNode and
isIndirect = true
}
pragma[noinline]
predicate isBarrierNode(DataFlow::Node node) {
underscoreMacro([node.asExpr(), node.asIndirectExpr()])
or
exists(node.asExpr()) and
cannotContainString(node.getType(), false)
}
predicate isSinkImpl(DataFlow::Node sink, Expr formatString) { predicate isSinkImpl(DataFlow::Node sink, Expr formatString) {
[sink.asExpr(), sink.asIndirectExpr()] = formatString and [sink.asExpr(), sink.asIndirectExpr()] = formatString and
exists(FormattingFunctionCall fc | formatString = fc.getArgument(fc.getFormatParameterIndex())) exists(FormattingFunctionCall fc | formatString = fc.getArgument(fc.getFormatParameterIndex()))
} }
module NonConstFlowConfig implements DataFlow::ConfigSig { module NonConstFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { predicate isSource(DataFlow::Node source) { isNonConst(source) }
exists(boolean isIndirect, Type t |
isNonConst(source, isIndirect) and
t = source.getType() and
not cannotContainString(t, isIndirect)
)
}
predicate isSink(DataFlow::Node sink) { isSinkImpl(sink, _) } predicate isSink(DataFlow::Node sink) { isSinkImpl(sink, _) }
predicate isBarrier(DataFlow::Node node) { isBarrierNode(node) } predicate isBarrier(DataFlow::Node node) {
// Ignore tracing non-const through array indices
exists(ArrayExpr a | a.getArrayOffset() = node.asExpr())
}
} }
module NonConstFlow = TaintTracking::Global<NonConstFlowConfig>; module NonConstFlow = TaintTracking::Global<NonConstFlowConfig>;
from FormattingFunctionCall call, Expr formatString from FormattingFunctionCall call, Expr formatString, DataFlow::Node sink
where where
call.getArgument(call.getFormatParameterIndex()) = formatString and call.getArgument(call.getFormatParameterIndex()) = formatString and
exists(DataFlow::Node sink |
NonConstFlow::flowTo(sink) and NonConstFlow::flowTo(sink) and
isSinkImpl(sink, formatString) isSinkImpl(sink, formatString)
)
select formatString, select formatString,
"The format string argument to " + call.getTarget().getName() + "The format string argument to " + call.getTarget().getName() +
" should be constant to prevent security issues and other potential errors." " should be constant to prevent security issues and other potential errors."

View File

@@ -6,5 +6,4 @@
* The "Incorrect return-value check for a 'scanf'-like function" query (`cpp/incorrectly-checked-scanf`) no longer reports an alert when an explicit check for EOF is added. * The "Incorrect return-value check for a 'scanf'-like function" query (`cpp/incorrectly-checked-scanf`) no longer reports an alert when an explicit check for EOF is added.
* The "Incorrect return-value check for a 'scanf'-like function" query (`cpp/incorrectly-checked-scanf`) now recognizes more EOF checks. * The "Incorrect return-value check for a 'scanf'-like function" query (`cpp/incorrectly-checked-scanf`) now recognizes more EOF checks.
* The "Potentially uninitialized local variable" query (`cpp/uninitialized-local`) no longer reports an alert when the local variable is used as a qualifier to a static member function call. * The "Potentially uninitialized local variable" query (`cpp/uninitialized-local`) no longer reports an alert when the local variable is used as a qualifier to a static member function call.
* ```
* The diagnostic query `cpp/diagnostics/successfully-extracted-files` now considers any C/C++ file seen during extraction, even one with some errors, to be extracted / scanned. This affects the Code Scanning UI measure of scanned C/C++ files. * The diagnostic query `cpp/diagnostics/successfully-extracted-files` now considers any C/C++ file seen during extraction, even one with some errors, to be extracted / scanned. This affects the Code Scanning UI measure of scanned C/C++ files.

View File

@@ -0,0 +1,6 @@
## 0.9.5
### Minor Analysis Improvements
* The "non-constant format string" query (`cpp/non-constant-format`) has been updated to produce fewer false positives.
* Added dataflow models for the `gettext` function variants.

View File

@@ -1,2 +1,2 @@
--- ---
lastReleaseVersion: 0.9.4 lastReleaseVersion: 0.9.5

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-queries name: codeql/cpp-queries
version: 0.9.4 version: 0.9.5
groups: groups:
- cpp - cpp
- queries - queries

View File

@@ -1,5 +1,5 @@
edges edges
| test.cpp:22:27:22:30 | **argv | test.cpp:29:13:29:20 | *filePath | | test.cpp:22:27:22:30 | **argv | test.cpp:29:13:29:20 | *filePath | provenance | |
nodes nodes
| test.cpp:22:27:22:30 | **argv | semmle.label | **argv | | test.cpp:22:27:22:30 | **argv | semmle.label | **argv |
| test.cpp:29:13:29:20 | *filePath | semmle.label | *filePath | | test.cpp:29:13:29:20 | *filePath | semmle.label | *filePath |

View File

@@ -1,7 +1,7 @@
edges edges
| test.cpp:22:17:22:21 | ... * ... | test.cpp:23:33:23:37 | size1 | | test.cpp:22:17:22:21 | ... * ... | test.cpp:23:33:23:37 | size1 | provenance | |
| test.cpp:37:24:37:27 | size | test.cpp:37:46:37:49 | size | | test.cpp:37:24:37:27 | size | test.cpp:37:46:37:49 | size | provenance | |
| test.cpp:45:36:45:40 | ... * ... | test.cpp:37:24:37:27 | size | | test.cpp:45:36:45:40 | ... * ... | test.cpp:37:24:37:27 | size | provenance | |
nodes nodes
| test.cpp:13:33:13:37 | ... * ... | semmle.label | ... * ... | | test.cpp:13:33:13:37 | ... * ... | semmle.label | ... * ... |
| test.cpp:15:31:15:35 | ... * ... | semmle.label | ... * ... | | test.cpp:15:31:15:35 | ... * ... | semmle.label | ... * ... |

View File

@@ -1,43 +1,43 @@
edges edges
| test.cpp:4:17:4:22 | call to malloc | test.cpp:6:9:6:11 | arr | | test.cpp:4:17:4:22 | call to malloc | test.cpp:6:9:6:11 | arr | provenance | |
| test.cpp:4:17:4:22 | call to malloc | test.cpp:10:9:10:11 | arr | | test.cpp:4:17:4:22 | call to malloc | test.cpp:10:9:10:11 | arr | provenance | |
| test.cpp:19:9:19:16 | *mk_array [p] | test.cpp:28:19:28:26 | call to mk_array [p] | | test.cpp:19:9:19:16 | *mk_array [p] | test.cpp:28:19:28:26 | call to mk_array [p] | provenance | |
| test.cpp:19:9:19:16 | *mk_array [p] | test.cpp:50:18:50:25 | call to mk_array [p] | | test.cpp:19:9:19:16 | *mk_array [p] | test.cpp:50:18:50:25 | call to mk_array [p] | provenance | |
| test.cpp:21:5:21:7 | *arr [post update] [p] | test.cpp:22:5:22:7 | *arr [p] | | test.cpp:21:5:21:7 | *arr [post update] [p] | test.cpp:22:5:22:7 | *arr [p] | provenance | |
| test.cpp:21:5:21:24 | ... = ... | test.cpp:21:5:21:7 | *arr [post update] [p] | | test.cpp:21:5:21:24 | ... = ... | test.cpp:21:5:21:7 | *arr [post update] [p] | provenance | |
| test.cpp:21:13:21:18 | call to malloc | test.cpp:21:5:21:24 | ... = ... | | test.cpp:21:13:21:18 | call to malloc | test.cpp:21:5:21:24 | ... = ... | provenance | |
| test.cpp:22:5:22:7 | *arr [p] | test.cpp:19:9:19:16 | *mk_array [p] | | test.cpp:22:5:22:7 | *arr [p] | test.cpp:19:9:19:16 | *mk_array [p] | provenance | |
| test.cpp:28:19:28:26 | call to mk_array [p] | test.cpp:31:9:31:11 | *arr [p] | | test.cpp:28:19:28:26 | call to mk_array [p] | test.cpp:31:9:31:11 | *arr [p] | provenance | |
| test.cpp:28:19:28:26 | call to mk_array [p] | test.cpp:35:9:35:11 | *arr [p] | | test.cpp:28:19:28:26 | call to mk_array [p] | test.cpp:35:9:35:11 | *arr [p] | provenance | |
| test.cpp:31:9:31:11 | *arr [p] | test.cpp:31:13:31:13 | p | | test.cpp:31:9:31:11 | *arr [p] | test.cpp:31:13:31:13 | p | provenance | |
| test.cpp:35:9:35:11 | *arr [p] | test.cpp:35:13:35:13 | p | | test.cpp:35:9:35:11 | *arr [p] | test.cpp:35:13:35:13 | p | provenance | |
| test.cpp:39:27:39:29 | arr [p] | test.cpp:41:9:41:11 | *arr [p] | | test.cpp:39:27:39:29 | arr [p] | test.cpp:41:9:41:11 | *arr [p] | provenance | |
| test.cpp:39:27:39:29 | arr [p] | test.cpp:45:9:45:11 | *arr [p] | | test.cpp:39:27:39:29 | arr [p] | test.cpp:45:9:45:11 | *arr [p] | provenance | |
| test.cpp:41:9:41:11 | *arr [p] | test.cpp:41:13:41:13 | p | | test.cpp:41:9:41:11 | *arr [p] | test.cpp:41:13:41:13 | p | provenance | |
| test.cpp:45:9:45:11 | *arr [p] | test.cpp:45:13:45:13 | p | | test.cpp:45:9:45:11 | *arr [p] | test.cpp:45:13:45:13 | p | provenance | |
| test.cpp:50:18:50:25 | call to mk_array [p] | test.cpp:39:27:39:29 | arr [p] | | test.cpp:50:18:50:25 | call to mk_array [p] | test.cpp:39:27:39:29 | arr [p] | provenance | |
| test.cpp:55:5:55:7 | *arr [post update] [p] | test.cpp:56:5:56:7 | *arr [p] | | test.cpp:55:5:55:7 | *arr [post update] [p] | test.cpp:56:5:56:7 | *arr [p] | provenance | |
| test.cpp:55:5:55:24 | ... = ... | test.cpp:55:5:55:7 | *arr [post update] [p] | | test.cpp:55:5:55:24 | ... = ... | test.cpp:55:5:55:7 | *arr [post update] [p] | provenance | |
| test.cpp:55:13:55:18 | call to malloc | test.cpp:55:5:55:24 | ... = ... | | test.cpp:55:13:55:18 | call to malloc | test.cpp:55:5:55:24 | ... = ... | provenance | |
| test.cpp:56:5:56:7 | *arr [p] | test.cpp:59:9:59:11 | *arr [p] | | test.cpp:56:5:56:7 | *arr [p] | test.cpp:59:9:59:11 | *arr [p] | provenance | |
| test.cpp:56:5:56:7 | *arr [p] | test.cpp:63:9:63:11 | *arr [p] | | test.cpp:56:5:56:7 | *arr [p] | test.cpp:63:9:63:11 | *arr [p] | provenance | |
| test.cpp:59:9:59:11 | *arr [p] | test.cpp:59:13:59:13 | p | | test.cpp:59:9:59:11 | *arr [p] | test.cpp:59:13:59:13 | p | provenance | |
| test.cpp:63:9:63:11 | *arr [p] | test.cpp:63:13:63:13 | p | | test.cpp:63:9:63:11 | *arr [p] | test.cpp:63:13:63:13 | p | provenance | |
| test.cpp:67:10:67:19 | **mk_array_p [p] | test.cpp:76:20:76:29 | *call to mk_array_p [p] | | test.cpp:67:10:67:19 | **mk_array_p [p] | test.cpp:76:20:76:29 | *call to mk_array_p [p] | provenance | |
| test.cpp:67:10:67:19 | **mk_array_p [p] | test.cpp:98:18:98:27 | *call to mk_array_p [p] | | test.cpp:67:10:67:19 | **mk_array_p [p] | test.cpp:98:18:98:27 | *call to mk_array_p [p] | provenance | |
| test.cpp:69:5:69:7 | *arr [post update] [p] | test.cpp:70:5:70:7 | *arr [p] | | test.cpp:69:5:69:7 | *arr [post update] [p] | test.cpp:70:5:70:7 | *arr [p] | provenance | |
| test.cpp:69:5:69:25 | ... = ... | test.cpp:69:5:69:7 | *arr [post update] [p] | | test.cpp:69:5:69:25 | ... = ... | test.cpp:69:5:69:7 | *arr [post update] [p] | provenance | |
| test.cpp:69:14:69:19 | call to malloc | test.cpp:69:5:69:25 | ... = ... | | test.cpp:69:14:69:19 | call to malloc | test.cpp:69:5:69:25 | ... = ... | provenance | |
| test.cpp:70:5:70:7 | *arr [p] | test.cpp:67:10:67:19 | **mk_array_p [p] | | test.cpp:70:5:70:7 | *arr [p] | test.cpp:67:10:67:19 | **mk_array_p [p] | provenance | |
| test.cpp:76:20:76:29 | *call to mk_array_p [p] | test.cpp:79:9:79:11 | *arr [p] | | test.cpp:76:20:76:29 | *call to mk_array_p [p] | test.cpp:79:9:79:11 | *arr [p] | provenance | |
| test.cpp:76:20:76:29 | *call to mk_array_p [p] | test.cpp:83:9:83:11 | *arr [p] | | test.cpp:76:20:76:29 | *call to mk_array_p [p] | test.cpp:83:9:83:11 | *arr [p] | provenance | |
| test.cpp:79:9:79:11 | *arr [p] | test.cpp:79:14:79:14 | p | | test.cpp:79:9:79:11 | *arr [p] | test.cpp:79:14:79:14 | p | provenance | |
| test.cpp:83:9:83:11 | *arr [p] | test.cpp:83:14:83:14 | p | | test.cpp:83:9:83:11 | *arr [p] | test.cpp:83:14:83:14 | p | provenance | |
| test.cpp:87:28:87:30 | *arr [p] | test.cpp:89:9:89:11 | *arr [p] | | test.cpp:87:28:87:30 | *arr [p] | test.cpp:89:9:89:11 | *arr [p] | provenance | |
| test.cpp:87:28:87:30 | *arr [p] | test.cpp:93:9:93:11 | *arr [p] | | test.cpp:87:28:87:30 | *arr [p] | test.cpp:93:9:93:11 | *arr [p] | provenance | |
| test.cpp:89:9:89:11 | *arr [p] | test.cpp:89:14:89:14 | p | | test.cpp:89:9:89:11 | *arr [p] | test.cpp:89:14:89:14 | p | provenance | |
| test.cpp:93:9:93:11 | *arr [p] | test.cpp:93:14:93:14 | p | | test.cpp:93:9:93:11 | *arr [p] | test.cpp:93:14:93:14 | p | provenance | |
| test.cpp:98:18:98:27 | *call to mk_array_p [p] | test.cpp:87:28:87:30 | *arr [p] | | test.cpp:98:18:98:27 | *call to mk_array_p [p] | test.cpp:87:28:87:30 | *arr [p] | provenance | |
nodes nodes
| test.cpp:4:17:4:22 | call to malloc | semmle.label | call to malloc | | test.cpp:4:17:4:22 | call to malloc | semmle.label | call to malloc |
| test.cpp:6:9:6:11 | arr | semmle.label | arr | | test.cpp:6:9:6:11 | arr | semmle.label | arr |

View File

@@ -1,74 +1,74 @@
edges edges
| test.cpp:34:10:34:12 | buf | test.cpp:34:5:34:24 | access to array | | test.cpp:34:10:34:12 | buf | test.cpp:34:5:34:24 | access to array | provenance | |
| test.cpp:35:10:35:12 | buf | test.cpp:35:5:35:22 | access to array | | test.cpp:35:10:35:12 | buf | test.cpp:35:5:35:22 | access to array | provenance | |
| test.cpp:36:10:36:12 | buf | test.cpp:36:5:36:24 | access to array | | test.cpp:36:10:36:12 | buf | test.cpp:36:5:36:24 | access to array | provenance | |
| test.cpp:39:14:39:16 | buf | test.cpp:39:9:39:19 | access to array | | test.cpp:39:14:39:16 | buf | test.cpp:39:9:39:19 | access to array | provenance | |
| test.cpp:43:14:43:16 | buf | test.cpp:43:9:43:19 | access to array | | test.cpp:43:14:43:16 | buf | test.cpp:43:9:43:19 | access to array | provenance | |
| test.cpp:48:10:48:12 | buf | test.cpp:48:5:48:24 | access to array | | test.cpp:48:10:48:12 | buf | test.cpp:48:5:48:24 | access to array | provenance | |
| test.cpp:49:10:49:12 | buf | test.cpp:49:5:49:22 | access to array | | test.cpp:49:10:49:12 | buf | test.cpp:49:5:49:22 | access to array | provenance | |
| test.cpp:50:10:50:12 | buf | test.cpp:50:5:50:24 | access to array | | test.cpp:50:10:50:12 | buf | test.cpp:50:5:50:24 | access to array | provenance | |
| test.cpp:53:14:53:16 | buf | test.cpp:53:9:53:19 | access to array | | test.cpp:53:14:53:16 | buf | test.cpp:53:9:53:19 | access to array | provenance | |
| test.cpp:57:14:57:16 | buf | test.cpp:57:9:57:19 | access to array | | test.cpp:57:14:57:16 | buf | test.cpp:57:9:57:19 | access to array | provenance | |
| test.cpp:61:14:61:16 | buf | test.cpp:61:9:61:19 | access to array | | test.cpp:61:14:61:16 | buf | test.cpp:61:9:61:19 | access to array | provenance | |
| test.cpp:70:33:70:33 | p | test.cpp:71:5:71:17 | access to array | | test.cpp:70:33:70:33 | p | test.cpp:71:5:71:17 | access to array | provenance | |
| test.cpp:70:33:70:33 | p | test.cpp:72:5:72:15 | access to array | | test.cpp:70:33:70:33 | p | test.cpp:72:5:72:15 | access to array | provenance | |
| test.cpp:76:26:76:46 | & ... | test.cpp:66:32:66:32 | p | | test.cpp:76:26:76:46 | & ... | test.cpp:66:32:66:32 | p | provenance | |
| test.cpp:76:32:76:34 | buf | test.cpp:76:26:76:46 | & ... | | test.cpp:76:32:76:34 | buf | test.cpp:76:26:76:46 | & ... | provenance | |
| test.cpp:77:26:77:44 | & ... | test.cpp:66:32:66:32 | p | | test.cpp:77:26:77:44 | & ... | test.cpp:66:32:66:32 | p | provenance | |
| test.cpp:77:32:77:34 | buf | test.cpp:77:26:77:44 | & ... | | test.cpp:77:32:77:34 | buf | test.cpp:77:26:77:44 | & ... | provenance | |
| test.cpp:79:27:79:34 | buf | test.cpp:70:33:70:33 | p | | test.cpp:79:27:79:34 | buf | test.cpp:70:33:70:33 | p | provenance | |
| test.cpp:79:32:79:34 | buf | test.cpp:79:27:79:34 | buf | | test.cpp:79:32:79:34 | buf | test.cpp:79:27:79:34 | buf | provenance | |
| test.cpp:85:34:85:36 | buf | test.cpp:87:5:87:31 | access to array | | test.cpp:85:34:85:36 | buf | test.cpp:87:5:87:31 | access to array | provenance | |
| test.cpp:85:34:85:36 | buf | test.cpp:88:5:88:27 | access to array | | test.cpp:85:34:85:36 | buf | test.cpp:88:5:88:27 | access to array | provenance | |
| test.cpp:96:13:96:15 | arr | test.cpp:96:13:96:18 | access to array | | test.cpp:96:13:96:15 | arr | test.cpp:96:13:96:18 | access to array | provenance | |
| test.cpp:111:17:111:19 | arr | test.cpp:111:17:111:22 | access to array | | test.cpp:111:17:111:19 | arr | test.cpp:111:17:111:22 | access to array | provenance | |
| test.cpp:111:17:111:19 | arr | test.cpp:115:35:115:40 | access to array | | test.cpp:111:17:111:19 | arr | test.cpp:115:35:115:40 | access to array | provenance | |
| test.cpp:111:17:111:19 | arr | test.cpp:119:17:119:22 | access to array | | test.cpp:111:17:111:19 | arr | test.cpp:119:17:119:22 | access to array | provenance | |
| test.cpp:115:35:115:37 | arr | test.cpp:111:17:111:22 | access to array | | test.cpp:115:35:115:37 | arr | test.cpp:111:17:111:22 | access to array | provenance | |
| test.cpp:115:35:115:37 | arr | test.cpp:115:35:115:40 | access to array | | test.cpp:115:35:115:37 | arr | test.cpp:115:35:115:40 | access to array | provenance | |
| test.cpp:115:35:115:37 | arr | test.cpp:119:17:119:22 | access to array | | test.cpp:115:35:115:37 | arr | test.cpp:119:17:119:22 | access to array | provenance | |
| test.cpp:119:17:119:19 | arr | test.cpp:111:17:111:22 | access to array | | test.cpp:119:17:119:19 | arr | test.cpp:111:17:111:22 | access to array | provenance | |
| test.cpp:119:17:119:19 | arr | test.cpp:115:35:115:40 | access to array | | test.cpp:119:17:119:19 | arr | test.cpp:115:35:115:40 | access to array | provenance | |
| test.cpp:119:17:119:19 | arr | test.cpp:119:17:119:22 | access to array | | test.cpp:119:17:119:19 | arr | test.cpp:119:17:119:22 | access to array | provenance | |
| test.cpp:128:9:128:11 | arr | test.cpp:128:9:128:14 | access to array | | test.cpp:128:9:128:11 | arr | test.cpp:128:9:128:14 | access to array | provenance | |
| test.cpp:134:25:134:27 | arr | test.cpp:136:9:136:16 | ... += ... | | test.cpp:134:25:134:27 | arr | test.cpp:136:9:136:16 | ... += ... | provenance | |
| test.cpp:136:9:136:16 | ... += ... | test.cpp:138:13:138:15 | arr | | test.cpp:136:9:136:16 | ... += ... | test.cpp:138:13:138:15 | arr | provenance | |
| test.cpp:143:18:143:21 | asdf | test.cpp:134:25:134:27 | arr | | test.cpp:143:18:143:21 | asdf | test.cpp:134:25:134:27 | arr | provenance | |
| test.cpp:143:18:143:21 | asdf | test.cpp:143:18:143:21 | asdf | | test.cpp:143:18:143:21 | asdf | test.cpp:143:18:143:21 | asdf | provenance | |
| test.cpp:146:26:146:26 | *p | test.cpp:147:4:147:9 | -- ... | | test.cpp:146:26:146:26 | *p | test.cpp:147:4:147:9 | -- ... | provenance | |
| test.cpp:156:12:156:14 | buf | test.cpp:156:12:156:18 | ... + ... | | test.cpp:156:12:156:14 | buf | test.cpp:156:12:156:18 | ... + ... | provenance | |
| test.cpp:156:12:156:18 | ... + ... | test.cpp:158:17:158:18 | *& ... | | test.cpp:156:12:156:18 | ... + ... | test.cpp:158:17:158:18 | *& ... | provenance | |
| test.cpp:158:17:158:18 | *& ... | test.cpp:146:26:146:26 | *p | | test.cpp:158:17:158:18 | *& ... | test.cpp:146:26:146:26 | *p | provenance | |
| test.cpp:218:23:218:28 | buffer | test.cpp:220:5:220:11 | access to array | | test.cpp:218:23:218:28 | buffer | test.cpp:220:5:220:11 | access to array | provenance | |
| test.cpp:218:23:218:28 | buffer | test.cpp:221:5:221:11 | access to array | | test.cpp:218:23:218:28 | buffer | test.cpp:221:5:221:11 | access to array | provenance | |
| test.cpp:229:25:229:29 | array | test.cpp:231:5:231:10 | access to array | | test.cpp:229:25:229:29 | array | test.cpp:231:5:231:10 | access to array | provenance | |
| test.cpp:229:25:229:29 | array | test.cpp:232:5:232:10 | access to array | | test.cpp:229:25:229:29 | array | test.cpp:232:5:232:10 | access to array | provenance | |
| test.cpp:245:30:245:30 | p | test.cpp:261:27:261:30 | access to array | | test.cpp:245:30:245:30 | p | test.cpp:261:27:261:30 | access to array | provenance | |
| test.cpp:245:30:245:30 | p | test.cpp:261:27:261:30 | access to array | | test.cpp:245:30:245:30 | p | test.cpp:261:27:261:30 | access to array | provenance | |
| test.cpp:274:14:274:20 | buffer3 | test.cpp:245:30:245:30 | p | | test.cpp:274:14:274:20 | buffer3 | test.cpp:245:30:245:30 | p | provenance | |
| test.cpp:274:14:274:20 | buffer3 | test.cpp:274:14:274:20 | buffer3 | | test.cpp:274:14:274:20 | buffer3 | test.cpp:274:14:274:20 | buffer3 | provenance | |
| test.cpp:277:35:277:35 | p | test.cpp:278:14:278:14 | p | | test.cpp:277:35:277:35 | p | test.cpp:278:14:278:14 | p | provenance | |
| test.cpp:278:14:278:14 | p | test.cpp:245:30:245:30 | p | | test.cpp:278:14:278:14 | p | test.cpp:245:30:245:30 | p | provenance | |
| test.cpp:283:19:283:25 | buffer1 | test.cpp:277:35:277:35 | p | | test.cpp:283:19:283:25 | buffer1 | test.cpp:277:35:277:35 | p | provenance | |
| test.cpp:283:19:283:25 | buffer1 | test.cpp:283:19:283:25 | buffer1 | | test.cpp:283:19:283:25 | buffer1 | test.cpp:283:19:283:25 | buffer1 | provenance | |
| test.cpp:286:19:286:25 | buffer2 | test.cpp:277:35:277:35 | p | | test.cpp:286:19:286:25 | buffer2 | test.cpp:277:35:277:35 | p | provenance | |
| test.cpp:286:19:286:25 | buffer2 | test.cpp:286:19:286:25 | buffer2 | | test.cpp:286:19:286:25 | buffer2 | test.cpp:286:19:286:25 | buffer2 | provenance | |
| test.cpp:289:19:289:25 | buffer3 | test.cpp:277:35:277:35 | p | | test.cpp:289:19:289:25 | buffer3 | test.cpp:277:35:277:35 | p | provenance | |
| test.cpp:289:19:289:25 | buffer3 | test.cpp:289:19:289:25 | buffer3 | | test.cpp:289:19:289:25 | buffer3 | test.cpp:289:19:289:25 | buffer3 | provenance | |
| test.cpp:292:25:292:27 | arr | test.cpp:299:16:299:21 | access to array | | test.cpp:292:25:292:27 | arr | test.cpp:299:16:299:21 | access to array | provenance | |
| test.cpp:292:25:292:27 | arr | test.cpp:299:16:299:21 | access to array | | test.cpp:292:25:292:27 | arr | test.cpp:299:16:299:21 | access to array | provenance | |
| test.cpp:306:20:306:23 | arr1 | test.cpp:292:25:292:27 | arr | | test.cpp:306:20:306:23 | arr1 | test.cpp:292:25:292:27 | arr | provenance | |
| test.cpp:306:20:306:23 | arr1 | test.cpp:306:20:306:23 | arr1 | | test.cpp:306:20:306:23 | arr1 | test.cpp:306:20:306:23 | arr1 | provenance | |
| test.cpp:309:20:309:23 | arr2 | test.cpp:292:25:292:27 | arr | | test.cpp:309:20:309:23 | arr2 | test.cpp:292:25:292:27 | arr | provenance | |
| test.cpp:309:20:309:23 | arr2 | test.cpp:309:20:309:23 | arr2 | | test.cpp:309:20:309:23 | arr2 | test.cpp:309:20:309:23 | arr2 | provenance | |
| test.cpp:319:19:319:22 | temp | test.cpp:319:19:319:27 | ... + ... | | test.cpp:319:19:319:22 | temp | test.cpp:319:19:319:27 | ... + ... | provenance | |
| test.cpp:319:19:319:22 | temp | test.cpp:324:23:324:32 | ... + ... | | test.cpp:319:19:319:22 | temp | test.cpp:324:23:324:32 | ... + ... | provenance | |
| test.cpp:319:19:319:27 | ... + ... | test.cpp:325:24:325:26 | end | | test.cpp:319:19:319:27 | ... + ... | test.cpp:325:24:325:26 | end | provenance | |
| test.cpp:322:19:322:22 | temp | test.cpp:322:19:322:27 | ... + ... | | test.cpp:322:19:322:22 | temp | test.cpp:322:19:322:27 | ... + ... | provenance | |
| test.cpp:322:19:322:22 | temp | test.cpp:324:23:324:32 | ... + ... | | test.cpp:322:19:322:22 | temp | test.cpp:324:23:324:32 | ... + ... | provenance | |
| test.cpp:322:19:322:27 | ... + ... | test.cpp:325:24:325:26 | end | | test.cpp:322:19:322:27 | ... + ... | test.cpp:325:24:325:26 | end | provenance | |
| test.cpp:324:23:324:26 | temp | test.cpp:324:23:324:32 | ... + ... | | test.cpp:324:23:324:26 | temp | test.cpp:324:23:324:32 | ... + ... | provenance | |
| test.cpp:324:23:324:32 | ... + ... | test.cpp:325:15:325:19 | temp2 | | test.cpp:324:23:324:32 | ... + ... | test.cpp:325:15:325:19 | temp2 | provenance | |
nodes nodes
| test.cpp:34:5:34:24 | access to array | semmle.label | access to array | | test.cpp:34:5:34:24 | access to array | semmle.label | access to array |
| test.cpp:34:10:34:12 | buf | semmle.label | buf | | test.cpp:34:10:34:12 | buf | semmle.label | buf |

View File

@@ -1,14 +1,14 @@
edges edges
| test.cpp:45:18:45:23 | buffer | test.cpp:45:7:45:10 | *func | | test.cpp:45:18:45:23 | buffer | test.cpp:45:7:45:10 | *func | provenance | |
| test.cpp:74:24:74:30 | medical | test.cpp:78:24:78:27 | temp | | test.cpp:74:24:74:30 | medical | test.cpp:78:24:78:27 | temp | provenance | |
| test.cpp:74:24:74:30 | medical | test.cpp:81:22:81:28 | medical | | test.cpp:74:24:74:30 | medical | test.cpp:81:22:81:28 | medical | provenance | |
| test.cpp:77:16:77:22 | medical | test.cpp:78:24:78:27 | temp | | test.cpp:77:16:77:22 | medical | test.cpp:78:24:78:27 | temp | provenance | |
| test.cpp:77:16:77:22 | medical | test.cpp:81:22:81:28 | medical | | test.cpp:77:16:77:22 | medical | test.cpp:81:22:81:28 | medical | provenance | |
| test.cpp:81:17:81:20 | call to func | test.cpp:82:24:82:28 | buff5 | | test.cpp:81:17:81:20 | call to func | test.cpp:82:24:82:28 | buff5 | provenance | |
| test.cpp:81:22:81:28 | medical | test.cpp:45:18:45:23 | buffer | | test.cpp:81:22:81:28 | medical | test.cpp:45:18:45:23 | buffer | provenance | |
| test.cpp:81:22:81:28 | medical | test.cpp:81:17:81:20 | call to func | | test.cpp:81:22:81:28 | medical | test.cpp:81:17:81:20 | call to func | provenance | |
| test.cpp:96:37:96:46 | theZipcode | test.cpp:99:42:99:51 | theZipcode | | test.cpp:96:37:96:46 | theZipcode | test.cpp:99:42:99:51 | theZipcode | provenance | |
| test.cpp:99:61:99:70 | theZipcode | test.cpp:99:42:99:51 | theZipcode | | test.cpp:99:61:99:70 | theZipcode | test.cpp:99:42:99:51 | theZipcode | provenance | |
nodes nodes
| test.cpp:45:7:45:10 | *func | semmle.label | *func | | test.cpp:45:7:45:10 | *func | semmle.label | *func |
| test.cpp:45:18:45:23 | buffer | semmle.label | buffer | | test.cpp:45:18:45:23 | buffer | semmle.label | buffer |

View File

@@ -165,6 +165,7 @@ postWithInFlow
| test.cpp:931:5:931:18 | global_pointer [post update] | PostUpdateNode should not be the target of local flow. | | test.cpp:931:5:931:18 | global_pointer [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:932:5:932:19 | * ... [post update] | PostUpdateNode should not be the target of local flow. | | test.cpp:932:5:932:19 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:932:6:932:19 | global_pointer [inner post update] | PostUpdateNode should not be the target of local flow. | | test.cpp:932:6:932:19 | global_pointer [inner post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:1045:9:1045:11 | ref arg buf | PostUpdateNode should not be the target of local flow. |
viableImplInCallContextTooLarge viableImplInCallContextTooLarge
uniqueParameterNodeAtPosition uniqueParameterNodeAtPosition
uniqueParameterNodePosition uniqueParameterNodePosition

View File

@@ -25,6 +25,7 @@ postWithInFlow
| test.cpp:391:10:391:13 | memcpy output argument | PostUpdateNode should not be the target of local flow. | | test.cpp:391:10:391:13 | memcpy output argument | PostUpdateNode should not be the target of local flow. |
| test.cpp:400:10:400:13 | memcpy output argument | PostUpdateNode should not be the target of local flow. | | test.cpp:400:10:400:13 | memcpy output argument | PostUpdateNode should not be the target of local flow. |
| test.cpp:407:10:407:13 | memcpy output argument | PostUpdateNode should not be the target of local flow. | | test.cpp:407:10:407:13 | memcpy output argument | PostUpdateNode should not be the target of local flow. |
| test.cpp:1045:9:1045:11 | memset output argument | PostUpdateNode should not be the target of local flow. |
viableImplInCallContextTooLarge viableImplInCallContextTooLarge
uniqueParameterNodeAtPosition uniqueParameterNodeAtPosition
uniqueParameterNodePosition uniqueParameterNodePosition

View File

@@ -303,6 +303,13 @@ irFlow
| test.cpp:914:46:914:53 | source | test.cpp:919:10:919:30 | global_pointer_static | | test.cpp:914:46:914:53 | source | test.cpp:919:10:919:30 | global_pointer_static |
| test.cpp:915:57:915:76 | *indirect_source(1) | test.cpp:921:19:921:50 | *global_pointer_static_indirect_1 | | test.cpp:915:57:915:76 | *indirect_source(1) | test.cpp:921:19:921:50 | *global_pointer_static_indirect_1 |
| test.cpp:932:23:932:28 | call to source | test.cpp:937:10:937:24 | * ... | | test.cpp:932:23:932:28 | call to source | test.cpp:937:10:937:24 | * ... |
| test.cpp:958:18:958:32 | *call to indirect_source | test.cpp:961:19:961:28 | *translated |
| test.cpp:973:18:973:32 | *call to indirect_source | test.cpp:977:19:977:28 | *translated |
| test.cpp:994:18:994:32 | *call to indirect_source | test.cpp:999:19:999:28 | *translated |
| test.cpp:994:18:994:32 | *call to indirect_source | test.cpp:1003:19:1003:28 | *translated |
| test.cpp:1021:18:1021:32 | *call to indirect_source | test.cpp:1027:19:1027:28 | *translated |
| test.cpp:1021:18:1021:32 | *call to indirect_source | test.cpp:1031:19:1031:28 | *translated |
| test.cpp:1045:14:1045:19 | call to source | test.cpp:1046:7:1046:10 | * ... |
| true_upon_entry.cpp:9:11:9:16 | call to source | true_upon_entry.cpp:13:8:13:8 | x | | true_upon_entry.cpp:9:11:9:16 | call to source | true_upon_entry.cpp:13:8:13:8 | x |
| true_upon_entry.cpp:17:11:17:16 | call to source | true_upon_entry.cpp:21:8:21:8 | x | | true_upon_entry.cpp:17:11:17:16 | call to source | true_upon_entry.cpp:21:8:21:8 | x |
| true_upon_entry.cpp:27:9:27:14 | call to source | true_upon_entry.cpp:29:8:29:8 | x | | true_upon_entry.cpp:27:9:27:14 | call to source | true_upon_entry.cpp:29:8:29:8 | x |

View File

@@ -937,3 +937,111 @@ namespace global_variable_conflation_test {
sink(*global_pointer); // $ ir MISSING: ast sink(*global_pointer); // $ ir MISSING: ast
} }
} }
char* gettext(const char*);
char* dgettext(const char*, const char*);
char* ngettext(const char*, const char*, unsigned long int);
char* dngettext (const char*, const char *, const char *, unsigned long int);
namespace test_gettext {
char* source();
char* indirect_source();
void test_gettext() {
char* data = source();
char* translated = gettext(data);
sink(translated); // clean
indirect_sink(translated); // clean
}
void indirect_test_dgettext() {
char* data = indirect_source();
char* translated = gettext(data);
sink(translated); // clean
indirect_sink(translated); // $ ir MISSING: ast
}
void test_dgettext() {
char* data = source();
char* domain = source(); // Should not trace from this source
char* translated = dgettext(domain, data);
sink(translated); // clean
indirect_sink(translated); // clean
}
void indirect_test_gettext() {
char* data = indirect_source();
char* domain = indirect_source(); // Should not trace from this source
char* translated = dgettext(domain, data);
sink(translated); // clean
indirect_sink(translated); // $ ir MISSING: ast
}
void test_ngettext() {
char* data = source();
char* np = nullptr; // Don't coun't as a source
char* translated = ngettext(data, np, 0);
sink(translated); // clean
indirect_sink(translated); // clean
translated = ngettext(np, data, 0);
sink(translated); // clean
indirect_sink(translated); // clean
}
void indirect_test_ngettext() {
char* data = indirect_source();
char* np = nullptr; // Don't coun't as a source
char* translated = ngettext(data, np, 0);
sink(translated); // clean
indirect_sink(translated); // $ ir MISSING: ast
translated = ngettext(np, data, 0);
sink(translated); // clean
indirect_sink(translated); // $ ir MISSING: ast
}
void test_dngettext() {
char* data = source();
char* np = nullptr; // Don't coun't as a source
char* domain = source(); // Should not trace from this source
char* translated = dngettext(domain, data, np, 0);
sink(translated); // clean
indirect_sink(translated); // clean
translated = dngettext(domain, np, data, 0);
sink(translated); // clean
indirect_sink(translated); // clean
}
void indirect_test_dngettext() {
char* data = indirect_source();
char* np = nullptr; // Don't coun't as a source
char* domain = indirect_source(); // Should not trace from this source
char* translated = dngettext(domain, data, np, 0);
sink(translated); // clean
indirect_sink(translated); // $ ir MISSING: ast
translated = dngettext(domain, np, data, 0);
sink(translated); // clean
indirect_sink(translated); // $ ir MISSING: ast
}
void indirect_test_gettext_no_flow_from_domain() {
char* domain = source(); // Should not trace from this source
char* translated = dgettext(domain, nullptr);
sink(translated); // clean
indirect_sink(translated); // clean
}
}
void* memset(void*, int, size_t);
void memset_test(char* buf) { // $ ast-def=buf
memset(buf, source(), 10);
sink(*buf); // $ ir MISSING: ast
}

View File

@@ -1,3 +1,18 @@
astTypeBugs astTypeBugs
irTypeBugs irTypeBugs
incorrectBaseType
| clang.cpp:22:8:22:20 | *& ... | Expected 'Node.getType()' to be int, but it was int * |
| clang.cpp:23:17:23:29 | *& ... | Expected 'Node.getType()' to be int, but it was int * |
| flowOut.cpp:50:14:50:15 | *& ... | Expected 'Node.getType()' to be int, but it was int * |
| flowOut.cpp:84:9:84:10 | *& ... | Expected 'Node.getType()' to be int, but it was int * |
| flowOut.cpp:101:13:101:14 | *& ... | Expected 'Node.getType()' to be int, but it was int * |
| self_parameter_flow.cpp:8:8:8:9 | *& ... | Expected 'Node.getType()' to be unsigned char, but it was unsigned char * |
| test.cpp:67:28:67:37 | (reference dereference) | Expected 'Node.getType()' to be const int, but it was int * |
| test.cpp:531:39:531:40 | *& ... | Expected 'Node.getType()' to be int, but it was const int * |
| test.cpp:615:13:615:21 | *& ... | Expected 'Node.getType()' to be int, but it was void |
| test.cpp:704:22:704:25 | *& ... | Expected 'Node.getType()' to be int, but it was int * |
| test.cpp:715:24:715:25 | *& ... | Expected 'Node.getType()' to be unsigned char, but it was unsigned char * |
| test.cpp:848:23:848:25 | (reference dereference) | Expected 'Node.getType()' to be int, but it was int * |
| test.cpp:854:10:854:36 | * ... | Expected 'Node.getType()' to be const int, but it was int |
| test.cpp:867:10:867:30 | * ... | Expected 'Node.getType()' to be const int, but it was int |
failures failures

View File

@@ -25,6 +25,17 @@ module IrTest {
n != 1 n != 1
) )
} }
query predicate incorrectBaseType(Node n, string msg) {
exists(PointerType pointerType, Type nodeType, Type baseType |
not n.isGLValue() and
pointerType = n.asIndirectExpr(1).getActualType() and
baseType = pointerType.getBaseType() and
nodeType = n.getType() and
nodeType != baseType and
msg = "Expected 'Node.getType()' to be " + baseType + ", but it was " + nodeType
)
}
} }
import IrTest import IrTest

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -12,7 +12,11 @@ unnecessaryPhiInstruction
memoryOperandDefinitionIsUnmodeled memoryOperandDefinitionIsUnmodeled
operandAcrossFunctions operandAcrossFunctions
instructionWithoutUniqueBlock instructionWithoutUniqueBlock
missingCanonicalLanguageType
multipleCanonicalLanguageTypes
containsLoopOfForwardEdges containsLoopOfForwardEdges
missingIRType
multipleIRTypes
lostReachability lostReachability
backEdgeCountMismatch backEdgeCountMismatch
useNotDominatedByDefinition useNotDominatedByDefinition
@@ -24,8 +28,4 @@ nonUniqueEnclosingIRFunction
fieldAddressOnNonPointer fieldAddressOnNonPointer
thisArgumentIsNonPointer thisArgumentIsNonPointer
nonUniqueIRVariable nonUniqueIRVariable
missingCanonicalLanguageType
multipleCanonicalLanguageTypes
missingIRType
multipleIRTypes
missingCppType missingCppType

View File

@@ -12,7 +12,11 @@ unnecessaryPhiInstruction
memoryOperandDefinitionIsUnmodeled memoryOperandDefinitionIsUnmodeled
operandAcrossFunctions operandAcrossFunctions
instructionWithoutUniqueBlock instructionWithoutUniqueBlock
missingCanonicalLanguageType
multipleCanonicalLanguageTypes
containsLoopOfForwardEdges containsLoopOfForwardEdges
missingIRType
multipleIRTypes
lostReachability lostReachability
backEdgeCountMismatch backEdgeCountMismatch
useNotDominatedByDefinition useNotDominatedByDefinition
@@ -24,8 +28,4 @@ nonUniqueEnclosingIRFunction
fieldAddressOnNonPointer fieldAddressOnNonPointer
thisArgumentIsNonPointer thisArgumentIsNonPointer
nonUniqueIRVariable nonUniqueIRVariable
missingCanonicalLanguageType
multipleCanonicalLanguageTypes
missingIRType
multipleIRTypes
missingCppType missingCppType

View File

@@ -1065,6 +1065,8 @@ struct vector {
bool operator!=(iterator right) const; bool operator!=(iterator right) const;
}; };
vector(T);
~vector();
iterator begin() const; iterator begin() const;
iterator end() const; iterator end() const;
}; };
@@ -2112,4 +2114,56 @@ char* test_strtod(char *s) {
return end; return end;
} }
// semmle-extractor-options: -std=c++17 --clang struct HasOperatorBool {
operator bool();
};
void call_as_child_of_ConditionDeclExpr() {
if(HasOperatorBool b = HasOperatorBool()) {}
}
class ClassWithDestructor {
char *x;
public:
ClassWithDestructor() { x = new char; }
~ClassWithDestructor() { delete x; }
void set_x(char y) { *x = y; }
char get_x() { return *x; }
};
constexpr bool initialization_with_destructor_bool = true;
void initialization_with_destructor(bool b, char c) {
if (ClassWithDestructor x; b)
x.set_x('a');
if constexpr (ClassWithDestructor x; initialization_with_destructor_bool)
x.set_x('a');
switch(ClassWithDestructor x; c) {
case 'a':
x.set_x('a');
break;
default:
x.set_x('b');
break;
}
ClassWithDestructor x;
for(vector<ClassWithDestructor> ys(x); ClassWithDestructor y : ys)
y.set_x('a');
for(vector<ClassWithDestructor> ys(x); ClassWithDestructor y : ys) {
y.set_x('a');
if (y.get_x() == 'b')
return;
}
for(vector<int> ys(1); int y : ys) {
if (y == 1)
return;
}
}
// semmle-extractor-options: -std=c++20 --clang

File diff suppressed because it is too large Load Diff

View File

@@ -20,7 +20,7 @@ multipleIRTypes
lostReachability lostReachability
backEdgeCountMismatch backEdgeCountMismatch
useNotDominatedByDefinition useNotDominatedByDefinition
| ir.cpp:1486:8:1486:8 | Unary | Operand 'Unary' is not dominated by its definition in function '$@'. | ir.cpp:1486:8:1486:8 | void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct() | void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct() | | ir.cpp:1488:8:1488:8 | Unary | Operand 'Unary' is not dominated by its definition in function '$@'. | ir.cpp:1488:8:1488:8 | void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct() | void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct() |
| try_except.c:13:13:13:13 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | try_except.c:6:6:6:6 | void f() | void f() | | try_except.c:13:13:13:13 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | try_except.c:6:6:6:6 | void f() | void f() |
| try_except.c:13:13:13:13 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | try_except.c:6:6:6:6 | void f() | void f() | | try_except.c:13:13:13:13 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | try_except.c:6:6:6:6 | void f() | void f() |
| try_except.c:39:15:39:15 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | try_except.c:32:6:32:6 | void h(int) | void h(int) | | try_except.c:39:15:39:15 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | try_except.c:32:6:32:6 | void h(int) | void h(int) |

File diff suppressed because it is too large Load Diff

View File

@@ -12,7 +12,11 @@ unnecessaryPhiInstruction
memoryOperandDefinitionIsUnmodeled memoryOperandDefinitionIsUnmodeled
operandAcrossFunctions operandAcrossFunctions
instructionWithoutUniqueBlock instructionWithoutUniqueBlock
missingCanonicalLanguageType
multipleCanonicalLanguageTypes
containsLoopOfForwardEdges containsLoopOfForwardEdges
missingIRType
multipleIRTypes
lostReachability lostReachability
backEdgeCountMismatch backEdgeCountMismatch
useNotDominatedByDefinition useNotDominatedByDefinition
@@ -24,8 +28,4 @@ nonUniqueEnclosingIRFunction
fieldAddressOnNonPointer fieldAddressOnNonPointer
thisArgumentIsNonPointer thisArgumentIsNonPointer
nonUniqueIRVariable nonUniqueIRVariable
missingCanonicalLanguageType
multipleCanonicalLanguageTypes
missingIRType
multipleIRTypes
missingCppType missingCppType

View File

@@ -12,7 +12,11 @@ unnecessaryPhiInstruction
memoryOperandDefinitionIsUnmodeled memoryOperandDefinitionIsUnmodeled
operandAcrossFunctions operandAcrossFunctions
instructionWithoutUniqueBlock instructionWithoutUniqueBlock
missingCanonicalLanguageType
multipleCanonicalLanguageTypes
containsLoopOfForwardEdges containsLoopOfForwardEdges
missingIRType
multipleIRTypes
lostReachability lostReachability
backEdgeCountMismatch backEdgeCountMismatch
useNotDominatedByDefinition useNotDominatedByDefinition
@@ -24,8 +28,4 @@ nonUniqueEnclosingIRFunction
fieldAddressOnNonPointer fieldAddressOnNonPointer
thisArgumentIsNonPointer thisArgumentIsNonPointer
nonUniqueIRVariable nonUniqueIRVariable
missingCanonicalLanguageType
multipleCanonicalLanguageTypes
missingIRType
multipleIRTypes
missingCppType missingCppType

View File

@@ -8,10 +8,6 @@ duplicateChiOperand
sideEffectWithoutPrimary sideEffectWithoutPrimary
instructionWithoutSuccessor instructionWithoutSuccessor
| VacuousDestructorCall.cpp:2:29:2:29 | InitializeIndirection: y | Instruction 'InitializeIndirection: y' has no successors in function '$@'. | VacuousDestructorCall.cpp:2:6:2:6 | void CallDestructor<int>(int, int*) | void CallDestructor<int>(int, int*) | | VacuousDestructorCall.cpp:2:29:2:29 | InitializeIndirection: y | Instruction 'InitializeIndirection: y' has no successors in function '$@'. | VacuousDestructorCall.cpp:2:6:2:6 | void CallDestructor<int>(int, int*) | void CallDestructor<int>(int, int*) |
| condition_decls.cpp:16:19:16:20 | Chi: call to BoxedInt | Instruction 'Chi: call to BoxedInt' has no successors in function '$@'. | condition_decls.cpp:15:6:15:17 | void if_decl_bind(int) | void if_decl_bind(int) |
| condition_decls.cpp:26:23:26:24 | Chi: call to BoxedInt | Instruction 'Chi: call to BoxedInt' has no successors in function '$@'. | condition_decls.cpp:25:6:25:21 | void switch_decl_bind(int) | void switch_decl_bind(int) |
| condition_decls.cpp:41:22:41:23 | Chi: call to BoxedInt | Instruction 'Chi: call to BoxedInt' has no successors in function '$@'. | condition_decls.cpp:40:6:40:20 | void while_decl_bind(int) | void while_decl_bind(int) |
| condition_decls.cpp:48:52:48:53 | Chi: call to BoxedInt | Instruction 'Chi: call to BoxedInt' has no successors in function '$@'. | condition_decls.cpp:47:6:47:18 | void for_decl_bind(int) | void for_decl_bind(int) |
| ms_try_mix.cpp:35:13:35:19 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:29:6:29:19 | void ms_finally_mix(int) | void ms_finally_mix(int) | | ms_try_mix.cpp:35:13:35:19 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:29:6:29:19 | void ms_finally_mix(int) | void ms_finally_mix(int) |
| ms_try_mix.cpp:53:5:53:11 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:49:6:49:28 | void ms_empty_finally_at_end() | void ms_empty_finally_at_end() | | ms_try_mix.cpp:53:5:53:11 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:49:6:49:28 | void ms_empty_finally_at_end() | void ms_empty_finally_at_end() |
| stmt_expr.cpp:27:5:27:15 | Store: ... = ... | Instruction 'Store: ... = ...' has no successors in function '$@'. | stmt_expr.cpp:21:13:21:13 | void stmtexpr::g(int) | void stmtexpr::g(int) | | stmt_expr.cpp:27:5:27:15 | Store: ... = ... | Instruction 'Store: ... = ...' has no successors in function '$@'. | stmt_expr.cpp:21:13:21:13 | void stmtexpr::g(int) | void stmtexpr::g(int) |
@@ -21,7 +17,11 @@ unnecessaryPhiInstruction
memoryOperandDefinitionIsUnmodeled memoryOperandDefinitionIsUnmodeled
operandAcrossFunctions operandAcrossFunctions
instructionWithoutUniqueBlock instructionWithoutUniqueBlock
missingCanonicalLanguageType
multipleCanonicalLanguageTypes
containsLoopOfForwardEdges containsLoopOfForwardEdges
missingIRType
multipleIRTypes
lostReachability lostReachability
backEdgeCountMismatch backEdgeCountMismatch
useNotDominatedByDefinition useNotDominatedByDefinition
@@ -36,8 +36,4 @@ thisArgumentIsNonPointer
| pointer_to_member.cpp:23:5:23:54 | Call: call to expression | Call instruction 'Call: call to expression' has a `this` argument operand that is not an address, in function '$@'. | pointer_to_member.cpp:14:5:14:9 | int usePM(int PM::*) | int usePM(int PM::*) | | pointer_to_member.cpp:23:5:23:54 | Call: call to expression | Call instruction 'Call: call to expression' has a `this` argument operand that is not an address, in function '$@'. | pointer_to_member.cpp:14:5:14:9 | int usePM(int PM::*) | int usePM(int PM::*) |
| pointer_to_member.cpp:24:5:24:49 | Call: call to expression | Call instruction 'Call: call to expression' has a `this` argument operand that is not an address, in function '$@'. | pointer_to_member.cpp:14:5:14:9 | int usePM(int PM::*) | int usePM(int PM::*) | | pointer_to_member.cpp:24:5:24:49 | Call: call to expression | Call instruction 'Call: call to expression' has a `this` argument operand that is not an address, in function '$@'. | pointer_to_member.cpp:14:5:14:9 | int usePM(int PM::*) | int usePM(int PM::*) |
nonUniqueIRVariable nonUniqueIRVariable
missingCanonicalLanguageType
multipleCanonicalLanguageTypes
missingIRType
multipleIRTypes
missingCppType missingCppType

View File

@@ -1,8 +1,4 @@
missingOperand missingOperand
| condition_decls.cpp:16:6:16:20 | CopyValue: (condition decl) | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | condition_decls.cpp:15:6:15:17 | void if_decl_bind(int) | void if_decl_bind(int) |
| condition_decls.cpp:26:10:26:24 | CopyValue: (condition decl) | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | condition_decls.cpp:25:6:25:21 | void switch_decl_bind(int) | void switch_decl_bind(int) |
| condition_decls.cpp:41:9:41:23 | CopyValue: (condition decl) | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | condition_decls.cpp:40:6:40:20 | void while_decl_bind(int) | void while_decl_bind(int) |
| condition_decls.cpp:48:39:48:53 | CopyValue: (condition decl) | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | condition_decls.cpp:47:6:47:18 | void for_decl_bind(int) | void for_decl_bind(int) |
| misc.c:125:5:125:11 | CopyValue: (statement expression) | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | misc.c:97:6:97:10 | void misc3() | void misc3() | | misc.c:125:5:125:11 | CopyValue: (statement expression) | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | misc.c:97:6:97:10 | void misc3() | void misc3() |
| try_catch.cpp:23:5:23:18 | CopyValue: (statement expression) | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | try_catch.cpp:19:6:19:23 | void throw_from_nonstmt(int) | void throw_from_nonstmt(int) | | try_catch.cpp:23:5:23:18 | CopyValue: (statement expression) | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | try_catch.cpp:19:6:19:23 | void throw_from_nonstmt(int) | void throw_from_nonstmt(int) |
unexpectedOperand unexpectedOperand
@@ -15,14 +11,6 @@ instructionWithoutSuccessor
| VacuousDestructorCall.cpp:2:29:2:29 | InitializeIndirection: y | Instruction 'InitializeIndirection: y' has no successors in function '$@'. | VacuousDestructorCall.cpp:2:6:2:6 | void CallDestructor<int>(int, int*) | void CallDestructor<int>(int, int*) | | VacuousDestructorCall.cpp:2:29:2:29 | InitializeIndirection: y | Instruction 'InitializeIndirection: y' has no successors in function '$@'. | VacuousDestructorCall.cpp:2:6:2:6 | void CallDestructor<int>(int, int*) | void CallDestructor<int>(int, int*) |
| VacuousDestructorCall.cpp:3:3:3:3 | VariableAddress: x | Instruction 'VariableAddress: x' has no successors in function '$@'. | VacuousDestructorCall.cpp:2:6:2:6 | void CallDestructor<int>(int, int*) | void CallDestructor<int>(int, int*) | | VacuousDestructorCall.cpp:3:3:3:3 | VariableAddress: x | Instruction 'VariableAddress: x' has no successors in function '$@'. | VacuousDestructorCall.cpp:2:6:2:6 | void CallDestructor<int>(int, int*) | void CallDestructor<int>(int, int*) |
| VacuousDestructorCall.cpp:4:3:4:3 | Load: y | Instruction 'Load: y' has no successors in function '$@'. | VacuousDestructorCall.cpp:2:6:2:6 | void CallDestructor<int>(int, int*) | void CallDestructor<int>(int, int*) | | VacuousDestructorCall.cpp:4:3:4:3 | Load: y | Instruction 'Load: y' has no successors in function '$@'. | VacuousDestructorCall.cpp:2:6:2:6 | void CallDestructor<int>(int, int*) | void CallDestructor<int>(int, int*) |
| condition_decls.cpp:16:19:16:20 | IndirectMayWriteSideEffect: call to BoxedInt | Instruction 'IndirectMayWriteSideEffect: call to BoxedInt' has no successors in function '$@'. | condition_decls.cpp:15:6:15:17 | void if_decl_bind(int) | void if_decl_bind(int) |
| condition_decls.cpp:26:19:26:20 | IndirectMayWriteSideEffect: bi | Instruction 'IndirectMayWriteSideEffect: bi' has no successors in function '$@'. | condition_decls.cpp:25:6:25:21 | void switch_decl_bind(int) | void switch_decl_bind(int) |
| condition_decls.cpp:26:23:26:24 | IndirectMayWriteSideEffect: call to BoxedInt | Instruction 'IndirectMayWriteSideEffect: call to BoxedInt' has no successors in function '$@'. | condition_decls.cpp:25:6:25:21 | void switch_decl_bind(int) | void switch_decl_bind(int) |
| condition_decls.cpp:41:22:41:23 | IndirectMayWriteSideEffect: call to BoxedInt | Instruction 'IndirectMayWriteSideEffect: call to BoxedInt' has no successors in function '$@'. | condition_decls.cpp:40:6:40:20 | void while_decl_bind(int) | void while_decl_bind(int) |
| condition_decls.cpp:48:52:48:53 | IndirectMayWriteSideEffect: call to BoxedInt | Instruction 'IndirectMayWriteSideEffect: call to BoxedInt' has no successors in function '$@'. | condition_decls.cpp:47:6:47:18 | void for_decl_bind(int) | void for_decl_bind(int) |
| file://:0:0:0:0 | CompareNE: (bool)... | Instruction 'CompareNE: (bool)...' has no successors in function '$@'. | condition_decls.cpp:15:6:15:17 | void if_decl_bind(int) | void if_decl_bind(int) |
| file://:0:0:0:0 | CompareNE: (bool)... | Instruction 'CompareNE: (bool)...' has no successors in function '$@'. | condition_decls.cpp:40:6:40:20 | void while_decl_bind(int) | void while_decl_bind(int) |
| file://:0:0:0:0 | CompareNE: (bool)... | Instruction 'CompareNE: (bool)...' has no successors in function '$@'. | condition_decls.cpp:47:6:47:18 | void for_decl_bind(int) | void for_decl_bind(int) |
| ms_try_mix.cpp:35:13:35:19 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:29:6:29:19 | void ms_finally_mix(int) | void ms_finally_mix(int) | | ms_try_mix.cpp:35:13:35:19 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:29:6:29:19 | void ms_finally_mix(int) | void ms_finally_mix(int) |
| ms_try_mix.cpp:53:5:53:11 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:49:6:49:28 | void ms_empty_finally_at_end() | void ms_empty_finally_at_end() | | ms_try_mix.cpp:53:5:53:11 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:49:6:49:28 | void ms_empty_finally_at_end() | void ms_empty_finally_at_end() |
| stmt_expr.cpp:27:5:27:15 | Store: ... = ... | Instruction 'Store: ... = ...' has no successors in function '$@'. | stmt_expr.cpp:21:13:21:13 | void stmtexpr::g(int) | void stmtexpr::g(int) | | stmt_expr.cpp:27:5:27:15 | Store: ... = ... | Instruction 'Store: ... = ...' has no successors in function '$@'. | stmt_expr.cpp:21:13:21:13 | void stmtexpr::g(int) | void stmtexpr::g(int) |

View File

@@ -8,10 +8,6 @@ duplicateChiOperand
sideEffectWithoutPrimary sideEffectWithoutPrimary
instructionWithoutSuccessor instructionWithoutSuccessor
| VacuousDestructorCall.cpp:2:29:2:29 | InitializeIndirection: y | Instruction 'InitializeIndirection: y' has no successors in function '$@'. | VacuousDestructorCall.cpp:2:6:2:6 | void CallDestructor<int>(int, int*) | void CallDestructor<int>(int, int*) | | VacuousDestructorCall.cpp:2:29:2:29 | InitializeIndirection: y | Instruction 'InitializeIndirection: y' has no successors in function '$@'. | VacuousDestructorCall.cpp:2:6:2:6 | void CallDestructor<int>(int, int*) | void CallDestructor<int>(int, int*) |
| condition_decls.cpp:16:19:16:20 | IndirectMayWriteSideEffect: call to BoxedInt | Instruction 'IndirectMayWriteSideEffect: call to BoxedInt' has no successors in function '$@'. | condition_decls.cpp:15:6:15:17 | void if_decl_bind(int) | void if_decl_bind(int) |
| condition_decls.cpp:26:23:26:24 | IndirectMayWriteSideEffect: call to BoxedInt | Instruction 'IndirectMayWriteSideEffect: call to BoxedInt' has no successors in function '$@'. | condition_decls.cpp:25:6:25:21 | void switch_decl_bind(int) | void switch_decl_bind(int) |
| condition_decls.cpp:41:22:41:23 | IndirectMayWriteSideEffect: call to BoxedInt | Instruction 'IndirectMayWriteSideEffect: call to BoxedInt' has no successors in function '$@'. | condition_decls.cpp:40:6:40:20 | void while_decl_bind(int) | void while_decl_bind(int) |
| condition_decls.cpp:48:52:48:53 | IndirectMayWriteSideEffect: call to BoxedInt | Instruction 'IndirectMayWriteSideEffect: call to BoxedInt' has no successors in function '$@'. | condition_decls.cpp:47:6:47:18 | void for_decl_bind(int) | void for_decl_bind(int) |
| ms_try_mix.cpp:35:13:35:19 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:29:6:29:19 | void ms_finally_mix(int) | void ms_finally_mix(int) | | ms_try_mix.cpp:35:13:35:19 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:29:6:29:19 | void ms_finally_mix(int) | void ms_finally_mix(int) |
| ms_try_mix.cpp:53:5:53:11 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:49:6:49:28 | void ms_empty_finally_at_end() | void ms_empty_finally_at_end() | | ms_try_mix.cpp:53:5:53:11 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:49:6:49:28 | void ms_empty_finally_at_end() | void ms_empty_finally_at_end() |
| stmt_expr.cpp:27:5:27:15 | Store: ... = ... | Instruction 'Store: ... = ...' has no successors in function '$@'. | stmt_expr.cpp:21:13:21:13 | void stmtexpr::g(int) | void stmtexpr::g(int) | | stmt_expr.cpp:27:5:27:15 | Store: ... = ... | Instruction 'Store: ... = ...' has no successors in function '$@'. | stmt_expr.cpp:21:13:21:13 | void stmtexpr::g(int) | void stmtexpr::g(int) |
@@ -21,7 +17,11 @@ unnecessaryPhiInstruction
memoryOperandDefinitionIsUnmodeled memoryOperandDefinitionIsUnmodeled
operandAcrossFunctions operandAcrossFunctions
instructionWithoutUniqueBlock instructionWithoutUniqueBlock
missingCanonicalLanguageType
multipleCanonicalLanguageTypes
containsLoopOfForwardEdges containsLoopOfForwardEdges
missingIRType
multipleIRTypes
lostReachability lostReachability
backEdgeCountMismatch backEdgeCountMismatch
useNotDominatedByDefinition useNotDominatedByDefinition
@@ -36,8 +36,4 @@ thisArgumentIsNonPointer
| pointer_to_member.cpp:23:5:23:54 | Call: call to expression | Call instruction 'Call: call to expression' has a `this` argument operand that is not an address, in function '$@'. | pointer_to_member.cpp:14:5:14:9 | int usePM(int PM::*) | int usePM(int PM::*) | | pointer_to_member.cpp:23:5:23:54 | Call: call to expression | Call instruction 'Call: call to expression' has a `this` argument operand that is not an address, in function '$@'. | pointer_to_member.cpp:14:5:14:9 | int usePM(int PM::*) | int usePM(int PM::*) |
| pointer_to_member.cpp:24:5:24:49 | Call: call to expression | Call instruction 'Call: call to expression' has a `this` argument operand that is not an address, in function '$@'. | pointer_to_member.cpp:14:5:14:9 | int usePM(int PM::*) | int usePM(int PM::*) | | pointer_to_member.cpp:24:5:24:49 | Call: call to expression | Call instruction 'Call: call to expression' has a `this` argument operand that is not an address, in function '$@'. | pointer_to_member.cpp:14:5:14:9 | int usePM(int PM::*) | int usePM(int PM::*) |
nonUniqueIRVariable nonUniqueIRVariable
missingCanonicalLanguageType
multipleCanonicalLanguageTypes
missingIRType
multipleIRTypes
missingCppType missingCppType

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