Merge branch 'main' into call-graph-code

This commit is contained in:
Rasmus Wriedt Larsen
2023-02-02 11:56:55 +01:00
610 changed files with 50609 additions and 13793 deletions

View File

@@ -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"

View File

@@ -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

View File

@@ -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"

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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"

View File

@@ -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>

View File

@@ -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 />

View File

@@ -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]

View File

@@ -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]

View File

@@ -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]

View File

@@ -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]

View File

@@ -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()
}
}

View File

@@ -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]

View File

@@ -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]

View File

@@ -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]

View File

@@ -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]

View File

@@ -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]

View File

@@ -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]

View File

@@ -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]

View File

@@ -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]

View File

@@ -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]

View File

@@ -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

View File

@@ -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 }
} }
/** /**

View File

@@ -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 }
} }
/** /**

View File

@@ -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 }
} }
/** /**

View File

@@ -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()

View File

@@ -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()

View File

@@ -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
( (

View File

@@ -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(_))
) )
} }

View File

@@ -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)
) )
} }

View File

@@ -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 |

View File

@@ -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()

View File

@@ -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]
}
}

View File

@@ -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

View File

@@ -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. |

View File

@@ -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);
}
}

View File

@@ -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 |

View File

@@ -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 | |

View File

@@ -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 {

View File

@@ -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);
}
} }

View File

@@ -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 |

View File

@@ -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

View File

@@ -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>

View File

@@ -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/>

View File

@@ -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>

View File

@@ -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

View File

@@ -0,0 +1,3 @@
description: Remove UTF-8 expression kind.
compatibility: backwards
expressions.rel: run expressions.qlo

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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>

View File

@@ -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);
} }
} }

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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 _);

View File

@@ -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:

View File

@@ -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()}");

View File

@@ -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:

View File

@@ -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);

View File

@@ -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)

View File

@@ -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";
}

View File

@@ -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);
} }

View File

@@ -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,
} }
} }

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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.")

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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`

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* C# 11: Added extractor support for `ref` fields in `ref struct` declarations.

View File

@@ -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) }
} }

View File

@@ -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") }

View File

@@ -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]

View File

@@ -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]

View File

@@ -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]

View File

@@ -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]

View File

@@ -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]

View File

@@ -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]

View File

@@ -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.
*/ */

View File

@@ -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

View File

@@ -0,0 +1,2 @@
description: Add UTF-8 expression kind.
compatibility: backwards

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