mirror of
https://github.com/github/codeql.git
synced 2025-12-24 04:36:35 +01:00
Merge branch 'main' into call-graph-code
This commit is contained in:
13
.github/dependabot.yml
vendored
13
.github/dependabot.yml
vendored
@@ -1,19 +1,12 @@
|
|||||||
version: 2
|
version: 2
|
||||||
updates:
|
updates:
|
||||||
- package-ecosystem: "cargo"
|
- package-ecosystem: "cargo"
|
||||||
directory: "ruby/node-types"
|
directory: "ruby"
|
||||||
schedule:
|
schedule:
|
||||||
interval: "daily"
|
interval: "daily"
|
||||||
|
|
||||||
- package-ecosystem: "cargo"
|
- package-ecosystem: "cargo"
|
||||||
directory: "ruby/generator"
|
directory: "ql"
|
||||||
schedule:
|
|
||||||
interval: "daily"
|
|
||||||
- package-ecosystem: "cargo"
|
|
||||||
directory: "ruby/extractor"
|
|
||||||
schedule:
|
|
||||||
interval: "daily"
|
|
||||||
- package-ecosystem: "cargo"
|
|
||||||
directory: "ruby/autobuilder"
|
|
||||||
schedule:
|
schedule:
|
||||||
interval: "daily"
|
interval: "daily"
|
||||||
|
|
||||||
|
|||||||
2
.github/workflows/codeql-analysis.yml
vendored
2
.github/workflows/codeql-analysis.yml
vendored
@@ -30,7 +30,7 @@ jobs:
|
|||||||
- name: Setup dotnet
|
- name: Setup dotnet
|
||||||
uses: actions/setup-dotnet@v2
|
uses: actions/setup-dotnet@v2
|
||||||
with:
|
with:
|
||||||
dotnet-version: 6.0.202
|
dotnet-version: 7.0.102
|
||||||
|
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|||||||
10
.github/workflows/csharp-qltest.yml
vendored
10
.github/workflows/csharp-qltest.yml
vendored
@@ -77,10 +77,10 @@ jobs:
|
|||||||
- name: Setup dotnet
|
- name: Setup dotnet
|
||||||
uses: actions/setup-dotnet@v3
|
uses: actions/setup-dotnet@v3
|
||||||
with:
|
with:
|
||||||
dotnet-version: 6.0.202
|
dotnet-version: 7.0.102
|
||||||
- name: Extractor unit tests
|
- name: Extractor unit tests
|
||||||
run: |
|
run: |
|
||||||
dotnet test -p:RuntimeFrameworkVersion=6.0.4 "${{ github.workspace }}/csharp/extractor/Semmle.Util.Tests"
|
dotnet test -p:RuntimeFrameworkVersion=7.0.2 "${{ github.workspace }}/csharp/extractor/Semmle.Util.Tests"
|
||||||
dotnet test -p:RuntimeFrameworkVersion=6.0.4 "${{ github.workspace }}/csharp/extractor/Semmle.Extraction.Tests"
|
dotnet test -p:RuntimeFrameworkVersion=7.0.2 "${{ github.workspace }}/csharp/extractor/Semmle.Extraction.Tests"
|
||||||
dotnet test -p:RuntimeFrameworkVersion=6.0.4 "${{ github.workspace }}/csharp/autobuilder/Semmle.Autobuild.CSharp.Tests"
|
dotnet test -p:RuntimeFrameworkVersion=7.0.2 "${{ github.workspace }}/csharp/autobuilder/Semmle.Autobuild.CSharp.Tests"
|
||||||
dotnet test -p:RuntimeFrameworkVersion=6.0.4 "${{ github.workspace }}/cpp/autobuilder/Semmle.Autobuild.Cpp.Tests"
|
dotnet test -p:RuntimeFrameworkVersion=7.0.2 "${{ github.workspace }}/cpp/autobuilder/Semmle.Autobuild.Cpp.Tests"
|
||||||
|
|||||||
6
.github/workflows/ql-for-ql-build.yml
vendored
6
.github/workflows/ql-for-ql-build.yml
vendored
@@ -27,7 +27,7 @@ jobs:
|
|||||||
uses: ./.github/actions/find-latest-bundle
|
uses: ./.github/actions/find-latest-bundle
|
||||||
- name: Find codeql
|
- name: Find codeql
|
||||||
id: find-codeql
|
id: find-codeql
|
||||||
uses: github/codeql-action/init@45955cb1830b640e2c1603ad72ad542a49d47b96
|
uses: github/codeql-action/init@beae46e6b1da530ed5e9fc6a756f92433ca47ae1
|
||||||
with:
|
with:
|
||||||
languages: javascript # does not matter
|
languages: javascript # does not matter
|
||||||
tools: ${{ steps.find-latest-bundle.outputs.url }}
|
tools: ${{ steps.find-latest-bundle.outputs.url }}
|
||||||
@@ -139,7 +139,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
CONF: ./ql-for-ql-config.yml
|
CONF: ./ql-for-ql-config.yml
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@45955cb1830b640e2c1603ad72ad542a49d47b96
|
uses: github/codeql-action/init@beae46e6b1da530ed5e9fc6a756f92433ca47ae1
|
||||||
with:
|
with:
|
||||||
languages: ql
|
languages: ql
|
||||||
db-location: ${{ runner.temp }}/db
|
db-location: ${{ runner.temp }}/db
|
||||||
@@ -152,7 +152,7 @@ jobs:
|
|||||||
PACK: ${{ runner.temp }}/pack
|
PACK: ${{ runner.temp }}/pack
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@45955cb1830b640e2c1603ad72ad542a49d47b96
|
uses: github/codeql-action/analyze@beae46e6b1da530ed5e9fc6a756f92433ca47ae1
|
||||||
with:
|
with:
|
||||||
category: "ql-for-ql"
|
category: "ql-for-ql"
|
||||||
- name: Copy sarif file to CWD
|
- name: Copy sarif file to CWD
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Find codeql
|
- name: Find codeql
|
||||||
id: find-codeql
|
id: find-codeql
|
||||||
uses: github/codeql-action/init@45955cb1830b640e2c1603ad72ad542a49d47b96
|
uses: github/codeql-action/init@beae46e6b1da530ed5e9fc6a756f92433ca47ae1
|
||||||
with:
|
with:
|
||||||
languages: javascript # does not matter
|
languages: javascript # does not matter
|
||||||
- uses: ./.github/actions/os-version
|
- uses: ./.github/actions/os-version
|
||||||
|
|||||||
6
.github/workflows/ql-for-ql-tests.yml
vendored
6
.github/workflows/ql-for-ql-tests.yml
vendored
@@ -6,11 +6,13 @@ on:
|
|||||||
paths:
|
paths:
|
||||||
- "ql/**"
|
- "ql/**"
|
||||||
- codeql-workspace.yml
|
- codeql-workspace.yml
|
||||||
|
- .github/workflows/ql-for-ql-tests.yml
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [main]
|
branches: [main]
|
||||||
paths:
|
paths:
|
||||||
- "ql/**"
|
- "ql/**"
|
||||||
- codeql-workspace.yml
|
- codeql-workspace.yml
|
||||||
|
- .github/workflows/ql-for-ql-tests.yml
|
||||||
|
|
||||||
env:
|
env:
|
||||||
CARGO_TERM_COLOR: always
|
CARGO_TERM_COLOR: always
|
||||||
@@ -22,7 +24,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Find codeql
|
- name: Find codeql
|
||||||
id: find-codeql
|
id: find-codeql
|
||||||
uses: github/codeql-action/init@45955cb1830b640e2c1603ad72ad542a49d47b96
|
uses: github/codeql-action/init@beae46e6b1da530ed5e9fc6a756f92433ca47ae1
|
||||||
with:
|
with:
|
||||||
languages: javascript # does not matter
|
languages: javascript # does not matter
|
||||||
- uses: ./.github/actions/os-version
|
- uses: ./.github/actions/os-version
|
||||||
@@ -65,7 +67,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@77a8d2d10c0b403a8b4aadbd223dc489ecd22683
|
uses: github/codeql-action/init@beae46e6b1da530ed5e9fc6a756f92433ca47ae1
|
||||||
with:
|
with:
|
||||||
languages: javascript # does not matter
|
languages: javascript # does not matter
|
||||||
- uses: ./.github/actions/os-version
|
- uses: ./.github/actions/os-version
|
||||||
|
|||||||
@@ -34,9 +34,9 @@
|
|||||||
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll",
|
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll",
|
||||||
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll",
|
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll",
|
||||||
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll",
|
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll",
|
||||||
|
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplForRegExp.qll",
|
||||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll",
|
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll",
|
||||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll",
|
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll",
|
||||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForRegExp.qll",
|
|
||||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForHttpClientLibraries.qll",
|
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForHttpClientLibraries.qll",
|
||||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForPathname.qll",
|
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForPathname.qll",
|
||||||
"swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll"
|
"swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll"
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||||
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
<AssemblyName>Semmle.Autobuild.Cpp</AssemblyName>
|
<AssemblyName>Semmle.Autobuild.Cpp</AssemblyName>
|
||||||
<RootNamespace>Semmle.Autobuild.Cpp</RootNamespace>
|
<RootNamespace>Semmle.Autobuild.Cpp</RootNamespace>
|
||||||
<ApplicationIcon />
|
<ApplicationIcon />
|
||||||
|
|||||||
@@ -1487,6 +1487,10 @@ private module MkStage<StageSig PrevStage> {
|
|||||||
PrevStage::readStepCand(node1, _, _, config)
|
PrevStage::readStepCand(node1, _, _, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bindingset[ap, c]
|
||||||
|
pragma[inline_late]
|
||||||
|
private predicate hasHeadContent(Ap ap, Content c) { getHeadContent(ap) = c }
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowRead(
|
private predicate fwdFlowRead(
|
||||||
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
|
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
|
||||||
@@ -1494,7 +1498,7 @@ private module MkStage<StageSig PrevStage> {
|
|||||||
) {
|
) {
|
||||||
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
|
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
|
||||||
PrevStage::readStepCand(node1, c, node2, config) and
|
PrevStage::readStepCand(node1, c, node2, config) and
|
||||||
getHeadContent(ap) = c
|
hasHeadContent(ap, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
|
|||||||
@@ -1487,6 +1487,10 @@ private module MkStage<StageSig PrevStage> {
|
|||||||
PrevStage::readStepCand(node1, _, _, config)
|
PrevStage::readStepCand(node1, _, _, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bindingset[ap, c]
|
||||||
|
pragma[inline_late]
|
||||||
|
private predicate hasHeadContent(Ap ap, Content c) { getHeadContent(ap) = c }
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowRead(
|
private predicate fwdFlowRead(
|
||||||
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
|
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
|
||||||
@@ -1494,7 +1498,7 @@ private module MkStage<StageSig PrevStage> {
|
|||||||
) {
|
) {
|
||||||
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
|
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
|
||||||
PrevStage::readStepCand(node1, c, node2, config) and
|
PrevStage::readStepCand(node1, c, node2, config) and
|
||||||
getHeadContent(ap) = c
|
hasHeadContent(ap, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
|
|||||||
@@ -1487,6 +1487,10 @@ private module MkStage<StageSig PrevStage> {
|
|||||||
PrevStage::readStepCand(node1, _, _, config)
|
PrevStage::readStepCand(node1, _, _, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bindingset[ap, c]
|
||||||
|
pragma[inline_late]
|
||||||
|
private predicate hasHeadContent(Ap ap, Content c) { getHeadContent(ap) = c }
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowRead(
|
private predicate fwdFlowRead(
|
||||||
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
|
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
|
||||||
@@ -1494,7 +1498,7 @@ private module MkStage<StageSig PrevStage> {
|
|||||||
) {
|
) {
|
||||||
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
|
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
|
||||||
PrevStage::readStepCand(node1, c, node2, config) and
|
PrevStage::readStepCand(node1, c, node2, config) and
|
||||||
getHeadContent(ap) = c
|
hasHeadContent(ap, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
|
|||||||
@@ -1487,6 +1487,10 @@ private module MkStage<StageSig PrevStage> {
|
|||||||
PrevStage::readStepCand(node1, _, _, config)
|
PrevStage::readStepCand(node1, _, _, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bindingset[ap, c]
|
||||||
|
pragma[inline_late]
|
||||||
|
private predicate hasHeadContent(Ap ap, Content c) { getHeadContent(ap) = c }
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowRead(
|
private predicate fwdFlowRead(
|
||||||
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
|
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
|
||||||
@@ -1494,7 +1498,7 @@ private module MkStage<StageSig PrevStage> {
|
|||||||
) {
|
) {
|
||||||
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
|
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
|
||||||
PrevStage::readStepCand(node1, c, node2, config) and
|
PrevStage::readStepCand(node1, c, node2, config) and
|
||||||
getHeadContent(ap) = c
|
hasHeadContent(ap, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
|
|||||||
@@ -0,0 +1,263 @@
|
|||||||
|
private import cpp
|
||||||
|
private import experimental.semmle.code.cpp.models.interfaces.SimpleRangeAnalysisExpr
|
||||||
|
private import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils
|
||||||
|
|
||||||
|
float evaluateConstantExpr(Expr e) {
|
||||||
|
result = e.getValue().toFloat()
|
||||||
|
or
|
||||||
|
// This handles when a constant value is put into a variable
|
||||||
|
// and the variable is used later
|
||||||
|
exists(SsaDefinition defn, StackVariable sv |
|
||||||
|
defn.getAUse(sv) = e and
|
||||||
|
result = defn.getDefiningValue(sv).getValue().toFloat()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the constant right operand is negative or is greater than or equal to the number of
|
||||||
|
// bits in the left operands type, then the result is undefined (except on the IA-32
|
||||||
|
// architecture where the shift value is masked with 0b00011111, but we can't
|
||||||
|
// assume the architecture).
|
||||||
|
bindingset[val]
|
||||||
|
private predicate isValidShiftExprShift(float val, Expr l) {
|
||||||
|
val >= 0 and
|
||||||
|
// We use getFullyConverted because the spec says to use the *promoted* left operand
|
||||||
|
val < (l.getFullyConverted().getUnderlyingType().getSize() * 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
bindingset[val, shift, max_val]
|
||||||
|
private predicate canLShiftOverflow(int val, int shift, int max_val) {
|
||||||
|
// val << shift = val * 2^shift > max_val => val > max_val/2^shift = max_val >> b
|
||||||
|
val > max_val.bitShiftRight(shift)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A range analysis expression consisting of the `>>` or `>>=` operator when at least
|
||||||
|
* one operand is a constant (and if the right operand is a constant, it must be "valid"
|
||||||
|
* (see `isValidShiftExprShift`)). When handling any undefined behavior, it leaves the
|
||||||
|
* values unconstrained. From the C++ standard: "The behavior is undefined if the right
|
||||||
|
* operand is negative, or greater than or equal to the length in bits of the promoted
|
||||||
|
* left operand. The value of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an
|
||||||
|
* unsigned type or if E1 has a signed type and a non-negative value, the value of the
|
||||||
|
* result is the integral part of the quotient of E1/2^E2. If E1 has a signed type and a
|
||||||
|
* negative value, the resulting value is implementation-defined."
|
||||||
|
*/
|
||||||
|
class ConstantRShiftExprRange extends SimpleRangeAnalysisExpr {
|
||||||
|
/**
|
||||||
|
* Holds for `a >> b` or `a >>= b` in one of the following two cases:
|
||||||
|
* 1. `a` is a constant and `b` is not
|
||||||
|
* 2. `b` is constant
|
||||||
|
*
|
||||||
|
* We don't handle the case where `a` and `b` are both non-constant values.
|
||||||
|
*/
|
||||||
|
ConstantRShiftExprRange() {
|
||||||
|
getUnspecifiedType() instanceof IntegralType and
|
||||||
|
exists(Expr l, Expr r |
|
||||||
|
l = this.(RShiftExpr).getLeftOperand() and
|
||||||
|
r = this.(RShiftExpr).getRightOperand()
|
||||||
|
or
|
||||||
|
l = this.(AssignRShiftExpr).getLValue() and
|
||||||
|
r = this.(AssignRShiftExpr).getRValue()
|
||||||
|
|
|
||||||
|
l.getUnspecifiedType() instanceof IntegralType and
|
||||||
|
r.getUnspecifiedType() instanceof IntegralType and
|
||||||
|
(
|
||||||
|
// If the left operand is a constant, verify that the right operand is not a constant
|
||||||
|
exists(evaluateConstantExpr(l)) and not exists(evaluateConstantExpr(r))
|
||||||
|
or
|
||||||
|
// If the right operand is a constant, check if it is a valid shift expression
|
||||||
|
exists(float constROp |
|
||||||
|
constROp = evaluateConstantExpr(r) and isValidShiftExprShift(constROp, l)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Expr getLeftOperand() {
|
||||||
|
result = this.(RShiftExpr).getLeftOperand() or
|
||||||
|
result = this.(AssignRShiftExpr).getLValue()
|
||||||
|
}
|
||||||
|
|
||||||
|
Expr getRightOperand() {
|
||||||
|
result = this.(RShiftExpr).getRightOperand() or
|
||||||
|
result = this.(AssignRShiftExpr).getRValue()
|
||||||
|
}
|
||||||
|
|
||||||
|
override float getLowerBounds() {
|
||||||
|
exists(int lLower, int lUpper, int rLower, int rUpper |
|
||||||
|
lLower = getFullyConvertedLowerBounds(getLeftOperand()) and
|
||||||
|
lUpper = getFullyConvertedUpperBounds(getLeftOperand()) and
|
||||||
|
rLower = getFullyConvertedLowerBounds(getRightOperand()) and
|
||||||
|
rUpper = getFullyConvertedUpperBounds(getRightOperand()) and
|
||||||
|
lLower <= lUpper and
|
||||||
|
rLower <= rUpper
|
||||||
|
|
|
||||||
|
if
|
||||||
|
lLower < 0
|
||||||
|
or
|
||||||
|
not (
|
||||||
|
isValidShiftExprShift(rLower, getLeftOperand()) and
|
||||||
|
isValidShiftExprShift(rUpper, getLeftOperand())
|
||||||
|
)
|
||||||
|
then
|
||||||
|
// We don't want to deal with shifting negative numbers at the moment,
|
||||||
|
// and a negative shift is implementation defined, so we set the result
|
||||||
|
// to the minimum value
|
||||||
|
result = exprMinVal(this)
|
||||||
|
else
|
||||||
|
// We can get the smallest value by shifting the smallest bound by the largest bound
|
||||||
|
result = lLower.bitShiftRight(rUpper)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override float getUpperBounds() {
|
||||||
|
exists(int lLower, int lUpper, int rLower, int rUpper |
|
||||||
|
lLower = getFullyConvertedLowerBounds(getLeftOperand()) and
|
||||||
|
lUpper = getFullyConvertedUpperBounds(getLeftOperand()) and
|
||||||
|
rLower = getFullyConvertedLowerBounds(getRightOperand()) and
|
||||||
|
rUpper = getFullyConvertedUpperBounds(getRightOperand()) and
|
||||||
|
lLower <= lUpper and
|
||||||
|
rLower <= rUpper
|
||||||
|
|
|
||||||
|
if
|
||||||
|
lLower < 0
|
||||||
|
or
|
||||||
|
not (
|
||||||
|
isValidShiftExprShift(rLower, getLeftOperand()) and
|
||||||
|
isValidShiftExprShift(rUpper, getLeftOperand())
|
||||||
|
)
|
||||||
|
then
|
||||||
|
// We don't want to deal with shifting negative numbers at the moment,
|
||||||
|
// and a negative shift is implementation defined, so we set the result
|
||||||
|
// to the maximum value
|
||||||
|
result = exprMaxVal(this)
|
||||||
|
else
|
||||||
|
// We can get the largest value by shifting the largest bound by the smallest bound
|
||||||
|
result = lUpper.bitShiftRight(rLower)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate dependsOnChild(Expr child) {
|
||||||
|
child = getLeftOperand() or child = getRightOperand()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A range analysis expression consisting of the `<<` or `<<=` operator when at least
|
||||||
|
* one operand is a constant (and if the right operand is a constant, it must be "valid"
|
||||||
|
* (see `isValidShiftExprShift`)). When handling any undefined behavior, it leaves the
|
||||||
|
* values unconstrained. From the C++ standard: "The behavior is undefined if the right
|
||||||
|
* operand is negative, or greater than or equal to the length in bits of the promoted left operand.
|
||||||
|
* The value of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are zero-filled. If E1
|
||||||
|
* has an unsigned type, the value of the result is E1 x 2 E2, reduced modulo one more than the
|
||||||
|
* maximum value representable in the result type. Otherwise, if E1 has a signed type and
|
||||||
|
* non-negative value, and E1 x 2 E2 is representable in the corresponding unsigned type of the
|
||||||
|
* result type, then that value, converted to the result type, is the resulting value; otherwise,
|
||||||
|
* the behavior is undefined."
|
||||||
|
*/
|
||||||
|
class ConstantLShiftExprRange extends SimpleRangeAnalysisExpr {
|
||||||
|
/**
|
||||||
|
* Holds for `a << b` or `a <<= b` in one of the following two cases:
|
||||||
|
* 1. `a` is a constant and `b` is not
|
||||||
|
* 2. `b` is constant
|
||||||
|
*
|
||||||
|
* We don't handle the case where `a` and `b` are both non-constant values.
|
||||||
|
*/
|
||||||
|
ConstantLShiftExprRange() {
|
||||||
|
getUnspecifiedType() instanceof IntegralType and
|
||||||
|
exists(Expr l, Expr r |
|
||||||
|
l = this.(LShiftExpr).getLeftOperand() and
|
||||||
|
r = this.(LShiftExpr).getRightOperand()
|
||||||
|
or
|
||||||
|
l = this.(AssignLShiftExpr).getLValue() and
|
||||||
|
r = this.(AssignLShiftExpr).getRValue()
|
||||||
|
|
|
||||||
|
l.getUnspecifiedType() instanceof IntegralType and
|
||||||
|
r.getUnspecifiedType() instanceof IntegralType and
|
||||||
|
(
|
||||||
|
// If the left operand is a constant, verify that the right operand is not a constant
|
||||||
|
exists(evaluateConstantExpr(l)) and not exists(evaluateConstantExpr(r))
|
||||||
|
or
|
||||||
|
// If the right operand is a constant, check if it is a valid shift expression
|
||||||
|
exists(float constROp |
|
||||||
|
constROp = evaluateConstantExpr(r) and isValidShiftExprShift(constROp, l)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Expr getLeftOperand() {
|
||||||
|
result = this.(LShiftExpr).getLeftOperand() or
|
||||||
|
result = this.(AssignLShiftExpr).getLValue()
|
||||||
|
}
|
||||||
|
|
||||||
|
Expr getRightOperand() {
|
||||||
|
result = this.(LShiftExpr).getRightOperand() or
|
||||||
|
result = this.(AssignLShiftExpr).getRValue()
|
||||||
|
}
|
||||||
|
|
||||||
|
override float getLowerBounds() {
|
||||||
|
exists(int lLower, int lUpper, int rLower, int rUpper |
|
||||||
|
lLower = getFullyConvertedLowerBounds(getLeftOperand()) and
|
||||||
|
lUpper = getFullyConvertedUpperBounds(getLeftOperand()) and
|
||||||
|
rLower = getFullyConvertedLowerBounds(getRightOperand()) and
|
||||||
|
rUpper = getFullyConvertedUpperBounds(getRightOperand()) and
|
||||||
|
lLower <= lUpper and
|
||||||
|
rLower <= rUpper
|
||||||
|
|
|
||||||
|
if
|
||||||
|
lLower < 0
|
||||||
|
or
|
||||||
|
not (
|
||||||
|
isValidShiftExprShift(rLower, getLeftOperand()) and
|
||||||
|
isValidShiftExprShift(rUpper, getLeftOperand())
|
||||||
|
)
|
||||||
|
then
|
||||||
|
// We don't want to deal with shifting negative numbers at the moment,
|
||||||
|
// and a negative shift is undefined, so we set to the minimum value
|
||||||
|
result = exprMinVal(this)
|
||||||
|
else
|
||||||
|
// If we have `0b01010000 << [0, 2]`, the max value for 8 bits is 0b10100000
|
||||||
|
// (a shift of 1) but doing a shift by the upper bound would give 0b01000000.
|
||||||
|
// So if the left shift operation causes an overflow, we just assume the max value
|
||||||
|
// If necessary, we may be able to improve this bound in the future
|
||||||
|
if canLShiftOverflow(lUpper, rUpper, exprMaxVal(this))
|
||||||
|
then result = exprMinVal(this)
|
||||||
|
else result = lLower.bitShiftLeft(rLower)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override float getUpperBounds() {
|
||||||
|
exists(int lLower, int lUpper, int rLower, int rUpper |
|
||||||
|
lLower = getFullyConvertedLowerBounds(getLeftOperand()) and
|
||||||
|
lUpper = getFullyConvertedUpperBounds(getLeftOperand()) and
|
||||||
|
rLower = getFullyConvertedLowerBounds(getRightOperand()) and
|
||||||
|
rUpper = getFullyConvertedUpperBounds(getRightOperand()) and
|
||||||
|
lLower <= lUpper and
|
||||||
|
rLower <= rUpper
|
||||||
|
|
|
||||||
|
if
|
||||||
|
lLower < 0
|
||||||
|
or
|
||||||
|
not (
|
||||||
|
isValidShiftExprShift(rLower, getLeftOperand()) and
|
||||||
|
isValidShiftExprShift(rUpper, getLeftOperand())
|
||||||
|
)
|
||||||
|
then
|
||||||
|
// We don't want to deal with shifting negative numbers at the moment,
|
||||||
|
// and a negative shift is undefined, so we set it to the maximum value
|
||||||
|
result = exprMaxVal(this)
|
||||||
|
else
|
||||||
|
// If we have `0b01010000 << [0, 2]`, the max value for 8 bits is 0b10100000
|
||||||
|
// (a shift of 1) but doing a shift by the upper bound would give 0b01000000.
|
||||||
|
// So if the left shift operation causes an overflow, we just assume the max value
|
||||||
|
// If necessary, we may be able to improve this bound in the future
|
||||||
|
if canLShiftOverflow(lUpper, rUpper, exprMaxVal(this))
|
||||||
|
then result = exprMaxVal(this)
|
||||||
|
else result = lUpper.bitShiftLeft(rUpper)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate dependsOnChild(Expr child) {
|
||||||
|
child = getLeftOperand() or child = getRightOperand()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1487,6 +1487,10 @@ private module MkStage<StageSig PrevStage> {
|
|||||||
PrevStage::readStepCand(node1, _, _, config)
|
PrevStage::readStepCand(node1, _, _, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bindingset[ap, c]
|
||||||
|
pragma[inline_late]
|
||||||
|
private predicate hasHeadContent(Ap ap, Content c) { getHeadContent(ap) = c }
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowRead(
|
private predicate fwdFlowRead(
|
||||||
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
|
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
|
||||||
@@ -1494,7 +1498,7 @@ private module MkStage<StageSig PrevStage> {
|
|||||||
) {
|
) {
|
||||||
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
|
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
|
||||||
PrevStage::readStepCand(node1, c, node2, config) and
|
PrevStage::readStepCand(node1, c, node2, config) and
|
||||||
getHeadContent(ap) = c
|
hasHeadContent(ap, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
|
|||||||
@@ -1487,6 +1487,10 @@ private module MkStage<StageSig PrevStage> {
|
|||||||
PrevStage::readStepCand(node1, _, _, config)
|
PrevStage::readStepCand(node1, _, _, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bindingset[ap, c]
|
||||||
|
pragma[inline_late]
|
||||||
|
private predicate hasHeadContent(Ap ap, Content c) { getHeadContent(ap) = c }
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowRead(
|
private predicate fwdFlowRead(
|
||||||
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
|
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
|
||||||
@@ -1494,7 +1498,7 @@ private module MkStage<StageSig PrevStage> {
|
|||||||
) {
|
) {
|
||||||
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
|
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
|
||||||
PrevStage::readStepCand(node1, c, node2, config) and
|
PrevStage::readStepCand(node1, c, node2, config) and
|
||||||
getHeadContent(ap) = c
|
hasHeadContent(ap, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
|
|||||||
@@ -1487,6 +1487,10 @@ private module MkStage<StageSig PrevStage> {
|
|||||||
PrevStage::readStepCand(node1, _, _, config)
|
PrevStage::readStepCand(node1, _, _, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bindingset[ap, c]
|
||||||
|
pragma[inline_late]
|
||||||
|
private predicate hasHeadContent(Ap ap, Content c) { getHeadContent(ap) = c }
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowRead(
|
private predicate fwdFlowRead(
|
||||||
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
|
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
|
||||||
@@ -1494,7 +1498,7 @@ private module MkStage<StageSig PrevStage> {
|
|||||||
) {
|
) {
|
||||||
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
|
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
|
||||||
PrevStage::readStepCand(node1, c, node2, config) and
|
PrevStage::readStepCand(node1, c, node2, config) and
|
||||||
getHeadContent(ap) = c
|
hasHeadContent(ap, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
|
|||||||
@@ -1487,6 +1487,10 @@ private module MkStage<StageSig PrevStage> {
|
|||||||
PrevStage::readStepCand(node1, _, _, config)
|
PrevStage::readStepCand(node1, _, _, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bindingset[ap, c]
|
||||||
|
pragma[inline_late]
|
||||||
|
private predicate hasHeadContent(Ap ap, Content c) { getHeadContent(ap) = c }
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowRead(
|
private predicate fwdFlowRead(
|
||||||
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
|
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
|
||||||
@@ -1494,7 +1498,7 @@ private module MkStage<StageSig PrevStage> {
|
|||||||
) {
|
) {
|
||||||
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
|
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
|
||||||
PrevStage::readStepCand(node1, c, node2, config) and
|
PrevStage::readStepCand(node1, c, node2, config) and
|
||||||
getHeadContent(ap) = c
|
hasHeadContent(ap, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
|
|||||||
@@ -1487,6 +1487,10 @@ private module MkStage<StageSig PrevStage> {
|
|||||||
PrevStage::readStepCand(node1, _, _, config)
|
PrevStage::readStepCand(node1, _, _, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bindingset[ap, c]
|
||||||
|
pragma[inline_late]
|
||||||
|
private predicate hasHeadContent(Ap ap, Content c) { getHeadContent(ap) = c }
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowRead(
|
private predicate fwdFlowRead(
|
||||||
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
|
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
|
||||||
@@ -1494,7 +1498,7 @@ private module MkStage<StageSig PrevStage> {
|
|||||||
) {
|
) {
|
||||||
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
|
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
|
||||||
PrevStage::readStepCand(node1, c, node2, config) and
|
PrevStage::readStepCand(node1, c, node2, config) and
|
||||||
getHeadContent(ap) = c
|
hasHeadContent(ap, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
|
|||||||
@@ -1487,6 +1487,10 @@ private module MkStage<StageSig PrevStage> {
|
|||||||
PrevStage::readStepCand(node1, _, _, config)
|
PrevStage::readStepCand(node1, _, _, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bindingset[ap, c]
|
||||||
|
pragma[inline_late]
|
||||||
|
private predicate hasHeadContent(Ap ap, Content c) { getHeadContent(ap) = c }
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowRead(
|
private predicate fwdFlowRead(
|
||||||
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
|
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
|
||||||
@@ -1494,7 +1498,7 @@ private module MkStage<StageSig PrevStage> {
|
|||||||
) {
|
) {
|
||||||
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
|
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
|
||||||
PrevStage::readStepCand(node1, c, node2, config) and
|
PrevStage::readStepCand(node1, c, node2, config) and
|
||||||
getHeadContent(ap) = c
|
hasHeadContent(ap, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
|
|||||||
@@ -1487,6 +1487,10 @@ private module MkStage<StageSig PrevStage> {
|
|||||||
PrevStage::readStepCand(node1, _, _, config)
|
PrevStage::readStepCand(node1, _, _, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bindingset[ap, c]
|
||||||
|
pragma[inline_late]
|
||||||
|
private predicate hasHeadContent(Ap ap, Content c) { getHeadContent(ap) = c }
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowRead(
|
private predicate fwdFlowRead(
|
||||||
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
|
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
|
||||||
@@ -1494,7 +1498,7 @@ private module MkStage<StageSig PrevStage> {
|
|||||||
) {
|
) {
|
||||||
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
|
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
|
||||||
PrevStage::readStepCand(node1, c, node2, config) and
|
PrevStage::readStepCand(node1, c, node2, config) and
|
||||||
getHeadContent(ap) = c
|
hasHeadContent(ap, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
|
|||||||
@@ -1487,6 +1487,10 @@ private module MkStage<StageSig PrevStage> {
|
|||||||
PrevStage::readStepCand(node1, _, _, config)
|
PrevStage::readStepCand(node1, _, _, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bindingset[ap, c]
|
||||||
|
pragma[inline_late]
|
||||||
|
private predicate hasHeadContent(Ap ap, Content c) { getHeadContent(ap) = c }
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowRead(
|
private predicate fwdFlowRead(
|
||||||
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
|
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
|
||||||
@@ -1494,7 +1498,7 @@ private module MkStage<StageSig PrevStage> {
|
|||||||
) {
|
) {
|
||||||
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
|
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
|
||||||
PrevStage::readStepCand(node1, c, node2, config) and
|
PrevStage::readStepCand(node1, c, node2, config) and
|
||||||
getHeadContent(ap) = c
|
hasHeadContent(ap, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
|
|||||||
@@ -1487,6 +1487,10 @@ private module MkStage<StageSig PrevStage> {
|
|||||||
PrevStage::readStepCand(node1, _, _, config)
|
PrevStage::readStepCand(node1, _, _, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bindingset[ap, c]
|
||||||
|
pragma[inline_late]
|
||||||
|
private predicate hasHeadContent(Ap ap, Content c) { getHeadContent(ap) = c }
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowRead(
|
private predicate fwdFlowRead(
|
||||||
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
|
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
|
||||||
@@ -1494,7 +1498,7 @@ private module MkStage<StageSig PrevStage> {
|
|||||||
) {
|
) {
|
||||||
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
|
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
|
||||||
PrevStage::readStepCand(node1, c, node2, config) and
|
PrevStage::readStepCand(node1, c, node2, config) and
|
||||||
getHeadContent(ap) = c
|
hasHeadContent(ap, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
|
|||||||
@@ -169,19 +169,11 @@ predicate defaultTaintSanitizer(DataFlow::Node node) { none() }
|
|||||||
*/
|
*/
|
||||||
predicate modeledTaintStep(Operand nodeIn, Instruction nodeOut) {
|
predicate modeledTaintStep(Operand nodeIn, Instruction nodeOut) {
|
||||||
exists(CallInstruction call, TaintFunction func, FunctionInput modelIn, FunctionOutput modelOut |
|
exists(CallInstruction call, TaintFunction func, FunctionInput modelIn, FunctionOutput modelOut |
|
||||||
(
|
|
||||||
nodeIn = callInput(call, modelIn)
|
|
||||||
or
|
|
||||||
exists(int n |
|
|
||||||
modelIn.isParameterDerefOrQualifierObject(n) and
|
|
||||||
if n = -1
|
|
||||||
then nodeIn = callInput(call, any(InQualifierObject inQualifier))
|
|
||||||
else nodeIn = callInput(call, any(InParameter inParam | inParam.getIndex() = n))
|
|
||||||
)
|
|
||||||
) and
|
|
||||||
nodeOut = callOutput(call, modelOut) and
|
|
||||||
call.getStaticCallTarget() = func and
|
call.getStaticCallTarget() = func and
|
||||||
func.hasTaintFlow(modelIn, modelOut)
|
func.hasTaintFlow(modelIn, modelOut)
|
||||||
|
|
|
||||||
|
nodeIn = callInput(call, modelIn) and
|
||||||
|
nodeOut = callOutput(call, modelOut)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
// Taint flow from one argument to another and data flow from an argument to a
|
// Taint flow from one argument to another and data flow from an argument to a
|
||||||
|
|||||||
@@ -412,6 +412,9 @@ class CallTargetOperand extends RegisterOperand {
|
|||||||
*/
|
*/
|
||||||
class ArgumentOperand extends RegisterOperand {
|
class ArgumentOperand extends RegisterOperand {
|
||||||
override ArgumentOperandTag tag;
|
override ArgumentOperandTag tag;
|
||||||
|
|
||||||
|
/** Gets the `CallInstruction` for which this is an argument. */
|
||||||
|
CallInstruction getCall() { result.getAnArgumentOperand() = this }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -412,6 +412,9 @@ class CallTargetOperand extends RegisterOperand {
|
|||||||
*/
|
*/
|
||||||
class ArgumentOperand extends RegisterOperand {
|
class ArgumentOperand extends RegisterOperand {
|
||||||
override ArgumentOperandTag tag;
|
override ArgumentOperandTag tag;
|
||||||
|
|
||||||
|
/** Gets the `CallInstruction` for which this is an argument. */
|
||||||
|
CallInstruction getCall() { result.getAnArgumentOperand() = this }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -412,6 +412,9 @@ class CallTargetOperand extends RegisterOperand {
|
|||||||
*/
|
*/
|
||||||
class ArgumentOperand extends RegisterOperand {
|
class ArgumentOperand extends RegisterOperand {
|
||||||
override ArgumentOperandTag tag;
|
override ArgumentOperandTag tag;
|
||||||
|
|
||||||
|
/** Gets the `CallInstruction` for which this is an argument. */
|
||||||
|
CallInstruction getCall() { result.getAnArgumentOperand() = this }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -107,130 +107,34 @@ private FunctionInput getIteratorArgumentInput(Operator op, int index) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* A non-member prefix `operator*` function for an iterator type.
|
|
||||||
*/
|
|
||||||
private class IteratorPointerDereferenceOperator extends Operator, TaintFunction,
|
|
||||||
IteratorReferenceFunction {
|
|
||||||
FunctionInput iteratorInput;
|
|
||||||
|
|
||||||
IteratorPointerDereferenceOperator() {
|
|
||||||
this.hasName("operator*") and
|
|
||||||
iteratorInput = getIteratorArgumentInput(this, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
|
||||||
input = iteratorInput and
|
|
||||||
output.isReturnValue()
|
|
||||||
or
|
|
||||||
input.isReturnValueDeref() and
|
|
||||||
output.isParameterDeref(0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A non-member `operator++` or `operator--` function for an iterator type.
|
* A non-member `operator++` or `operator--` function for an iterator type.
|
||||||
|
*
|
||||||
|
* Note that this class _only_ matches non-member functions. To find both
|
||||||
|
* non-member and versions, use `IteratorCrementOperator`.
|
||||||
*/
|
*/
|
||||||
private class IteratorCrementOperator extends Operator, DataFlowFunction {
|
class IteratorCrementNonMemberOperator extends Operator {
|
||||||
FunctionInput iteratorInput;
|
IteratorCrementNonMemberOperator() {
|
||||||
|
|
||||||
IteratorCrementOperator() {
|
|
||||||
this.hasName(["operator++", "operator--"]) and
|
this.hasName(["operator++", "operator--"]) and
|
||||||
iteratorInput = getIteratorArgumentInput(this, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
|
|
||||||
input = iteratorInput and
|
|
||||||
output.isReturnValue()
|
|
||||||
or
|
|
||||||
input.isParameterDeref(0) and output.isReturnValueDeref()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A non-member `operator+` function for an iterator type.
|
|
||||||
*/
|
|
||||||
private class IteratorAddOperator extends Operator, TaintFunction {
|
|
||||||
FunctionInput iteratorInput;
|
|
||||||
|
|
||||||
IteratorAddOperator() {
|
|
||||||
this.hasName("operator+") and
|
|
||||||
iteratorInput = getIteratorArgumentInput(this, [0, 1])
|
|
||||||
}
|
|
||||||
|
|
||||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
|
||||||
input = iteratorInput and
|
|
||||||
output.isReturnValue()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A non-member `operator-` function that takes a pointer difference type as its second argument.
|
|
||||||
*/
|
|
||||||
private class IteratorSubOperator extends Operator, TaintFunction {
|
|
||||||
FunctionInput iteratorInput;
|
|
||||||
|
|
||||||
IteratorSubOperator() {
|
|
||||||
this.hasName("operator-") and
|
|
||||||
iteratorInput = getIteratorArgumentInput(this, 0) and
|
|
||||||
this.getParameter(1).getUnspecifiedType() instanceof IntegralType // not an iterator difference
|
|
||||||
}
|
|
||||||
|
|
||||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
|
||||||
input = iteratorInput and
|
|
||||||
output.isReturnValue()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A non-member `operator+=` or `operator-=` function for an iterator type.
|
|
||||||
*/
|
|
||||||
class IteratorAssignArithmeticOperator extends Operator {
|
|
||||||
IteratorAssignArithmeticOperator() {
|
|
||||||
this.hasName(["operator+=", "operator-="]) and
|
|
||||||
exists(getIteratorArgumentInput(this, 0))
|
exists(getIteratorArgumentInput(this, 0))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class IteratorAssignArithmeticOperatorModel extends IteratorAssignArithmeticOperator,
|
private class IteratorCrementNonMemberOperatorModel extends IteratorCrementNonMemberOperator,
|
||||||
DataFlowFunction, TaintFunction {
|
DataFlowFunction {
|
||||||
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
|
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
|
||||||
input.isParameter(0) and
|
input = getIteratorArgumentInput(this, 0) and
|
||||||
output.isReturnValue()
|
output.isReturnValue()
|
||||||
}
|
or
|
||||||
|
|
||||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
|
||||||
input.isParameterDeref(0) and output.isReturnValueDeref()
|
input.isParameterDeref(0) and output.isReturnValueDeref()
|
||||||
or
|
|
||||||
// reverse flow from returned reference to the object referenced by the first parameter
|
|
||||||
input.isReturnValueDeref() and
|
|
||||||
output.isParameterDeref(0)
|
|
||||||
or
|
|
||||||
input.isParameterDeref(1) and
|
|
||||||
output.isParameterDeref(0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A prefix `operator*` member function for an iterator type.
|
|
||||||
*/
|
|
||||||
class IteratorPointerDereferenceMemberOperator extends MemberFunction, TaintFunction,
|
|
||||||
IteratorReferenceFunction {
|
|
||||||
IteratorPointerDereferenceMemberOperator() {
|
|
||||||
this.getClassAndName("operator*") instanceof Iterator
|
|
||||||
}
|
|
||||||
|
|
||||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
|
||||||
input.isQualifierObject() and
|
|
||||||
output.isReturnValue()
|
|
||||||
or
|
|
||||||
input.isReturnValueDeref() and
|
|
||||||
output.isQualifierObject()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An `operator++` or `operator--` member function for an iterator type.
|
* An `operator++` or `operator--` member function for an iterator type.
|
||||||
|
*
|
||||||
|
* Note that this class _only_ matches member functions. To find both
|
||||||
|
* non-member and member versions, use `IteratorCrementOperator`.
|
||||||
*/
|
*/
|
||||||
class IteratorCrementMemberOperator extends MemberFunction {
|
class IteratorCrementMemberOperator extends MemberFunction {
|
||||||
IteratorCrementMemberOperator() {
|
IteratorCrementMemberOperator() {
|
||||||
@@ -258,25 +162,49 @@ private class IteratorCrementMemberOperatorModel extends IteratorCrementMemberOp
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A member `operator->` function for an iterator type.
|
* A (member or non-member) `operator++` or `operator--` function for an iterator type.
|
||||||
*/
|
*/
|
||||||
private class IteratorFieldMemberOperator extends Operator, TaintFunction {
|
class IteratorCrementOperator extends Function {
|
||||||
IteratorFieldMemberOperator() { this.getClassAndName("operator->") instanceof Iterator }
|
IteratorCrementOperator() {
|
||||||
|
this instanceof IteratorCrementNonMemberOperator or
|
||||||
|
this instanceof IteratorCrementMemberOperator
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A non-member `operator+` function for an iterator type.
|
||||||
|
*
|
||||||
|
* Note that this class _only_ matches non-member functions. To find both
|
||||||
|
* non-member and member versions, use `IteratorBinaryAddOperator`.
|
||||||
|
*/
|
||||||
|
class IteratorAddNonMemberOperator extends Operator {
|
||||||
|
IteratorAddNonMemberOperator() {
|
||||||
|
this.hasName("operator+") and
|
||||||
|
exists(getIteratorArgumentInput(this, [0, 1]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class IteratorAddNonMemberOperatorModel extends IteratorAddNonMemberOperator, TaintFunction {
|
||||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||||
input.isQualifierObject() and
|
input = getIteratorArgumentInput(this, [0, 1]) and
|
||||||
output.isReturnValue()
|
output.isReturnValue()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An `operator+` or `operator-` member function of an iterator class.
|
* An `operator+` or `operator-` member function of an iterator class.
|
||||||
|
*
|
||||||
|
* Note that this class _only_ matches member functions. To find both
|
||||||
|
* non-member and member versions, use `IteratorBinaryAddOperator`.
|
||||||
*/
|
*/
|
||||||
private class IteratorBinaryArithmeticMemberOperator extends MemberFunction, TaintFunction {
|
class IteratorBinaryArithmeticMemberOperator extends MemberFunction {
|
||||||
IteratorBinaryArithmeticMemberOperator() {
|
IteratorBinaryArithmeticMemberOperator() {
|
||||||
this.getClassAndName(["operator+", "operator-"]) instanceof Iterator
|
this.getClassAndName(["operator+", "operator-"]) instanceof Iterator
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class IteratorBinaryArithmeticMemberOperatorModel extends IteratorBinaryArithmeticMemberOperator,
|
||||||
|
TaintFunction {
|
||||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||||
input.isQualifierObject() and
|
input.isQualifierObject() and
|
||||||
output.isReturnValue()
|
output.isReturnValue()
|
||||||
@@ -284,14 +212,84 @@ private class IteratorBinaryArithmeticMemberOperator extends MemberFunction, Tai
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An `operator+=` or `operator-=` member function of an iterator class.
|
* A (member or non-member) `operator+` or `operator-` function for an iterator type.
|
||||||
*/
|
*/
|
||||||
private class IteratorAssignArithmeticMemberOperator extends MemberFunction, DataFlowFunction,
|
class IteratorBinaryArithmeticOperator extends Function {
|
||||||
TaintFunction {
|
IteratorBinaryArithmeticOperator() {
|
||||||
|
this instanceof IteratorAddNonMemberOperator or
|
||||||
|
this instanceof IteratorSubNonMemberOperator or
|
||||||
|
this instanceof IteratorBinaryArithmeticMemberOperator
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A non-member `operator-` function that takes a pointer difference type as its second argument.
|
||||||
|
*
|
||||||
|
* Note that this class _only_ matches non-member functions. To find both
|
||||||
|
* non-member and member versions, use `IteratorBinaryArithmeticOperator` (which also
|
||||||
|
* includes `operator+` versions).
|
||||||
|
*/
|
||||||
|
class IteratorSubNonMemberOperator extends Operator {
|
||||||
|
IteratorSubNonMemberOperator() {
|
||||||
|
this.hasName("operator-") and
|
||||||
|
exists(getIteratorArgumentInput(this, 0)) and
|
||||||
|
this.getParameter(1).getUnspecifiedType() instanceof IntegralType // not an iterator difference
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class IteratorSubOperatorModel extends IteratorSubNonMemberOperator, TaintFunction {
|
||||||
|
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||||
|
input = getIteratorArgumentInput(this, 0) and
|
||||||
|
output.isReturnValue()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A non-member `operator+=` or `operator-=` function for an iterator type.
|
||||||
|
*
|
||||||
|
* Note that this class _only_ matches non-member functions. To find both
|
||||||
|
* non-member and member versions, use `IteratorAssignArithmeticOperator`.
|
||||||
|
*/
|
||||||
|
class IteratorAssignArithmeticNonMemberOperator extends Operator {
|
||||||
|
IteratorAssignArithmeticNonMemberOperator() {
|
||||||
|
this.hasName(["operator+=", "operator-="]) and
|
||||||
|
exists(getIteratorArgumentInput(this, 0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class IteratorAssignArithmeticNonMemberOperatorModel extends IteratorAssignArithmeticNonMemberOperator,
|
||||||
|
DataFlowFunction, TaintFunction {
|
||||||
|
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
|
||||||
|
input.isParameter(0) and
|
||||||
|
output.isReturnValue()
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||||
|
input.isParameterDeref(0) and output.isReturnValueDeref()
|
||||||
|
or
|
||||||
|
// reverse flow from returned reference to the object referenced by the first parameter
|
||||||
|
input.isReturnValueDeref() and
|
||||||
|
output.isParameterDeref(0)
|
||||||
|
or
|
||||||
|
(input.isParameter(1) or input.isParameterDeref(1)) and
|
||||||
|
output.isParameterDeref(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An `operator+=` or `operator-=` member function of an iterator class.
|
||||||
|
*
|
||||||
|
* Note that this class _only_ matches member functions. To find both
|
||||||
|
* non-member and member versions, use `IteratorAssignArithmeticOperator`.
|
||||||
|
*/
|
||||||
|
class IteratorAssignArithmeticMemberOperator extends MemberFunction {
|
||||||
IteratorAssignArithmeticMemberOperator() {
|
IteratorAssignArithmeticMemberOperator() {
|
||||||
this.getClassAndName(["operator+=", "operator-="]) instanceof Iterator
|
this.getClassAndName(["operator+=", "operator-="]) instanceof Iterator
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class IteratorAssignArithmeticMemberOperatorModel extends IteratorAssignArithmeticMemberOperator,
|
||||||
|
DataFlowFunction, TaintFunction {
|
||||||
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
|
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
|
||||||
input.isQualifierAddress() and
|
input.isQualifierAddress() and
|
||||||
output.isReturnValue()
|
output.isReturnValue()
|
||||||
@@ -305,11 +303,88 @@ private class IteratorAssignArithmeticMemberOperator extends MemberFunction, Dat
|
|||||||
input.isReturnValueDeref() and
|
input.isReturnValueDeref() and
|
||||||
output.isQualifierObject()
|
output.isQualifierObject()
|
||||||
or
|
or
|
||||||
input.isParameterDeref(0) and
|
(input.isParameter(0) or input.isParameterDeref(0)) and
|
||||||
output.isQualifierObject()
|
output.isQualifierObject()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A (member or non-member) `operator+=` or `operator-=` function for an iterator type.
|
||||||
|
*/
|
||||||
|
class IteratorAssignArithmeticOperator extends Function {
|
||||||
|
IteratorAssignArithmeticOperator() {
|
||||||
|
this instanceof IteratorAssignArithmeticNonMemberOperator or
|
||||||
|
this instanceof IteratorAssignArithmeticMemberOperator
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A prefix `operator*` member function for an iterator type.
|
||||||
|
*
|
||||||
|
* Note that this class _only_ matches member functions. To find both
|
||||||
|
* non-member and member versions, use `IteratorPointerDereferenceOperator`.
|
||||||
|
*/
|
||||||
|
class IteratorPointerDereferenceMemberOperator extends MemberFunction, TaintFunction,
|
||||||
|
IteratorReferenceFunction {
|
||||||
|
IteratorPointerDereferenceMemberOperator() {
|
||||||
|
this.getClassAndName("operator*") instanceof Iterator
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||||
|
input.isQualifierObject() and
|
||||||
|
output.isReturnValue()
|
||||||
|
or
|
||||||
|
input.isReturnValueDeref() and
|
||||||
|
output.isQualifierObject()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A non-member prefix `operator*` function for an iterator type.
|
||||||
|
*
|
||||||
|
* Note that this class _only_ matches non-member functions. To find both
|
||||||
|
* non-member and member versions, use `IteratorPointerDereferenceOperator`.
|
||||||
|
*/
|
||||||
|
class IteratorPointerDereferenceNonMemberOperator extends Operator, IteratorReferenceFunction {
|
||||||
|
IteratorPointerDereferenceNonMemberOperator() {
|
||||||
|
this.hasName("operator*") and
|
||||||
|
exists(getIteratorArgumentInput(this, 0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class IteratorPointerDereferenceNonMemberOperatorModel extends IteratorPointerDereferenceNonMemberOperator,
|
||||||
|
TaintFunction {
|
||||||
|
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||||
|
input = getIteratorArgumentInput(this, 0) and
|
||||||
|
output.isReturnValue()
|
||||||
|
or
|
||||||
|
input.isReturnValueDeref() and
|
||||||
|
output.isParameterDeref(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A (member or non-member) prefix `operator*` function for an iterator type.
|
||||||
|
*/
|
||||||
|
class IteratorPointerDereferenceOperator extends Function {
|
||||||
|
IteratorPointerDereferenceOperator() {
|
||||||
|
this instanceof IteratorPointerDereferenceNonMemberOperator or
|
||||||
|
this instanceof IteratorPointerDereferenceMemberOperator
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A member `operator->` function for an iterator type.
|
||||||
|
*/
|
||||||
|
private class IteratorFieldMemberOperator extends Operator, TaintFunction {
|
||||||
|
IteratorFieldMemberOperator() { this.getClassAndName("operator->") instanceof Iterator }
|
||||||
|
|
||||||
|
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||||
|
input.isQualifierObject() and
|
||||||
|
output.isReturnValue()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An `operator[]` member function of an iterator class.
|
* An `operator[]` member function of an iterator class.
|
||||||
*/
|
*/
|
||||||
@@ -326,17 +401,24 @@ private class IteratorArrayMemberOperator extends MemberFunction, TaintFunction,
|
|||||||
/**
|
/**
|
||||||
* An `operator=` member function of an iterator class that is not a copy or move assignment
|
* An `operator=` member function of an iterator class that is not a copy or move assignment
|
||||||
* operator.
|
* operator.
|
||||||
*
|
|
||||||
* The `hasTaintFlow` override provides flow through output iterators that return themselves with
|
|
||||||
* `operator*` and use their own `operator=` to assign to the container.
|
|
||||||
*/
|
*/
|
||||||
private class IteratorAssignmentMemberOperator extends MemberFunction, TaintFunction {
|
class IteratorAssignmentMemberOperator extends MemberFunction {
|
||||||
IteratorAssignmentMemberOperator() {
|
IteratorAssignmentMemberOperator() {
|
||||||
this.getClassAndName("operator=") instanceof Iterator and
|
this.getClassAndName("operator=") instanceof Iterator and
|
||||||
not this instanceof CopyAssignmentOperator and
|
not this instanceof CopyAssignmentOperator and
|
||||||
not this instanceof MoveAssignmentOperator
|
not this instanceof MoveAssignmentOperator
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An `operator=` member function of an iterator class that is not a copy or move assignment
|
||||||
|
* operator.
|
||||||
|
*
|
||||||
|
* The `hasTaintFlow` override provides flow through output iterators that return themselves with
|
||||||
|
* `operator*` and use their own `operator=` to assign to the container.
|
||||||
|
*/
|
||||||
|
private class IteratorAssignmentMemberOperatorModel extends IteratorAssignmentMemberOperator,
|
||||||
|
TaintFunction {
|
||||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||||
input.isParameterDeref(0) and
|
input.isParameterDeref(0) and
|
||||||
output.isQualifierObject()
|
output.isQualifierObject()
|
||||||
|
|||||||
@@ -27,7 +27,12 @@ private class StdSetConstructor extends Constructor, TaintFunction {
|
|||||||
|
|
||||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||||
// taint flow from any parameter of an iterator type to the qualifier
|
// taint flow from any parameter of an iterator type to the qualifier
|
||||||
input.isParameterDeref(this.getAnIteratorParameterIndex()) and
|
(
|
||||||
|
// AST dataflow doesn't have indirection for iterators.
|
||||||
|
// Once we deprecate AST dataflow we can delete this first disjunct.
|
||||||
|
input.isParameter(this.getAnIteratorParameterIndex()) or
|
||||||
|
input.isParameterDeref(this.getAnIteratorParameterIndex())
|
||||||
|
) and
|
||||||
(
|
(
|
||||||
output.isReturnValue() // TODO: this is only needed for AST data flow, which treats constructors as returning the new object
|
output.isReturnValue() // TODO: this is only needed for AST data flow, which treats constructors as returning the new object
|
||||||
or
|
or
|
||||||
@@ -45,7 +50,12 @@ private class StdSetInsert extends TaintFunction {
|
|||||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||||
// flow from last parameter to qualifier and return value
|
// flow from last parameter to qualifier and return value
|
||||||
// (where the return value is a pair, this should really flow just to the first part of it)
|
// (where the return value is a pair, this should really flow just to the first part of it)
|
||||||
input.isParameterDeref(this.getNumberOfParameters() - 1) and
|
(
|
||||||
|
// AST dataflow doesn't have indirection for iterators.
|
||||||
|
// Once we deprecate AST dataflow we can delete this first disjunct.
|
||||||
|
input.isParameter(this.getNumberOfParameters() - 1) or
|
||||||
|
input.isParameterDeref(this.getNumberOfParameters() - 1)
|
||||||
|
) and
|
||||||
(
|
(
|
||||||
output.isQualifierObject() or
|
output.isQualifierObject() or
|
||||||
output.isReturnValue()
|
output.isReturnValue()
|
||||||
|
|||||||
@@ -38,8 +38,7 @@ private class StdBasicStringIterator extends Iterator, Type {
|
|||||||
*/
|
*/
|
||||||
abstract private class StdStringTaintFunction extends TaintFunction {
|
abstract private class StdStringTaintFunction extends TaintFunction {
|
||||||
/**
|
/**
|
||||||
* Gets the index of a parameter to this function that is a string (or
|
* Gets the index of a parameter to this function that is a string.
|
||||||
* character).
|
|
||||||
*/
|
*/
|
||||||
final int getAStringParameterIndex() {
|
final int getAStringParameterIndex() {
|
||||||
exists(Type paramType | paramType = this.getParameter(result).getUnspecifiedType() |
|
exists(Type paramType | paramType = this.getParameter(result).getUnspecifiedType() |
|
||||||
@@ -50,7 +49,14 @@ abstract private class StdStringTaintFunction extends TaintFunction {
|
|||||||
paramType instanceof ReferenceType and
|
paramType instanceof ReferenceType and
|
||||||
not paramType.(ReferenceType).getBaseType() =
|
not paramType.(ReferenceType).getBaseType() =
|
||||||
this.getDeclaringType().getTemplateArgument(2).(Type).getUnspecifiedType()
|
this.getDeclaringType().getTemplateArgument(2).(Type).getUnspecifiedType()
|
||||||
or
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the index of a parameter to this function that is a character.
|
||||||
|
*/
|
||||||
|
final int getACharParameterIndex() {
|
||||||
|
exists(Type paramType | paramType = this.getParameter(result).getUnspecifiedType() |
|
||||||
// i.e. `std::basic_string::CharT`
|
// i.e. `std::basic_string::CharT`
|
||||||
paramType = this.getDeclaringType().getTemplateArgument(0).(Type).getUnspecifiedType()
|
paramType = this.getDeclaringType().getTemplateArgument(0).(Type).getUnspecifiedType()
|
||||||
)
|
)
|
||||||
@@ -79,6 +85,7 @@ private class StdStringConstructor extends Constructor, StdStringTaintFunction {
|
|||||||
// taint flow from any parameter of the value type to the returned object
|
// taint flow from any parameter of the value type to the returned object
|
||||||
(
|
(
|
||||||
input.isParameterDeref(this.getAStringParameterIndex()) or
|
input.isParameterDeref(this.getAStringParameterIndex()) or
|
||||||
|
input.isParameter(this.getACharParameterIndex()) or
|
||||||
input.isParameter(this.getAnIteratorParameterIndex())
|
input.isParameter(this.getAnIteratorParameterIndex())
|
||||||
) and
|
) and
|
||||||
(
|
(
|
||||||
@@ -128,7 +135,7 @@ private class StdStringPush extends StdStringTaintFunction {
|
|||||||
|
|
||||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||||
// flow from parameter to qualifier
|
// flow from parameter to qualifier
|
||||||
input.isParameterDeref(0) and
|
input.isParameter(0) and
|
||||||
output.isQualifierObject()
|
output.isQualifierObject()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -180,6 +187,7 @@ private class StdStringAppend extends StdStringTaintFunction {
|
|||||||
(
|
(
|
||||||
input.isQualifierObject() or
|
input.isQualifierObject() or
|
||||||
input.isParameterDeref(this.getAStringParameterIndex()) or
|
input.isParameterDeref(this.getAStringParameterIndex()) or
|
||||||
|
input.isParameter(this.getACharParameterIndex()) or
|
||||||
input.isParameter(this.getAnIteratorParameterIndex())
|
input.isParameter(this.getAnIteratorParameterIndex())
|
||||||
) and
|
) and
|
||||||
(
|
(
|
||||||
@@ -210,6 +218,7 @@ private class StdStringInsert extends StdStringTaintFunction {
|
|||||||
(
|
(
|
||||||
input.isQualifierObject() or
|
input.isQualifierObject() or
|
||||||
input.isParameterDeref(this.getAStringParameterIndex()) or
|
input.isParameterDeref(this.getAStringParameterIndex()) or
|
||||||
|
input.isParameter(this.getACharParameterIndex()) or
|
||||||
input.isParameter(this.getAnIteratorParameterIndex())
|
input.isParameter(this.getAnIteratorParameterIndex())
|
||||||
) and
|
) and
|
||||||
(
|
(
|
||||||
@@ -236,6 +245,7 @@ private class StdStringAssign extends StdStringTaintFunction {
|
|||||||
// flow from parameter to string itself (qualifier) and return value
|
// flow from parameter to string itself (qualifier) and return value
|
||||||
(
|
(
|
||||||
input.isParameterDeref(this.getAStringParameterIndex()) or
|
input.isParameterDeref(this.getAStringParameterIndex()) or
|
||||||
|
input.isParameter(this.getACharParameterIndex()) or
|
||||||
input.isParameter(this.getAnIteratorParameterIndex())
|
input.isParameter(this.getAnIteratorParameterIndex())
|
||||||
) and
|
) and
|
||||||
(
|
(
|
||||||
|
|||||||
@@ -158,11 +158,10 @@ abstract class FormattingFunction extends ArrayFunction, TaintFunction {
|
|||||||
|
|
||||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||||
exists(int arg |
|
exists(int arg |
|
||||||
(
|
arg = getFormatParameterIndex() or
|
||||||
arg = getFormatParameterIndex() or
|
arg >= getFirstFormatArgumentIndex()
|
||||||
arg >= getFirstFormatArgumentIndex()
|
|
|
||||||
) and
|
(input.isParameterDeref(arg) or input.isParameter(arg)) and
|
||||||
input.isParameterDeref(arg) and
|
|
||||||
output.isParameterDeref(getOutputParameterIndex(_))
|
output.isParameterDeref(getOutputParameterIndex(_))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ private predicate fwdFlow(Instruction instr, ValueNumber vn) {
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate revFlow(Instruction instr, ValueNumber vn) {
|
predicate revFlow(Instruction instr, ValueNumber vn) {
|
||||||
fwdFlow(instr, vn) and
|
fwdFlow(instr, pragma[only_bind_out](vn)) and
|
||||||
(
|
(
|
||||||
isSink(instr, _, vn)
|
isSink(instr, _, vn)
|
||||||
or
|
or
|
||||||
@@ -126,7 +126,7 @@ class Node extends MkNode {
|
|||||||
|
|
||||||
final string toString() { result = instr.toString() }
|
final string toString() { result = instr.toString() }
|
||||||
|
|
||||||
final Node getASuccessor() { result = MkNode(instr.getASuccessor(), vn) }
|
final Node getASuccessor() { result = MkNode(pragma[only_bind_out](instr.getASuccessor()), vn) }
|
||||||
|
|
||||||
final Location getLocation() { result = instr.getLocation() }
|
final Location getLocation() { result = instr.getLocation() }
|
||||||
}
|
}
|
||||||
@@ -167,7 +167,7 @@ predicate hasFlow(
|
|||||||
) {
|
) {
|
||||||
exists(ValueNumber vn |
|
exists(ValueNumber vn |
|
||||||
isSource(call, index, source, vn, _) and
|
isSource(call, index, source, vn, _) and
|
||||||
hasFlow(getNode(source, vn), getNode(sink, vn)) and
|
hasFlow(getNode(source, pragma[only_bind_into](vn)), getNode(sink, pragma[only_bind_into](vn))) and
|
||||||
isSink(sink, access, vn)
|
isSink(sink, access, vn)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
| bitshift.cpp:23:3:23:9 | ... <<= ... | 0.0 | 255.0 | file://:0:0:0:0 | unsigned char | file://:0:0:0:0 | int | file://:0:0:0:0 | unsigned char | file://:0:0:0:0 | int |
|
||||||
|
| bitshift.cpp:25:5:25:11 | ... <<= ... | 0.0 | 240.0 | file://:0:0:0:0 | unsigned char | file://:0:0:0:0 | int | file://:0:0:0:0 | unsigned char | file://:0:0:0:0 | int |
|
||||||
|
| bitshift.cpp:29:3:29:8 | ... << ... | 0.0 | 1020.0 | file://:0:0:0:0 | unsigned char | file://:0:0:0:0 | int | file://:0:0:0:0 | int | file://:0:0:0:0 | int |
|
||||||
|
| bitshift.cpp:32:3:32:9 | ... << ... | -2.147483648E9 | 2.147483647E9 | file://:0:0:0:0 | unsigned char | file://:0:0:0:0 | int | file://:0:0:0:0 | int | file://:0:0:0:0 | int |
|
||||||
|
| bitshift.cpp:35:3:35:9 | ... << ... | -2.147483648E9 | 2.147483647E9 | file://:0:0:0:0 | unsigned char | file://:0:0:0:0 | int | file://:0:0:0:0 | int | file://:0:0:0:0 | int |
|
||||||
|
| bitshift.cpp:38:3:38:22 | ... << ... | 0.0 | 32640.0 | file://:0:0:0:0 | unsigned char | file://:0:0:0:0 | unsigned char | file://:0:0:0:0 | int | file://:0:0:0:0 | int |
|
||||||
|
| bitshift.cpp:39:3:39:22 | ... << ... | 0.0 | 32640.0 | file://:0:0:0:0 | unsigned char | file://:0:0:0:0 | unsigned char | file://:0:0:0:0 | int | file://:0:0:0:0 | int |
|
||||||
|
| bitshift.cpp:40:3:40:22 | ... << ... | 0.0 | 32640.0 | file://:0:0:0:0 | unsigned char | file://:0:0:0:0 | unsigned char | file://:0:0:0:0 | int | file://:0:0:0:0 | int |
|
||||||
|
| bitshift.cpp:43:3:43:19 | ... << ... | -2.147483648E9 | 2.147483647E9 | file://:0:0:0:0 | unsigned char | file://:0:0:0:0 | signed char | file://:0:0:0:0 | int | file://:0:0:0:0 | int |
|
||||||
|
| bitshift.cpp:46:3:46:22 | ... << ... | 128.0 | 128.0 | file://:0:0:0:0 | int | file://:0:0:0:0 | unsigned char | file://:0:0:0:0 | int | file://:0:0:0:0 | int |
|
||||||
|
| bitshift.cpp:49:3:49:8 | ... << ... | -2.147483648E9 | 2.147483647E9 | file://:0:0:0:0 | int | file://:0:0:0:0 | unsigned char | file://:0:0:0:0 | int | file://:0:0:0:0 | int |
|
||||||
|
| bitshift.cpp:52:5:52:10 | ... << ... | 1.0 | 128.0 | file://:0:0:0:0 | int | file://:0:0:0:0 | unsigned char | file://:0:0:0:0 | int | file://:0:0:0:0 | int |
|
||||||
|
| bitshift.cpp:57:3:57:8 | ... << ... | -2.147483648E9 | 2.147483647E9 | file://:0:0:0:0 | signed char | file://:0:0:0:0 | int | file://:0:0:0:0 | int | file://:0:0:0:0 | int |
|
||||||
|
| bitshift.cpp:58:3:58:9 | ... << ... | -2.147483648E9 | 2.147483647E9 | file://:0:0:0:0 | signed char | file://:0:0:0:0 | int | file://:0:0:0:0 | int | file://:0:0:0:0 | int |
|
||||||
|
| bitshift.cpp:59:3:59:9 | ... << ... | -2.147483648E9 | 2.147483647E9 | file://:0:0:0:0 | signed char | file://:0:0:0:0 | int | file://:0:0:0:0 | int | file://:0:0:0:0 | int |
|
||||||
|
| bitshift.cpp:60:3:60:22 | ... << ... | -2.147483648E9 | 2.147483647E9 | file://:0:0:0:0 | signed char | file://:0:0:0:0 | unsigned char | file://:0:0:0:0 | int | file://:0:0:0:0 | int |
|
||||||
|
| bitshift.cpp:61:3:61:19 | ... << ... | -2.147483648E9 | 2.147483647E9 | file://:0:0:0:0 | signed char | file://:0:0:0:0 | signed char | file://:0:0:0:0 | int | file://:0:0:0:0 | int |
|
||||||
|
| bitshift.cpp:64:3:64:19 | ... << ... | -2.147483648E9 | 2.147483647E9 | file://:0:0:0:0 | int | file://:0:0:0:0 | signed char | file://:0:0:0:0 | int | file://:0:0:0:0 | int |
|
||||||
|
| bitshift.cpp:67:3:67:8 | ... << ... | -2.147483648E9 | 2.147483647E9 | file://:0:0:0:0 | int | file://:0:0:0:0 | signed char | file://:0:0:0:0 | int | file://:0:0:0:0 | int |
|
||||||
|
| bitshift.cpp:70:5:70:10 | ... << ... | 1.0 | 128.0 | file://:0:0:0:0 | int | file://:0:0:0:0 | signed char | file://:0:0:0:0 | int | file://:0:0:0:0 | int |
|
||||||
|
| bitshift.cpp:75:5:75:10 | ... << ... | -2.147483648E9 | 2.147483647E9 | file://:0:0:0:0 | unsigned char | file://:0:0:0:0 | signed char | file://:0:0:0:0 | int | file://:0:0:0:0 | int |
|
||||||
|
| bitshift.cpp:76:5:76:10 | ... << ... | -2.147483648E9 | 2.147483647E9 | file://:0:0:0:0 | signed char | file://:0:0:0:0 | unsigned char | file://:0:0:0:0 | int | file://:0:0:0:0 | int |
|
||||||
|
| bitshift.cpp:90:3:90:9 | ... >>= ... | 0.0 | 63.0 | file://:0:0:0:0 | unsigned char | file://:0:0:0:0 | int | file://:0:0:0:0 | unsigned char | file://:0:0:0:0 | int |
|
||||||
|
| bitshift.cpp:92:5:92:11 | ... >>= ... | 0.0 | 15.0 | file://:0:0:0:0 | unsigned char | file://:0:0:0:0 | int | file://:0:0:0:0 | unsigned char | file://:0:0:0:0 | int |
|
||||||
|
| bitshift.cpp:96:3:96:8 | ... >> ... | 0.0 | 63.0 | file://:0:0:0:0 | unsigned char | file://:0:0:0:0 | int | file://:0:0:0:0 | int | file://:0:0:0:0 | int |
|
||||||
|
| bitshift.cpp:99:3:99:9 | ... >> ... | 0.0 | 0.0 | file://:0:0:0:0 | unsigned char | file://:0:0:0:0 | int | file://:0:0:0:0 | int | file://:0:0:0:0 | int |
|
||||||
|
| bitshift.cpp:103:3:103:9 | ... >> ... | 0.0 | 0.0 | file://:0:0:0:0 | unsigned char | file://:0:0:0:0 | int | file://:0:0:0:0 | int | file://:0:0:0:0 | int |
|
||||||
|
| bitshift.cpp:106:3:106:22 | ... >> ... | 0.0 | 63.0 | file://:0:0:0:0 | unsigned char | file://:0:0:0:0 | unsigned char | file://:0:0:0:0 | int | file://:0:0:0:0 | int |
|
||||||
|
| bitshift.cpp:107:3:107:22 | ... >> ... | 0.0 | 63.0 | file://:0:0:0:0 | unsigned char | file://:0:0:0:0 | unsigned char | file://:0:0:0:0 | int | file://:0:0:0:0 | int |
|
||||||
|
| bitshift.cpp:108:3:108:22 | ... >> ... | 0.0 | 63.0 | file://:0:0:0:0 | unsigned char | file://:0:0:0:0 | unsigned char | file://:0:0:0:0 | int | file://:0:0:0:0 | int |
|
||||||
|
| bitshift.cpp:111:3:111:19 | ... >> ... | -2.147483648E9 | 2.147483647E9 | file://:0:0:0:0 | unsigned char | file://:0:0:0:0 | signed char | file://:0:0:0:0 | int | file://:0:0:0:0 | int |
|
||||||
|
| bitshift.cpp:114:3:114:24 | ... >> ... | 32.0 | 32.0 | file://:0:0:0:0 | int | file://:0:0:0:0 | unsigned char | file://:0:0:0:0 | int | file://:0:0:0:0 | int |
|
||||||
|
| bitshift.cpp:117:3:117:10 | ... >> ... | -2.147483648E9 | 2.147483647E9 | file://:0:0:0:0 | int | file://:0:0:0:0 | unsigned char | file://:0:0:0:0 | int | file://:0:0:0:0 | int |
|
||||||
|
| bitshift.cpp:120:5:120:12 | ... >> ... | 32.0 | 128.0 | file://:0:0:0:0 | int | file://:0:0:0:0 | unsigned char | file://:0:0:0:0 | int | file://:0:0:0:0 | int |
|
||||||
|
| bitshift.cpp:126:3:126:8 | ... >> ... | -2.147483648E9 | 2.147483647E9 | file://:0:0:0:0 | signed char | file://:0:0:0:0 | int | file://:0:0:0:0 | int | file://:0:0:0:0 | int |
|
||||||
|
| bitshift.cpp:127:3:127:9 | ... >> ... | -2.147483648E9 | 2.147483647E9 | file://:0:0:0:0 | signed char | file://:0:0:0:0 | int | file://:0:0:0:0 | int | file://:0:0:0:0 | int |
|
||||||
|
| bitshift.cpp:128:3:128:9 | ... >> ... | -1.0 | 0.0 | file://:0:0:0:0 | signed char | file://:0:0:0:0 | int | file://:0:0:0:0 | int | file://:0:0:0:0 | int |
|
||||||
|
| bitshift.cpp:129:3:129:22 | ... >> ... | -2.147483648E9 | 2.147483647E9 | file://:0:0:0:0 | signed char | file://:0:0:0:0 | unsigned char | file://:0:0:0:0 | int | file://:0:0:0:0 | int |
|
||||||
|
| bitshift.cpp:130:3:130:19 | ... >> ... | -2.147483648E9 | 2.147483647E9 | file://:0:0:0:0 | signed char | file://:0:0:0:0 | signed char | file://:0:0:0:0 | int | file://:0:0:0:0 | int |
|
||||||
|
| bitshift.cpp:133:3:133:21 | ... >> ... | -2.147483648E9 | 2.147483647E9 | file://:0:0:0:0 | int | file://:0:0:0:0 | signed char | file://:0:0:0:0 | int | file://:0:0:0:0 | int |
|
||||||
|
| bitshift.cpp:136:3:136:10 | ... >> ... | -2.147483648E9 | 2.147483647E9 | file://:0:0:0:0 | int | file://:0:0:0:0 | signed char | file://:0:0:0:0 | int | file://:0:0:0:0 | int |
|
||||||
|
| bitshift.cpp:139:5:139:12 | ... >> ... | 32.0 | 128.0 | file://:0:0:0:0 | int | file://:0:0:0:0 | signed char | file://:0:0:0:0 | int | file://:0:0:0:0 | int |
|
||||||
|
| bitshift.cpp:144:5:144:10 | ... >> ... | -2.147483648E9 | 2.147483647E9 | file://:0:0:0:0 | unsigned char | file://:0:0:0:0 | signed char | file://:0:0:0:0 | int | file://:0:0:0:0 | int |
|
||||||
|
| bitshift.cpp:145:5:145:10 | ... >> ... | -2.147483648E9 | 2.147483647E9 | file://:0:0:0:0 | signed char | file://:0:0:0:0 | unsigned char | file://:0:0:0:0 | int | file://:0:0:0:0 | int |
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import cpp
|
||||||
|
import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
|
||||||
|
import experimental.semmle.code.cpp.rangeanalysis.extensions.ConstantShiftExprRange
|
||||||
|
|
||||||
|
Expr getLOp(Operation o) {
|
||||||
|
result = o.(BinaryOperation).getLeftOperand() or
|
||||||
|
result = o.(Assignment).getLValue()
|
||||||
|
}
|
||||||
|
|
||||||
|
Expr getROp(Operation o) {
|
||||||
|
result = o.(BinaryOperation).getRightOperand() or
|
||||||
|
result = o.(Assignment).getRValue()
|
||||||
|
}
|
||||||
|
|
||||||
|
from Operation o
|
||||||
|
where
|
||||||
|
(
|
||||||
|
o instanceof BinaryBitwiseOperation
|
||||||
|
or
|
||||||
|
o instanceof AssignBitwiseOperation
|
||||||
|
)
|
||||||
|
select o, lowerBound(o), upperBound(o), getLOp(o).getUnderlyingType(),
|
||||||
|
getROp(o).getUnderlyingType(), getLOp(o).getFullyConverted().getUnderlyingType(),
|
||||||
|
getROp(o).getFullyConverted().getUnderlyingType()
|
||||||
@@ -0,0 +1,147 @@
|
|||||||
|
typedef signed char int8_t;
|
||||||
|
typedef short int16_t;
|
||||||
|
typedef int int32_t;
|
||||||
|
typedef long int64_t;
|
||||||
|
|
||||||
|
typedef unsigned char uint8_t;
|
||||||
|
typedef unsigned short uint16_t;
|
||||||
|
typedef unsigned int uint32_t;
|
||||||
|
typedef unsigned long uint64_t;
|
||||||
|
|
||||||
|
extern uint8_t value_known_at_runtime8();
|
||||||
|
|
||||||
|
void testLShiftOperator() {
|
||||||
|
uint8_t unsigned_const1 = 7;
|
||||||
|
uint8_t unsigned_const2(7);
|
||||||
|
uint8_t unsigned_const3{7};
|
||||||
|
int8_t signed_const = -7;
|
||||||
|
uint8_t x = value_known_at_runtime8();
|
||||||
|
int8_t y = (int8_t)value_known_at_runtime8();
|
||||||
|
uint8_t z = value_known_at_runtime8();
|
||||||
|
|
||||||
|
// An assign left shift operator. Note that no promotion occurs here
|
||||||
|
z <<= 2; // [0, 255]
|
||||||
|
if (z <= 60) {
|
||||||
|
z <<= 2; // [0, 240]
|
||||||
|
}
|
||||||
|
|
||||||
|
// A normal shift
|
||||||
|
x << 2; // [0, 1020]
|
||||||
|
|
||||||
|
// Possible to exceed the maximum size
|
||||||
|
x << 25; // [-2147483648, 2147483648]
|
||||||
|
|
||||||
|
// Undefined behavior
|
||||||
|
x << 34; // [-2147483648, 2147483648]
|
||||||
|
|
||||||
|
// A normal shift by a constant in a variable
|
||||||
|
x << unsigned_const1; // [0, 32640]
|
||||||
|
x << unsigned_const2; // [0, 32640]
|
||||||
|
x << unsigned_const3; // [0, 32640]
|
||||||
|
|
||||||
|
// Negative shifts are undefined
|
||||||
|
x << signed_const; // [-2147483648, 2147483648]
|
||||||
|
|
||||||
|
// Now the left operand is a constant
|
||||||
|
1 << unsigned_const1; // [128, 128]
|
||||||
|
|
||||||
|
// x could be large enough to cause undefined behavior
|
||||||
|
1 << x; // [-2147483648, 2147483647]
|
||||||
|
if (x < 8) {
|
||||||
|
// x is now constrained so the shift is defined
|
||||||
|
1 << x; // [1, 128]
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't support shifting negative values (and some of these are undefined
|
||||||
|
// anyway)
|
||||||
|
y << 2; // [-2147483648, 2147483647]
|
||||||
|
y << 25; // [-2147483648, 2147483648]
|
||||||
|
y << 34; // [-2147483648, 2147483648]
|
||||||
|
y << unsigned_const1; // [-2147483648, 2147483647]
|
||||||
|
y << signed_const; // [-2147483648, 2147483648]
|
||||||
|
|
||||||
|
// Negative shifts are undefined
|
||||||
|
1 << signed_const; // [-2147483648, 2147483648]
|
||||||
|
|
||||||
|
// We don't handle cases where the shift range could be negative
|
||||||
|
1 << y; // [-2147483648, 2147483648]
|
||||||
|
if (y >= 0 && y < 8) {
|
||||||
|
// The shift range is now positive
|
||||||
|
1 << y; // [1, 128]
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x > 0 and x < 2 and y > 0 and x < 2) {
|
||||||
|
// We don't support shifts where neither operand is a constant at the moment
|
||||||
|
x << y; // [-2147483648, 2147483648]
|
||||||
|
y << x; // [-2147483648, 2147483648]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void testRShiftOperator() {
|
||||||
|
uint8_t unsigned_const1 = 2;
|
||||||
|
uint8_t unsigned_const2(2);
|
||||||
|
uint8_t unsigned_const3{2};
|
||||||
|
int8_t signed_const = -2;
|
||||||
|
uint8_t x = value_known_at_runtime8();
|
||||||
|
int8_t y = (int8_t)value_known_at_runtime8();
|
||||||
|
uint8_t z = value_known_at_runtime8();
|
||||||
|
|
||||||
|
// An assign right shift operator. Note that no promotion occurs here
|
||||||
|
z >>= 2; // [0, 63]
|
||||||
|
if (z <= 60) {
|
||||||
|
z >>= 2; // [0, 15]
|
||||||
|
}
|
||||||
|
|
||||||
|
// A normal shift
|
||||||
|
x >> 2; // [0, 63]
|
||||||
|
|
||||||
|
// Possible to exceed the maximum size
|
||||||
|
x >> 25; // [0, 0]
|
||||||
|
|
||||||
|
// Undefined behavior, but this case is handled by the SimpleRangeAnalysis
|
||||||
|
// library and sets the the bounds to [0, 0], which is fine
|
||||||
|
x >> 34; // [0, 0]
|
||||||
|
|
||||||
|
// A normal shift by a constant in a variable
|
||||||
|
x >> unsigned_const1; // [0, 63]
|
||||||
|
x >> unsigned_const2; // [0, 63]
|
||||||
|
x >> unsigned_const3; // [0, 63]
|
||||||
|
|
||||||
|
// Negative shifts are undefined
|
||||||
|
x >> signed_const; // [-2147483648, 2147483648]
|
||||||
|
|
||||||
|
// Now the left operand is a constant
|
||||||
|
128 >> unsigned_const1; // [32, 32]
|
||||||
|
|
||||||
|
// x could be large enough to cause undefined behavior
|
||||||
|
128 >> x; // [-2147483648, 2147483647]
|
||||||
|
if (x < 3) {
|
||||||
|
// x is now constrained so the shift is defined
|
||||||
|
128 >> x; // [32, 128]
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't support shifting negative values, but the SimpleRangeAnalysis
|
||||||
|
// library handles the first three cases even though they're implementation
|
||||||
|
// defined or undefined behavior (TODO: Check ideone)
|
||||||
|
y >> 2; // [-2147483648, 2147483647] (Default is [-32, 31])
|
||||||
|
y >> 25; // -2147483648, 2147483647] (Default is [-1, 0])
|
||||||
|
y >> 34; // [-1, 0] (My code doesn't touch this, so default code is used)
|
||||||
|
y >> unsigned_const1; // [-2147483648, 2147483647]
|
||||||
|
y >> signed_const; // [-2147483648, 2147483648]
|
||||||
|
|
||||||
|
// Negative shifts are undefined
|
||||||
|
128 >> signed_const; // [-2147483648, 2147483648]
|
||||||
|
|
||||||
|
// We don't handle cases where the shift range could be negative
|
||||||
|
128 >> y; // [-2147483648, 2147483648]
|
||||||
|
if (y >= 0 && y < 3) {
|
||||||
|
// The shift range is now positive
|
||||||
|
128 >> y; // [32, 128]
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x > 0 and x < 2 and y > 0 and x < 2) {
|
||||||
|
// We don't support shifts where neither operand is a constant at the moment
|
||||||
|
x >> y; // [-2147483648, 2147483648]
|
||||||
|
y >> x; // [-2147483648, 2147483648]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -92,6 +92,12 @@ postWithInFlow
|
|||||||
| test.cpp:499:3:499:4 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
|
| test.cpp:499:3:499:4 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||||
| test.cpp:499:4:499:4 | p [inner post update] | PostUpdateNode should not be the target of local flow. |
|
| test.cpp:499:4:499:4 | p [inner post update] | PostUpdateNode should not be the target of local flow. |
|
||||||
| test.cpp:505:35:505:35 | x [inner post update] | PostUpdateNode should not be the target of local flow. |
|
| test.cpp:505:35:505:35 | x [inner post update] | PostUpdateNode should not be the target of local flow. |
|
||||||
|
| test.cpp:511:5:511:6 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||||
|
| test.cpp:511:6:511:6 | p [inner post update] | PostUpdateNode should not be the target of local flow. |
|
||||||
|
| test.cpp:516:5:516:6 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||||
|
| test.cpp:516:6:516:6 | p [inner post update] | PostUpdateNode should not be the target of local flow. |
|
||||||
|
| test.cpp:522:25:522:25 | x [inner post update] | PostUpdateNode should not be the target of local flow. |
|
||||||
|
| test.cpp:526:25:526:25 | y [inner post update] | PostUpdateNode should not be the target of local flow. |
|
||||||
viableImplInCallContextTooLarge
|
viableImplInCallContextTooLarge
|
||||||
uniqueParameterNodeAtPosition
|
uniqueParameterNodeAtPosition
|
||||||
uniqueParameterNodePosition
|
uniqueParameterNodePosition
|
||||||
|
|||||||
@@ -591,6 +591,18 @@ postWithInFlow
|
|||||||
| test.cpp:505:34:505:35 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
| test.cpp:505:34:505:35 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||||
| test.cpp:505:34:505:35 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
| test.cpp:505:34:505:35 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||||
| test.cpp:505:35:505:35 | x [post update] | PostUpdateNode should not be the target of local flow. |
|
| test.cpp:505:35:505:35 | x [post update] | PostUpdateNode should not be the target of local flow. |
|
||||||
|
| test.cpp:511:5:511:6 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||||
|
| test.cpp:511:6:511:6 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||||
|
| test.cpp:511:6:511:6 | p [post update] | PostUpdateNode should not be the target of local flow. |
|
||||||
|
| test.cpp:516:5:516:6 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||||
|
| test.cpp:516:6:516:6 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||||
|
| test.cpp:516:6:516:6 | p [post update] | PostUpdateNode should not be the target of local flow. |
|
||||||
|
| test.cpp:522:24:522:25 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||||
|
| test.cpp:522:24:522:25 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||||
|
| test.cpp:522:25:522:25 | x [post update] | PostUpdateNode should not be the target of local flow. |
|
||||||
|
| test.cpp:526:24:526:25 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||||
|
| test.cpp:526:24:526:25 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||||
|
| test.cpp:526:25:526:25 | y [post update] | PostUpdateNode should not be the target of local flow. |
|
||||||
| true_upon_entry.cpp:9:7:9:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
| true_upon_entry.cpp:9:7:9:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||||
| true_upon_entry.cpp:10:12:10:12 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
| true_upon_entry.cpp:10:12:10:12 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||||
| true_upon_entry.cpp:10:27:10:27 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
| true_upon_entry.cpp:10:27:10:27 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||||
|
|||||||
@@ -505,3 +505,24 @@ void viaOutparamMissingReturn() {
|
|||||||
intOutparamSourceMissingReturn(&x);
|
intOutparamSourceMissingReturn(&x);
|
||||||
sink(x); // $ ast,ir
|
sink(x); // $ ast,ir
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sink_then_source_1(int* p) {
|
||||||
|
sink(*p); // clean
|
||||||
|
*p = source();
|
||||||
|
}
|
||||||
|
|
||||||
|
void sink_then_source_2(int* p, int y) {
|
||||||
|
sink(y); // $ SPURIOUS: ast
|
||||||
|
*p = source();
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_sink_then_source() {
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
sink_then_source_1(&x);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
int y;
|
||||||
|
sink_then_source_2(&y, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -34,3 +34,6 @@
|
|||||||
| test.cpp:441:7:441:11 | local | test.cpp:442:18:442:22 | local |
|
| test.cpp:441:7:441:11 | local | test.cpp:442:18:442:22 | local |
|
||||||
| test.cpp:441:7:441:11 | local | test.cpp:443:8:443:12 | local |
|
| test.cpp:441:7:441:11 | local | test.cpp:443:8:443:12 | local |
|
||||||
| test.cpp:441:7:441:11 | local | test.cpp:444:9:444:13 | local |
|
| test.cpp:441:7:441:11 | local | test.cpp:444:9:444:13 | local |
|
||||||
|
| test.cpp:521:9:521:9 | x | test.cpp:522:25:522:25 | x |
|
||||||
|
| test.cpp:525:9:525:9 | y | test.cpp:526:25:526:25 | y |
|
||||||
|
| test.cpp:525:9:525:9 | y | test.cpp:526:28:526:28 | y |
|
||||||
|
|||||||
@@ -3482,106 +3482,106 @@
|
|||||||
| smart_pointer.cpp:137:10:137:11 | p2 | smart_pointer.cpp:137:9:137:9 | call to operator* | TAINT |
|
| smart_pointer.cpp:137:10:137:11 | p2 | smart_pointer.cpp:137:9:137:9 | call to operator* | TAINT |
|
||||||
| smart_pointer.cpp:137:10:137:11 | ref arg p2 | smart_pointer.cpp:132:95:132:96 | p2 | |
|
| smart_pointer.cpp:137:10:137:11 | ref arg p2 | smart_pointer.cpp:132:95:132:96 | p2 | |
|
||||||
| smart_pointer.cpp:137:10:137:11 | ref arg p2 | smart_pointer.cpp:137:10:137:11 | p2 [inner post update] | |
|
| smart_pointer.cpp:137:10:137:11 | ref arg p2 | smart_pointer.cpp:137:10:137:11 | p2 [inner post update] | |
|
||||||
| standalone_iterators.cpp:39:45:39:51 | source1 | standalone_iterators.cpp:39:45:39:51 | source1 | |
|
| standalone_iterators.cpp:43:45:43:51 | source1 | standalone_iterators.cpp:43:45:43:51 | source1 | |
|
||||||
| standalone_iterators.cpp:39:45:39:51 | source1 | standalone_iterators.cpp:40:11:40:17 | source1 | |
|
| standalone_iterators.cpp:43:45:43:51 | source1 | standalone_iterators.cpp:44:11:44:17 | source1 | |
|
||||||
| standalone_iterators.cpp:39:45:39:51 | source1 | standalone_iterators.cpp:41:12:41:18 | source1 | |
|
| standalone_iterators.cpp:43:45:43:51 | source1 | standalone_iterators.cpp:45:12:45:18 | source1 | |
|
||||||
| standalone_iterators.cpp:39:45:39:51 | source1 | standalone_iterators.cpp:42:14:42:20 | source1 | |
|
| standalone_iterators.cpp:43:45:43:51 | source1 | standalone_iterators.cpp:46:14:46:20 | source1 | |
|
||||||
| standalone_iterators.cpp:40:11:40:17 | source1 | standalone_iterators.cpp:40:10:40:10 | call to operator* | TAINT |
|
| standalone_iterators.cpp:44:11:44:17 | source1 | standalone_iterators.cpp:44:10:44:10 | call to operator* | TAINT |
|
||||||
| standalone_iterators.cpp:41:12:41:18 | ref arg source1 | standalone_iterators.cpp:39:45:39:51 | source1 | |
|
| standalone_iterators.cpp:45:12:45:18 | ref arg source1 | standalone_iterators.cpp:43:45:43:51 | source1 | |
|
||||||
| standalone_iterators.cpp:41:12:41:18 | ref arg source1 | standalone_iterators.cpp:42:14:42:20 | source1 | |
|
| standalone_iterators.cpp:45:12:45:18 | ref arg source1 | standalone_iterators.cpp:46:14:46:20 | source1 | |
|
||||||
| standalone_iterators.cpp:41:12:41:18 | source1 | standalone_iterators.cpp:41:19:41:19 | call to operator++ | |
|
| standalone_iterators.cpp:45:12:45:18 | source1 | standalone_iterators.cpp:45:19:45:19 | call to operator++ | |
|
||||||
| standalone_iterators.cpp:41:19:41:19 | call to operator++ | standalone_iterators.cpp:41:10:41:10 | call to operator* | TAINT |
|
| standalone_iterators.cpp:45:19:45:19 | call to operator++ | standalone_iterators.cpp:45:10:45:10 | call to operator* | TAINT |
|
||||||
| standalone_iterators.cpp:42:12:42:12 | call to operator++ | standalone_iterators.cpp:42:10:42:10 | call to operator* | TAINT |
|
| standalone_iterators.cpp:46:12:46:12 | call to operator++ | standalone_iterators.cpp:46:10:46:10 | call to operator* | TAINT |
|
||||||
| standalone_iterators.cpp:42:14:42:20 | ref arg source1 | standalone_iterators.cpp:39:45:39:51 | source1 | |
|
| standalone_iterators.cpp:46:14:46:20 | ref arg source1 | standalone_iterators.cpp:43:45:43:51 | source1 | |
|
||||||
| standalone_iterators.cpp:42:14:42:20 | source1 | standalone_iterators.cpp:42:12:42:12 | call to operator++ | |
|
| standalone_iterators.cpp:46:14:46:20 | source1 | standalone_iterators.cpp:46:12:46:12 | call to operator++ | |
|
||||||
| standalone_iterators.cpp:45:39:45:45 | source1 | standalone_iterators.cpp:45:39:45:45 | source1 | |
|
| standalone_iterators.cpp:49:39:49:45 | source1 | standalone_iterators.cpp:49:39:49:45 | source1 | |
|
||||||
| standalone_iterators.cpp:45:39:45:45 | source1 | standalone_iterators.cpp:46:11:46:17 | source1 | |
|
| standalone_iterators.cpp:49:39:49:45 | source1 | standalone_iterators.cpp:50:11:50:17 | source1 | |
|
||||||
| standalone_iterators.cpp:45:39:45:45 | source1 | standalone_iterators.cpp:47:12:47:18 | source1 | |
|
| standalone_iterators.cpp:49:39:49:45 | source1 | standalone_iterators.cpp:51:12:51:18 | source1 | |
|
||||||
| standalone_iterators.cpp:45:39:45:45 | source1 | standalone_iterators.cpp:48:14:48:20 | source1 | |
|
| standalone_iterators.cpp:49:39:49:45 | source1 | standalone_iterators.cpp:52:14:52:20 | source1 | |
|
||||||
| standalone_iterators.cpp:46:11:46:17 | source1 | standalone_iterators.cpp:46:10:46:10 | call to operator* | TAINT |
|
| standalone_iterators.cpp:50:11:50:17 | source1 | standalone_iterators.cpp:50:10:50:10 | call to operator* | TAINT |
|
||||||
| standalone_iterators.cpp:47:12:47:18 | ref arg source1 | standalone_iterators.cpp:45:39:45:45 | source1 | |
|
| standalone_iterators.cpp:51:12:51:18 | ref arg source1 | standalone_iterators.cpp:49:39:49:45 | source1 | |
|
||||||
| standalone_iterators.cpp:47:12:47:18 | ref arg source1 | standalone_iterators.cpp:48:14:48:20 | source1 | |
|
| standalone_iterators.cpp:51:12:51:18 | ref arg source1 | standalone_iterators.cpp:52:14:52:20 | source1 | |
|
||||||
| standalone_iterators.cpp:47:12:47:18 | source1 | standalone_iterators.cpp:47:19:47:19 | call to operator++ | |
|
| standalone_iterators.cpp:51:12:51:18 | source1 | standalone_iterators.cpp:51:19:51:19 | call to operator++ | |
|
||||||
| standalone_iterators.cpp:47:19:47:19 | call to operator++ | standalone_iterators.cpp:47:10:47:10 | call to operator* | TAINT |
|
| standalone_iterators.cpp:51:19:51:19 | call to operator++ | standalone_iterators.cpp:51:10:51:10 | call to operator* | TAINT |
|
||||||
| standalone_iterators.cpp:48:12:48:12 | call to operator++ | standalone_iterators.cpp:48:10:48:10 | call to operator* | TAINT |
|
| standalone_iterators.cpp:52:12:52:12 | call to operator++ | standalone_iterators.cpp:52:10:52:10 | call to operator* | TAINT |
|
||||||
| standalone_iterators.cpp:48:14:48:20 | ref arg source1 | standalone_iterators.cpp:45:39:45:45 | source1 | |
|
| standalone_iterators.cpp:52:14:52:20 | ref arg source1 | standalone_iterators.cpp:49:39:49:45 | source1 | |
|
||||||
| standalone_iterators.cpp:48:14:48:20 | source1 | standalone_iterators.cpp:48:12:48:12 | call to operator++ | |
|
| standalone_iterators.cpp:52:14:52:20 | source1 | standalone_iterators.cpp:52:12:52:12 | call to operator++ | |
|
||||||
| standalone_iterators.cpp:51:37:51:43 | source1 | standalone_iterators.cpp:52:11:52:17 | source1 | |
|
| standalone_iterators.cpp:55:37:55:43 | source1 | standalone_iterators.cpp:56:11:56:17 | source1 | |
|
||||||
| standalone_iterators.cpp:51:37:51:43 | source1 | standalone_iterators.cpp:53:12:53:18 | source1 | |
|
| standalone_iterators.cpp:55:37:55:43 | source1 | standalone_iterators.cpp:57:12:57:18 | source1 | |
|
||||||
| standalone_iterators.cpp:51:37:51:43 | source1 | standalone_iterators.cpp:54:14:54:20 | source1 | |
|
| standalone_iterators.cpp:55:37:55:43 | source1 | standalone_iterators.cpp:58:14:58:20 | source1 | |
|
||||||
| standalone_iterators.cpp:53:12:53:18 | ref arg source1 | standalone_iterators.cpp:54:14:54:20 | source1 | |
|
| standalone_iterators.cpp:57:12:57:18 | ref arg source1 | standalone_iterators.cpp:58:14:58:20 | source1 | |
|
||||||
| standalone_iterators.cpp:83:15:83:16 | call to container | standalone_iterators.cpp:85:35:85:36 | c1 | |
|
| standalone_iterators.cpp:91:15:91:16 | call to container | standalone_iterators.cpp:93:35:93:36 | c1 | |
|
||||||
| standalone_iterators.cpp:83:15:83:16 | call to container | standalone_iterators.cpp:87:10:87:11 | c1 | |
|
| standalone_iterators.cpp:91:15:91:16 | call to container | standalone_iterators.cpp:95:10:95:11 | c1 | |
|
||||||
| standalone_iterators.cpp:83:19:83:20 | call to container | standalone_iterators.cpp:89:35:89:36 | c2 | |
|
| standalone_iterators.cpp:91:19:91:20 | call to container | standalone_iterators.cpp:97:35:97:36 | c2 | |
|
||||||
| standalone_iterators.cpp:83:19:83:20 | call to container | standalone_iterators.cpp:91:10:91:11 | c2 | |
|
| standalone_iterators.cpp:91:19:91:20 | call to container | standalone_iterators.cpp:99:10:99:11 | c2 | |
|
||||||
| standalone_iterators.cpp:85:35:85:36 | c1 | standalone_iterators.cpp:85:38:85:42 | call to begin | TAINT |
|
| standalone_iterators.cpp:93:35:93:36 | c1 | standalone_iterators.cpp:93:38:93:42 | call to begin | TAINT |
|
||||||
| standalone_iterators.cpp:85:35:85:36 | ref arg c1 | standalone_iterators.cpp:87:10:87:11 | c1 | |
|
| standalone_iterators.cpp:93:35:93:36 | ref arg c1 | standalone_iterators.cpp:95:10:95:11 | c1 | |
|
||||||
| standalone_iterators.cpp:85:38:85:42 | call to begin | standalone_iterators.cpp:86:6:86:7 | i1 | |
|
| standalone_iterators.cpp:93:38:93:42 | call to begin | standalone_iterators.cpp:94:6:94:7 | i1 | |
|
||||||
| standalone_iterators.cpp:86:5:86:5 | ref arg call to operator* | standalone_iterators.cpp:86:8:86:8 | ref arg call to operator-- | TAINT |
|
| standalone_iterators.cpp:94:5:94:5 | ref arg call to operator* | standalone_iterators.cpp:94:8:94:8 | ref arg call to operator-- | TAINT |
|
||||||
| standalone_iterators.cpp:86:5:86:5 | ref arg call to operator* | standalone_iterators.cpp:87:10:87:11 | c1 | |
|
| standalone_iterators.cpp:94:5:94:5 | ref arg call to operator* | standalone_iterators.cpp:95:10:95:11 | c1 | |
|
||||||
| standalone_iterators.cpp:86:6:86:7 | i1 | standalone_iterators.cpp:86:8:86:8 | call to operator-- | |
|
| standalone_iterators.cpp:94:6:94:7 | i1 | standalone_iterators.cpp:94:8:94:8 | call to operator-- | |
|
||||||
| standalone_iterators.cpp:86:8:86:8 | call to operator-- | standalone_iterators.cpp:86:5:86:5 | call to operator* | TAINT |
|
| standalone_iterators.cpp:94:8:94:8 | call to operator-- | standalone_iterators.cpp:94:5:94:5 | call to operator* | TAINT |
|
||||||
| standalone_iterators.cpp:86:8:86:8 | ref arg call to operator-- | standalone_iterators.cpp:86:6:86:7 | ref arg i1 | |
|
| standalone_iterators.cpp:94:8:94:8 | ref arg call to operator-- | standalone_iterators.cpp:94:6:94:7 | ref arg i1 | |
|
||||||
| standalone_iterators.cpp:86:13:86:18 | call to source | standalone_iterators.cpp:86:5:86:5 | ref arg call to operator* | TAINT |
|
| standalone_iterators.cpp:94:13:94:18 | call to source | standalone_iterators.cpp:94:5:94:5 | ref arg call to operator* | TAINT |
|
||||||
| standalone_iterators.cpp:89:35:89:36 | c2 | standalone_iterators.cpp:89:38:89:42 | call to begin | TAINT |
|
| standalone_iterators.cpp:97:35:97:36 | c2 | standalone_iterators.cpp:97:38:97:42 | call to begin | TAINT |
|
||||||
| standalone_iterators.cpp:89:35:89:36 | ref arg c2 | standalone_iterators.cpp:91:10:91:11 | c2 | |
|
| standalone_iterators.cpp:97:35:97:36 | ref arg c2 | standalone_iterators.cpp:99:10:99:11 | c2 | |
|
||||||
| standalone_iterators.cpp:89:38:89:42 | call to begin | standalone_iterators.cpp:90:6:90:7 | i2 | |
|
| standalone_iterators.cpp:97:38:97:42 | call to begin | standalone_iterators.cpp:98:6:98:7 | i2 | |
|
||||||
| standalone_iterators.cpp:90:5:90:5 | ref arg call to operator* | standalone_iterators.cpp:90:8:90:8 | ref arg call to operator-- | TAINT |
|
| standalone_iterators.cpp:98:5:98:5 | ref arg call to operator* | standalone_iterators.cpp:98:8:98:8 | ref arg call to operator-- | TAINT |
|
||||||
| standalone_iterators.cpp:90:5:90:5 | ref arg call to operator* | standalone_iterators.cpp:91:10:91:11 | c2 | |
|
| standalone_iterators.cpp:98:5:98:5 | ref arg call to operator* | standalone_iterators.cpp:99:10:99:11 | c2 | |
|
||||||
| standalone_iterators.cpp:90:6:90:7 | i2 | standalone_iterators.cpp:90:8:90:8 | call to operator-- | |
|
| standalone_iterators.cpp:98:6:98:7 | i2 | standalone_iterators.cpp:98:8:98:8 | call to operator-- | |
|
||||||
| standalone_iterators.cpp:90:8:90:8 | call to operator-- | standalone_iterators.cpp:90:5:90:5 | call to operator* | TAINT |
|
| standalone_iterators.cpp:98:8:98:8 | call to operator-- | standalone_iterators.cpp:98:5:98:5 | call to operator* | TAINT |
|
||||||
| standalone_iterators.cpp:90:8:90:8 | ref arg call to operator-- | standalone_iterators.cpp:90:6:90:7 | ref arg i2 | |
|
| standalone_iterators.cpp:98:8:98:8 | ref arg call to operator-- | standalone_iterators.cpp:98:6:98:7 | ref arg i2 | |
|
||||||
| standalone_iterators.cpp:90:13:90:13 | 0 | standalone_iterators.cpp:90:5:90:5 | ref arg call to operator* | TAINT |
|
| standalone_iterators.cpp:98:13:98:13 | 0 | standalone_iterators.cpp:98:5:98:5 | ref arg call to operator* | TAINT |
|
||||||
| standalone_iterators.cpp:98:15:98:16 | call to container | standalone_iterators.cpp:101:6:101:7 | c1 | |
|
| standalone_iterators.cpp:106:15:106:16 | call to container | standalone_iterators.cpp:109:6:109:7 | c1 | |
|
||||||
| standalone_iterators.cpp:98:15:98:16 | call to container | standalone_iterators.cpp:102:6:102:7 | c1 | |
|
| standalone_iterators.cpp:106:15:106:16 | call to container | standalone_iterators.cpp:110:6:110:7 | c1 | |
|
||||||
| standalone_iterators.cpp:98:15:98:16 | call to container | standalone_iterators.cpp:106:6:106:7 | c1 | |
|
| standalone_iterators.cpp:106:15:106:16 | call to container | standalone_iterators.cpp:114:6:114:7 | c1 | |
|
||||||
| standalone_iterators.cpp:98:15:98:16 | call to container | standalone_iterators.cpp:109:7:109:8 | c1 | |
|
| standalone_iterators.cpp:106:15:106:16 | call to container | standalone_iterators.cpp:117:7:117:8 | c1 | |
|
||||||
| standalone_iterators.cpp:101:6:101:7 | c1 | standalone_iterators.cpp:101:9:101:13 | call to begin | TAINT |
|
| standalone_iterators.cpp:109:6:109:7 | c1 | standalone_iterators.cpp:109:9:109:13 | call to begin | TAINT |
|
||||||
| standalone_iterators.cpp:101:6:101:7 | ref arg c1 | standalone_iterators.cpp:102:6:102:7 | c1 | |
|
| standalone_iterators.cpp:109:6:109:7 | ref arg c1 | standalone_iterators.cpp:110:6:110:7 | c1 | |
|
||||||
| standalone_iterators.cpp:101:6:101:7 | ref arg c1 | standalone_iterators.cpp:106:6:106:7 | c1 | |
|
| standalone_iterators.cpp:109:6:109:7 | ref arg c1 | standalone_iterators.cpp:114:6:114:7 | c1 | |
|
||||||
| standalone_iterators.cpp:101:6:101:7 | ref arg c1 | standalone_iterators.cpp:109:7:109:8 | c1 | |
|
| standalone_iterators.cpp:109:6:109:7 | ref arg c1 | standalone_iterators.cpp:117:7:117:8 | c1 | |
|
||||||
| standalone_iterators.cpp:101:9:101:13 | call to begin | standalone_iterators.cpp:101:2:101:15 | ... = ... | |
|
| standalone_iterators.cpp:109:9:109:13 | call to begin | standalone_iterators.cpp:109:2:109:15 | ... = ... | |
|
||||||
| standalone_iterators.cpp:101:9:101:13 | call to begin | standalone_iterators.cpp:103:3:103:3 | a | |
|
| standalone_iterators.cpp:109:9:109:13 | call to begin | standalone_iterators.cpp:111:3:111:3 | a | |
|
||||||
| standalone_iterators.cpp:101:9:101:13 | call to begin | standalone_iterators.cpp:104:7:104:7 | a | |
|
| standalone_iterators.cpp:109:9:109:13 | call to begin | standalone_iterators.cpp:112:7:112:7 | a | |
|
||||||
| standalone_iterators.cpp:102:6:102:7 | c1 | standalone_iterators.cpp:102:9:102:13 | call to begin | TAINT |
|
| standalone_iterators.cpp:110:6:110:7 | c1 | standalone_iterators.cpp:110:9:110:13 | call to begin | TAINT |
|
||||||
| standalone_iterators.cpp:102:6:102:7 | ref arg c1 | standalone_iterators.cpp:106:6:106:7 | c1 | |
|
| standalone_iterators.cpp:110:6:110:7 | ref arg c1 | standalone_iterators.cpp:114:6:114:7 | c1 | |
|
||||||
| standalone_iterators.cpp:102:6:102:7 | ref arg c1 | standalone_iterators.cpp:109:7:109:8 | c1 | |
|
| standalone_iterators.cpp:110:6:110:7 | ref arg c1 | standalone_iterators.cpp:117:7:117:8 | c1 | |
|
||||||
| standalone_iterators.cpp:102:9:102:13 | call to begin | standalone_iterators.cpp:102:2:102:15 | ... = ... | |
|
| standalone_iterators.cpp:110:9:110:13 | call to begin | standalone_iterators.cpp:110:2:110:15 | ... = ... | |
|
||||||
| standalone_iterators.cpp:102:9:102:13 | call to begin | standalone_iterators.cpp:107:7:107:7 | b | |
|
| standalone_iterators.cpp:110:9:110:13 | call to begin | standalone_iterators.cpp:115:7:115:7 | b | |
|
||||||
| standalone_iterators.cpp:103:2:103:2 | ref arg call to operator* | standalone_iterators.cpp:103:3:103:3 | ref arg a | TAINT |
|
| standalone_iterators.cpp:111:2:111:2 | ref arg call to operator* | standalone_iterators.cpp:111:3:111:3 | ref arg a | TAINT |
|
||||||
| standalone_iterators.cpp:103:2:103:2 | ref arg call to operator* | standalone_iterators.cpp:106:6:106:7 | c1 | |
|
| standalone_iterators.cpp:111:2:111:2 | ref arg call to operator* | standalone_iterators.cpp:114:6:114:7 | c1 | |
|
||||||
| standalone_iterators.cpp:103:2:103:2 | ref arg call to operator* | standalone_iterators.cpp:109:7:109:8 | c1 | |
|
| standalone_iterators.cpp:111:2:111:2 | ref arg call to operator* | standalone_iterators.cpp:117:7:117:8 | c1 | |
|
||||||
| standalone_iterators.cpp:103:3:103:3 | a | standalone_iterators.cpp:103:2:103:2 | call to operator* | TAINT |
|
| standalone_iterators.cpp:111:3:111:3 | a | standalone_iterators.cpp:111:2:111:2 | call to operator* | TAINT |
|
||||||
| standalone_iterators.cpp:103:3:103:3 | ref arg a | standalone_iterators.cpp:104:7:104:7 | a | |
|
| standalone_iterators.cpp:111:3:111:3 | ref arg a | standalone_iterators.cpp:112:7:112:7 | a | |
|
||||||
| standalone_iterators.cpp:103:7:103:12 | call to source | standalone_iterators.cpp:103:2:103:2 | ref arg call to operator* | TAINT |
|
| standalone_iterators.cpp:111:7:111:12 | call to source | standalone_iterators.cpp:111:2:111:2 | ref arg call to operator* | TAINT |
|
||||||
| standalone_iterators.cpp:104:7:104:7 | a [post update] | standalone_iterators.cpp:106:6:106:7 | c1 | |
|
| standalone_iterators.cpp:112:7:112:7 | a [post update] | standalone_iterators.cpp:114:6:114:7 | c1 | |
|
||||||
| standalone_iterators.cpp:104:7:104:7 | a [post update] | standalone_iterators.cpp:109:7:109:8 | c1 | |
|
| standalone_iterators.cpp:112:7:112:7 | a [post update] | standalone_iterators.cpp:117:7:117:8 | c1 | |
|
||||||
| standalone_iterators.cpp:106:6:106:7 | c1 | standalone_iterators.cpp:106:9:106:13 | call to begin | TAINT |
|
| standalone_iterators.cpp:114:6:114:7 | c1 | standalone_iterators.cpp:114:9:114:13 | call to begin | TAINT |
|
||||||
| standalone_iterators.cpp:106:6:106:7 | ref arg c1 | standalone_iterators.cpp:109:7:109:8 | c1 | |
|
| standalone_iterators.cpp:114:6:114:7 | ref arg c1 | standalone_iterators.cpp:117:7:117:8 | c1 | |
|
||||||
| standalone_iterators.cpp:106:9:106:13 | call to begin | standalone_iterators.cpp:106:2:106:15 | ... = ... | |
|
| standalone_iterators.cpp:114:9:114:13 | call to begin | standalone_iterators.cpp:114:2:114:15 | ... = ... | |
|
||||||
| standalone_iterators.cpp:106:9:106:13 | call to begin | standalone_iterators.cpp:108:7:108:7 | c | |
|
| standalone_iterators.cpp:114:9:114:13 | call to begin | standalone_iterators.cpp:116:7:116:7 | c | |
|
||||||
| standalone_iterators.cpp:107:7:107:7 | b [post update] | standalone_iterators.cpp:109:7:109:8 | c1 | |
|
| standalone_iterators.cpp:115:7:115:7 | b [post update] | standalone_iterators.cpp:117:7:117:8 | c1 | |
|
||||||
| standalone_iterators.cpp:108:7:108:7 | c [post update] | standalone_iterators.cpp:109:7:109:8 | c1 | |
|
| standalone_iterators.cpp:116:7:116:7 | c [post update] | standalone_iterators.cpp:117:7:117:8 | c1 | |
|
||||||
| standalone_iterators.cpp:113:15:113:16 | call to container | standalone_iterators.cpp:116:7:116:8 | c1 | |
|
| standalone_iterators.cpp:121:15:121:16 | call to container | standalone_iterators.cpp:124:7:124:8 | c1 | |
|
||||||
| standalone_iterators.cpp:113:15:113:16 | call to container | standalone_iterators.cpp:122:7:122:8 | c1 | |
|
| standalone_iterators.cpp:121:15:121:16 | call to container | standalone_iterators.cpp:130:7:130:8 | c1 | |
|
||||||
| standalone_iterators.cpp:116:7:116:8 | c1 | standalone_iterators.cpp:116:10:116:14 | call to begin | TAINT |
|
| standalone_iterators.cpp:124:7:124:8 | c1 | standalone_iterators.cpp:124:10:124:14 | call to begin | TAINT |
|
||||||
| standalone_iterators.cpp:116:7:116:8 | ref arg c1 | standalone_iterators.cpp:122:7:122:8 | c1 | |
|
| standalone_iterators.cpp:124:7:124:8 | ref arg c1 | standalone_iterators.cpp:130:7:130:8 | c1 | |
|
||||||
| standalone_iterators.cpp:116:10:116:14 | call to begin | standalone_iterators.cpp:116:2:116:16 | ... = ... | |
|
| standalone_iterators.cpp:124:10:124:14 | call to begin | standalone_iterators.cpp:124:2:124:16 | ... = ... | |
|
||||||
| standalone_iterators.cpp:116:10:116:14 | call to begin | standalone_iterators.cpp:117:7:117:8 | it | |
|
| standalone_iterators.cpp:124:10:124:14 | call to begin | standalone_iterators.cpp:125:7:125:8 | it | |
|
||||||
| standalone_iterators.cpp:116:10:116:14 | call to begin | standalone_iterators.cpp:118:2:118:3 | it | |
|
| standalone_iterators.cpp:124:10:124:14 | call to begin | standalone_iterators.cpp:126:2:126:3 | it | |
|
||||||
| standalone_iterators.cpp:116:10:116:14 | call to begin | standalone_iterators.cpp:119:7:119:8 | it | |
|
| standalone_iterators.cpp:124:10:124:14 | call to begin | standalone_iterators.cpp:127:7:127:8 | it | |
|
||||||
| standalone_iterators.cpp:116:10:116:14 | call to begin | standalone_iterators.cpp:120:2:120:3 | it | |
|
| standalone_iterators.cpp:124:10:124:14 | call to begin | standalone_iterators.cpp:128:2:128:3 | it | |
|
||||||
| standalone_iterators.cpp:116:10:116:14 | call to begin | standalone_iterators.cpp:121:7:121:8 | it | |
|
| standalone_iterators.cpp:124:10:124:14 | call to begin | standalone_iterators.cpp:129:7:129:8 | it | |
|
||||||
| standalone_iterators.cpp:117:7:117:8 | it [post update] | standalone_iterators.cpp:122:7:122:8 | c1 | |
|
| standalone_iterators.cpp:125:7:125:8 | it [post update] | standalone_iterators.cpp:130:7:130:8 | c1 | |
|
||||||
| standalone_iterators.cpp:118:2:118:3 | it | standalone_iterators.cpp:118:5:118:5 | call to operator+= | TAINT |
|
| standalone_iterators.cpp:126:2:126:3 | it | standalone_iterators.cpp:126:5:126:5 | call to operator+= | TAINT |
|
||||||
| standalone_iterators.cpp:118:2:118:3 | ref arg it | standalone_iterators.cpp:119:7:119:8 | it | |
|
| standalone_iterators.cpp:126:2:126:3 | ref arg it | standalone_iterators.cpp:127:7:127:8 | it | |
|
||||||
| standalone_iterators.cpp:118:2:118:3 | ref arg it | standalone_iterators.cpp:120:2:120:3 | it | |
|
| standalone_iterators.cpp:126:2:126:3 | ref arg it | standalone_iterators.cpp:128:2:128:3 | it | |
|
||||||
| standalone_iterators.cpp:118:2:118:3 | ref arg it | standalone_iterators.cpp:121:7:121:8 | it | |
|
| standalone_iterators.cpp:126:2:126:3 | ref arg it | standalone_iterators.cpp:129:7:129:8 | it | |
|
||||||
| standalone_iterators.cpp:118:2:118:3 | ref arg it | standalone_iterators.cpp:122:7:122:8 | c1 | |
|
| standalone_iterators.cpp:126:2:126:3 | ref arg it | standalone_iterators.cpp:130:7:130:8 | c1 | |
|
||||||
| standalone_iterators.cpp:118:8:118:8 | 1 | standalone_iterators.cpp:118:2:118:3 | ref arg it | TAINT |
|
| standalone_iterators.cpp:126:8:126:8 | 1 | standalone_iterators.cpp:126:2:126:3 | ref arg it | TAINT |
|
||||||
| standalone_iterators.cpp:120:2:120:3 | it | standalone_iterators.cpp:120:5:120:5 | call to operator+= | TAINT |
|
| standalone_iterators.cpp:128:2:128:3 | it | standalone_iterators.cpp:128:5:128:5 | call to operator+= | TAINT |
|
||||||
| standalone_iterators.cpp:120:2:120:3 | ref arg it | standalone_iterators.cpp:121:7:121:8 | it | |
|
| standalone_iterators.cpp:128:2:128:3 | ref arg it | standalone_iterators.cpp:129:7:129:8 | it | |
|
||||||
| standalone_iterators.cpp:120:8:120:13 | call to source | standalone_iterators.cpp:120:2:120:3 | ref arg it | TAINT |
|
| standalone_iterators.cpp:128:8:128:13 | call to source | standalone_iterators.cpp:128:2:128:3 | ref arg it | TAINT |
|
||||||
| stl.h:75:8:75:8 | container | stl.h:75:8:75:8 | constructor init of field container | TAINT |
|
| stl.h:75:8:75:8 | container | stl.h:75:8:75:8 | constructor init of field container | TAINT |
|
||||||
| stl.h:75:8:75:8 | container | stl.h:75:8:75:8 | constructor init of field container | TAINT |
|
| stl.h:75:8:75:8 | container | stl.h:75:8:75:8 | constructor init of field container | TAINT |
|
||||||
| stl.h:75:8:75:8 | container | stl.h:75:8:75:8 | container | |
|
| stl.h:75:8:75:8 | container | stl.h:75:8:75:8 | container | |
|
||||||
|
|||||||
@@ -27,6 +27,10 @@ public:
|
|||||||
template<>
|
template<>
|
||||||
struct std::iterator_traits<int_iterator_by_trait> {
|
struct std::iterator_traits<int_iterator_by_trait> {
|
||||||
typedef input_iterator_tag iterator_category;
|
typedef input_iterator_tag iterator_category;
|
||||||
|
typedef int value_type;
|
||||||
|
typedef size_t difference_type;
|
||||||
|
typedef int* pointer;
|
||||||
|
typedef int& reference;
|
||||||
};
|
};
|
||||||
|
|
||||||
class non_iterator {
|
class non_iterator {
|
||||||
@@ -69,6 +73,10 @@ public:
|
|||||||
template<>
|
template<>
|
||||||
struct std::iterator_traits<insert_iterator_by_trait> {
|
struct std::iterator_traits<insert_iterator_by_trait> {
|
||||||
typedef output_iterator_tag iterator_category;
|
typedef output_iterator_tag iterator_category;
|
||||||
|
typedef int value_type;
|
||||||
|
typedef size_t difference_type;
|
||||||
|
typedef int* pointer;
|
||||||
|
typedef int& reference;
|
||||||
};
|
};
|
||||||
|
|
||||||
class container {
|
class container {
|
||||||
|
|||||||
@@ -168,4 +168,34 @@ int main(int argc, char **argv) {
|
|||||||
int i10 = (int) argv[1];
|
int i10 = (int) argv[1];
|
||||||
printf((char *) i10);
|
printf((char *) i10);
|
||||||
printWrapper((char *) i10);
|
printWrapper((char *) i10);
|
||||||
|
|
||||||
|
// BAD: b value comes from argv
|
||||||
|
{
|
||||||
|
char b[64];
|
||||||
|
char *bp = &b[0];
|
||||||
|
char *t;
|
||||||
|
if (0) {
|
||||||
|
t = 0;
|
||||||
|
} else {
|
||||||
|
t = bp;
|
||||||
|
}
|
||||||
|
memcpy(t, argv[1] + 1, 1);
|
||||||
|
printf(bp);
|
||||||
|
printWrapper(bp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// BAD: b value comes from argv
|
||||||
|
{
|
||||||
|
char b[64];
|
||||||
|
char *bp = &b[0];
|
||||||
|
char *t;
|
||||||
|
if (1) {
|
||||||
|
t = ++bp;
|
||||||
|
} else {
|
||||||
|
t = 0;
|
||||||
|
}
|
||||||
|
memcpy(t, argv[1] + 1, 1);
|
||||||
|
printf(bp);
|
||||||
|
printWrapper(bp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -260,6 +260,30 @@ edges
|
|||||||
| argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:24:170:26 | i10 |
|
| argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:24:170:26 | i10 |
|
||||||
| argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:24:170:26 | i10 |
|
| argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:24:170:26 | i10 |
|
||||||
| argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:24:170:26 | i10 |
|
| argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:24:170:26 | i10 |
|
||||||
|
| argvLocal.c:182:13:182:16 | argv | argvLocal.c:183:10:183:11 | (const char *)... |
|
||||||
|
| argvLocal.c:182:13:182:16 | argv | argvLocal.c:183:10:183:11 | (const char *)... |
|
||||||
|
| argvLocal.c:182:13:182:16 | argv | argvLocal.c:183:10:183:11 | bp |
|
||||||
|
| argvLocal.c:182:13:182:16 | argv | argvLocal.c:183:10:183:11 | bp |
|
||||||
|
| argvLocal.c:182:13:182:16 | argv | argvLocal.c:183:10:183:11 | bp indirection |
|
||||||
|
| argvLocal.c:182:13:182:16 | argv | argvLocal.c:183:10:183:11 | bp indirection |
|
||||||
|
| argvLocal.c:182:13:182:16 | argv | argvLocal.c:184:16:184:17 | bp |
|
||||||
|
| argvLocal.c:182:13:182:16 | argv | argvLocal.c:184:16:184:17 | bp |
|
||||||
|
| argvLocal.c:182:13:182:16 | argv | argvLocal.c:184:16:184:17 | bp |
|
||||||
|
| argvLocal.c:182:13:182:16 | argv | argvLocal.c:184:16:184:17 | bp |
|
||||||
|
| argvLocal.c:182:13:182:16 | argv | argvLocal.c:184:16:184:17 | bp indirection |
|
||||||
|
| argvLocal.c:182:13:182:16 | argv | argvLocal.c:184:16:184:17 | bp indirection |
|
||||||
|
| argvLocal.c:197:13:197:16 | argv | argvLocal.c:198:10:198:11 | (const char *)... |
|
||||||
|
| argvLocal.c:197:13:197:16 | argv | argvLocal.c:198:10:198:11 | (const char *)... |
|
||||||
|
| argvLocal.c:197:13:197:16 | argv | argvLocal.c:198:10:198:11 | bp |
|
||||||
|
| argvLocal.c:197:13:197:16 | argv | argvLocal.c:198:10:198:11 | bp |
|
||||||
|
| argvLocal.c:197:13:197:16 | argv | argvLocal.c:198:10:198:11 | bp indirection |
|
||||||
|
| argvLocal.c:197:13:197:16 | argv | argvLocal.c:198:10:198:11 | bp indirection |
|
||||||
|
| argvLocal.c:197:13:197:16 | argv | argvLocal.c:199:16:199:17 | bp |
|
||||||
|
| argvLocal.c:197:13:197:16 | argv | argvLocal.c:199:16:199:17 | bp |
|
||||||
|
| argvLocal.c:197:13:197:16 | argv | argvLocal.c:199:16:199:17 | bp |
|
||||||
|
| argvLocal.c:197:13:197:16 | argv | argvLocal.c:199:16:199:17 | bp |
|
||||||
|
| argvLocal.c:197:13:197:16 | argv | argvLocal.c:199:16:199:17 | bp indirection |
|
||||||
|
| argvLocal.c:197:13:197:16 | argv | argvLocal.c:199:16:199:17 | bp indirection |
|
||||||
subpaths
|
subpaths
|
||||||
| argvLocal.c:102:15:102:16 | i1 indirection | argvLocal.c:9:25:9:31 | *correct | argvLocal.c:9:25:9:31 | ReturnIndirection | argvLocal.c:102:15:102:16 | printWrapper output argument |
|
| argvLocal.c:102:15:102:16 | i1 indirection | argvLocal.c:9:25:9:31 | *correct | argvLocal.c:9:25:9:31 | ReturnIndirection | argvLocal.c:102:15:102:16 | printWrapper output argument |
|
||||||
| argvLocal.c:107:15:107:19 | access to array indirection | argvLocal.c:9:25:9:31 | *correct | argvLocal.c:9:25:9:31 | ReturnIndirection | argvLocal.c:107:15:107:19 | printWrapper output argument |
|
| argvLocal.c:107:15:107:19 | access to array indirection | argvLocal.c:9:25:9:31 | *correct | argvLocal.c:9:25:9:31 | ReturnIndirection | argvLocal.c:107:15:107:19 | printWrapper output argument |
|
||||||
@@ -396,6 +420,22 @@ nodes
|
|||||||
| argvLocal.c:170:15:170:26 | i10 indirection | semmle.label | i10 indirection |
|
| argvLocal.c:170:15:170:26 | i10 indirection | semmle.label | i10 indirection |
|
||||||
| argvLocal.c:170:24:170:26 | i10 | semmle.label | i10 |
|
| argvLocal.c:170:24:170:26 | i10 | semmle.label | i10 |
|
||||||
| argvLocal.c:170:24:170:26 | i10 | semmle.label | i10 |
|
| argvLocal.c:170:24:170:26 | i10 | semmle.label | i10 |
|
||||||
|
| argvLocal.c:182:13:182:16 | argv | semmle.label | argv |
|
||||||
|
| argvLocal.c:182:13:182:16 | argv | semmle.label | argv |
|
||||||
|
| argvLocal.c:183:10:183:11 | (const char *)... | semmle.label | (const char *)... |
|
||||||
|
| argvLocal.c:183:10:183:11 | bp | semmle.label | bp |
|
||||||
|
| argvLocal.c:183:10:183:11 | bp indirection | semmle.label | bp indirection |
|
||||||
|
| argvLocal.c:184:16:184:17 | bp | semmle.label | bp |
|
||||||
|
| argvLocal.c:184:16:184:17 | bp | semmle.label | bp |
|
||||||
|
| argvLocal.c:184:16:184:17 | bp indirection | semmle.label | bp indirection |
|
||||||
|
| argvLocal.c:197:13:197:16 | argv | semmle.label | argv |
|
||||||
|
| argvLocal.c:197:13:197:16 | argv | semmle.label | argv |
|
||||||
|
| argvLocal.c:198:10:198:11 | (const char *)... | semmle.label | (const char *)... |
|
||||||
|
| argvLocal.c:198:10:198:11 | bp | semmle.label | bp |
|
||||||
|
| argvLocal.c:198:10:198:11 | bp indirection | semmle.label | bp indirection |
|
||||||
|
| argvLocal.c:199:16:199:17 | bp | semmle.label | bp |
|
||||||
|
| argvLocal.c:199:16:199:17 | bp | semmle.label | bp |
|
||||||
|
| argvLocal.c:199:16:199:17 | bp indirection | semmle.label | bp indirection |
|
||||||
#select
|
#select
|
||||||
| argvLocal.c:95:9:95:15 | access to array | argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | access to array | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | argvLocal.c:95:9:95:12 | argv | argv |
|
| argvLocal.c:95:9:95:15 | access to array | argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | access to array | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | argvLocal.c:95:9:95:12 | argv | argv |
|
||||||
| argvLocal.c:96:15:96:21 | access to array | argvLocal.c:96:15:96:18 | argv | argvLocal.c:96:15:96:21 | access to array | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:96:15:96:18 | argv | argv |
|
| argvLocal.c:96:15:96:21 | access to array | argvLocal.c:96:15:96:18 | argv | argvLocal.c:96:15:96:21 | access to array | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:96:15:96:18 | argv | argv |
|
||||||
@@ -425,3 +465,7 @@ nodes
|
|||||||
| argvLocal.c:165:15:165:17 | i91 | argvLocal.c:163:22:163:25 | argv | argvLocal.c:165:15:165:17 | i91 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:163:22:163:25 | argv | argv |
|
| argvLocal.c:165:15:165:17 | i91 | argvLocal.c:163:22:163:25 | argv | argvLocal.c:165:15:165:17 | i91 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:163:22:163:25 | argv | argv |
|
||||||
| argvLocal.c:169:18:169:20 | i10 | argvLocal.c:168:18:168:21 | argv | argvLocal.c:169:18:169:20 | i10 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | argvLocal.c:168:18:168:21 | argv | argv |
|
| argvLocal.c:169:18:169:20 | i10 | argvLocal.c:168:18:168:21 | argv | argvLocal.c:169:18:169:20 | i10 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | argvLocal.c:168:18:168:21 | argv | argv |
|
||||||
| argvLocal.c:170:24:170:26 | i10 | argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:24:170:26 | i10 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:168:18:168:21 | argv | argv |
|
| argvLocal.c:170:24:170:26 | i10 | argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:24:170:26 | i10 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:168:18:168:21 | argv | argv |
|
||||||
|
| argvLocal.c:183:10:183:11 | bp | argvLocal.c:182:13:182:16 | argv | argvLocal.c:183:10:183:11 | bp | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | argvLocal.c:182:13:182:16 | argv | argv |
|
||||||
|
| argvLocal.c:184:16:184:17 | bp | argvLocal.c:182:13:182:16 | argv | argvLocal.c:184:16:184:17 | bp | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:182:13:182:16 | argv | argv |
|
||||||
|
| argvLocal.c:198:10:198:11 | bp | argvLocal.c:197:13:197:16 | argv | argvLocal.c:198:10:198:11 | bp | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | argvLocal.c:197:13:197:16 | argv | argv |
|
||||||
|
| argvLocal.c:199:16:199:17 | bp | argvLocal.c:197:13:197:16 | argv | argvLocal.c:199:16:199:17 | bp | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:197:13:197:16 | argv | argv |
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ runs:
|
|||||||
- name: Setup dotnet
|
- name: Setup dotnet
|
||||||
uses: actions/setup-dotnet@v3
|
uses: actions/setup-dotnet@v3
|
||||||
with:
|
with:
|
||||||
dotnet-version: 6.0.202
|
dotnet-version: 7.0.102
|
||||||
- name: Build Extractor
|
- name: Build Extractor
|
||||||
shell: bash
|
shell: bash
|
||||||
run: scripts/create-extractor-pack.sh
|
run: scripts/create-extractor-pack.sh
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||||
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
<AssemblyName>Semmle.Autobuild.CSharp</AssemblyName>
|
<AssemblyName>Semmle.Autobuild.CSharp</AssemblyName>
|
||||||
<RootNamespace>Semmle.Autobuild.CSharp</RootNamespace>
|
<RootNamespace>Semmle.Autobuild.CSharp</RootNamespace>
|
||||||
<ApplicationIcon/>
|
<ApplicationIcon/>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
<AssemblyName>Semmle.Autobuild.Shared</AssemblyName>
|
<AssemblyName>Semmle.Autobuild.Shared</AssemblyName>
|
||||||
<RootNamespace>Semmle.Autobuild.Shared</RootNamespace>
|
<RootNamespace>Semmle.Autobuild.Shared</RootNamespace>
|
||||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
class Expression extends @expr {
|
||||||
|
string toString() { none() }
|
||||||
|
}
|
||||||
|
|
||||||
|
class TypeOrRef extends @type_or_ref {
|
||||||
|
string toString() { none() }
|
||||||
|
}
|
||||||
|
|
||||||
|
from Expression e, int k, int kind, TypeOrRef t
|
||||||
|
where
|
||||||
|
expressions(e, k, t) and
|
||||||
|
if k = 135 then kind = 106 else kind = k
|
||||||
|
select e, kind, t
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,3 @@
|
|||||||
|
description: Remove UTF-8 expression kind.
|
||||||
|
compatibility: backwards
|
||||||
|
expressions.rel: run expressions.qlo
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
class AnnotatedElement extends @cil_has_type_annotation {
|
||||||
|
string toString() { none() }
|
||||||
|
}
|
||||||
|
|
||||||
|
class Field extends @cil_field {
|
||||||
|
string toString() { none() }
|
||||||
|
}
|
||||||
|
|
||||||
|
from AnnotatedElement element, int annotation
|
||||||
|
where cil_type_annotation(element, annotation) and not element instanceof Field
|
||||||
|
select element, annotation
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
|||||||
|
class AnnotatedElement extends @has_type_annotation {
|
||||||
|
string toString() { none() }
|
||||||
|
}
|
||||||
|
|
||||||
|
class Field extends @field {
|
||||||
|
string toString() { none() }
|
||||||
|
}
|
||||||
|
|
||||||
|
from AnnotatedElement element, int annotation
|
||||||
|
where type_annotation(element, annotation) and not element instanceof Field
|
||||||
|
select element, annotation
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
description: Remove CIL fields as entities that can have type annotations and remove field type annotations.
|
||||||
|
compatibility: backwards
|
||||||
|
cil_type_annotation.rel: run cil_type_annotation.qlo
|
||||||
|
type_annotation.rel: run type_annotation.qlo
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
<AssemblyName>Semmle.Extraction.CIL.Driver</AssemblyName>
|
<AssemblyName>Semmle.Extraction.CIL.Driver</AssemblyName>
|
||||||
<RootNamespace>Semmle.Extraction.CIL.Driver</RootNamespace>
|
<RootNamespace>Semmle.Extraction.CIL.Driver</RootNamespace>
|
||||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
|
||||||
using Microsoft.CodeAnalysis;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace Semmle.Extraction.CIL.Entities
|
namespace Semmle.Extraction.CIL.Entities
|
||||||
{
|
{
|
||||||
@@ -38,6 +35,11 @@ namespace Semmle.Extraction.CIL.Entities
|
|||||||
t = mt.Unmodified;
|
t = mt.Unmodified;
|
||||||
yield return Tuples.cil_custom_modifiers(this, mt.Modifier, mt.IsRequired);
|
yield return Tuples.cil_custom_modifiers(this, mt.Modifier, mt.IsRequired);
|
||||||
}
|
}
|
||||||
|
if (t is ByRefType brt)
|
||||||
|
{
|
||||||
|
t = brt.ElementType;
|
||||||
|
yield return Tuples.cil_type_annotation(this, TypeAnnotation.Ref);
|
||||||
|
}
|
||||||
yield return Tuples.cil_field(this, DeclaringType, Name, t);
|
yield return Tuples.cil_field(this, DeclaringType, Name, t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
<AssemblyName>Semmle.Extraction.CIL</AssemblyName>
|
<AssemblyName>Semmle.Extraction.CIL</AssemblyName>
|
||||||
<RootNamespace>Semmle.Extraction.CIL</RootNamespace>
|
<RootNamespace>Semmle.Extraction.CIL</RootNamespace>
|
||||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
<AssemblyName>Semmle.Extraction.CSharp.Driver</AssemblyName>
|
<AssemblyName>Semmle.Extraction.CSharp.Driver</AssemblyName>
|
||||||
<RootNamespace>Semmle.Extraction.CSharp.Driver</RootNamespace>
|
<RootNamespace>Semmle.Extraction.CSharp.Driver</RootNamespace>
|
||||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
<AssemblyName>Semmle.Extraction.CSharp.Standalone</AssemblyName>
|
<AssemblyName>Semmle.Extraction.CSharp.Standalone</AssemblyName>
|
||||||
<RootNamespace>Semmle.Extraction.CSharp.Standalone</RootNamespace>
|
<RootNamespace>Semmle.Extraction.CSharp.Standalone</RootNamespace>
|
||||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ using Microsoft.CodeAnalysis;
|
|||||||
using Microsoft.CodeAnalysis.CSharp;
|
using Microsoft.CodeAnalysis.CSharp;
|
||||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||||
using Semmle.Extraction.CSharp.Populators;
|
using Semmle.Extraction.CSharp.Populators;
|
||||||
using Semmle.Extraction.Entities;
|
|
||||||
using Semmle.Extraction.Kinds;
|
using Semmle.Extraction.Kinds;
|
||||||
|
|
||||||
namespace Semmle.Extraction.CSharp.Entities
|
namespace Semmle.Extraction.CSharp.Entities
|
||||||
@@ -107,6 +106,11 @@ namespace Semmle.Extraction.CSharp.Entities
|
|||||||
return Expression.ValueAsString(val);
|
return Expression.ValueAsString(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (TryGetStringValueFromUtf8Literal(out var s))
|
||||||
|
{
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -181,6 +185,17 @@ namespace Semmle.Extraction.CSharp.Entities
|
|||||||
return isTrue || isFalse;
|
return isTrue || isFalse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool TryGetStringValueFromUtf8Literal(out string? value)
|
||||||
|
{
|
||||||
|
value = null;
|
||||||
|
if (Node.IsKind(SyntaxKind.Utf8StringLiteralExpression) && Node is LiteralExpressionSyntax literal)
|
||||||
|
{
|
||||||
|
value = literal.Token.ValueText;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public bool IsBoolLiteral()
|
public bool IsBoolLiteral()
|
||||||
{
|
{
|
||||||
return TryGetBoolValueFromLiteral(out var _);
|
return TryGetBoolValueFromLiteral(out var _);
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
|||||||
case SyntaxKind.FalseLiteralExpression:
|
case SyntaxKind.FalseLiteralExpression:
|
||||||
case SyntaxKind.TrueLiteralExpression:
|
case SyntaxKind.TrueLiteralExpression:
|
||||||
case SyntaxKind.StringLiteralExpression:
|
case SyntaxKind.StringLiteralExpression:
|
||||||
|
case SyntaxKind.Utf8StringLiteralExpression:
|
||||||
case SyntaxKind.NullLiteralExpression:
|
case SyntaxKind.NullLiteralExpression:
|
||||||
case SyntaxKind.NumericLiteralExpression:
|
case SyntaxKind.NumericLiteralExpression:
|
||||||
case SyntaxKind.CharacterLiteralExpression:
|
case SyntaxKind.CharacterLiteralExpression:
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
|||||||
case SyntaxKind.InterpolatedStringText:
|
case SyntaxKind.InterpolatedStringText:
|
||||||
// Create a string literal
|
// Create a string literal
|
||||||
var interpolatedText = (InterpolatedStringTextSyntax)c;
|
var interpolatedText = (InterpolatedStringTextSyntax)c;
|
||||||
new Expression(new ExpressionInfo(Context, Type, Context.CreateLocation(c.GetLocation()), ExprKind.STRING_LITERAL, this, child++, false, interpolatedText.TextToken.Text));
|
new Expression(new ExpressionInfo(Context, Type, Context.CreateLocation(c.GetLocation()), ExprKind.UTF16_STRING_LITERAL, this, child++, false, interpolatedText.TextToken.ValueText));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new InternalError(c, $"Unhandled interpolation kind {c.Kind()}");
|
throw new InternalError(c, $"Unhandled interpolation kind {c.Kind()}");
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
|||||||
{
|
{
|
||||||
case SyntaxKind.DefaultLiteralExpression:
|
case SyntaxKind.DefaultLiteralExpression:
|
||||||
return ExprKind.DEFAULT;
|
return ExprKind.DEFAULT;
|
||||||
|
case SyntaxKind.Utf8StringLiteralExpression:
|
||||||
|
return ExprKind.UTF8_STRING_LITERAL;
|
||||||
case SyntaxKind.NullLiteralExpression:
|
case SyntaxKind.NullLiteralExpression:
|
||||||
info.SetType(null); // Don't use converted type.
|
info.SetType(null); // Don't use converted type.
|
||||||
return ExprKind.NULL_LITERAL;
|
return ExprKind.NULL_LITERAL;
|
||||||
@@ -63,7 +65,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
|||||||
return ExprKind.FLOAT_LITERAL;
|
return ExprKind.FLOAT_LITERAL;
|
||||||
|
|
||||||
case SpecialType.System_String:
|
case SpecialType.System_String:
|
||||||
return ExprKind.STRING_LITERAL;
|
return ExprKind.UTF16_STRING_LITERAL;
|
||||||
|
|
||||||
case SpecialType.System_UInt16:
|
case SpecialType.System_UInt16:
|
||||||
case SpecialType.System_UInt32:
|
case SpecialType.System_UInt32:
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
|||||||
PopulateAttributes();
|
PopulateAttributes();
|
||||||
ContainingType!.PopulateGenerics();
|
ContainingType!.PopulateGenerics();
|
||||||
PopulateNullability(trapFile, Symbol.GetAnnotatedType());
|
PopulateNullability(trapFile, Symbol.GetAnnotatedType());
|
||||||
|
PopulateRefKind(trapFile, Symbol.RefKind);
|
||||||
|
|
||||||
var unboundFieldKey = Field.Create(Context, Symbol.OriginalDefinition);
|
var unboundFieldKey = Field.Create(Context, Symbol.OriginalDefinition);
|
||||||
trapFile.fields(this, (Symbol.IsConst ? 2 : 1), Symbol.Name, ContainingType, Type.TypeRef, unboundFieldKey);
|
trapFile.fields(this, (Symbol.IsConst ? 2 : 1), Symbol.Name, ContainingType, Type.TypeRef, unboundFieldKey);
|
||||||
|
|||||||
@@ -25,19 +25,14 @@ namespace Semmle.Extraction.CSharp.Entities
|
|||||||
|
|
||||||
public static string AccessibilityModifier(Accessibility access)
|
public static string AccessibilityModifier(Accessibility access)
|
||||||
{
|
{
|
||||||
switch (access)
|
return access switch
|
||||||
{
|
{
|
||||||
case Accessibility.Private:
|
Accessibility.Private => Modifiers.Private,
|
||||||
return "private";
|
Accessibility.Protected => Modifiers.Protected,
|
||||||
case Accessibility.Protected:
|
Accessibility.Public => Modifiers.Public,
|
||||||
return "protected";
|
Accessibility.Internal => Modifiers.Internal,
|
||||||
case Accessibility.Public:
|
_ => throw new InternalError("Unavailable modifier combination"),
|
||||||
return "public";
|
};
|
||||||
case Accessibility.Internal:
|
|
||||||
return "internal";
|
|
||||||
default:
|
|
||||||
throw new InternalError("Unavailable modifier combination");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void HasAccessibility(Context cx, TextWriter trapFile, IEntity type, Accessibility access)
|
public static void HasAccessibility(Context cx, TextWriter trapFile, IEntity type, Accessibility access)
|
||||||
@@ -48,17 +43,17 @@ namespace Semmle.Extraction.CSharp.Entities
|
|||||||
case Accessibility.Public:
|
case Accessibility.Public:
|
||||||
case Accessibility.Protected:
|
case Accessibility.Protected:
|
||||||
case Accessibility.Internal:
|
case Accessibility.Internal:
|
||||||
HasModifier(cx, trapFile, type, Modifier.AccessibilityModifier(access));
|
HasModifier(cx, trapFile, type, AccessibilityModifier(access));
|
||||||
break;
|
break;
|
||||||
case Accessibility.NotApplicable:
|
case Accessibility.NotApplicable:
|
||||||
break;
|
break;
|
||||||
case Accessibility.ProtectedOrInternal:
|
case Accessibility.ProtectedOrInternal:
|
||||||
HasModifier(cx, trapFile, type, "protected");
|
HasModifier(cx, trapFile, type, Modifiers.Protected);
|
||||||
HasModifier(cx, trapFile, type, "internal");
|
HasModifier(cx, trapFile, type, Modifiers.Internal);
|
||||||
break;
|
break;
|
||||||
case Accessibility.ProtectedAndInternal:
|
case Accessibility.ProtectedAndInternal:
|
||||||
HasModifier(cx, trapFile, type, "protected");
|
HasModifier(cx, trapFile, type, Modifiers.Protected);
|
||||||
HasModifier(cx, trapFile, type, "private");
|
HasModifier(cx, trapFile, type, Modifiers.Private);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new InternalError($"Unhandled Microsoft.CodeAnalysis.Accessibility value: {access}");
|
throw new InternalError($"Unhandled Microsoft.CodeAnalysis.Accessibility value: {access}");
|
||||||
@@ -70,6 +65,27 @@ namespace Semmle.Extraction.CSharp.Entities
|
|||||||
trapFile.has_modifiers(target, Modifier.Create(cx, modifier));
|
trapFile.has_modifiers(target, Modifier.Create(cx, modifier));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void ExtractNamedTypeModifiers(Context cx, TextWriter trapFile, IEntity key, ISymbol symbol)
|
||||||
|
{
|
||||||
|
if (symbol.Kind != SymbolKind.NamedType)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (symbol is not INamedTypeSymbol nt)
|
||||||
|
throw new InternalError(symbol, "Symbol kind is inconsistent with its type");
|
||||||
|
|
||||||
|
if (nt.IsRecord)
|
||||||
|
HasModifier(cx, trapFile, key, Modifiers.Record);
|
||||||
|
|
||||||
|
if (nt.TypeKind == TypeKind.Struct)
|
||||||
|
{
|
||||||
|
if (nt.IsReadOnly)
|
||||||
|
HasModifier(cx, trapFile, key, Modifiers.Readonly);
|
||||||
|
|
||||||
|
if (nt.IsRefLikeType)
|
||||||
|
HasModifier(cx, trapFile, key, Modifiers.Ref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void ExtractModifiers(Context cx, TextWriter trapFile, IEntity key, ISymbol symbol)
|
public static void ExtractModifiers(Context cx, TextWriter trapFile, IEntity key, ISymbol symbol)
|
||||||
{
|
{
|
||||||
HasAccessibility(cx, trapFile, key, symbol.DeclaredAccessibility);
|
HasAccessibility(cx, trapFile, key, symbol.DeclaredAccessibility);
|
||||||
@@ -77,51 +93,35 @@ namespace Semmle.Extraction.CSharp.Entities
|
|||||||
trapFile.has_modifiers(key, Modifier.Create(cx, Accessibility.Public));
|
trapFile.has_modifiers(key, Modifier.Create(cx, Accessibility.Public));
|
||||||
|
|
||||||
if (symbol.IsAbstract && (symbol.Kind != SymbolKind.NamedType || ((INamedTypeSymbol)symbol).TypeKind != TypeKind.Interface))
|
if (symbol.IsAbstract && (symbol.Kind != SymbolKind.NamedType || ((INamedTypeSymbol)symbol).TypeKind != TypeKind.Interface))
|
||||||
HasModifier(cx, trapFile, key, "abstract");
|
HasModifier(cx, trapFile, key, Modifiers.Abstract);
|
||||||
|
|
||||||
if (symbol.IsSealed)
|
if (symbol.IsSealed)
|
||||||
HasModifier(cx, trapFile, key, "sealed");
|
HasModifier(cx, trapFile, key, Modifiers.Sealed);
|
||||||
|
|
||||||
var fromSource = symbol.DeclaringSyntaxReferences.Length > 0;
|
var fromSource = symbol.DeclaringSyntaxReferences.Length > 0;
|
||||||
|
|
||||||
if (symbol.IsStatic && !(symbol.Kind == SymbolKind.Field && ((IFieldSymbol)symbol).IsConst && !fromSource))
|
if (symbol.IsStatic && !(symbol.Kind == SymbolKind.Field && ((IFieldSymbol)symbol).IsConst && !fromSource))
|
||||||
HasModifier(cx, trapFile, key, "static");
|
HasModifier(cx, trapFile, key, Modifiers.Static);
|
||||||
|
|
||||||
if (symbol.IsVirtual)
|
if (symbol.IsVirtual)
|
||||||
HasModifier(cx, trapFile, key, "virtual");
|
HasModifier(cx, trapFile, key, Modifiers.Virtual);
|
||||||
|
|
||||||
if (symbol.Kind == SymbolKind.Field && ((IFieldSymbol)symbol).IsReadOnly)
|
if (symbol.Kind == SymbolKind.Field && ((IFieldSymbol)symbol).IsReadOnly)
|
||||||
HasModifier(cx, trapFile, key, "readonly");
|
HasModifier(cx, trapFile, key, Modifiers.Readonly);
|
||||||
|
|
||||||
if (symbol.IsOverride)
|
if (symbol.IsOverride)
|
||||||
HasModifier(cx, trapFile, key, "override");
|
HasModifier(cx, trapFile, key, Modifiers.Override);
|
||||||
|
|
||||||
if (symbol.Kind == SymbolKind.Method && ((IMethodSymbol)symbol).IsAsync)
|
if (symbol.Kind == SymbolKind.Method && ((IMethodSymbol)symbol).IsAsync)
|
||||||
HasModifier(cx, trapFile, key, "async");
|
HasModifier(cx, trapFile, key, Modifiers.Async);
|
||||||
|
|
||||||
if (symbol.IsExtern)
|
if (symbol.IsExtern)
|
||||||
HasModifier(cx, trapFile, key, "extern");
|
HasModifier(cx, trapFile, key, Modifiers.Extern);
|
||||||
|
|
||||||
foreach (var modifier in symbol.GetSourceLevelModifiers())
|
foreach (var modifier in symbol.GetSourceLevelModifiers())
|
||||||
HasModifier(cx, trapFile, key, modifier);
|
HasModifier(cx, trapFile, key, modifier);
|
||||||
|
|
||||||
if (symbol.Kind == SymbolKind.NamedType)
|
ExtractNamedTypeModifiers(cx, trapFile, key, symbol);
|
||||||
{
|
|
||||||
var nt = symbol as INamedTypeSymbol;
|
|
||||||
if (nt is null)
|
|
||||||
throw new InternalError(symbol, "Symbol kind is inconsistent with its type");
|
|
||||||
|
|
||||||
if (nt.IsRecord)
|
|
||||||
HasModifier(cx, trapFile, key, "record");
|
|
||||||
|
|
||||||
if (nt.TypeKind == TypeKind.Struct)
|
|
||||||
{
|
|
||||||
if (nt.IsReadOnly)
|
|
||||||
HasModifier(cx, trapFile, key, "readonly");
|
|
||||||
if (nt.IsRefLikeType)
|
|
||||||
HasModifier(cx, trapFile, key, "ref");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Modifier Create(Context cx, string modifier)
|
public static Modifier Create(Context cx, string modifier)
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
internal static class Modifiers
|
||||||
|
{
|
||||||
|
public const string Abstract = "abstract";
|
||||||
|
public const string Async = "async";
|
||||||
|
public const string Const = "const";
|
||||||
|
public const string Extern = "extern";
|
||||||
|
public const string Internal = "internal";
|
||||||
|
public const string New = "new";
|
||||||
|
public const string Override = "override";
|
||||||
|
public const string Partial = "partial";
|
||||||
|
public const string Private = "private";
|
||||||
|
public const string Protected = "protected";
|
||||||
|
public const string Public = "public";
|
||||||
|
public const string Readonly = "readonly";
|
||||||
|
public const string Record = "record";
|
||||||
|
public const string Ref = "ref";
|
||||||
|
public const string Sealed = "sealed";
|
||||||
|
public const string Static = "static";
|
||||||
|
public const string Virtual = "virtual";
|
||||||
|
}
|
||||||
@@ -23,7 +23,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
|||||||
{
|
{
|
||||||
var info = Context.GetModel(node).GetSymbolInfo(node.Name);
|
var info = Context.GetModel(node).GetSymbolInfo(node.Name);
|
||||||
|
|
||||||
if (node.StaticKeyword.Kind() == SyntaxKind.None)
|
if (node.StaticKeyword.IsKind(SyntaxKind.None))
|
||||||
{
|
{
|
||||||
// A normal using
|
// A normal using
|
||||||
if (info.Symbol is INamespaceSymbol namespaceSymbol)
|
if (info.Symbol is INamespaceSymbol namespaceSymbol)
|
||||||
@@ -47,7 +47,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
|||||||
trapFile.using_directive_location(this, Context.CreateLocation(ReportingLocation));
|
trapFile.using_directive_location(this, Context.CreateLocation(ReportingLocation));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node.GlobalKeyword.Kind() == SyntaxKind.GlobalKeyword)
|
if (node.GlobalKeyword.IsKind(SyntaxKind.GlobalKeyword))
|
||||||
{
|
{
|
||||||
trapFile.using_global(this);
|
trapFile.using_global(this);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ namespace Semmle.Extraction.Kinds
|
|||||||
ULONG_LITERAL = 7,
|
ULONG_LITERAL = 7,
|
||||||
FLOAT_LITERAL = 8,
|
FLOAT_LITERAL = 8,
|
||||||
DOUBLE_LITERAL = 9,
|
DOUBLE_LITERAL = 9,
|
||||||
STRING_LITERAL = 10,
|
UTF16_STRING_LITERAL = 10,
|
||||||
NULL_LITERAL = 11,
|
NULL_LITERAL = 11,
|
||||||
THIS_ACCESS = 12,
|
THIS_ACCESS = 12,
|
||||||
BASE_ACCESS = 13,
|
BASE_ACCESS = 13,
|
||||||
@@ -129,6 +129,7 @@ namespace Semmle.Extraction.Kinds
|
|||||||
SLICE_PATTERN = 132,
|
SLICE_PATTERN = 132,
|
||||||
URSHIFT = 133,
|
URSHIFT = 133,
|
||||||
ASSIGN_URSHIFT = 134,
|
ASSIGN_URSHIFT = 134,
|
||||||
|
UTF8_STRING_LITERAL = 135,
|
||||||
DEFINE_SYMBOL = 999,
|
DEFINE_SYMBOL = 999,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
<AssemblyName>Semmle.Extraction.CSharp</AssemblyName>
|
<AssemblyName>Semmle.Extraction.CSharp</AssemblyName>
|
||||||
<RootNamespace>Semmle.Extraction.CSharp</RootNamespace>
|
<RootNamespace>Semmle.Extraction.CSharp</RootNamespace>
|
||||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||||
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
<AssemblyName>Semmle.Extraction</AssemblyName>
|
<AssemblyName>Semmle.Extraction</AssemblyName>
|
||||||
<RootNamespace>Semmle.Extraction</RootNamespace>
|
<RootNamespace>Semmle.Extraction</RootNamespace>
|
||||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||||
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
<AssemblyName>Semmle.Util</AssemblyName>
|
<AssemblyName>Semmle.Util</AssemblyName>
|
||||||
<RootNamespace>Semmle.Util</RootNamespace>
|
<RootNamespace>Semmle.Util</RootNamespace>
|
||||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -4,5 +4,5 @@ from create_database_utils import *
|
|||||||
run_codeql_database_create(['dotnet publish'], test_db="default-db", db=None, lang="csharp")
|
run_codeql_database_create(['dotnet publish'], test_db="default-db", db=None, lang="csharp")
|
||||||
|
|
||||||
## Check that the publish folder is created.
|
## Check that the publish folder is created.
|
||||||
if not os.path.isdir("bin/Debug/net6.0/publish/"):
|
if not os.path.isdir("bin/Debug/net7.0/publish/"):
|
||||||
raise Exception("The publish artifact folder was not created.")
|
raise Exception("The publish artifact folder was not created.")
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
category: majorAnalysis
|
||||||
|
---
|
||||||
|
* Add extractor and library support for UTF-8 encoded strings.
|
||||||
|
* The `StringLiteral` class includes UTF-8 encoded strings.
|
||||||
|
* In the DB Schema `@string_literal_expr` is renamed to `@utf16_string_literal_expr`
|
||||||
4
csharp/ql/lib/change-notes/2023-01-26-reffields.md
Normal file
4
csharp/ql/lib/change-notes/2023-01-26-reffields.md
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
category: minorAnalysis
|
||||||
|
---
|
||||||
|
* C# 11: Added extractor support for `ref` fields in `ref struct` declarations.
|
||||||
@@ -152,4 +152,7 @@ class Field extends DotNet::Field, Variable, Member, CustomModifierReceiver, @ci
|
|||||||
override ValueOrRefType getDeclaringType() { cil_field(this, result, _, _) }
|
override ValueOrRefType getDeclaringType() { cil_field(this, result, _, _) }
|
||||||
|
|
||||||
override Location getLocation() { result = this.getDeclaringType().getLocation() }
|
override Location getLocation() { result = this.getDeclaringType().getLocation() }
|
||||||
|
|
||||||
|
/** Holds if this declaration is `ref`. */
|
||||||
|
predicate isRef() { cil_type_annotation(this, 32) }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -399,6 +399,12 @@ class Field extends Variable, AssignableMember, Attributable, TopLevelExprParent
|
|||||||
/** Holds if this field is `volatile`. */
|
/** Holds if this field is `volatile`. */
|
||||||
predicate isVolatile() { this.hasModifier("volatile") }
|
predicate isVolatile() { this.hasModifier("volatile") }
|
||||||
|
|
||||||
|
/** Holds if this is a `ref` field. */
|
||||||
|
predicate isRef() { this.getAnnotatedType().isRef() }
|
||||||
|
|
||||||
|
/** Holds if this is a `ref readonly` field. */
|
||||||
|
predicate isReadonlyRef() { this.getAnnotatedType().isReadonlyRef() }
|
||||||
|
|
||||||
/** Holds if this field is `readonly`. */
|
/** Holds if this field is `readonly`. */
|
||||||
predicate isReadOnly() { this.hasModifier("readonly") }
|
predicate isReadOnly() { this.hasModifier("readonly") }
|
||||||
|
|
||||||
|
|||||||
@@ -1487,6 +1487,10 @@ private module MkStage<StageSig PrevStage> {
|
|||||||
PrevStage::readStepCand(node1, _, _, config)
|
PrevStage::readStepCand(node1, _, _, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bindingset[ap, c]
|
||||||
|
pragma[inline_late]
|
||||||
|
private predicate hasHeadContent(Ap ap, Content c) { getHeadContent(ap) = c }
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowRead(
|
private predicate fwdFlowRead(
|
||||||
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
|
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
|
||||||
@@ -1494,7 +1498,7 @@ private module MkStage<StageSig PrevStage> {
|
|||||||
) {
|
) {
|
||||||
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
|
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
|
||||||
PrevStage::readStepCand(node1, c, node2, config) and
|
PrevStage::readStepCand(node1, c, node2, config) and
|
||||||
getHeadContent(ap) = c
|
hasHeadContent(ap, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
|
|||||||
@@ -1487,6 +1487,10 @@ private module MkStage<StageSig PrevStage> {
|
|||||||
PrevStage::readStepCand(node1, _, _, config)
|
PrevStage::readStepCand(node1, _, _, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bindingset[ap, c]
|
||||||
|
pragma[inline_late]
|
||||||
|
private predicate hasHeadContent(Ap ap, Content c) { getHeadContent(ap) = c }
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowRead(
|
private predicate fwdFlowRead(
|
||||||
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
|
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
|
||||||
@@ -1494,7 +1498,7 @@ private module MkStage<StageSig PrevStage> {
|
|||||||
) {
|
) {
|
||||||
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
|
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
|
||||||
PrevStage::readStepCand(node1, c, node2, config) and
|
PrevStage::readStepCand(node1, c, node2, config) and
|
||||||
getHeadContent(ap) = c
|
hasHeadContent(ap, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
|
|||||||
@@ -1487,6 +1487,10 @@ private module MkStage<StageSig PrevStage> {
|
|||||||
PrevStage::readStepCand(node1, _, _, config)
|
PrevStage::readStepCand(node1, _, _, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bindingset[ap, c]
|
||||||
|
pragma[inline_late]
|
||||||
|
private predicate hasHeadContent(Ap ap, Content c) { getHeadContent(ap) = c }
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowRead(
|
private predicate fwdFlowRead(
|
||||||
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
|
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
|
||||||
@@ -1494,7 +1498,7 @@ private module MkStage<StageSig PrevStage> {
|
|||||||
) {
|
) {
|
||||||
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
|
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
|
||||||
PrevStage::readStepCand(node1, c, node2, config) and
|
PrevStage::readStepCand(node1, c, node2, config) and
|
||||||
getHeadContent(ap) = c
|
hasHeadContent(ap, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
|
|||||||
@@ -1487,6 +1487,10 @@ private module MkStage<StageSig PrevStage> {
|
|||||||
PrevStage::readStepCand(node1, _, _, config)
|
PrevStage::readStepCand(node1, _, _, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bindingset[ap, c]
|
||||||
|
pragma[inline_late]
|
||||||
|
private predicate hasHeadContent(Ap ap, Content c) { getHeadContent(ap) = c }
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowRead(
|
private predicate fwdFlowRead(
|
||||||
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
|
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
|
||||||
@@ -1494,7 +1498,7 @@ private module MkStage<StageSig PrevStage> {
|
|||||||
) {
|
) {
|
||||||
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
|
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
|
||||||
PrevStage::readStepCand(node1, c, node2, config) and
|
PrevStage::readStepCand(node1, c, node2, config) and
|
||||||
getHeadContent(ap) = c
|
hasHeadContent(ap, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
|
|||||||
@@ -1487,6 +1487,10 @@ private module MkStage<StageSig PrevStage> {
|
|||||||
PrevStage::readStepCand(node1, _, _, config)
|
PrevStage::readStepCand(node1, _, _, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bindingset[ap, c]
|
||||||
|
pragma[inline_late]
|
||||||
|
private predicate hasHeadContent(Ap ap, Content c) { getHeadContent(ap) = c }
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowRead(
|
private predicate fwdFlowRead(
|
||||||
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
|
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
|
||||||
@@ -1494,7 +1498,7 @@ private module MkStage<StageSig PrevStage> {
|
|||||||
) {
|
) {
|
||||||
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
|
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
|
||||||
PrevStage::readStepCand(node1, c, node2, config) and
|
PrevStage::readStepCand(node1, c, node2, config) and
|
||||||
getHeadContent(ap) = c
|
hasHeadContent(ap, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
|
|||||||
@@ -1487,6 +1487,10 @@ private module MkStage<StageSig PrevStage> {
|
|||||||
PrevStage::readStepCand(node1, _, _, config)
|
PrevStage::readStepCand(node1, _, _, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bindingset[ap, c]
|
||||||
|
pragma[inline_late]
|
||||||
|
private predicate hasHeadContent(Ap ap, Content c) { getHeadContent(ap) = c }
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowRead(
|
private predicate fwdFlowRead(
|
||||||
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
|
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
|
||||||
@@ -1494,7 +1498,7 @@ private module MkStage<StageSig PrevStage> {
|
|||||||
) {
|
) {
|
||||||
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
|
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
|
||||||
PrevStage::readStepCand(node1, c, node2, config) and
|
PrevStage::readStepCand(node1, c, node2, config) and
|
||||||
getHeadContent(ap) = c
|
hasHeadContent(ap, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
|
|||||||
@@ -102,7 +102,8 @@ class DecimalLiteral extends RealLiteral, @decimal_literal_expr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A `string` literal, for example `"Hello, World!"`.
|
* A `string` literal. Either a `string` literal (`StringLiteralUtf16`),
|
||||||
|
* or a `u8` literal (`StringLiteralUtf8`).
|
||||||
*/
|
*/
|
||||||
class StringLiteral extends DotNet::StringLiteral, Literal, @string_literal_expr {
|
class StringLiteral extends DotNet::StringLiteral, Literal, @string_literal_expr {
|
||||||
override string toString() { result = "\"" + this.getValue().replaceAll("\"", "\\\"") + "\"" }
|
override string toString() { result = "\"" + this.getValue().replaceAll("\"", "\\\"") + "\"" }
|
||||||
@@ -110,6 +111,20 @@ class StringLiteral extends DotNet::StringLiteral, Literal, @string_literal_expr
|
|||||||
override string getAPrimaryQlClass() { result = "StringLiteral" }
|
override string getAPrimaryQlClass() { result = "StringLiteral" }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A `string` literal, for example `"Hello, World!"`.
|
||||||
|
*/
|
||||||
|
class StringLiteralUtf16 extends StringLiteral, @utf16_string_literal_expr {
|
||||||
|
override string getAPrimaryQlClass() { result = "StringLiteralUtf16" }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A `u8` literal, for example `"AUTH"u8`
|
||||||
|
*/
|
||||||
|
class StringLiteralUtf8 extends StringLiteral, @utf8_string_literal_expr {
|
||||||
|
override string getAPrimaryQlClass() { result = "StringLiteralUtf8" }
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A `null` literal.
|
* A `null` literal.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1005,7 +1005,7 @@ case @expr.kind of
|
|||||||
| 7 = @ulong_literal_expr
|
| 7 = @ulong_literal_expr
|
||||||
| 8 = @float_literal_expr
|
| 8 = @float_literal_expr
|
||||||
| 9 = @double_literal_expr
|
| 9 = @double_literal_expr
|
||||||
| 10 = @string_literal_expr
|
| 10 = @utf16_string_literal_expr
|
||||||
| 11 = @null_literal_expr
|
| 11 = @null_literal_expr
|
||||||
/* primary & unary */
|
/* primary & unary */
|
||||||
| 12 = @this_access_expr
|
| 12 = @this_access_expr
|
||||||
@@ -1139,6 +1139,7 @@ case @expr.kind of
|
|||||||
| 132 = @slice_pattern_expr
|
| 132 = @slice_pattern_expr
|
||||||
| 133 = @urshift_expr
|
| 133 = @urshift_expr
|
||||||
| 134 = @assign_urshift_expr
|
| 134 = @assign_urshift_expr
|
||||||
|
| 135 = @utf8_string_literal_expr
|
||||||
/* Preprocessor */
|
/* Preprocessor */
|
||||||
| 999 = @define_symbol_expr
|
| 999 = @define_symbol_expr
|
||||||
;
|
;
|
||||||
@@ -1152,6 +1153,7 @@ case @expr.kind of
|
|||||||
|
|
||||||
@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr;
|
@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr;
|
||||||
@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr;
|
@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr;
|
||||||
|
@string_literal_expr = @utf16_string_literal_expr | @utf8_string_literal_expr;
|
||||||
@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr
|
@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr
|
||||||
| @string_literal_expr | @null_literal_expr;
|
| @string_literal_expr | @null_literal_expr;
|
||||||
|
|
||||||
@@ -1866,7 +1868,7 @@ cil_field(
|
|||||||
@cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event;
|
@cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event;
|
||||||
@cil_custom_modifier_receiver = @cil_method | @cil_property | @cil_parameter | @cil_field | @cil_function_pointer_type;
|
@cil_custom_modifier_receiver = @cil_method | @cil_property | @cil_parameter | @cil_field | @cil_function_pointer_type;
|
||||||
@cil_parameterizable = @cil_method | @cil_function_pointer_type;
|
@cil_parameterizable = @cil_method | @cil_function_pointer_type;
|
||||||
@cil_has_type_annotation = @cil_stack_variable | @cil_property | @cil_method | @cil_function_pointer_type;
|
@cil_has_type_annotation = @cil_stack_variable | @cil_property | @cil_field | @cil_method | @cil_function_pointer_type;
|
||||||
|
|
||||||
#keyset[parameterizable, index]
|
#keyset[parameterizable, index]
|
||||||
cil_parameter(
|
cil_parameter(
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
|||||||
|
description: Add UTF-8 expression kind.
|
||||||
|
compatibility: backwards
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user