Compare commits

..

9 Commits

Author SHA1 Message Date
erik-krogh
26f81f1c37 Merge branch 'main' into XMLXml-no-dead-removal 2022-08-22 13:38:27 +02:00
erik-krogh
942392a9a1 Revert "delete some dead code in the kotlin extractor"
This reverts commit 98acb1db01.
2022-08-22 13:37:27 +02:00
erik-krogh
39820ee561 Merge branch 'main' into XMLXml 2022-08-22 11:14:34 +02:00
erik-krogh
fd581f74aa Merge branch 'main' into XMLXml 2022-08-22 09:45:31 +02:00
erik-krogh
21bec8a3d3 add change-note 2022-08-22 09:45:17 +02:00
erik-krogh
108a0bbd29 rename the XMLDTD class to XmlDTD 2022-08-19 15:41:30 +02:00
erik-krogh
f735821630 update some comments from XML to Xml 2022-08-19 15:40:29 +02:00
erik-krogh
98acb1db01 delete some dead code in the kotlin extractor 2022-08-19 13:18:59 +02:00
erik-krogh
ade7130935 rename all occurrences of XML to Xml 2022-08-19 13:18:58 +02:00
891 changed files with 7339 additions and 96830 deletions

1
.github/labeler.yml vendored
View File

@@ -42,4 +42,3 @@ documentation:
"QL-for-QL":
- ql/**/*
- .github/workflows/ql-for-ql*

View File

@@ -11,10 +11,10 @@ jobs:
name: Test Linux (Ubuntu)
runs-on: ubuntu-latest
steps:
- name: Set up Go 1.19
- name: Set up Go 1.18.1
uses: actions/setup-go@v3
with:
go-version: 1.19
go-version: 1.18.1
id: go
- name: Check out code
@@ -57,10 +57,10 @@ jobs:
name: Test MacOS
runs-on: macos-latest
steps:
- name: Set up Go 1.19
- name: Set up Go 1.18.1
uses: actions/setup-go@v3
with:
go-version: 1.19
go-version: 1.18.1
id: go
- name: Check out code
@@ -87,10 +87,10 @@ jobs:
name: Test Windows
runs-on: windows-2019
steps:
- name: Set up Go 1.19
- name: Set up Go 1.18.1
uses: actions/setup-go@v3
with:
go-version: 1.19
go-version: 1.18.1
id: go
- name: Check out code

View File

@@ -17,7 +17,7 @@ jobs:
- uses: actions/checkout@v3
- name: Find codeql
id: find-codeql
uses: github/codeql-action/init@71a8b35ff4c80fcfcd05bc1cd932fe3c08f943ca
uses: github/codeql-action/init@aa93aea877e5fb8841bcb1193f672abf6e9f2980
with:
languages: javascript # does not matter
- name: Get CodeQL version
@@ -27,37 +27,31 @@ jobs:
shell: bash
env:
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
- name: Cache entire pack
id: cache-pack
uses: actions/cache@v3
with:
path: ${{ runner.temp }}/pack
key: ${{ runner.os }}-pack-${{ hashFiles('ql/**/Cargo.lock') }}-${{ hashFiles('ql/**/*.rs') }}-${{ hashFiles('ql/**/*.ql*') }}-${{ hashFiles('ql/**/qlpack.yml') }}-${{ hashFiles('ql/ql/src/ql.dbscheme*') }}-${{ steps.get-codeql-version.outputs.version }}--${{ hashFiles('.github/workflows/ql-for-ql-build.yml') }}
- name: Cache queries
if: steps.cache-pack.outputs.cache-hit != 'true'
id: cache-queries
uses: actions/cache@v3
with:
path: ${{ runner.temp }}/queries
key: queries-${{ hashFiles('ql/**/*.ql*') }}-${{ hashFiles('ql/**/qlpack.yml') }}-${{ hashFiles('ql/ql/src/ql.dbscheme*') }}-${{ steps.get-codeql-version.outputs.version }}--${{ hashFiles('.github/workflows/ql-for-ql-build.yml') }}
path: ${{ runner.temp }}/query-pack.zip
key: queries-${{ hashFiles('ql/**/*.ql*') }}-${{ hashFiles('ql/**/qlpack.yml') }}-${{ hashFiles('ql/ql/src/ql.dbscheme*') }}-${{ steps.get-codeql-version.outputs.version }}
- name: Build query pack
if: steps.cache-queries.outputs.cache-hit != 'true' && steps.cache-pack.outputs.cache-hit != 'true'
if: steps.cache-queries.outputs.cache-hit != 'true'
run: |
cd ql/ql/src
"${CODEQL}" pack create -j 16
mv .codeql/pack/codeql/ql/0.0.0 ${{ runner.temp }}/queries
"${CODEQL}" pack create
cd .codeql/pack/codeql/ql/0.0.0
zip "${PACKZIP}" -r .
rm -rf *
env:
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
- name: Move cache queries to pack
if: steps.cache-pack.outputs.cache-hit != 'true'
run: |
cp -r ${{ runner.temp }}/queries ${{ runner.temp }}/pack
env:
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
PACKZIP: ${{ runner.temp }}/query-pack.zip
- name: Upload query pack
uses: actions/upload-artifact@v3
with:
name: query-pack-zip
path: ${{ runner.temp }}/query-pack.zip
### Build the extractor ###
- name: Cache entire extractor
if: steps.cache-pack.outputs.cache-hit != 'true'
id: cache-extractor
uses: actions/cache@v3
with:
@@ -68,7 +62,7 @@ jobs:
ql/target/release/ql-extractor.exe
key: ${{ runner.os }}-extractor-${{ hashFiles('ql/**/Cargo.lock') }}-${{ hashFiles('ql/**/*.rs') }}
- name: Cache cargo
if: steps.cache-extractor.outputs.cache-hit != 'true' && steps.cache-pack.outputs.cache-hit != 'true'
if: steps.cache-extractor.outputs.cache-hit != 'true'
uses: actions/cache@v3
with:
path: |
@@ -77,35 +71,73 @@ jobs:
ql/target
key: ${{ runner.os }}-rust-cargo-${{ hashFiles('ql/**/Cargo.lock') }}
- name: Check formatting
if: steps.cache-extractor.outputs.cache-hit != 'true' && steps.cache-pack.outputs.cache-hit != 'true'
if: steps.cache-extractor.outputs.cache-hit != 'true'
run: cd ql; cargo fmt --all -- --check
- name: Build
if: steps.cache-extractor.outputs.cache-hit != 'true' && steps.cache-pack.outputs.cache-hit != 'true'
if: steps.cache-extractor.outputs.cache-hit != 'true'
run: cd ql; cargo build --verbose
- name: Run tests
if: steps.cache-extractor.outputs.cache-hit != 'true' && steps.cache-pack.outputs.cache-hit != 'true'
if: steps.cache-extractor.outputs.cache-hit != 'true'
run: cd ql; cargo test --verbose
- name: Release build
if: steps.cache-extractor.outputs.cache-hit != 'true' && steps.cache-pack.outputs.cache-hit != 'true'
if: steps.cache-extractor.outputs.cache-hit != 'true'
run: cd ql; cargo build --release
- name: Generate dbscheme
if: steps.cache-extractor.outputs.cache-hit != 'true' && steps.cache-pack.outputs.cache-hit != 'true'
if: steps.cache-extractor.outputs.cache-hit != 'true'
run: ql/target/release/ql-generator --dbscheme ql/ql/src/ql.dbscheme --library ql/ql/src/codeql_ql/ast/internal/TreeSitter.qll
- uses: actions/upload-artifact@v3
with:
name: extractor-ubuntu-latest
path: |
ql/target/release/ql-autobuilder
ql/target/release/ql-autobuilder.exe
ql/target/release/ql-extractor
ql/target/release/ql-extractor.exe
retention-days: 1
### Package the queries and extractor ###
- name: Package pack
if: steps.cache-pack.outputs.cache-hit != 'true'
run: |
cp -r ql/codeql-extractor.yml ql/tools ql/ql/src/ql.dbscheme.stats ${PACK}/
mkdir -p ${PACK}/tools/linux64
cp ql/target/release/ql-autobuilder ${PACK}/tools/linux64/autobuilder
cp ql/target/release/ql-extractor ${PACK}/tools/linux64/extractor
chmod +x ${PACK}/tools/linux64/autobuilder
chmod +x ${PACK}/tools/linux64/extractor
env:
PACK: ${{ runner.temp }}/pack
- uses: actions/download-artifact@v3
with:
name: query-pack-zip
path: query-pack-zip
- uses: actions/download-artifact@v3
with:
name: extractor-ubuntu-latest
path: linux64
- run: |
unzip query-pack-zip/*.zip -d pack
cp -r ql/codeql-extractor.yml ql/tools ql/ql/src/ql.dbscheme.stats pack/
mkdir -p pack/tools/linux64
if [[ -f linux64/ql-autobuilder ]]; then
cp linux64/ql-autobuilder pack/tools/linux64/autobuilder
chmod +x pack/tools/linux64/autobuilder
fi
if [[ -f linux64/ql-extractor ]]; then
cp linux64/ql-extractor pack/tools/linux64/extractor
chmod +x pack/tools/linux64/extractor
fi
cd pack
zip -rq ../codeql-ql.zip .
rm -rf *
- uses: actions/upload-artifact@v3
with:
name: codeql-ql-pack
path: codeql-ql.zip
retention-days: 1
### Run the analysis ###
- name: Download pack
uses: actions/download-artifact@v3
with:
name: codeql-ql-pack
path: ${{ runner.temp }}/codeql-ql-pack-artifact
- name: Prepare pack
run: |
unzip "${PACK_ARTIFACT}/*.zip" -d "${PACK}"
env:
PACK_ARTIFACT: ${{ runner.temp }}/codeql-ql-pack-artifact
PACK: ${{ runner.temp }}/pack
- name: Hack codeql-action options
run: |
JSON=$(jq -nc --arg pack "${PACK}" '.database."run-queries"=["--search-path", $pack] | .resolve.queries=["--search-path", $pack] | .resolve.extractor=["--search-path", $pack] | .database.init=["--search-path", $pack]')
@@ -119,26 +151,21 @@ jobs:
echo " - ql/ql/test" >> ${CONF}
echo " - \"*/ql/lib/upgrades/\"" >> ${CONF}
echo "disable-default-queries: true" >> ${CONF}
echo "queries:" >> ${CONF}
echo " - uses: ./ql/ql/src/codeql-suites/ql-code-scanning.qls" >> ${CONF}
echo "packs:" >> ${CONF}
echo " - codeql/ql" >> ${CONF}
echo "Config file: "
cat ${CONF}
env:
CONF: ./ql-for-ql-config.yml
- name: Initialize CodeQL
uses: github/codeql-action/init@71a8b35ff4c80fcfcd05bc1cd932fe3c08f943ca
uses: github/codeql-action/init@aa93aea877e5fb8841bcb1193f672abf6e9f2980
with:
languages: ql
db-location: ${{ runner.temp }}/db
config-file: ./ql-for-ql-config.yml
- name: Move pack cache
run: |
cp -r ${PACK}/.cache ql/ql/src/.cache
env:
PACK: ${{ runner.temp }}/pack
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@71a8b35ff4c80fcfcd05bc1cd932fe3c08f943ca
uses: github/codeql-action/analyze@aa93aea877e5fb8841bcb1193f672abf6e9f2980
with:
category: "ql-for-ql"
- name: Copy sarif file to CWD

View File

@@ -25,7 +25,7 @@ jobs:
- name: Find codeql
id: find-codeql
uses: github/codeql-action/init@71a8b35ff4c80fcfcd05bc1cd932fe3c08f943ca
uses: github/codeql-action/init@aa93aea877e5fb8841bcb1193f672abf6e9f2980
with:
languages: javascript # does not matter
- uses: actions/cache@v3

View File

@@ -22,7 +22,7 @@ jobs:
- uses: actions/checkout@v3
- name: Find codeql
id: find-codeql
uses: github/codeql-action/init@71a8b35ff4c80fcfcd05bc1cd932fe3c08f943ca
uses: github/codeql-action/init@aa93aea877e5fb8841bcb1193f672abf6e9f2980
with:
languages: javascript # does not matter
- uses: actions/cache@v3

View File

@@ -1,21 +1,3 @@
## 0.3.5
## 0.3.4
### Deprecated APIs
* Many classes/predicates/modules with upper-case acronyms in their name have been renamed to follow our style-guide.
The old name still exists as a deprecated alias.
### New Features
* Added support for getting the link targets of global and namespace variables.
* Added a `BlockAssignExpr` class, which models a `memcpy`-like operation used in compiler generated copy/move constructors and assignment operations.
### Minor Analysis Improvements
* All deprecated predicates/classes/modules that have been deprecated for over a year have been deleted.
## 0.3.3
### New Features

View File

@@ -0,0 +1,4 @@
---
category: feature
---
* Added a `BlockAssignExpr` class, which models a `memcpy`-like operation used in compiler generated copy/move constructors and assignment operations.

View File

@@ -0,0 +1,6 @@
---
category: minorAnalysis
---
* All deprecated predicates/classes/modules that have been deprecated for over a year have been
deleted.

View File

@@ -0,0 +1,4 @@
---
category: feature
---
* Added support for getting the link targets of global and namespace variables.

View File

@@ -0,0 +1,5 @@
---
category: deprecated
---
* Classes/predicates that had upper-case acronym XML in their name have been renamed to Xml to follow our style-guide.
The old name still exists as a deprecated alias.

View File

@@ -1,15 +0,0 @@
## 0.3.4
### Deprecated APIs
* Many classes/predicates/modules with upper-case acronyms in their name have been renamed to follow our style-guide.
The old name still exists as a deprecated alias.
### New Features
* Added support for getting the link targets of global and namespace variables.
* Added a `BlockAssignExpr` class, which models a `memcpy`-like operation used in compiler generated copy/move constructors and assignment operations.
### Minor Analysis Improvements
* All deprecated predicates/classes/modules that have been deprecated for over a year have been deleted.

View File

@@ -1 +0,0 @@
## 0.3.5

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.3.5
lastReleaseVersion: 0.3.3

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-all
version: 0.3.6-dev
version: 0.3.4-dev
groups: cpp
dbscheme: semmlecode.cpp.dbscheme
extractor: cpp

20
cpp/ql/lib/semmle/code/cpp/XML.qll Normal file → Executable file
View File

@@ -132,10 +132,7 @@ class XmlFile extends XmlParent, File {
XmlElement getARootElement() { result = this.getAChild() }
/** Gets a DTD associated with this XML file. */
XmlDtd getADtd() { xmlDTDs(result, _, _, _, this) }
/** DEPRECATED: Alias for getADtd */
deprecated XmlDtd getADTD() { result = this.getADtd() }
XmlDTD getADTD() { xmlDTDs(result, _, _, _, this) }
}
/** DEPRECATED: Alias for XmlFile */
@@ -152,7 +149,7 @@ deprecated class XMLFile = XmlFile;
* <!ELEMENT lastName (#PCDATA)>
* ```
*/
class XmlDtd extends XmlLocatable, @xmldtd {
class XmlDTD extends XmlLocatable, @xmldtd {
/** Gets the name of the root element of this DTD. */
string getRoot() { xmlDTDs(this, result, _, _, _) }
@@ -177,8 +174,8 @@ class XmlDtd extends XmlLocatable, @xmldtd {
}
}
/** DEPRECATED: Alias for XmlDtd */
deprecated class XMLDTD = XmlDtd;
/** DEPRECATED: Alias for XmlDTD */
deprecated class XMLDTD = XmlDTD;
/**
* An XML element in an XML file.
@@ -285,18 +282,15 @@ class XmlNamespace extends XmlLocatable, @xmlnamespace {
string getPrefix() { xmlNs(this, result, _, _) }
/** Gets the URI of this namespace. */
string getUri() { xmlNs(this, _, result, _) }
/** DEPRECATED: Alias for getUri */
deprecated string getURI() { result = this.getUri() }
string getURI() { xmlNs(this, _, result, _) }
/** Holds if this namespace has no prefix. */
predicate isDefault() { this.getPrefix() = "" }
override string toString() {
this.isDefault() and result = this.getUri()
this.isDefault() and result = this.getURI()
or
not this.isDefault() and result = this.getPrefix() + ":" + this.getUri()
not this.isDefault() and result = this.getPrefix() + ":" + this.getURI()
}
}

View File

@@ -3,7 +3,7 @@ import semmle.code.cpp.ir.internal.Overlap
private import semmle.code.cpp.ir.internal.IRCppLanguage as Language
private import semmle.code.cpp.Print
private import semmle.code.cpp.ir.implementation.unaliased_ssa.IR
private import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.SSAConstruction as OldSsa
private import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.SSAConstruction as OldSSA
private import semmle.code.cpp.ir.internal.IntegerConstant as Ints
private import semmle.code.cpp.ir.internal.IntegerInterval as Interval
private import semmle.code.cpp.ir.implementation.internal.OperandTag
@@ -572,7 +572,7 @@ private Overlap getVariableMemoryLocationOverlap(
* Holds if the def/use information for the result of `instr` can be reused from the previous
* iteration of the IR.
*/
predicate canReuseSsaForOldResult(Instruction instr) { OldSsa::canReuseSsaForMemoryResult(instr) }
predicate canReuseSsaForOldResult(Instruction instr) { OldSSA::canReuseSsaForMemoryResult(instr) }
/** DEPRECATED: Alias for canReuseSsaForOldResult */
deprecated predicate canReuseSSAForOldResult = canReuseSsaForOldResult/1;

View File

@@ -5,8 +5,8 @@ private import Imports::OperandTag
private import Imports::Overlap
private import Imports::TInstruction
private import Imports::RawIR as RawIR
private import SsaInstructions
private import SsaOperands
private import SSAInstructions
private import SSAOperands
private import NewIR
private class OldBlock = Reachability::ReachableBlock;

View File

@@ -2,14 +2,7 @@ import semmle.code.cpp.ir.implementation.unaliased_ssa.IR as OldIR
import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.reachability.ReachableBlock as Reachability
import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.reachability.Dominance as Dominance
import semmle.code.cpp.ir.implementation.aliased_ssa.IR as NewIR
import semmle.code.cpp.ir.implementation.internal.TInstruction::AliasedSsaInstructions as SsaInstructions
/** DEPRECATED: Alias for SsaInstructions */
deprecated module SSAInstructions = SsaInstructions;
import semmle.code.cpp.ir.implementation.internal.TInstruction::AliasedSsaInstructions as SSAInstructions
import semmle.code.cpp.ir.internal.IRCppLanguage as Language
import AliasedSSA as Alias
import semmle.code.cpp.ir.implementation.internal.TOperand::AliasedSsaOperands as SsaOperands
/** DEPRECATED: Alias for SsaOperands */
deprecated module SSAOperands = SsaOperands;
import semmle.code.cpp.ir.implementation.internal.TOperand::AliasedSsaOperands as SSAOperands

View File

@@ -29,15 +29,15 @@ newtype TInstruction =
UnaliasedSsa::SSA::hasUnreachedInstruction(irFunc)
} or
TAliasedSsaPhiInstruction(
TRawInstruction blockStartInstr, AliasedSsa::SSA::MemoryLocation memoryLocation
TRawInstruction blockStartInstr, AliasedSSA::SSA::MemoryLocation memoryLocation
) {
AliasedSsa::SSA::hasPhiInstruction(blockStartInstr, memoryLocation)
AliasedSSA::SSA::hasPhiInstruction(blockStartInstr, memoryLocation)
} or
TAliasedSsaChiInstruction(TRawInstruction primaryInstruction) {
AliasedSsa::SSA::hasChiInstruction(primaryInstruction)
AliasedSSA::SSA::hasChiInstruction(primaryInstruction)
} or
TAliasedSsaUnreachedInstruction(IRFunctionBase irFunc) {
AliasedSsa::SSA::hasUnreachedInstruction(irFunc)
AliasedSSA::SSA::hasUnreachedInstruction(irFunc)
}
/**
@@ -83,7 +83,7 @@ module AliasedSsaInstructions {
class TPhiInstruction = TAliasedSsaPhiInstruction or TUnaliasedSsaPhiInstruction;
TPhiInstruction phiInstruction(
TRawInstruction blockStartInstr, AliasedSsa::SSA::MemoryLocation memoryLocation
TRawInstruction blockStartInstr, AliasedSSA::SSA::MemoryLocation memoryLocation
) {
result = TAliasedSsaPhiInstruction(blockStartInstr, memoryLocation)
}

View File

@@ -1,7 +1,4 @@
import semmle.code.cpp.ir.internal.IRCppLanguage as Language
import semmle.code.cpp.ir.implementation.raw.internal.IRConstruction as IRConstruction
import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.SSAConstruction as UnaliasedSsa
import semmle.code.cpp.ir.implementation.aliased_ssa.internal.SSAConstruction as AliasedSsa
/** DEPRECATED: Alias for AliasedSsa */
deprecated module AliasedSSA = AliasedSsa;
import semmle.code.cpp.ir.implementation.aliased_ssa.internal.SSAConstruction as AliasedSSA

View File

@@ -5,8 +5,8 @@ private import Imports::OperandTag
private import Imports::Overlap
private import Imports::TInstruction
private import Imports::RawIR as RawIR
private import SsaInstructions
private import SsaOperands
private import SSAInstructions
private import SSAOperands
private import NewIR
private class OldBlock = Reachability::ReachableBlock;

View File

@@ -3,14 +3,7 @@ import semmle.code.cpp.ir.implementation.raw.internal.reachability.ReachableBloc
import semmle.code.cpp.ir.implementation.raw.internal.reachability.Dominance as Dominance
import semmle.code.cpp.ir.implementation.unaliased_ssa.IR as NewIR
import semmle.code.cpp.ir.implementation.raw.internal.IRConstruction as RawStage
import semmle.code.cpp.ir.implementation.internal.TInstruction::UnaliasedSsaInstructions as SsaInstructions
/** DEPRECATED: Alias for SsaInstructions */
deprecated module SSAInstructions = SsaInstructions;
import semmle.code.cpp.ir.implementation.internal.TInstruction::UnaliasedSsaInstructions as SSAInstructions
import semmle.code.cpp.ir.internal.IRCppLanguage as Language
import SimpleSSA as Alias
import semmle.code.cpp.ir.implementation.internal.TOperand::UnaliasedSsaOperands as SsaOperands
/** DEPRECATED: Alias for SsaOperands */
deprecated module SSAOperands = SsaOperands;
import semmle.code.cpp.ir.implementation.internal.TOperand::UnaliasedSsaOperands as SSAOperands

View File

@@ -1,11 +1,3 @@
## 0.3.4
## 0.3.3
### Minor Analysis Improvements
* The "Cleartext storage of sensitive information in buffer" (`cpp/cleartext-storage-buffer`) query has been improved to produce fewer false positives.
## 0.3.2
### Minor Analysis Improvements

View File

@@ -163,46 +163,19 @@ TGlobalAddress globalAddress(Instruction instr) {
result = globalAddress(instr.(PointerOffsetInstruction).getLeft())
}
/**
* Gets a first `StoreInstruction` that writes to address `globalAddress` reachable
* from `block`.
*/
StoreInstruction getFirstStore(IRBlock block, TGlobalAddress globalAddress) {
1 = getStoreRank(result, block, globalAddress)
or
not exists(getStoreRank(_, block, globalAddress)) and
result = getFirstStore(block.getASuccessor(), globalAddress)
}
/**
* Gets the rank of `store` in block `block` (i.e., a rank of `1` means that it is the
* first `store` to write to `globalAddress`, a rank of `2` means it's the second, etc.)
*/
int getStoreRank(StoreInstruction store, IRBlock block, TGlobalAddress globalAddress) {
blockStoresToAddress(block, _, store, globalAddress) and
store =
rank[result](StoreInstruction anotherStore, int i |
blockStoresToAddress(_, i, anotherStore, globalAddress)
|
anotherStore order by i
)
}
/**
* Gets a next subsequent `StoreInstruction` to write to `globalAddress`
* after `store` has done so.
*/
StoreInstruction getANextStoreTo(StoreInstruction store, TGlobalAddress globalAddress) {
exists(IRBlock block, int rnk |
rnk = getStoreRank(store, block, globalAddress) and
rnk + 1 = getStoreRank(result, block, globalAddress)
/** Gets a `StoreInstruction` that may be executed after executing `store`. */
pragma[inline]
StoreInstruction getAStoreStrictlyAfter(StoreInstruction store) {
exists(IRBlock block, int index1, int index2 |
block.getInstruction(index1) = store and
block.getInstruction(index2) = result and
index2 > index1
)
or
exists(IRBlock block, int rnk, IRBlock succ |
rnk = getStoreRank(store, block, globalAddress) and
not rnk + 1 = getStoreRank(_, block, globalAddress) and
succ = block.getASuccessor() and
result = getFirstStore(succ, globalAddress)
exists(IRBlock block1, IRBlock block2 |
store.getBlock() = block1 and
result.getBlock() = block2 and
block1.getASuccessor+() = block2
)
}
@@ -219,7 +192,7 @@ predicate stackAddressEscapes(
stackPointerFlowsToUse(store.getSourceValue(), vai)
) and
// Ensure there's no subsequent store that overrides the global address.
not exists(getANextStoreTo(store, globalAddress))
not globalAddress = globalAddress(getAStoreStrictlyAfter(store).getDestinationAddress())
}
predicate blockStoresToAddress(

View File

@@ -21,9 +21,7 @@ class UntrustedExternalApiDataNode extends ExternalApiDataNode {
/** DEPRECATED: Alias for UntrustedExternalApiDataNode */
deprecated class UntrustedExternalAPIDataNode = UntrustedExternalApiDataNode;
/** An external API which is used with untrusted data. */
private newtype TExternalApi =
/** An untrusted API method `m` where untrusted data is passed at `index`. */
TExternalApiParameter(Function f, int index) {
exists(UntrustedExternalApiDataNode n |
f = n.getExternalFunction() and

View File

@@ -21,9 +21,7 @@ class UntrustedExternalApiDataNode extends ExternalApiDataNode {
/** DEPRECATED: Alias for UntrustedExternalApiDataNode */
deprecated class UntrustedExternalAPIDataNode = UntrustedExternalApiDataNode;
/** An external API which is used with untrusted data. */
private newtype TExternalApi =
/** An untrusted API method `m` where untrusted data is passed at `index`. */
TExternalApiParameter(Function f, int index) {
exists(UntrustedExternalApiDataNode n |
f = n.getExternalFunction() and

View File

@@ -17,8 +17,8 @@ import semmle.code.cpp.dataflow.DataFlow
/**
* A call to `SSL_get_verify_result`.
*/
class SslGetVerifyResultCall extends FunctionCall {
SslGetVerifyResultCall() { getTarget().getName() = "SSL_get_verify_result" }
class SSLGetVerifyResultCall extends FunctionCall {
SSLGetVerifyResultCall() { getTarget().getName() = "SSL_get_verify_result" }
}
/**
@@ -29,7 +29,7 @@ class VerifyResultConfig extends DataFlow::Configuration {
VerifyResultConfig() { this = "VerifyResultConfig" }
override predicate isSource(DataFlow::Node source) {
source.asExpr() instanceof SslGetVerifyResultCall
source.asExpr() instanceof SSLGetVerifyResultCall
}
override predicate isSink(DataFlow::Node sink) {

View File

@@ -17,33 +17,33 @@ import semmle.code.cpp.controlflow.IRGuards
/**
* A call to `SSL_get_peer_certificate`.
*/
class SslGetPeerCertificateCall extends FunctionCall {
SslGetPeerCertificateCall() {
class SSLGetPeerCertificateCall extends FunctionCall {
SSLGetPeerCertificateCall() {
getTarget().getName() = "SSL_get_peer_certificate" // SSL_get_peer_certificate(ssl)
}
Expr getSslArgument() { result = getArgument(0) }
Expr getSSLArgument() { result = getArgument(0) }
}
/**
* A call to `SSL_get_verify_result`.
*/
class SslGetVerifyResultCall extends FunctionCall {
SslGetVerifyResultCall() {
class SSLGetVerifyResultCall extends FunctionCall {
SSLGetVerifyResultCall() {
getTarget().getName() = "SSL_get_verify_result" // SSL_get_peer_certificate(ssl)
}
Expr getSslArgument() { result = getArgument(0) }
Expr getSSLArgument() { result = getArgument(0) }
}
/**
* Holds if the SSL object passed into `SSL_get_peer_certificate` is checked with
* `SSL_get_verify_result` entering `node`.
*/
predicate resultIsChecked(SslGetPeerCertificateCall getCertCall, ControlFlowNode node) {
exists(Expr ssl, SslGetVerifyResultCall check |
ssl = globalValueNumber(getCertCall.getSslArgument()).getAnExpr() and
ssl = check.getSslArgument() and
predicate resultIsChecked(SSLGetPeerCertificateCall getCertCall, ControlFlowNode node) {
exists(Expr ssl, SSLGetVerifyResultCall check |
ssl = globalValueNumber(getCertCall.getSSLArgument()).getAnExpr() and
ssl = check.getSSLArgument() and
node = check
)
}
@@ -53,7 +53,7 @@ predicate resultIsChecked(SslGetPeerCertificateCall getCertCall, ControlFlowNode
* `0` on the edge `node1` to `node2`.
*/
predicate certIsZero(
SslGetPeerCertificateCall getCertCall, ControlFlowNode node1, ControlFlowNode node2
SSLGetPeerCertificateCall getCertCall, ControlFlowNode node1, ControlFlowNode node2
) {
exists(Expr cert | cert = globalValueNumber(getCertCall).getAnExpr() |
exists(GuardCondition guard, Expr zero |
@@ -87,7 +87,7 @@ predicate certIsZero(
* `SSL_get_verify_result` at `node`. Note that this is only computed at the call to
* `SSL_get_peer_certificate` and at the start and end of `BasicBlock`s.
*/
predicate certNotChecked(SslGetPeerCertificateCall getCertCall, ControlFlowNode node) {
predicate certNotChecked(SSLGetPeerCertificateCall getCertCall, ControlFlowNode node) {
// cert is not checked at the call to `SSL_get_peer_certificate`
node = getCertCall
or
@@ -112,7 +112,7 @@ predicate certNotChecked(SslGetPeerCertificateCall getCertCall, ControlFlowNode
)
}
from SslGetPeerCertificateCall getCertCall, ControlFlowNode node
from SSLGetPeerCertificateCall getCertCall, ControlFlowNode node
where
certNotChecked(getCertCall, node) and
node instanceof Function // (function exit)

View File

@@ -26,10 +26,6 @@ class ToBufferConfiguration extends TaintTracking::Configuration {
override predicate isSource(DataFlow::Node source) { source instanceof FlowSource }
override predicate isSanitizer(DataFlow::Node node) {
node.asExpr().getUnspecifiedType() instanceof IntegralType
}
override predicate isSink(DataFlow::Node sink) {
exists(BufferWrite::BufferWrite w | w.getASource() = sink.asExpr())
}

View File

@@ -47,17 +47,14 @@ class EnvData extends SystemData {
/**
* Data originating from a call to `mysql_get_client_info()`.
*/
class SqlClientInfo extends SystemData {
SqlClientInfo() { this.(FunctionCall).getTarget().hasName("mysql_get_client_info") }
class SQLClientInfo extends SystemData {
SQLClientInfo() { this.(FunctionCall).getTarget().hasName("mysql_get_client_info") }
override DataFlow::Node getAnExpr() { result.asConvertedExpr() = this }
override predicate isSensitive() { any() }
}
/** DEPRECATED: Alias for SqlClientInfo */
deprecated class SQLClientInfo = SqlClientInfo;
private predicate sqlConnectInfo(FunctionCall source, Expr use) {
(
source.getTarget().hasName("mysql_connect") or
@@ -69,17 +66,14 @@ private predicate sqlConnectInfo(FunctionCall source, Expr use) {
/**
* Data passed into an SQL connect function.
*/
class SqlConnectInfo extends SystemData {
SqlConnectInfo() { sqlConnectInfo(this, _) }
class SQLConnectInfo extends SystemData {
SQLConnectInfo() { sqlConnectInfo(this, _) }
override DataFlow::Node getAnExpr() { sqlConnectInfo(this, result.asConvertedExpr()) }
override predicate isSensitive() { any() }
}
/** DEPRECATED: Alias for SqlConnectInfo */
deprecated class SQLConnectInfo = SqlConnectInfo;
private predicate posixSystemInfo(FunctionCall source, DataFlow::Node use) {
// size_t confstr(int name, char *buf, size_t len)
// - various OS / system strings, such as the libc version

View File

@@ -1,5 +0,0 @@
## 0.3.3
### Minor Analysis Improvements
* The "Cleartext storage of sensitive information in buffer" (`cpp/cleartext-storage-buffer`) query has been improved to produce fewer false positives.

View File

@@ -1 +0,0 @@
## 0.3.4

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.3.4
lastReleaseVersion: 0.3.2

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-queries
version: 0.3.5-dev
version: 0.3.3-dev
groups:
- cpp
- queries

View File

@@ -13,7 +13,7 @@
import cpp
private import semmle.code.cpp.ir.dataflow.DataFlow::DataFlow as IRDataFlow
private import semmle.code.cpp.dataflow.DataFlow::DataFlow as AstDataFlow
private import semmle.code.cpp.dataflow.DataFlow::DataFlow as ASTDataFlow
import TestUtilities.InlineExpectationsTest
class IRFlowTest extends InlineExpectationsTest {
@@ -49,11 +49,11 @@ class AstFlowTest extends InlineExpectationsTest {
override predicate hasActualResult(Location location, string element, string tag, string value) {
exists(
AstDataFlow::Node source, AstDataFlow::Node sink, AstDataFlow::Configuration conf, int n
ASTDataFlow::Node source, ASTDataFlow::Node sink, ASTDataFlow::Configuration conf, int n
|
tag = "ast" and
conf.hasFlow(source, sink) and
n = strictcount(AstDataFlow::Node otherSource | conf.hasFlow(otherSource, sink)) and
n = strictcount(ASTDataFlow::Node otherSource | conf.hasFlow(otherSource, sink)) and
(
n = 1 and value = ""
or

View File

@@ -4,7 +4,7 @@
*/
import cpp
import semmle.code.cpp.security.TaintTrackingImpl as AstTaintTracking
import semmle.code.cpp.security.TaintTrackingImpl as ASTTaintTracking
import semmle.code.cpp.ir.dataflow.DefaultTaintTracking as IRDefaultTaintTracking
import IRDefaultTaintTracking::TaintedWithPath as TaintedWithPath
import TaintedWithPath::Private
@@ -17,7 +17,7 @@ predicate isSinkArgument(Element sink) {
)
}
predicate astTaint(Expr source, Element sink) { AstTaintTracking::tainted(source, sink) }
predicate astTaint(Expr source, Element sink) { ASTTaintTracking::tainted(source, sink) }
class SourceConfiguration extends TaintedWithPath::TaintTrackingConfiguration {
override predicate isSink(Element e) { isSinkArgument(e) }

View File

@@ -5,7 +5,7 @@
*/
import cpp
import semmle.code.cpp.security.TaintTrackingImpl as AstTaintTracking
import semmle.code.cpp.security.TaintTrackingImpl as ASTTaintTracking
import semmle.code.cpp.ir.dataflow.DefaultTaintTracking as IRDefaultTaintTracking
import IRDefaultTaintTracking::TaintedWithPath as TaintedWithPath
import TestUtilities.InlineExpectationsTest
@@ -18,7 +18,7 @@ predicate argToSinkCall(Element sink) {
}
predicate astTaint(Expr source, Element sink) {
AstTaintTracking::tainted(source, sink) and argToSinkCall(sink)
ASTTaintTracking::tainted(source, sink) and argToSinkCall(sink)
}
class SourceConfiguration extends TaintedWithPath::TaintTrackingConfiguration {

View File

@@ -1,11 +1,11 @@
import cpp
import semmle.code.cpp.security.Security
import semmle.code.cpp.security.TaintTrackingImpl as AstTaintTracking
import semmle.code.cpp.security.TaintTrackingImpl as ASTTaintTracking
import semmle.code.cpp.ir.dataflow.DefaultTaintTracking as IRDefaultTaintTracking
import TestUtilities.InlineExpectationsTest
predicate astTaint(Expr source, Element sink, string globalVar) {
AstTaintTracking::taintedIncludingGlobalVars(source, sink, globalVar) and globalVar != ""
ASTTaintTracking::taintedIncludingGlobalVars(source, sink, globalVar) and globalVar != ""
}
predicate irTaint(Expr source, Element sink, string globalVar) {

View File

@@ -64,10 +64,6 @@ edges
| test.cpp:201:5:201:17 | EnterFunction: maybe_deref_p | test.cpp:201:5:201:17 | VariableAddress: maybe_deref_p |
| test.cpp:210:3:210:9 | Call: call to escape1 | test.cpp:201:5:201:17 | EnterFunction: maybe_deref_p |
| test.cpp:210:3:210:9 | Call: call to escape1 | test.cpp:201:5:201:17 | VariableAddress: maybe_deref_p |
| test.cpp:234:3:234:13 | Store: ... = ... | test.cpp:238:3:238:9 | Call: call to escape2 |
| test.cpp:238:3:238:9 | Call: call to escape2 | test.cpp:239:17:239:17 | Load: p |
| test.cpp:263:3:263:13 | Store: ... = ... | test.cpp:267:3:267:9 | Call: call to escape3 |
| test.cpp:267:3:267:9 | Call: call to escape3 | test.cpp:268:17:268:17 | Load: p |
#select
| test.cpp:15:16:15:16 | Load: p | test.cpp:10:3:10:13 | Store: ... = ... | test.cpp:15:16:15:16 | Load: p | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:9:7:9:7 | x | x | test.cpp:10:3:10:13 | Store: ... = ... | here |
| test.cpp:24:16:24:16 | Load: p | test.cpp:10:3:10:13 | Store: ... = ... | test.cpp:24:16:24:16 | Load: p | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:9:7:9:7 | x | x | test.cpp:10:3:10:13 | Store: ... = ... | here |
@@ -94,5 +90,3 @@ edges
| test.cpp:180:14:180:19 | Load: * ... | test.cpp:154:3:154:22 | Store: ... = ... | test.cpp:180:14:180:19 | Load: * ... | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:133:7:133:8 | b2 | b2 | test.cpp:154:3:154:22 | Store: ... = ... | here |
| test.cpp:181:13:181:20 | Load: access to array | test.cpp:155:3:155:21 | Store: ... = ... | test.cpp:181:13:181:20 | Load: access to array | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:134:7:134:8 | b3 | b3 | test.cpp:155:3:155:21 | Store: ... = ... | here |
| test.cpp:182:14:182:19 | Load: * ... | test.cpp:156:3:156:25 | Store: ... = ... | test.cpp:182:14:182:19 | Load: * ... | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:134:7:134:8 | b3 | b3 | test.cpp:156:3:156:25 | Store: ... = ... | here |
| test.cpp:239:17:239:17 | Load: p | test.cpp:234:3:234:13 | Store: ... = ... | test.cpp:239:17:239:17 | Load: p | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:232:7:232:7 | x | x | test.cpp:234:3:234:13 | Store: ... = ... | here |
| test.cpp:268:17:268:17 | Load: p | test.cpp:263:3:263:13 | Store: ... = ... | test.cpp:268:17:268:17 | Load: p | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:260:7:260:7 | x | x | test.cpp:263:3:263:13 | Store: ... = ... | here |

View File

@@ -209,61 +209,4 @@ int maybe_deref_p(bool b) {
int field_indirect_maybe_bad(bool b) {
escape1();
return maybe_deref_p(b);
}
// These next tests cover subsequent stores to the same address in the same basic block.
static struct S100 s102;
void not_escape1() {
int x;
s102.p = &x;
s102.p = nullptr;
}
void calls_not_escape1() {
not_escape1();
int x = *s102.p; // GOOD
}
static struct S100 s103;
void escape2() {
int x;
s103.p = nullptr;
s103.p = &x;
}
void calls_escape2() {
escape2();
int x = *s103.p; // BAD
}
bool unknown();
static struct S100 s104;
void not_escape2() {
int x;
s104.p = &x;
if(unknown()) { }
s104.p = nullptr;
}
void calls_not_escape2() {
not_escape2();
int x = *s104.p; // GOOD
}
static struct S100 s105;
void escape3() {
int x;
s105.p = nullptr;
if(unknown()) { }
s105.p = &x;
}
void calls_escape3() {
escape3();
int x = *s105.p; // BAD
}

View File

@@ -1,7 +1,3 @@
## 1.2.5
## 1.2.4
## 1.2.3
## 1.2.2

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.2.5
lastReleaseVersion: 1.2.3

View File

@@ -1,5 +1,5 @@
name: codeql/csharp-solorigate-all
version: 1.2.6-dev
version: 1.2.4-dev
groups:
- csharp
- solorigate

View File

@@ -1,7 +1,3 @@
## 1.2.5
## 1.2.4
## 1.2.3
## 1.2.2

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.2.5
lastReleaseVersion: 1.2.3

View File

@@ -1,5 +1,5 @@
name: codeql/csharp-solorigate-queries
version: 1.2.6-dev
version: 1.2.4-dev
groups:
- csharp
- solorigate

View File

@@ -1,16 +1,3 @@
## 0.3.5
## 0.3.4
### Deprecated APIs
* Many classes/predicates/modules with upper-case acronyms in their name have been renamed to follow our style-guide.
The old name still exists as a deprecated alias.
### Minor Analysis Improvements
* All deprecated predicates/classes/modules that have been deprecated for over a year have been deleted.
## 0.3.3
## 0.3.2

View File

@@ -0,0 +1,6 @@
---
category: minorAnalysis
---
* All deprecated predicates/classes/modules that have been deprecated for over a year have been
deleted.

View File

@@ -0,0 +1,5 @@
---
category: deprecated
---
* Classes/predicates that had upper-case acronym XML in their name have been renamed to Xml to follow our style-guide.
The old name still exists as a deprecated alias.

View File

@@ -1,10 +0,0 @@
## 0.3.4
### Deprecated APIs
* Many classes/predicates/modules with upper-case acronyms in their name have been renamed to follow our style-guide.
The old name still exists as a deprecated alias.
### Minor Analysis Improvements
* All deprecated predicates/classes/modules that have been deprecated for over a year have been deleted.

View File

@@ -1 +0,0 @@
## 0.3.5

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.3.5
lastReleaseVersion: 0.3.3

View File

@@ -1,5 +1,5 @@
name: codeql/csharp-all
version: 0.3.6-dev
version: 0.3.4-dev
groups: csharp
dbscheme: semmlecode.csharp.dbscheme
extractor: csharp

View File

@@ -94,20 +94,14 @@ class FormsElement extends XmlElement {
/**
* Gets attribute's `requireSSL` value.
*/
string getRequireSsl() {
string getRequireSSL() {
result = this.getAttribute("requireSSL").getValue().trim().toLowerCase()
}
/** DEPRECATED: Alias for getRequireSsl */
deprecated string getRequireSSL() { result = this.getRequireSsl() }
/**
* Holds if `requireSSL` value is true.
*/
predicate isRequireSsl() { this.getRequireSsl() = "true" }
/** DEPRECATED: Alias for isRequireSsl */
deprecated predicate isRequireSSL() { this.isRequireSsl() }
predicate isRequireSSL() { this.getRequireSSL() = "true" }
}
/** A `<httpCookies>` tag in an ASP.NET configuration file. */
@@ -129,23 +123,17 @@ class HttpCookiesElement extends XmlElement {
/**
* Gets attribute's `requireSSL` value.
*/
string getRequireSsl() {
string getRequireSSL() {
result = this.getAttribute("requireSSL").getValue().trim().toLowerCase()
}
/** DEPRECATED: Alias for getRequireSsl */
deprecated string getRequireSSL() { result = this.getRequireSsl() }
/**
* Holds if there is any chance that `requireSSL` is set to `true` either globally or for Forms.
*/
predicate isRequireSsl() {
this.getRequireSsl() = "true"
predicate isRequireSSL() {
this.getRequireSSL() = "true"
or
not this.getRequireSsl() = "false" and // not set all, i.e. default
exists(FormsElement forms | forms.getFile() = this.getFile() | forms.isRequireSsl())
not this.getRequireSSL() = "false" and // not set all, i.e. default
exists(FormsElement forms | forms.getFile() = this.getFile() | forms.isRequireSSL())
}
/** DEPRECATED: Alias for isRequireSsl */
deprecated predicate isRequireSSL() { this.isRequireSsl() }
}

20
csharp/ql/lib/semmle/code/csharp/XML.qll Normal file → Executable file
View File

@@ -132,10 +132,7 @@ class XmlFile extends XmlParent, File {
XmlElement getARootElement() { result = this.getAChild() }
/** Gets a DTD associated with this XML file. */
XmlDtd getADtd() { xmlDTDs(result, _, _, _, this) }
/** DEPRECATED: Alias for getADtd */
deprecated XmlDtd getADTD() { result = this.getADtd() }
XmlDTD getADTD() { xmlDTDs(result, _, _, _, this) }
}
/** DEPRECATED: Alias for XmlFile */
@@ -152,7 +149,7 @@ deprecated class XMLFile = XmlFile;
* <!ELEMENT lastName (#PCDATA)>
* ```
*/
class XmlDtd extends XmlLocatable, @xmldtd {
class XmlDTD extends XmlLocatable, @xmldtd {
/** Gets the name of the root element of this DTD. */
string getRoot() { xmlDTDs(this, result, _, _, _) }
@@ -177,8 +174,8 @@ class XmlDtd extends XmlLocatable, @xmldtd {
}
}
/** DEPRECATED: Alias for XmlDtd */
deprecated class XMLDTD = XmlDtd;
/** DEPRECATED: Alias for XmlDTD */
deprecated class XMLDTD = XmlDTD;
/**
* An XML element in an XML file.
@@ -285,18 +282,15 @@ class XmlNamespace extends XmlLocatable, @xmlnamespace {
string getPrefix() { xmlNs(this, result, _, _) }
/** Gets the URI of this namespace. */
string getUri() { xmlNs(this, _, result, _) }
/** DEPRECATED: Alias for getUri */
deprecated string getURI() { result = this.getUri() }
string getURI() { xmlNs(this, _, result, _) }
/** Holds if this namespace has no prefix. */
predicate isDefault() { this.getPrefix() = "" }
override string toString() {
this.isDefault() and result = this.getUri()
this.isDefault() and result = this.getURI()
or
not this.isDefault() and result = this.getPrefix() + ":" + this.getUri()
not this.isDefault() and result = this.getPrefix() + ":" + this.getURI()
}
}

View File

@@ -5,13 +5,12 @@
*
* The CSV specification has the following columns:
* - Sources:
* `namespace; type; subtypes; name; signature; ext; output; kind; provenance`
* `namespace; type; subtypes; name; signature; ext; output; kind`
* - Sinks:
* `namespace; type; subtypes; name; signature; ext; input; kind; provenance`
* `namespace; type; subtypes; name; signature; ext; input; kind`
* - Summaries:
* `namespace; type; subtypes; name; signature; ext; input; output; kind; provenance`
* - Negative Summaries:
* `namespace; type; name; signature; provenance`
* `namespace; type; subtypes; name; signature; ext; input; output; kind`
*
* The interpretation of a row is similar to API-graphs with a left-to-right
* reading.
* 1. The `namespace` column selects a namespace.
@@ -164,27 +163,11 @@ class SummaryModelCsv extends Unit {
abstract predicate row(string row);
}
/**
* A unit class for adding negative summary model rows.
*
* Extend this class to add additional flow summary definitions.
*/
class NegativeSummaryModelCsv extends Unit {
/** Holds if `row` specifies a negative summary definition. */
abstract predicate row(string row);
}
private predicate sourceModel(string row) { any(SourceModelCsv s).row(row) }
/** Holds if `row` is a source model. */
predicate sourceModel(string row) { any(SourceModelCsv s).row(row) }
private predicate sinkModel(string row) { any(SinkModelCsv s).row(row) }
/** Holds if `row` is a sink model. */
predicate sinkModel(string row) { any(SinkModelCsv s).row(row) }
/** Holds if `row` is a summary model. */
predicate summaryModel(string row) { any(SummaryModelCsv s).row(row) }
/** Holds if `row` is a negative summary model. */
predicate negativeSummaryModel(string row) { any(NegativeSummaryModelCsv s).row(row) }
private predicate summaryModel(string row) { any(SummaryModelCsv s).row(row) }
/** Holds if a source model exists for the given parameters. */
predicate sourceModel(
@@ -247,20 +230,6 @@ predicate summaryModel(
)
}
/** Holds if a summary model exists indicating there is no flow for the given parameters. */
predicate negativeSummaryModel(
string namespace, string type, string name, string signature, string provenance
) {
exists(string row |
negativeSummaryModel(row) and
row.splitAt(";", 0) = namespace and
row.splitAt(";", 1) = type and
row.splitAt(";", 2) = name and
row.splitAt(";", 3) = signature and
row.splitAt(";", 4) = provenance
)
}
private predicate relevantNamespace(string namespace) {
sourceModel(namespace, _, _, _, _, _, _, _, _) or
sinkModel(namespace, _, _, _, _, _, _, _, _) or
@@ -317,7 +286,38 @@ predicate modelCoverage(string namespace, int namespaces, string kind, string pa
/** Provides a query predicate to check the CSV data for validation errors. */
module CsvValidation {
private string getInvalidModelInput() {
/** Holds if some row in a CSV-based flow model appears to contain typos. */
query predicate invalidModelRow(string msg) {
exists(
string pred, string namespace, string type, string name, string signature, string ext,
string provenance
|
sourceModel(namespace, type, _, name, signature, ext, _, _, provenance) and pred = "source"
or
sinkModel(namespace, type, _, name, signature, ext, _, _, provenance) and pred = "sink"
or
summaryModel(namespace, type, _, name, signature, ext, _, _, _, provenance) and
pred = "summary"
|
not namespace.regexpMatch("[a-zA-Z0-9_\\.]+") and
msg = "Dubious namespace \"" + namespace + "\" in " + pred + " model."
or
not type.regexpMatch("[a-zA-Z0-9_<>,\\+]+") and
msg = "Dubious type \"" + type + "\" in " + pred + " model."
or
not name.regexpMatch("[a-zA-Z0-9_<>,]*") and
msg = "Dubious member name \"" + name + "\" in " + pred + " model."
or
not signature.regexpMatch("|\\([a-zA-Z0-9_<>\\.\\+\\*,\\[\\]]*\\)") and
msg = "Dubious signature \"" + signature + "\" in " + pred + " model."
or
not ext.regexpMatch("|Attribute") and
msg = "Unrecognized extra API graph element \"" + ext + "\" in " + pred + " model."
or
not provenance = ["manual", "generated"] and
msg = "Unrecognized provenance description \"" + provenance + "\" in " + pred + " model."
)
or
exists(string pred, AccessPath input, string part |
sinkModel(_, _, _, _, _, _, input, _, _) and pred = "sink"
or
@@ -332,11 +332,9 @@ module CsvValidation {
part = input.getToken(_) and
parseParam(part, _)
) and
result = "Unrecognized input specification \"" + part + "\" in " + pred + " model."
msg = "Unrecognized input specification \"" + part + "\" in " + pred + " model."
)
}
private string getInvalidModelOutput() {
or
exists(string pred, string output, string part |
sourceModel(_, _, _, _, _, _, output, _, _) and pred = "source"
or
@@ -345,123 +343,58 @@ module CsvValidation {
invalidSpecComponent(output, part) and
not part = "" and
not (part = ["Argument", "Parameter"] and pred = "source") and
result = "Unrecognized output specification \"" + part + "\" in " + pred + " model."
)
}
private string getInvalidModelKind() {
exists(string row, string kind | summaryModel(row) |
kind = row.splitAt(";", 8) and
not kind = ["taint", "value"] and
result = "Invalid kind \"" + kind + "\" in summary model."
msg = "Unrecognized output specification \"" + part + "\" in " + pred + " model."
)
or
exists(string row, string kind | sinkModel(row) |
kind = row.splitAt(";", 7) and
not kind = ["code", "sql", "xss", "remote", "html"] and
not kind.matches("encryption-%") and
result = "Invalid kind \"" + kind + "\" in sink model."
)
or
exists(string row, string kind | sourceModel(row) |
kind = row.splitAt(";", 7) and
not kind = ["local", "file"] and
result = "Invalid kind \"" + kind + "\" in source model."
)
}
private string getInvalidModelSubtype() {
exists(string pred, string row |
sourceModel(row) and pred = "source"
or
sinkModel(row) and pred = "sink"
or
summaryModel(row) and pred = "summary"
|
exists(string b |
b = row.splitAt(";", 2) and
not b = ["true", "false"] and
result = "Invalid boolean \"" + b + "\" in " + pred + " model."
)
)
}
private string getInvalidModelColumnCount() {
exists(string pred, string row, int expect |
sourceModel(row) and expect = 9 and pred = "source"
or
sinkModel(row) and expect = 9 and pred = "sink"
or
summaryModel(row) and expect = 10 and pred = "summary"
or
negativeSummaryModel(row) and expect = 5 and pred = "negative summary"
|
exists(int cols |
cols = 1 + max(int n | exists(row.splitAt(";", n))) and
cols != expect and
result =
msg =
"Wrong number of columns in " + pred + " model row, expected " + expect + ", got " + cols +
" in " + row + "."
)
or
exists(string b |
b = row.splitAt(";", 2) and
not b = ["true", "false"] and
msg = "Invalid boolean \"" + b + "\" in " + pred + " model."
)
)
}
private string getInvalidModelSignature() {
exists(
string pred, string namespace, string type, string name, string signature, string ext,
string provenance
|
sourceModel(namespace, type, _, name, signature, ext, _, _, provenance) and pred = "source"
or
sinkModel(namespace, type, _, name, signature, ext, _, _, provenance) and pred = "sink"
or
summaryModel(namespace, type, _, name, signature, ext, _, _, _, provenance) and
pred = "summary"
or
negativeSummaryModel(namespace, type, name, signature, provenance) and
ext = "" and
pred = "negative summary"
|
not namespace.regexpMatch("[a-zA-Z0-9_\\.]+") and
result = "Dubious namespace \"" + namespace + "\" in " + pred + " model."
or
not type.regexpMatch("[a-zA-Z0-9_<>,\\+]+") and
result = "Dubious type \"" + type + "\" in " + pred + " model."
or
not name.regexpMatch("[a-zA-Z0-9_<>,]*") and
result = "Dubious member name \"" + name + "\" in " + pred + " model."
or
not signature.regexpMatch("|\\([a-zA-Z0-9_<>\\.\\+\\*,\\[\\]]*\\)") and
result = "Dubious signature \"" + signature + "\" in " + pred + " model."
or
not ext.regexpMatch("|Attribute") and
result = "Unrecognized extra API graph element \"" + ext + "\" in " + pred + " model."
or
not provenance = ["manual", "generated"] and
result = "Unrecognized provenance description \"" + provenance + "\" in " + pred + " model."
or
exists(string row, string kind | summaryModel(row) |
kind = row.splitAt(";", 8) and
not kind = ["taint", "value"] and
msg = "Invalid kind \"" + kind + "\" in summary model."
)
or
exists(string row, string kind | sinkModel(row) |
kind = row.splitAt(";", 7) and
not kind = ["code", "sql", "xss", "remote", "html"] and
not kind.matches("encryption-%") and
msg = "Invalid kind \"" + kind + "\" in sink model."
)
or
exists(string row, string kind | sourceModel(row) |
kind = row.splitAt(";", 7) and
not kind = ["local", "file"] and
msg = "Invalid kind \"" + kind + "\" in source model."
)
}
/** Holds if some row in a CSV-based flow model appears to contain typos. */
query predicate invalidModelRow(string msg) {
msg =
[
getInvalidModelSignature(), getInvalidModelInput(), getInvalidModelOutput(),
getInvalidModelSubtype(), getInvalidModelColumnCount(), getInvalidModelKind()
]
}
}
private predicate elementSpec(
string namespace, string type, boolean subtypes, string name, string signature, string ext
) {
sourceModel(namespace, type, subtypes, name, signature, ext, _, _, _)
or
sinkModel(namespace, type, subtypes, name, signature, ext, _, _, _)
or
sourceModel(namespace, type, subtypes, name, signature, ext, _, _, _) or
sinkModel(namespace, type, subtypes, name, signature, ext, _, _, _) or
summaryModel(namespace, type, subtypes, name, signature, ext, _, _, _, _)
or
negativeSummaryModel(namespace, type, name, signature, _) and ext = "" and subtypes = false
}
private predicate elementSpec(
@@ -575,7 +508,7 @@ private Element interpretElement0(
)
}
/** Gets the source/sink/summary/negativesummary element corresponding to the supplied parameters. */
/** Gets the source/sink/summary element corresponding to the supplied parameters. */
Element interpretElement(
string namespace, string type, boolean subtypes, string name, string signature, string ext
) {

View File

@@ -173,7 +173,7 @@ module Ssa {
}
/**
* Holds if this SSA definition is live at the end of basic block `bb`.
* Holds is this SSA definition is live at the end of basic block `bb`.
* That is, this definition reaches the end of basic block `bb`, at which
* point it is still live, without crossing another SSA definition of the
* same source variable.

View File

View File

View File

View File

View File

View File

@@ -2129,37 +2129,18 @@ module Csv {
if isBaseCallableOrPrototype(c) then result = "true" else result = "false"
}
private predicate partialModel(
DotNet::Callable c, string namespace, string type, string name, string parameters
) {
c.getDeclaringType().hasQualifiedName(namespace, type) and
c.hasQualifiedName(_, name) and
parameters = "(" + parameterQualifiedTypeNamesToString(c) + ")"
}
/** Computes the first 6 columns for positive CSV rows of `c`. */
/** Computes the first 6 columns for CSV rows of `c`. */
string asPartialModel(DotNet::Callable c) {
exists(string namespace, string type, string name, string parameters |
partialModel(c, namespace, type, name, parameters) and
exists(string namespace, string type, string name |
c.getDeclaringType().hasQualifiedName(namespace, type) and
c.hasQualifiedName(_, name) and
result =
namespace + ";" //
+ type + ";" //
+ getCallableOverride(c) + ";" //
+ name + ";" //
+ parameters + ";" //
+ "(" + parameterQualifiedTypeNamesToString(c) + ")" + ";" //
+ /* ext + */ ";" //
)
}
/** Computes the first 4 columns for negative CSV rows of `c`. */
string asPartialNegativeModel(DotNet::Callable c) {
exists(string namespace, string type, string name, string parameters |
partialModel(c, namespace, type, name, parameters) and
result =
namespace + ";" //
+ type + ";" //
+ name + ";" //
+ parameters + ";" //
)
}
}

View File

@@ -240,16 +240,6 @@ module Public {
*/
predicate isAutoGenerated() { none() }
}
/** A callable with a flow summary stating there is no flow via the callable. */
class NegativeSummarizedCallable extends SummarizedCallableBase {
NegativeSummarizedCallable() { negativeSummaryElement(this, _) }
/**
* Holds if the negative summary is auto generated.
*/
predicate isAutoGenerated() { negativeSummaryElement(this, true) }
}
}
/**
@@ -1104,7 +1094,7 @@ module Private {
/** Provides a query predicate for outputting a set of relevant flow summaries. */
module TestOutput {
/** A flow summary to include in the `summary/1` query predicate. */
/** A flow summary to include in the `summary/3` query predicate. */
abstract class RelevantSummarizedCallable instanceof SummarizedCallable {
/** Gets the string representation of this callable used by `summary/1`. */
abstract string getCallableCsv();
@@ -1119,14 +1109,6 @@ module Private {
string toString() { result = super.toString() }
}
/** A flow summary to include in the `negativeSummary/1` query predicate. */
abstract class RelevantNegativeSummarizedCallable instanceof NegativeSummarizedCallable {
/** Gets the string representation of this callable used by `summary/1`. */
abstract string getCallableCsv();
string toString() { result = super.toString() }
}
/** Render the kind in the format used in flow summaries. */
private string renderKind(boolean preservesValue) {
preservesValue = true and result = "value"
@@ -1134,12 +1116,8 @@ module Private {
preservesValue = false and result = "taint"
}
private string renderProvenance(SummarizedCallable c) {
if c.isAutoGenerated() then result = "generated" else result = "manual"
}
private string renderProvenanceNegative(NegativeSummarizedCallable c) {
if c.isAutoGenerated() then result = "generated" else result = "manual"
private string renderProvenance(RelevantSummarizedCallable c) {
if c.(SummarizedCallable).isAutoGenerated() then result = "generated" else result = "manual"
}
/**
@@ -1154,23 +1132,8 @@ module Private {
|
c.relevantSummary(input, output, preservesValue) and
csv =
c.getCallableCsv() // Callable information
+ getComponentStackCsv(input) + ";" // input
+ getComponentStackCsv(output) + ";" // output
+ renderKind(preservesValue) + ";" // kind
+ renderProvenance(c) // provenance
)
}
/**
* Holds if a negative flow summary `csv` exists (semi-colon separated format). Used for testing purposes.
* The syntax is: "namespace;type;name;signature;provenance"",
*/
query predicate negativeSummary(string csv) {
exists(RelevantNegativeSummarizedCallable c |
csv =
c.getCallableCsv() // Callable information
+ renderProvenanceNegative(c) // provenance
c.getCallableCsv() + getComponentStackCsv(input) + ";" + getComponentStackCsv(output) +
";" + renderKind(preservesValue) + ";" + renderProvenance(c)
)
}
}

View File

@@ -114,18 +114,6 @@ predicate summaryElement(Callable c, string input, string output, string kind, b
)
}
/**
* Holds if a negative flow summary exists for `c`, which means that there is no
* flow through `c`. The flag `generated` states whether the summary is autogenerated.
*/
predicate negativeSummaryElement(Callable c, boolean generated) {
exists(string namespace, string type, string name, string signature, string provenance |
negativeSummaryModel(namespace, type, name, signature, provenance) and
generated = isGenerated(provenance) and
c = interpretElement(namespace, type, false, name, signature, "")
)
}
/**
* Holds if an external source specification exists for `e` with output specification
* `output`, kind `kind`, and a flag `generated` stating whether the source specification is

View File

@@ -1,9 +0,0 @@
/** Provides modules for importing negative summaries. */
/**
* A module importing the frameworks that provide external flow data,
* ensuring that they are visible to the taint tracking / data flow library.
*/
private module Frameworks {
private import semmle.code.csharp.frameworks.GeneratedNegative
}

View File

@@ -1,9 +0,0 @@
/**
* A module importing all generated negative Models as Data models.
*/
import csharp
private module GeneratedFrameworks {
private import generated.dotnet.NegativeRuntime
}

View File

@@ -119,13 +119,10 @@ class MicrosoftOwinIOwinRequestClass extends Class {
}
/** Gets the `URI` property. */
Property getUriProperty() {
Property getURIProperty() {
result = this.getAProperty() and
result.hasName("URI")
}
/** DEPRECATED: Alias for getUriProperty */
deprecated Property getURIProperty() { result = this.getUriProperty() }
}
/** A `Microsoft.Owin.*String` class. */

View File

@@ -102,9 +102,7 @@ class UntrustedExternalApiDataNode extends ExternalApiDataNode {
/** DEPRECATED: Alias for UntrustedExternalApiDataNode */
deprecated class UntrustedExternalAPIDataNode = UntrustedExternalApiDataNode;
/** An external API which is used with untrusted data. */
private newtype TExternalApi =
/** An untrusted API method `m` where untrusted data is passed at `index`. */
TExternalApiParameter(Callable m, int index) {
exists(UntrustedExternalApiDataNode n |
m = n.getCallable().getUnboundDeclaration() and

View File

@@ -146,7 +146,7 @@ class MicrosoftOwinRequestRemoteFlowSource extends RemoteFlowSource, DataFlow::E
p = owinRequest.getQueryStringProperty() or
p = owinRequest.getRemoteIpAddressProperty() or
p = owinRequest.getSchemeProperty() or
p = owinRequest.getUriProperty()
p = owinRequest.getURIProperty()
)
}

View File

@@ -1,14 +1,3 @@
## 0.3.4
## 0.3.3
### Minor Analysis Improvements
* Parameters of delegates passed to routing endpoint calls like `MapGet` in ASP.NET Core are now considered remote flow sources.
* The query `cs/unsafe-deserialization-untrusted-input` is not reporting on all calls of `JsonConvert.DeserializeObject` any longer, it only covers cases that explicitly use unsafe serialization settings.
* Added better support for the SQLite framework in the SQL injection query.
* File streams are now considered stored flow sources. For example, reading query elements from a file can lead to a Second Order SQL injection alert.
## 0.3.2
## 0.3.1

0
csharp/ql/src/Concurrency/FutileSyncOnField.cs Normal file → Executable file
View File

0
csharp/ql/src/Concurrency/FutileSyncOnField.ql Normal file → Executable file
View File

0
csharp/ql/src/Concurrency/FutileSyncOnFieldFix.cs Normal file → Executable file
View File

0
csharp/ql/src/Likely Bugs/BadCheckOdd.ql Normal file → Executable file
View File

View File

View File

0
csharp/ql/src/Likely Bugs/RandomUsedOnce.ql Normal file → Executable file
View File

0
csharp/ql/src/Likely Bugs/Statements/UseBraces.cs Normal file → Executable file
View File

0
csharp/ql/src/Likely Bugs/Statements/UseBraces.ql Normal file → Executable file
View File

0
csharp/ql/src/Likely Bugs/Statements/UseBracesFix.cs Normal file → Executable file
View File

View File

@@ -22,9 +22,9 @@ import semmle.code.csharp.frameworks.system.Web
from XmlElement element
where
element instanceof FormsElement and
not element.(FormsElement).isRequireSsl()
not element.(FormsElement).isRequireSSL()
or
element instanceof HttpCookiesElement and
not element.(HttpCookiesElement).isRequireSsl() and
not element.(HttpCookiesElement).isRequireSSL() and
not any(SystemWebHttpCookie c).getSecureProperty().getAnAssignedValue().getValue() = "true"
select element, "The 'requireSSL' attribute is not set to 'true'."

View File

@@ -8,14 +8,11 @@
private import csharp
private import semmle.code.csharp.dispatch.Dispatch
private import semmle.code.csharp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
private import semmle.code.csharp.dataflow.internal.NegativeSummary
private import ExternalApi
private predicate getRelevantUsages(ExternalApi api, int usages) {
not api.isUninteresting() and
not api.isSupported() and
not api instanceof FlowSummaryImpl::Public::NegativeSummarizedCallable and
usages = strictcount(DispatchCall c | c = api.getACall())
}

View File

@@ -0,0 +1,5 @@
---
category: minorAnalysis
---
* Added better support for the SQLite framework in the SQL injection query.
* File streams are now considered stored flow sources. Eg. reading query elements from a file can lead to a Second Order SQL injection alert.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The query `cs/unsafe-deserialization-untrusted-input` is not reporting on all calls of `JsonConvert.DeserializeObject` any longer, it only covers cases that explicitly use unsafe serialization settings.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Parameters of delegates passed to routing endpoint calls like `MapGet` in ASP.NET Core are now considered remote flow sources.

View File

@@ -1,8 +0,0 @@
## 0.3.3
### Minor Analysis Improvements
* Parameters of delegates passed to routing endpoint calls like `MapGet` in ASP.NET Core are now considered remote flow sources.
* The query `cs/unsafe-deserialization-untrusted-input` is not reporting on all calls of `JsonConvert.DeserializeObject` any longer, it only covers cases that explicitly use unsafe serialization settings.
* Added better support for the SQLite framework in the SQL injection query.
* File streams are now considered stored flow sources. For example, reading query elements from a file can lead to a Second Order SQL injection alert.

View File

@@ -1 +0,0 @@
## 0.3.4

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.3.4
lastReleaseVersion: 0.3.2

View File

@@ -66,10 +66,10 @@ where
// the `exists` below covers the `cs/web/requiressl-not-set`
not exists(XmlElement element |
element instanceof FormsElement and
element.(FormsElement).isRequireSsl()
element.(FormsElement).isRequireSSL()
or
element instanceof HttpCookiesElement and
element.(HttpCookiesElement).isRequireSsl()
element.(HttpCookiesElement).isRequireSSL()
)
)
)

View File

@@ -29,15 +29,15 @@ newtype TInstruction =
UnaliasedSsa::SSA::hasUnreachedInstruction(irFunc)
} or
TAliasedSsaPhiInstruction(
TRawInstruction blockStartInstr, AliasedSsa::SSA::MemoryLocation memoryLocation
TRawInstruction blockStartInstr, AliasedSSA::SSA::MemoryLocation memoryLocation
) {
AliasedSsa::SSA::hasPhiInstruction(blockStartInstr, memoryLocation)
AliasedSSA::SSA::hasPhiInstruction(blockStartInstr, memoryLocation)
} or
TAliasedSsaChiInstruction(TRawInstruction primaryInstruction) {
AliasedSsa::SSA::hasChiInstruction(primaryInstruction)
AliasedSSA::SSA::hasChiInstruction(primaryInstruction)
} or
TAliasedSsaUnreachedInstruction(IRFunctionBase irFunc) {
AliasedSsa::SSA::hasUnreachedInstruction(irFunc)
AliasedSSA::SSA::hasUnreachedInstruction(irFunc)
}
/**
@@ -83,7 +83,7 @@ module AliasedSsaInstructions {
class TPhiInstruction = TAliasedSsaPhiInstruction or TUnaliasedSsaPhiInstruction;
TPhiInstruction phiInstruction(
TRawInstruction blockStartInstr, AliasedSsa::SSA::MemoryLocation memoryLocation
TRawInstruction blockStartInstr, AliasedSSA::SSA::MemoryLocation memoryLocation
) {
result = TAliasedSsaPhiInstruction(blockStartInstr, memoryLocation)
}

View File

@@ -1,7 +1,4 @@
import experimental.ir.internal.IRCSharpLanguage as Language
import experimental.ir.implementation.raw.internal.IRConstruction as IRConstruction
import experimental.ir.implementation.unaliased_ssa.internal.SSAConstruction as UnaliasedSsa
import AliasedSSAStub as AliasedSsa
/** DEPRECATED: Alias for AliasedSsa */
deprecated module AliasedSSA = AliasedSsa;
import AliasedSSAStub as AliasedSSA

View File

@@ -5,8 +5,8 @@ private import Imports::OperandTag
private import Imports::Overlap
private import Imports::TInstruction
private import Imports::RawIR as RawIR
private import SsaInstructions
private import SsaOperands
private import SSAInstructions
private import SSAOperands
private import NewIR
private class OldBlock = Reachability::ReachableBlock;

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