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
1469 changed files with 18336 additions and 133826 deletions

1
.github/labeler.yml vendored
View File

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

View File

@@ -56,7 +56,7 @@ jobs:
# uses a compiled language
- run: |
dotnet build csharp
dotnet build csharp /p:UseSharedCompilation=false
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@main

View File

@@ -55,7 +55,7 @@ jobs:
DATABASE="${{ runner.temp }}/csharp-database"
PROJECT="${{ runner.temp }}/csharp-project"
dotnet new classlib --language=C# --output="$PROJECT"
codeql database create "$DATABASE" --language=csharp --source-root="$PROJECT" --command 'dotnet build /t:rebuild csharp-project.csproj'
codeql database create "$DATABASE" --language=csharp --source-root="$PROJECT" --command 'dotnet build /t:rebuild csharp-project.csproj /p:UseSharedCompilation=false'
- name: Capture coverage information
run: |
DATABASE="${{ runner.temp }}/csharp-database"

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

@@ -5,13 +5,6 @@ on:
branches: [main]
pull_request:
branches: [main]
paths:
- "ql/**"
- "**.qll"
- "**.ql"
- "**.dbscheme"
- "**/qlpack.yml"
- ".github/workflows/ql-for-ql-build.yml"
env:
CARGO_TERM_COLOR: always
@@ -24,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
@@ -34,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
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
"${CODEQL}" pack create
cd .codeql/pack/codeql/ql/0.0.0
zip "${PACKZIP}" -r .
rm -rf *
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:
@@ -75,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: |
@@ -84,38 +71,76 @@ 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] | .resolve.languages=["--search-path", $pack] | .database.init=["--search-path", $pack]')
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]')
echo "CODEQL_ACTION_EXTRA_OPTIONS=${JSON}" >> ${GITHUB_ENV}
env:
PACK: ${{ runner.temp }}/pack
@@ -123,36 +148,31 @@ jobs:
- name: Create CodeQL config file
run: |
echo "paths-ignore:" >> ${CONF}
echo " - ql/ql/test" >> ${CONF}
echo " - \"*/ql/lib/upgrades/\"" >> ${CONF}
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:
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
with:
uses: github/codeql-action/analyze@aa93aea877e5fb8841bcb1193f672abf6e9f2980
with:
category: "ql-for-ql"
- name: Copy sarif file to CWD
run: cp ../results/ql.sarif ./ql-for-ql.sarif
- name: Fixup the $scema in sarif # Until https://github.com/microsoft/sarif-vscode-extension/pull/436/ is part in a stable release
run: |
sed -i 's/\$schema.*/\$schema": "https:\/\/raw.githubusercontent.com\/oasis-tcs\/sarif-spec\/master\/Schemata\/sarif-schema-2.1.0",/' ql-for-ql.sarif
sed -i 's/\$schema.*/\$schema": "https:\/\/raw.githubusercontent.com\/oasis-tcs\/sarif-spec\/master\/Schemata\/sarif-schema-2.1.0",/' ql-for-ql.sarif
- name: Sarif as artifact
uses: actions/upload-artifact@v3
with:

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

@@ -462,6 +462,9 @@
],
"SSA C#": [
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/SsaImplCommon.qll",
"csharp/ql/lib/semmle/code/csharp/controlflow/internal/pressa/SsaImplCommon.qll",
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/basessa/SsaImplCommon.qll",
"csharp/ql/lib/semmle/code/cil/internal/SsaImplCommon.qll",
"ruby/ql/lib/codeql/ruby/dataflow/internal/SsaImplCommon.qll",
"cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaImplCommon.qll",
"swift/ql/lib/codeql/swift/dataflow/internal/SsaImplCommon.qll"
@@ -581,22 +584,22 @@
],
"Swift declarations test file": [
"swift/ql/test/extractor-tests/declarations/declarations.swift",
"swift/ql/test/library-tests/ast/declarations.swift"
"swift/ql/test/library-tests/parent/declarations.swift"
],
"Swift statements test file": [
"swift/ql/test/extractor-tests/statements/statements.swift",
"swift/ql/test/library-tests/ast/statements.swift"
"swift/ql/test/library-tests/parent/statements.swift"
],
"Swift expressions test file": [
"swift/ql/test/extractor-tests/expressions/expressions.swift",
"swift/ql/test/library-tests/ast/expressions.swift"
"swift/ql/test/library-tests/parent/expressions.swift"
],
"Swift patterns test file": [
"swift/ql/test/extractor-tests/patterns/patterns.swift",
"swift/ql/test/library-tests/ast/patterns.swift"
"swift/ql/test/library-tests/parent/patterns.swift"
],
"IncompleteMultiCharacterSanitization JS/Ruby": [
"javascript/ql/lib/semmle/javascript/security/IncompleteMultiCharacterSanitizationQuery.qll",
"ruby/ql/lib/codeql/ruby/security/IncompleteMultiCharacterSanitizationQuery.qll"
]
}
}

View File

@@ -299,7 +299,7 @@ namespace Semmle.Autobuild.Cpp.Tests
{
Actions.RunProcess[@"cmd.exe /C nuget restore C:\Project\test.sln -DisableParallelProcessing"] = 1;
Actions.RunProcess[@"cmd.exe /C C:\Project\.nuget\nuget.exe restore C:\Project\test.sln -DisableParallelProcessing"] = 0;
Actions.RunProcess[@"cmd.exe /C CALL ^""C:\Program Files ^(x86^)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat^"" && set Platform=&& type NUL && C:\odasa\tools\odasa index --auto msbuild C:\Project\test.sln /t:rebuild /p:Platform=""x86"" /p:Configuration=""Release"" /p:MvcBuildViews=true"] = 0;
Actions.RunProcess[@"cmd.exe /C CALL ^""C:\Program Files ^(x86^)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat^"" && set Platform=&& type NUL && C:\odasa\tools\odasa index --auto msbuild C:\Project\test.sln /p:UseSharedCompilation=false /t:rebuild /p:Platform=""x86"" /p:Configuration=""Release"" /p:MvcBuildViews=true"] = 0;
Actions.RunProcessOut[@"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe -prerelease -legacy -property installationPath"] = "";
Actions.RunProcess[@"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe -prerelease -legacy -property installationPath"] = 1;
Actions.RunProcess[@"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe -prerelease -legacy -property installationVersion"] = 0;

View File

@@ -1,19 +1,3 @@
## 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,2 +1,2 @@
---
lastReleaseVersion: 0.3.4
lastReleaseVersion: 0.3.3

View File

@@ -162,7 +162,7 @@ module SemanticExprConfig {
predicate phi(SsaVariable v) { v.asInstruction() instanceof IR::PhiInstruction }
SsaVariable getAPhiInput(SsaVariable v) {
exists(IR::PhiInstruction instr | v.asInstruction() = instr |
exists(IR::PhiInstruction instr |
result.asInstruction() = instr.getAnInput()
or
result.asOperand() = instr.getAnInputOperand()

View File

@@ -204,7 +204,6 @@ private class BinarySignExpr extends FlowSignExpr {
}
}
pragma[nomagic]
private predicate binaryExprOperands(SemBinaryExpr binary, SemExpr left, SemExpr right) {
binary.getLeftOperand() = left and binary.getRightOperand() = right
}

View File

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

View File

@@ -404,10 +404,7 @@ class Class extends UserType {
* compiled for. For this reason, the `is_pod_class` predicate is
* generated by the extractor.
*/
predicate isPod() { is_pod_class(underlyingElement(this)) }
/** DEPRECATED: Alias for isPod */
deprecated predicate isPOD() { this.isPod() }
predicate isPOD() { is_pod_class(underlyingElement(this)) }
/**
* Holds if this class, struct or union is a standard-layout class

View File

@@ -79,17 +79,17 @@ predicate isAggregateType03(Type t) {
* user-defined copy assignment operator and no user-defined destructor.
* A POD class is a class that is either a POD-struct or a POD-union.
*/
predicate isPodClass03(Class c) {
predicate isPODClass03(Class c) {
isAggregateClass03(c) and
not exists(Variable v |
v.getDeclaringType() = c and
not v.isStatic()
|
not isPodType03(v.getType())
not isPODType03(v.getType())
or
exists(ArrayType at |
at = v.getType() and
not isPodType03(at.getBaseType())
not isPODType03(at.getBaseType())
)
or
v.getType() instanceof ReferenceType
@@ -104,9 +104,6 @@ predicate isPodClass03(Class c) {
)
}
/** DEPRECATED: Alias for isPodClass03 */
deprecated predicate isPODClass03 = isPodClass03/1;
/**
* Holds if `t` is a POD type, according to the rules specified in
* C++03 3.9(10):
@@ -115,17 +112,14 @@ deprecated predicate isPODClass03 = isPodClass03/1;
* such types and cv-qualified versions of these types (3.9.3) are
* collectively called POD types.
*/
predicate isPodType03(Type t) {
predicate isPODType03(Type t) {
exists(Type ut | ut = t.getUnderlyingType() |
isScalarType03(ut)
or
isPodClass03(ut)
isPODClass03(ut)
or
exists(ArrayType at | at = ut and isPodType03(at.getBaseType()))
exists(ArrayType at | at = ut and isPODType03(at.getBaseType()))
or
isPodType03(ut.(SpecifiedType).getUnspecifiedType())
isPODType03(ut.(SpecifiedType).getUnspecifiedType())
)
}
/** DEPRECATED: Alias for isPodType03 */
deprecated predicate isPODType03 = isPodType03/1;

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

@@ -238,7 +238,7 @@ predicate dependsOnTransitive(DependsSource src, Element dest) {
/**
* A dependency that targets a TypeDeclarationEntry.
*/
private predicate dependsOnTde(Element src, Type t, TypeDeclarationEntry dest) {
private predicate dependsOnTDE(Element src, Type t, TypeDeclarationEntry dest) {
dependsOnTransitive(src, t) and
getDeclarationEntries(t, dest)
}
@@ -247,8 +247,8 @@ private predicate dependsOnTde(Element src, Type t, TypeDeclarationEntry dest) {
* A dependency that targets a visible TypeDeclarationEntry.
*/
pragma[noopt]
private predicate dependsOnVisibleTde(Element src, Type t, TypeDeclarationEntry dest) {
dependsOnTde(src, t, dest) and
private predicate dependsOnVisibleTDE(Element src, Type t, TypeDeclarationEntry dest) {
dependsOnTDE(src, t, dest) and
exists(File g | g = dest.getFile() |
exists(File f | f = src.getFile() | f.getAnIncludedFile*() = g)
)
@@ -260,8 +260,8 @@ private predicate dependsOnVisibleTde(Element src, Type t, TypeDeclarationEntry
private predicate dependsOnDeclarationEntry(Element src, DeclarationEntry dest) {
exists(Type t |
// dependency from a Type use -> unique visible TDE
dependsOnVisibleTde(src, t, dest) and
strictcount(TypeDeclarationEntry alt | dependsOnVisibleTde(src, t, alt)) = 1
dependsOnVisibleTDE(src, t, dest) and
strictcount(TypeDeclarationEntry alt | dependsOnVisibleTDE(src, t, alt)) = 1
)
or
exists(TypedefType mid |

View File

@@ -1,14 +1,11 @@
import semmle.code.cpp.Macro
/** A macro defining NULL. */
class NullMacro extends Macro {
NullMacro() { this.getHead() = "NULL" }
class NULLMacro extends Macro {
NULLMacro() { this.getHead() = "NULL" }
}
/** DEPRECATED: Alias for NullMacro */
deprecated class NULLMacro = NullMacro;
/** A use of the NULL macro. */
class NULL extends Literal {
NULL() { exists(NullMacro nm | this = nm.getAnInvocation().getAnExpandedElement()) }
NULL() { exists(NULLMacro nm | this = nm.getAnInvocation().getAnExpandedElement()) }
}

View File

@@ -143,28 +143,6 @@ class ScanfFunctionCall extends FunctionCall {
* (rather than a `char*`).
*/
predicate isWideCharDefault() { this.getScanfFunction().isWideCharDefault() }
/**
* Gets the output argument at position `n` in the vararg list of this call.
*
* The range of `n` is from `0` to `this.getNumberOfOutputArguments() - 1`.
*/
Expr getOutputArgument(int n) {
result = this.getArgument(this.getTarget().getNumberOfParameters() + n) and
n >= 0
}
/**
* Gets an output argument given to this call in vararg position.
*/
Expr getAnOutputArgument() { result = this.getOutputArgument(_) }
/**
* Gets the number of output arguments present in this call.
*/
int getNumberOfOutputArguments() {
result = this.getNumberOfArguments() - this.getTarget().getNumberOfParameters()
}
}
/**

View File

@@ -474,7 +474,7 @@ module FlowVar_internal {
}
/** Type-specialized version of `getEnclosingElement`. */
private ControlFlowNode getCfnParent(ControlFlowNode node) { result = node.getEnclosingElement() }
private ControlFlowNode getCFNParent(ControlFlowNode node) { result = node.getEnclosingElement() }
/**
* A for-loop or while-loop whose condition is always true upon entry but not
@@ -526,7 +526,7 @@ module FlowVar_internal {
}
private predicate bbInLoopCondition(BasicBlock bb) {
getCfnParent*(bb.getANode()) = this.(Loop).getCondition()
getCFNParent*(bb.getANode()) = this.(Loop).getCondition()
}
private predicate bbInLoop(BasicBlock bb) {

View File

@@ -0,0 +1,18 @@
private import semmle.code.cpp.ir.IR
private import SsaInternals as Ssa
class BasicBlock = IRBlock;
class SourceVariable = Ssa::SourceVariable;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result.immediatelyDominates(bb) }
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
class ExitBasicBlock extends IRBlock {
ExitBasicBlock() { this.getLastInstruction() instanceof ExitFunctionInstruction }
}
predicate variableWrite = Ssa::variableWrite/4;
predicate variableRead = Ssa::variableRead/4;

View File

@@ -1,10 +1,10 @@
import SsaImplCommon
private import cpp as Cpp
private import semmle.code.cpp.ir.IR
private import DataFlowUtil
private import DataFlowImplCommon as DataFlowImplCommon
private import semmle.code.cpp.models.interfaces.Allocation as Alloc
private import semmle.code.cpp.models.interfaces.DataFlow as DataFlow
private import SsaImplCommon as SsaImplCommon
private module SourceVariables {
private newtype TSourceVariable =
@@ -38,6 +38,8 @@ private module SourceVariables {
}
}
import SourceVariables
cached
private newtype TDefOrUse =
TExplicitDef(Instruction store) { explicitWrite(_, store, _) } or
@@ -84,7 +86,7 @@ abstract class Def extends DefOrUse {
Instruction getInstruction() { result = store }
/** Gets the variable that is defined by this definition. */
abstract SourceVariables::SourceVariable getSourceVariable();
abstract SourceVariable getSourceVariable();
/** Holds if this definition is guaranteed to happen. */
abstract predicate isCertain();
@@ -101,10 +103,10 @@ abstract class Def extends DefOrUse {
private class ExplicitDef extends Def, TExplicitDef {
ExplicitDef() { this = TExplicitDef(store) }
override SourceVariables::SourceVariable getSourceVariable() {
override SourceVariable getSourceVariable() {
exists(VariableInstruction var |
explicitWrite(_, this.getInstruction(), var) and
result.(SourceVariables::SourceIRVariable).getIRVariable() = var.getIRVariable()
result.(SourceIRVariable).getIRVariable() = var.getIRVariable()
)
}
@@ -114,11 +116,11 @@ private class ExplicitDef extends Def, TExplicitDef {
private class ParameterDef extends Def, TInitializeParam {
ParameterDef() { this = TInitializeParam(store) }
override SourceVariables::SourceVariable getSourceVariable() {
result.(SourceVariables::SourceIRVariable).getIRVariable() =
override SourceVariable getSourceVariable() {
result.(SourceIRVariable).getIRVariable() =
store.(InitializeParameterInstruction).getIRVariable()
or
result.(SourceVariables::SourceIRVariableIndirection).getUnderlyingIRVariable() =
result.(SourceIRVariableIndirection).getUnderlyingIRVariable() =
store.(InitializeIndirectionInstruction).getIRVariable()
}
@@ -136,7 +138,7 @@ abstract class Use extends DefOrUse {
override string toString() { result = "Use" }
/** Gets the variable that is used by this use. */
abstract SourceVariables::SourceVariable getSourceVariable();
abstract SourceVariable getSourceVariable();
override IRBlock getBlock() { result = use.getUse().getBlock() }
@@ -146,14 +148,12 @@ abstract class Use extends DefOrUse {
private class ExplicitUse extends Use, TExplicitUse {
ExplicitUse() { this = TExplicitUse(use) }
override SourceVariables::SourceVariable getSourceVariable() {
override SourceVariable getSourceVariable() {
exists(VariableInstruction var |
use.getDef() = var and
if use.getUse() instanceof ReadSideEffectInstruction
then
result.(SourceVariables::SourceIRVariableIndirection).getUnderlyingIRVariable() =
var.getIRVariable()
else result.(SourceVariables::SourceIRVariable).getIRVariable() = var.getIRVariable()
then result.(SourceIRVariableIndirection).getUnderlyingIRVariable() = var.getIRVariable()
else result.(SourceIRVariable).getIRVariable() = var.getIRVariable()
)
}
}
@@ -161,11 +161,10 @@ private class ExplicitUse extends Use, TExplicitUse {
private class ReturnParameterIndirection extends Use, TReturnParamIndirection {
ReturnParameterIndirection() { this = TReturnParamIndirection(use) }
override SourceVariables::SourceVariable getSourceVariable() {
override SourceVariable getSourceVariable() {
exists(ReturnIndirectionInstruction ret |
returnParameterIndirection(use, ret) and
result.(SourceVariables::SourceIRVariableIndirection).getUnderlyingIRVariable() =
ret.getIRVariable()
result.(SourceIRVariableIndirection).getUnderlyingIRVariable() = ret.getIRVariable()
)
}
}
@@ -611,45 +610,27 @@ private module Cached {
import Cached
private module SsaInput implements SsaImplCommon::InputSig {
private import semmle.code.cpp.ir.IR
class BasicBlock = IRBlock;
class SourceVariable = SourceVariables::SourceVariable;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result.immediatelyDominates(bb) }
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
class ExitBasicBlock extends IRBlock {
ExitBasicBlock() { this.getLastInstruction() instanceof ExitFunctionInstruction }
}
/**
* Holds if the `i`'th write in block `bb` writes to the variable `v`.
* `certain` is `true` if the write is guaranteed to overwrite the entire variable.
*/
predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) {
DataFlowImplCommon::forceCachingInSameStage() and
exists(Def def |
def.hasIndexInBlock(bb, i) and
v = def.getSourceVariable() and
(if def.isCertain() then certain = true else certain = false)
)
}
/**
* Holds if the `i`'th read in block `bb` reads to the variable `v`.
* `certain` is `true` if the read is guaranteed. For C++, this is always the case.
*/
predicate variableRead(BasicBlock bb, int i, SourceVariable v, boolean certain) {
exists(Use use |
use.hasIndexInBlock(bb, i) and
v = use.getSourceVariable() and
certain = true
)
}
/**
* Holds if the `i`'th write in block `bb` writes to the variable `v`.
* `certain` is `true` if the write is guaranteed to overwrite the entire variable.
*/
predicate variableWrite(IRBlock bb, int i, SourceVariable v, boolean certain) {
DataFlowImplCommon::forceCachingInSameStage() and
exists(Def def |
def.hasIndexInBlock(bb, i) and
v = def.getSourceVariable() and
(if def.isCertain() then certain = true else certain = false)
)
}
import SsaImplCommon::Make<SsaInput>
/**
* Holds if the `i`'th read in block `bb` reads to the variable `v`.
* `certain` is `true` if the read is guaranteed. For C++, this is always the case.
*/
predicate variableRead(IRBlock bb, int i, SourceVariable v, boolean certain) {
exists(Use use |
use.hasIndexInBlock(bb, i) and
v = use.getSourceVariable() and
certain = true
)
}

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

@@ -165,7 +165,7 @@ private ControlFlowNode mostRecentSideEffect(ControlFlowNode node) {
/** Used to represent the "global value number" of an expression. */
cached
private newtype GvnBase =
private newtype GVNBase =
GVN_IntConst(int val, Type t) { mk_IntConst(val, t, _) } or
GVN_FloatConst(float val, Type t) { mk_FloatConst(val, t, _) } or
// If the local variable does not have a defining value, then
@@ -221,8 +221,8 @@ private newtype GvnBase =
* expression with this `GVN` and using its `toString` and `getLocation`
* methods.
*/
class GVN extends GvnBase {
GVN() { this instanceof GvnBase }
class GVN extends GVNBase {
GVN() { this instanceof GVNBase }
/** Gets an expression that has this GVN. */
Expr getAnExpr() { this = globalValueNumber(result) }

View File

@@ -63,17 +63,17 @@ class VariableDeclarationLine extends TVariableDeclarationInfo {
/**
* Gets a `VariableDeclarationEntry` on this line.
*/
VariableDeclarationEntry getAVde() { vdeInfo(result, c, f, line) }
VariableDeclarationEntry getAVDE() { vdeInfo(result, c, f, line) }
/**
* Gets the start column of the first `VariableDeclarationEntry` on this line.
*/
int getStartColumn() { result = min(this.getAVde().getLocation().getStartColumn()) }
int getStartColumn() { result = min(this.getAVDE().getLocation().getStartColumn()) }
/**
* Gets the end column of the last `VariableDeclarationEntry` on this line.
*/
int getEndColumn() { result = max(this.getAVde().getLocation().getEndColumn()) }
int getEndColumn() { result = max(this.getAVDE().getLocation().getEndColumn()) }
/**
* Gets the rank of this `VariableDeclarationLine` in its file and class
@@ -134,13 +134,13 @@ class VariableDeclarationGroup extends VariableDeclarationLine {
count(VariableDeclarationLine l |
l = this.getProximateNext*()
|
l.getAVde().getVariable().getName()
l.getAVDE().getVariable().getName()
)
}
override string toString() {
this.getCount() = 1 and
result = "declaration of " + this.getAVde().getVariable().getName()
result = "declaration of " + this.getAVDE().getVariable().getName()
or
this.getCount() > 1 and
result = "group of " + this.getCount() + " fields here"

View File

@@ -29,4 +29,7 @@ where
n = strictcount(ComplexStmt s | s = b.getAStmt()) and
n > 3 and
complexStmt = b.getAStmt()
select b, "Block with too many statements (" + n.toString() + " complex statements in the block)."
select b,
"Block with too many statements (" + n.toString() +
" complex statements in the block). Complex statements at: $@", complexStmt,
complexStmt.toString()

View File

@@ -110,4 +110,4 @@ where
emptyBlock(s, eb) and
not emptyBlockContainsNonchild(eb) and
not lineComment(eb)
select eb, "Empty block without comment."
select eb, "Empty block without comment"

View File

@@ -16,7 +16,7 @@ import cpp
class JumpTarget extends Stmt {
JumpTarget() { exists(GotoStmt g | g.getTarget() = this) }
FunctionDeclarationEntry getFde() { result.getBlock() = this.getParentStmt+() }
FunctionDeclarationEntry getFDE() { result.getBlock() = this.getParentStmt+() }
predicate isForward() {
exists(GotoStmt g | g.getTarget() = this |
@@ -33,8 +33,8 @@ class JumpTarget extends Stmt {
from FunctionDeclarationEntry fde, int nforward, int nbackward
where
nforward = strictcount(JumpTarget t | t.getFde() = fde and t.isForward()) and
nbackward = strictcount(JumpTarget t | t.getFde() = fde and t.isBackward()) and
nforward = strictcount(JumpTarget t | t.getFDE() = fde and t.isForward()) and
nbackward = strictcount(JumpTarget t | t.getFDE() = fde and t.isBackward()) and
nforward != 1 and
nbackward != 1
select fde,

View File

@@ -1,9 +1,3 @@
## 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

@@ -1,17 +0,0 @@
{
int i, j, r;
r = scanf("%d %d", &i, &j);
use(i); // BAD: i is not guarded
if (r >= 1) {
use(i); // GOOD: i is guarded correctly
use(j); // BAD: j is guarded incorrectly
}
if (r != 2)
return;
use(j); // GOOD: j is guarded correctly
}

View File

@@ -1,51 +0,0 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
This query finds calls of <tt>scanf</tt>-like functions with missing or
improper return-value checking.
</p>
<p>
Specifically, the query flags uses of variables that may have been modified by
<tt>scanf</tt> and subsequently are used without being guarded by a correct
return-value check. A proper check is one that ensures that the corresponding
<tt>scanf</tt> has returned (at least) a certain minimum constant.
</p>
<p>
Functions in the <tt>scanf</tt> family return either EOF (a negative value)
in case of IO failure, or the number of items successfully read from the
input. Consequently, a simple check that the return value is truthy (nonzero)
is not enough.
</p>
<warning>
This query has medium precision because, in the current implementation, it
takes a strict stance on unguarded uses of output variables, and flags them
as problematic even if they have already been initialized.
</warning>
</overview>
<recommendation>
<p>
Ensure that all subsequent uses of <tt>scanf</tt> output arguments occur in a
branch of an <tt>if</tt> statement (or similar), in which it is known that the
corresponding <tt>scanf</tt> call has in fact read all possible items from its
input. This can be done by comparing the return value to a numerical constant.
</p>
</recommendation>
<example>
<p>This example shows different ways of guarding a <tt>scanf</tt> output:
</p>
<sample src="MissingCheckScanf.cpp" />
</example>
<references>
<li>SEI CERT C++ Coding Standard: <a href="https://wiki.sei.cmu.edu/confluence/display/cplusplus/ERR62-CPP.+Detect+errors+when+converting+a+string+to+a+number">ERR62-CPP. Detect errors when converting a string to a number</a>.</li>
<li>SEI CERT C Coding Standard: <a href="https://wiki.sei.cmu.edu/confluence/display/c/ERR33-C.+Detect+and+handle+standard+library+errors">ERR33-C. Detect and handle standard library errors</a>.</li>
<li>cppreference.com: <a href="https://en.cppreference.com/w/c/io/fscanf">scanf, fscanf, sscanf, scanf_s, fscanf_s, sscanf_s</a>.</li>
</references>
</qhelp>

View File

@@ -1,122 +0,0 @@
/**
* @name Missing return-value check for a 'scanf'-like function
* @description Failing to check that a call to 'scanf' actually writes to an
* output variable can lead to unexpected behavior at reading time.
* @kind problem
* @problem.severity warning
* @security-severity 7.5
* @precision medium
* @id cpp/missing-check-scanf
* @tags security
* correctness
* external/cwe/cwe-252
* external/cwe/cwe-253
*/
import cpp
import semmle.code.cpp.commons.Scanf
import semmle.code.cpp.controlflow.Guards
import semmle.code.cpp.dataflow.DataFlow
import semmle.code.cpp.ir.IR
import semmle.code.cpp.ir.ValueNumbering
/** An expression appearing as an output argument to a `scanf`-like call */
class ScanfOutput extends Expr {
ScanfFunctionCall call;
int varargIndex;
Instruction instr;
ValueNumber valNum;
ScanfOutput() {
this = call.getOutputArgument(varargIndex).getFullyConverted() and
instr.getConvertedResultExpression() = this and
valueNumber(instr) = valNum
}
ScanfFunctionCall getCall() { result = call }
/**
* Returns the smallest possible `scanf` return value that would indicate
* success in writing this output argument.
*/
int getMinimumGuardConstant() {
result =
varargIndex + 1 -
count(ScanfFormatLiteral f, int n |
// Special case: %n writes to an argument without reading any input.
// It does not increase the count returned by `scanf`.
n <= varargIndex and f.getUse() = call and f.getConversionChar(n) = "n"
)
}
predicate hasGuardedAccess(Access e, boolean isGuarded) {
e = this.getAnAccess() and
if
exists(int value, int minGuard | minGuard = this.getMinimumGuardConstant() |
e.getBasicBlock() = blockGuardedBy(value, "==", call) and minGuard <= value
or
e.getBasicBlock() = blockGuardedBy(value, "<", call) and minGuard - 1 <= value
or
e.getBasicBlock() = blockGuardedBy(value, "<=", call) and minGuard <= value
)
then isGuarded = true
else isGuarded = false
}
/**
* Get a subsequent access of the same underlying storage,
* but before it gets reset or reused in another `scanf` call.
*/
Access getAnAccess() {
exists(Instruction dst |
this.bigStep() = dst and
dst.getAst() = result and
valueNumber(dst) = valNum
)
}
private Instruction bigStep() {
result = this.smallStep(instr)
or
exists(Instruction i | i = this.bigStep() | result = this.smallStep(i))
}
private Instruction smallStep(Instruction i) {
instr.getASuccessor*() = i and
i.getASuccessor() = result and
not this.isBarrier(result)
}
private predicate isBarrier(Instruction i) {
valueNumber(i) = valNum and
exists(Expr e | i.getAst() = e |
i = any(StoreInstruction s).getDestinationAddress()
or
[e, e.getParent().(AddressOfExpr)] instanceof ScanfOutput
)
}
}
/** Returns a block guarded by the assertion of `value op call` */
BasicBlock blockGuardedBy(int value, string op, ScanfFunctionCall call) {
exists(GuardCondition g, Expr left, Expr right |
right = g.getAChild() and
value = left.getValue().toInt() and
DataFlow::localExprFlow(call, right)
|
g.ensuresEq(left, right, 0, result, true) and op = "=="
or
g.ensuresLt(left, right, 0, result, true) and op = "<"
or
g.ensuresLt(left, right, 1, result, true) and op = "<="
)
}
from ScanfOutput output, ScanfFunctionCall call, Access access
where
output.getCall() = call and
output.hasGuardedAccess(access, false)
select access,
"$@ is read here, but may not have been written. " +
"It should be guarded by a check that the $@ returns at least " +
output.getMinimumGuardConstant() + ".", access, access.toString(), call, call.toString()

View File

@@ -12,4 +12,4 @@
import CommentedOutCode
from CommentedOutCode comment
select comment, "This comment appears to contain commented-out code."
select comment, "This comment appears to contain commented-out code"

View File

@@ -1,6 +1,7 @@
/**
* @name Sign check of bitwise operation
* @description Checking the sign of the result of a bitwise operation may yield unexpected results.
* @description Checking the sign of a bitwise operation often has surprising
* edge cases.
* @kind problem
* @problem.severity warning
* @precision high
@@ -25,4 +26,4 @@ where
forall(int op | op = lhs.(BitwiseAndExpr).getAnOperand().getValue().toInt() | op < 0) and
// exception for cases involving macros
not e.isAffectedByMacro()
select e, "Potentially unsafe sign check of a bitwise operation."
select e, "Potential unsafe sign check of a bitwise operation."

View File

@@ -21,4 +21,4 @@ where
FloatingPointType and
not ro.getAnOperand().isConstant() and // comparisons to constants generate too many false positives
not left.(VariableAccess).getTarget() = right.(VariableAccess).getTarget() // skip self comparison
select ro, "Equality checks on floating point values can yield unexpected results."
select ro, "Equality test on floating point values may not behave as expected."

View File

@@ -13,11 +13,10 @@
import cpp
from EnumSwitch es, float missing, float total, EnumConstant case
from EnumSwitch es, float missing, float total
where
not es.hasDefaultCase() and
missing = count(es.getAMissingCase()) and
total = missing + count(es.getASwitchCase()) and
missing / total < 0.3 and
case = es.getAMissingCase()
select es, "Switch statement does not have a case for $@.", case, case.getName()
missing / total < 0.3
select es, "Switch statement is missing case for " + es.getAMissingCase().getName()

View File

@@ -13,7 +13,7 @@ import SAL
from Parameter p, Call c, Expr arg
where
any(SalNotNull a).getDeclaration() = p and
any(SALNotNull a).getDeclaration() = p and
c.getTarget() = p.getFunction() and
arg = c.getArgument(p.getIndex()) and
nullValue(arg)

View File

@@ -18,7 +18,7 @@ from Function f, FunctionCall call
where
call.getTarget() = f and
call instanceof ExprInVoidContext and
any(SalCheckReturn a).getDeclaration() = f and
any(SALCheckReturn a).getDeclaration() = f and
not getOptions().okToIgnoreReturnValue(call)
select call, "Return value of $@ discarded although a SAL annotation " + "requires inspecting it.",
f, f.getName()

View File

@@ -11,7 +11,7 @@ import SAL
/** Holds if `e` has SAL annotation `name`. */
predicate hasAnnotation(DeclarationEntry e, string name) {
exists(SalAnnotation a |
exists(SALAnnotation a |
a.getMacro().getName() = name and
a.getDeclarationEntry() = e
)
@@ -21,7 +21,7 @@ predicate hasAnnotation(DeclarationEntry e, string name) {
predicate inheritsDeclAnnotations(DeclarationEntry e) {
// Is directly annotated
e.isDefinition() and
exists(SalAnnotation a | a.getMacro().getName() = "_Use_decl_annotations_" |
exists(SALAnnotation a | a.getMacro().getName() = "_Use_decl_annotations_" |
a.getDeclarationEntry() = e
)
or

View File

@@ -8,8 +8,8 @@ import cpp
/**
* A SAL macro defined in `sal.h` or a similar header file.
*/
class SalMacro extends Macro {
SalMacro() {
class SALMacro extends Macro {
SALMacro() {
this.getFile().getBaseName() =
["sal.h", "specstrings_strict.h", "specstrings.h", "w32p.h", "minwindef.h"] and
(
@@ -22,18 +22,15 @@ class SalMacro extends Macro {
}
}
/** DEPRECATED: Alias for SalMacro */
deprecated class SALMacro = SalMacro;
pragma[noinline]
private predicate isTopLevelMacroAccess(MacroAccess ma) { not exists(ma.getParentInvocation()) }
/**
* An invocation of a SAL macro (excluding invocations inside other macros).
*/
class SalAnnotation extends MacroInvocation {
SalAnnotation() {
this.getMacro() instanceof SalMacro and
class SALAnnotation extends MacroInvocation {
SALAnnotation() {
this.getMacro() instanceof SALMacro and
isTopLevelMacroAccess(this)
}
@@ -50,29 +47,23 @@ class SalAnnotation extends MacroInvocation {
}
}
/** DEPRECATED: Alias for SalAnnotation */
deprecated class SALAnnotation = SalAnnotation;
/**
* A SAL macro indicating that the return value of a function should always be
* checked.
*/
class SalCheckReturn extends SalAnnotation {
SalCheckReturn() {
this.getMacro().(SalMacro).getName() = ["_Check_return_", "_Must_inspect_result_"]
class SALCheckReturn extends SALAnnotation {
SALCheckReturn() {
this.getMacro().(SALMacro).getName() = ["_Check_return_", "_Must_inspect_result_"]
}
}
/** DEPRECATED: Alias for SalCheckReturn */
deprecated class SALCheckReturn = SalCheckReturn;
/**
* A SAL macro indicating that a pointer variable or return value should not be
* `NULL`.
*/
class SalNotNull extends SalAnnotation {
SalNotNull() {
exists(SalMacro m | m = this.getMacro() |
class SALNotNull extends SALAnnotation {
SALNotNull() {
exists(SALMacro m | m = this.getMacro() |
not m.getName().matches("%\\_opt\\_%") and
(
m.getName().matches("_In%") or
@@ -89,15 +80,12 @@ class SalNotNull extends SalAnnotation {
}
}
/** DEPRECATED: Alias for SalNotNull */
deprecated class SALNotNull = SalNotNull;
/**
* A SAL macro indicating that a value may be `NULL`.
*/
class SalMaybeNull extends SalAnnotation {
SalMaybeNull() {
exists(SalMacro m | m = this.getMacro() |
class SALMaybeNull extends SALAnnotation {
SALMaybeNull() {
exists(SALMacro m | m = this.getMacro() |
m.getName().matches("%\\_opt\\_%") or
m.getName().matches("\\_Ret_maybenull\\_%") or
m.getName() = "_Result_nullonfailure_"
@@ -105,17 +93,14 @@ class SalMaybeNull extends SalAnnotation {
}
}
/** DEPRECATED: Alias for SalMaybeNull */
deprecated class SALMaybeNull = SalMaybeNull;
/**
* A parameter annotated by one or more SAL annotations.
*/
class SalParameter extends Parameter {
class SALParameter extends Parameter {
/** One of this parameter's annotations. */
SalAnnotation a;
SALAnnotation a;
SalParameter() { annotatesAt(a, this.getADeclarationEntry(), _, _) }
SALParameter() { annotatesAt(a, this.getADeclarationEntry(), _, _) }
predicate isIn() { a.getMacroName().toLowerCase().matches("%\\_in%") }
@@ -124,17 +109,14 @@ class SalParameter extends Parameter {
predicate isInOut() { a.getMacroName().toLowerCase().matches("%\\_inout%") }
}
/** DEPRECATED: Alias for SalParameter */
deprecated class SALParameter = SalParameter;
///////////////////////////////////////////////////////////////////////////////
// Implementation details
/**
* Holds if `a` annotates the declaration entry `d` and
* its start position is the `idx`th position in `file` that holds a SAL element.
*/
private predicate annotatesAt(SalAnnotation a, DeclarationEntry d, File file, int idx) {
annotatesAtPosition(a.(SalElement).getStartPosition(), d, file, idx)
private predicate annotatesAt(SALAnnotation a, DeclarationEntry d, File file, int idx) {
annotatesAtPosition(a.(SALElement).getStartPosition(), d, file, idx)
}
/**
@@ -145,12 +127,12 @@ private predicate annotatesAt(SalAnnotation a, DeclarationEntry d, File file, in
// For performance reasons, do not mention the annotation itself here,
// but compute with positions instead. This performs better on databases
// with many annotations at the same position.
private predicate annotatesAtPosition(SalPosition pos, DeclarationEntry d, File file, int idx) {
private predicate annotatesAtPosition(SALPosition pos, DeclarationEntry d, File file, int idx) {
pos = salRelevantPositionAt(file, idx) and
salAnnotationPos(pos) and
(
// Base case: `pos` right before `d`
d.(SalElement).getStartPosition() = salRelevantPositionAt(file, idx + 1)
d.(SALElement).getStartPosition() = salRelevantPositionAt(file, idx + 1)
or
// Recursive case: `pos` right before some annotation on `d`
annotatesAtPosition(_, d, file, idx + 1)
@@ -161,10 +143,10 @@ private predicate annotatesAtPosition(SalPosition pos, DeclarationEntry d, File
* A SAL element, that is, a SAL annotation or a declaration entry
* that may have SAL annotations.
*/
library class SalElement extends Element {
SalElement() {
containsSalAnnotation(this.(DeclarationEntry).getFile()) or
this instanceof SalAnnotation
library class SALElement extends Element {
SALElement() {
containsSALAnnotation(this.(DeclarationEntry).getFile()) or
this instanceof SALAnnotation
}
predicate hasStartPosition(File file, int line, int col) {
@@ -191,28 +173,25 @@ library class SalElement extends Element {
)
}
SalPosition getStartPosition() {
SALPosition getStartPosition() {
exists(File file, int line, int col |
this.hasStartPosition(file, line, col) and
result = MkSalPosition(file, line, col)
result = MkSALPosition(file, line, col)
)
}
}
/** DEPRECATED: Alias for SalElement */
deprecated class SALElement = SalElement;
/** Holds if `file` contains a SAL annotation. */
pragma[noinline]
private predicate containsSalAnnotation(File file) { any(SalAnnotation a).getFile() = file }
private predicate containsSALAnnotation(File file) { any(SALAnnotation a).getFile() = file }
/**
* A source-file position of a `SALElement`. Unlike location, this denotes a
* point in the file rather than a range.
*/
private newtype SalPosition =
MkSalPosition(File file, int line, int col) {
exists(SalElement e |
private newtype SALPosition =
MkSALPosition(File file, int line, int col) {
exists(SALElement e |
e.hasStartPosition(file, line, col)
or
e.hasEndPosition(file, line, col)
@@ -221,18 +200,18 @@ private newtype SalPosition =
/** Holds if `pos` is the start position of a SAL annotation. */
pragma[noinline]
private predicate salAnnotationPos(SalPosition pos) {
any(SalAnnotation a).(SalElement).getStartPosition() = pos
private predicate salAnnotationPos(SALPosition pos) {
any(SALAnnotation a).(SALElement).getStartPosition() = pos
}
/**
* Gets the `idx`th position in `file` that holds a SAL element,
* ordering positions lexicographically by their start line and start column.
*/
private SalPosition salRelevantPositionAt(File file, int idx) {
private SALPosition salRelevantPositionAt(File file, int idx) {
result =
rank[idx](SalPosition pos, int line, int col |
pos = MkSalPosition(file, line, col)
rank[idx](SALPosition pos, int line, int col |
pos = MkSALPosition(file, line, col)
|
pos order by line, col
)

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

@@ -24,7 +24,7 @@ where
if e = DefinitionInSnapshot()
then defined = ""
else
if e = SuggestiveSalAnnotation()
if e = SuggestiveSALAnnotation()
then defined = "externally defined (SAL) "
else defined = "externally defined (CSV) "
)

View File

@@ -149,7 +149,7 @@ newtype Evidence =
* The function is externally defined, but the parameter has an `_out` SAL annotation which
* suggests that it is initialized in the function.
*/
SuggestiveSalAnnotation() or
SuggestiveSALAnnotation() or
/**
* We have been given a CSV file which indicates this parameter is conditionally initialized.
*/
@@ -198,8 +198,8 @@ class InitializationFunction extends Function {
or
// If we have no definition, we look at SAL annotations
not this.hasDefinition() and
this.getParameter(i).(SalParameter).isOut() and
evidence = SuggestiveSalAnnotation()
this.getParameter(i).(SALParameter).isOut() and
evidence = SuggestiveSALAnnotation()
or
// We have some external information that this function conditionally initializes
not this.hasDefinition() and

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

@@ -19,8 +19,8 @@ import DataFlow::PathGraph
/**
* A configuration for tracking XML objects and their states.
*/
class XxeConfiguration extends DataFlow::Configuration {
XxeConfiguration() { this = "XXEConfiguration" }
class XXEConfiguration extends DataFlow::Configuration {
XXEConfiguration() { this = "XXEConfiguration" }
override predicate isSource(DataFlow::Node node, string flowstate) {
any(XmlLibrary l).configurationSource(node, flowstate)
@@ -45,7 +45,7 @@ class XxeConfiguration extends DataFlow::Configuration {
}
}
from XxeConfiguration conf, DataFlow::PathNode source, DataFlow::PathNode sink
from XXEConfiguration conf, DataFlow::PathNode source, DataFlow::PathNode sink
where conf.hasFlowPath(source, sink)
select sink, source, sink,
"This $@ is not configured to prevent an XML external entity (XXE) attack.", source, "XML parser"

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* The alert message of many queries have been changed to make the message consistent with other languages.

View File

@@ -1,4 +0,0 @@
---
category: newQuery
---
* Added a new medium-precision query, `cpp/missing-check-scanf`, which detects `scanf` output variables that are used without a proper return-value check to see that they were actually written. A variation of this query was originally contributed as an [experimental query by @ihsinme](https://github.com/github/codeql/pull/8246).

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,2 +1,2 @@
---
lastReleaseVersion: 0.3.3
lastReleaseVersion: 0.3.2

View File

@@ -16,17 +16,17 @@ import cpp
// pointers. This will obviously not catch code that uses inline assembly to achieve
// self-modification, nor will it spot the use of OS mechanisms to write into process
// memory (such as WriteProcessMemory under Windows).
predicate maybeSmcConversion(Type t1, Type t2) {
predicate maybeSMCConversion(Type t1, Type t2) {
t1 instanceof FunctionPointerType and
t2 instanceof PointerType and
not t2 instanceof FunctionPointerType and
not t2 instanceof VoidPointerType
or
maybeSmcConversion(t2, t1)
maybeSMCConversion(t2, t1)
}
from Expr e
where
e.fromSource() and
maybeSmcConversion(e.getUnderlyingType(), e.getActualType())
maybeSMCConversion(e.getUnderlyingType(), e.getActualType())
select e, "AV Rule 2: There shall not be any self-modifying code."

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-queries
version: 0.3.4-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

@@ -1,5 +1,5 @@
import cpp
from Class c, boolean ispod
where if c.isPod() then ispod = true else ispod = false
where if c.isPOD() then ispod = true else ispod = false
select c, ispod

View File

@@ -1,5 +1,5 @@
import semmle.code.cpp.PODType03
from Class c, boolean ispod
where if isPodClass03(c) then ispod = true else ispod = false
where if isPODClass03(c) then ispod = true else ispod = false
select c, ispod

View File

@@ -1,4 +1,4 @@
import Microsoft.SAL
from SalAnnotation a
from SALAnnotation a
select a, a.getDeclaration()

View File

@@ -1,3 +1,3 @@
| empty_block.cpp:9:10:9:11 | { ... } | Empty block without comment. |
| empty_block.cpp:12:10:13:3 | { ... } | Empty block without comment. |
| empty_block.cpp:20:10:21:3 | { ... } | Empty block without comment. |
| empty_block.cpp:9:10:9:11 | { ... } | Empty block without comment |
| empty_block.cpp:12:10:13:3 | { ... } | Empty block without comment |
| empty_block.cpp:20:10:21:3 | { ... } | Empty block without comment |

View File

@@ -1,19 +0,0 @@
| test.cpp:30:7:30:7 | i | $@ is read here, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:30:7:30:7 | i | i | test.cpp:29:3:29:7 | call to scanf | call to scanf |
| test.cpp:46:7:46:7 | i | $@ is read here, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:46:7:46:7 | i | i | test.cpp:45:3:45:7 | call to scanf | call to scanf |
| test.cpp:63:7:63:7 | i | $@ is read here, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:63:7:63:7 | i | i | test.cpp:62:3:62:7 | call to scanf | call to scanf |
| test.cpp:75:7:75:7 | i | $@ is read here, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:75:7:75:7 | i | i | test.cpp:74:3:74:7 | call to scanf | call to scanf |
| test.cpp:87:7:87:7 | i | $@ is read here, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:87:7:87:7 | i | i | test.cpp:86:3:86:8 | call to fscanf | call to fscanf |
| test.cpp:94:7:94:7 | i | $@ is read here, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:94:7:94:7 | i | i | test.cpp:93:3:93:8 | call to sscanf | call to sscanf |
| test.cpp:143:8:143:8 | i | $@ is read here, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:143:8:143:8 | i | i | test.cpp:141:7:141:11 | call to scanf | call to scanf |
| test.cpp:152:8:152:8 | i | $@ is read here, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:152:8:152:8 | i | i | test.cpp:150:7:150:11 | call to scanf | call to scanf |
| test.cpp:184:8:184:8 | i | $@ is read here, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:184:8:184:8 | i | i | test.cpp:183:7:183:11 | call to scanf | call to scanf |
| test.cpp:203:8:203:8 | j | $@ is read here, but may not have been written. It should be guarded by a check that the $@ returns at least 2. | test.cpp:203:8:203:8 | j | j | test.cpp:200:7:200:11 | call to scanf | call to scanf |
| test.cpp:227:9:227:9 | d | $@ is read here, but may not have been written. It should be guarded by a check that the $@ returns at least 2. | test.cpp:227:9:227:9 | d | d | test.cpp:225:25:225:29 | call to scanf | call to scanf |
| test.cpp:231:9:231:9 | d | $@ is read here, but may not have been written. It should be guarded by a check that the $@ returns at least 2. | test.cpp:231:9:231:9 | d | d | test.cpp:229:14:229:18 | call to scanf | call to scanf |
| test.cpp:243:7:243:7 | i | $@ is read here, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:243:7:243:7 | i | i | test.cpp:242:3:242:7 | call to scanf | call to scanf |
| test.cpp:251:7:251:7 | i | $@ is read here, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:251:7:251:7 | i | i | test.cpp:250:3:250:7 | call to scanf | call to scanf |
| test.cpp:259:7:259:7 | i | $@ is read here, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:259:7:259:7 | i | i | test.cpp:258:3:258:7 | call to scanf | call to scanf |
| test.cpp:271:7:271:7 | i | $@ is read here, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:271:7:271:7 | i | i | test.cpp:270:3:270:7 | call to scanf | call to scanf |
| test.cpp:281:8:281:12 | ptr_i | $@ is read here, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:281:8:281:12 | ptr_i | ptr_i | test.cpp:280:3:280:7 | call to scanf | call to scanf |
| test.cpp:289:7:289:7 | i | $@ is read here, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:289:7:289:7 | i | i | test.cpp:288:3:288:7 | call to scanf | call to scanf |
| test.cpp:383:25:383:25 | u | $@ is read here, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:383:25:383:25 | u | u | test.cpp:382:6:382:11 | call to sscanf | call to sscanf |

View File

@@ -1 +0,0 @@
Critical/MissingCheckScanf.ql

View File

@@ -1,387 +0,0 @@
typedef struct
{
} FILE;
typedef void *locale_t;
int scanf(const char *format, ...);
int fscanf(FILE *stream, const char *format, ...);
int sscanf(const char *s, const char *format, ...);
int _scanf_l(const char *format, locale_t locale, ...);
void use(int i);
void set_by_ref(int &i);
void set_by_ptr(int *i);
bool maybe();
FILE *get_a_stream();
const char *get_a_string();
extern locale_t get_a_locale();
int main()
{
// --- simple cases ---
{
int i;
scanf("%d", &i);
use(i); // BAD: may not have written `i`
}
{
int i;
if (scanf("%d", &i) == 1)
{
use(i); // GOOD: checks return value
}
}
{
int i = 0;
scanf("%d", &i);
use(i); // BAD. Design choice: already initialized variables shouldn't make a difference.
}
{
int i;
use(i); // GOOD: only care about uses after scanf call
if (scanf("%d", &i) == 1)
{
use(i); // GOOD
}
}
{
int i; // Reused variable
scanf("%d", &i);
use(i); // BAD
if (scanf("%d", &i) == 1)
{
use(i); // GOOD
}
}
{
int i; // Reset variable
scanf("%d", &i);
use(i); // BAD
i = 1;
use(i); // GOOD
}
// --- different scanf functions ---
{
int i;
fscanf(get_a_stream(), "%d", &i);
use(i); // BAD: may not have written `i`
}
{
int i;
sscanf(get_a_string(), "%d", &i);
use(i); // BAD: may not have written `i`
}
{
int i;
if (_scanf_l("%d", get_a_locale(), &i) == 1)
{
use(i); // GOOD
}
}
// --- different ways of checking ---
{
int i;
if (scanf("%d", &i) >= 1)
{
use(i); // GOOD
}
}
{
int i;
if (scanf("%d", &i) == 1)
{
use(i); // GOOD
}
}
{
int i;
if (0 < scanf("%d", &i))
{
if (true)
{
use(i); // GOOD
}
}
}
{
int i;
if (scanf("%d", &i) != 0)
{
use(i); // BAD: scanf can return EOF
}
}
{
int i;
if (scanf("%d", &i) == 0)
{
use(i); // BAD: checks return value incorrectly
}
}
{
int r;
int i;
r = scanf("%d", &i);
if (r >= 1)
{
use(i); // GOOD
}
}
{
bool b;
int i;
b = scanf("%d", &i);
if (b >= 1)
{
use(i); // BAD [NOT DETECTED]: scanf can return EOF (boolifies true)
}
}
{
int i;
if (scanf("%d", &i))
use(i); // BAD
}
{
int i, j;
if (scanf("%d %d", &i) >= 2)
{
use(i); // GOOD
use(j); // GOOD: `j` is not a scanf arg, so out of scope of MissingCheckScanf
}
}
{
int i, j;
if (scanf("%d %d", &i, &j) >= 1)
{
use(i); // GOOD
use(j); // BAD: checks return value incorrectly
}
}
{
int i, j;
if (scanf("%d %d", &i, &j) >= 2)
{
use(i); // GOOD
use(j); // GOOD
}
}
{
char c[5];
int d;
while(maybe()) {
if (maybe()) {
break;
}
else if (maybe() && (scanf("%5c %d", c, &d) == 1)) { // GOOD
use(*(int *)c); // GOOD
use(d); // BAD
}
else if ((scanf("%5c %d", c, &d) == 1) && maybe()) { // GOOD
use(*(int *)c); // GOOD
use(d); // BAD
}
}
}
// --- different initialization ---
{
int i;
i = 0;
scanf("%d", &i);
use(i); // BAD
}
{
int i;
set_by_ref(i);
scanf("%d", &i);
use(i); // BAD
}
{
int i;
set_by_ptr(&i);
scanf("%d", &i);
use(i); // BAD
}
{
int i;
if (maybe())
{
i = 0;
}
scanf("%d", &i);
use(i); // BAD: `i` may not have been initialized
}
// --- different use ---
{
int i;
int *ptr_i = &i;
scanf("%d", &i);
use(*ptr_i); // BAD: may not have written `i`
}
{
int i;
int *ptr_i = &i;
scanf("%d", ptr_i);
use(i); // BAD: may not have written `*ptr_i`
}
{
int i;
scanf("%d", &i);
i = 42;
use(i); // GOOD
}
// --- weird formatting strings ---
{
int i, j;
if (sscanf("123", "%n %*d %n", &i, &j) >= 0)
{
use(i); // GOOD (`%n` does not consume input, but writes 0 to i)
use(j); // GOOD (`%n` does not consume input, but writes 3 to j)
}
}
{
int i;
if (scanf("%% %d", &i) >= 1)
{
use(i); // GOOD (`%%` does not consume input)
}
}
{
int i;
if (scanf("%*d %d", &i) >= 1)
{
use(i); // GOOD (`%*d` does not consume input)
}
}
{
int d, n;
if (scanf("%*d %d %n", &d, &n) == 1) {
use(d); // GOOD
use(n); // GOOD
}
}
{
char substr[32];
int n;
while (sscanf(get_a_string(), "%31[^:]: %d", substr, &n) == 2) { // GOOD: cycle from write to unguarded access
use(*(int *)substr); // GOOD
use(n); // GOOD
}
}
}
// --- Non-local cases ---
bool my_scan_int(int &i)
{
return scanf("%d", &i) == 1; // GOOD
}
void my_scan_int_test()
{
int i;
use(i); // GOOD: used before scanf
my_scan_int(i);
use(i); // BAD [NOT DETECTED]
if (my_scan_int(i))
{
use(i); // GOOD
}
}
// --- Can be OK'd given a sufficiently smart analysis ---
char *my_string_copy() {
static const char SRC_STRING[] = "48656C6C6F";
static char DST_STRING[] = ".....";
int len = sizeof(SRC_STRING) - 1;
const char *src = SRC_STRING;
char *ptr = DST_STRING;
for (int i = 0; i < len; i += 2) {
unsigned int u;
sscanf(src + i, "%2x", &u);
*ptr++ = (char) u; // GOOD [FALSE POSITIVE]? src+i+{0,1} are always valid %x digits, so this should be OK.
}
*ptr++ = 0;
return DST_STRING;
}

View File

@@ -1,20 +1,20 @@
| test2.cpp:37:1:37:39 | // int myFunction() { return myValue; } | This comment appears to contain commented-out code. |
| test2.cpp:39:1:39:45 | // int myFunction() const { return myValue; } | This comment appears to contain commented-out code. |
| test2.cpp:41:1:41:54 | // int myFunction() const noexcept { return myValue; } | This comment appears to contain commented-out code. |
| test2.cpp:43:1:43:18 | // #define MYMACRO | This comment appears to contain commented-out code. |
| test2.cpp:45:1:45:23 | // #include "include.h" | This comment appears to contain commented-out code. |
| test2.cpp:47:1:51:2 | /*\n#ifdef\nvoid myFunction();\n#endif\n*/ | This comment appears to contain commented-out code. |
| test2.cpp:59:1:59:24 | // #if(defined(MYMACRO)) | This comment appears to contain commented-out code. |
| test2.cpp:63:1:63:15 | // #pragma once | This comment appears to contain commented-out code. |
| test2.cpp:65:1:65:17 | // # pragma once | This comment appears to contain commented-out code. |
| test2.cpp:67:1:67:19 | /*#error"myerror"*/ | This comment appears to contain commented-out code. |
| test2.cpp:91:1:95:2 | /*\n#ifdef MYMACRO\n\t// ...\n#endif // #ifdef MYMACRO\n*/ | This comment appears to contain commented-out code. |
| test2.cpp:107:21:107:43 | // #include "config2.h" | This comment appears to contain commented-out code. |
| test2.cpp:115:16:115:35 | /* #ifdef MYMACRO */ | This comment appears to contain commented-out code. |
| test2.cpp:117:1:117:24 | // commented_out_code(); | This comment appears to contain commented-out code. |
| test2.cpp:120:2:120:25 | // commented_out_code(); | This comment appears to contain commented-out code. |
| test.c:2:1:2:22 | // commented out code; | This comment appears to contain commented-out code. |
| test.c:4:1:7:8 | // some; | This comment appears to contain commented-out code. |
| test.c:9:1:13:8 | // also; | This comment appears to contain commented-out code. |
| test.c:21:1:26:2 | /*\n some;\n commented;\n out;\n code;\n*/ | This comment appears to contain commented-out code. |
| test.c:28:1:34:2 | /*\n also;\n this\n is;\n commented-out\n code;\n*/ | This comment appears to contain commented-out code. |
| test2.cpp:37:1:37:39 | // int myFunction() { return myValue; } | This comment appears to contain commented-out code |
| test2.cpp:39:1:39:45 | // int myFunction() const { return myValue; } | This comment appears to contain commented-out code |
| test2.cpp:41:1:41:54 | // int myFunction() const noexcept { return myValue; } | This comment appears to contain commented-out code |
| test2.cpp:43:1:43:18 | // #define MYMACRO | This comment appears to contain commented-out code |
| test2.cpp:45:1:45:23 | // #include "include.h" | This comment appears to contain commented-out code |
| test2.cpp:47:1:51:2 | /*\n#ifdef\nvoid myFunction();\n#endif\n*/ | This comment appears to contain commented-out code |
| test2.cpp:59:1:59:24 | // #if(defined(MYMACRO)) | This comment appears to contain commented-out code |
| test2.cpp:63:1:63:15 | // #pragma once | This comment appears to contain commented-out code |
| test2.cpp:65:1:65:17 | // # pragma once | This comment appears to contain commented-out code |
| test2.cpp:67:1:67:19 | /*#error"myerror"*/ | This comment appears to contain commented-out code |
| test2.cpp:91:1:95:2 | /*\n#ifdef MYMACRO\n\t// ...\n#endif // #ifdef MYMACRO\n*/ | This comment appears to contain commented-out code |
| test2.cpp:107:21:107:43 | // #include "config2.h" | This comment appears to contain commented-out code |
| test2.cpp:115:16:115:35 | /* #ifdef MYMACRO */ | This comment appears to contain commented-out code |
| test2.cpp:117:1:117:24 | // commented_out_code(); | This comment appears to contain commented-out code |
| test2.cpp:120:2:120:25 | // commented_out_code(); | This comment appears to contain commented-out code |
| test.c:2:1:2:22 | // commented out code; | This comment appears to contain commented-out code |
| test.c:4:1:7:8 | // some; | This comment appears to contain commented-out code |
| test.c:9:1:13:8 | // also; | This comment appears to contain commented-out code |
| test.c:21:1:26:2 | /*\n some;\n commented;\n out;\n code;\n*/ | This comment appears to contain commented-out code |
| test.c:28:1:34:2 | /*\n also;\n this\n is;\n commented-out\n code;\n*/ | This comment appears to contain commented-out code |

View File

@@ -1,4 +1,4 @@
| bsc.cpp:2:10:2:32 | ... > ... | Potentially unsafe sign check of a bitwise operation. |
| bsc.cpp:6:10:6:32 | ... > ... | Potentially unsafe sign check of a bitwise operation. |
| bsc.cpp:18:10:18:28 | ... > ... | Potentially unsafe sign check of a bitwise operation. |
| bsc.cpp:22:10:22:28 | ... < ... | Potentially unsafe sign check of a bitwise operation. |
| bsc.cpp:2:10:2:32 | ... > ... | Potential unsafe sign check of a bitwise operation. |
| bsc.cpp:6:10:6:32 | ... > ... | Potential unsafe sign check of a bitwise operation. |
| bsc.cpp:18:10:18:28 | ... > ... | Potential unsafe sign check of a bitwise operation. |
| bsc.cpp:22:10:22:28 | ... < ... | Potential unsafe sign check of a bitwise operation. |

View File

@@ -1,4 +1,4 @@
| c.c:10:5:10:10 | ... == ... | Equality checks on floating point values can yield unexpected results. |
| c.c:14:5:14:14 | ... == ... | Equality checks on floating point values can yield unexpected results. |
| c.c:16:5:16:12 | ... == ... | Equality checks on floating point values can yield unexpected results. |
| c.c:17:5:17:12 | ... == ... | Equality checks on floating point values can yield unexpected results. |
| c.c:10:5:10:10 | ... == ... | Equality test on floating point values may not behave as expected. |
| c.c:14:5:14:14 | ... == ... | Equality test on floating point values may not behave as expected. |
| c.c:16:5:16:12 | ... == ... | Equality test on floating point values may not behave as expected. |
| c.c:17:5:17:12 | ... == ... | Equality test on floating point values may not behave as expected. |

View File

@@ -413,7 +413,7 @@ namespace Semmle.Autobuild.CSharp.Tests
actions.RunProcess["cmd.exe /C dotnet --info"] = 0;
actions.RunProcess[@"cmd.exe /C dotnet clean C:\Project\test.csproj"] = 0;
actions.RunProcess[@"cmd.exe /C dotnet restore C:\Project\test.csproj"] = 0;
actions.RunProcess[@"cmd.exe /C dotnet build --no-incremental C:\Project\test.csproj"] = 0;
actions.RunProcess[@"cmd.exe /C dotnet build --no-incremental /p:UseSharedCompilation=false C:\Project\test.csproj"] = 0;
actions.FileExists["csharp.log"] = true;
actions.FileExists[@"C:\Project\test.csproj"] = true;
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_TRAP_DIR"] = "";
@@ -440,7 +440,7 @@ namespace Semmle.Autobuild.CSharp.Tests
actions.RunProcess["dotnet --info"] = 0;
actions.RunProcess[@"dotnet clean C:\Project/test.csproj"] = 0;
actions.RunProcess[@"dotnet restore C:\Project/test.csproj"] = 0;
actions.RunProcess[@"dotnet build --no-incremental C:\Project/test.csproj"] = 0;
actions.RunProcess[@"dotnet build --no-incremental /p:UseSharedCompilation=false C:\Project/test.csproj"] = 0;
actions.FileExists["csharp.log"] = true;
actions.FileExists[@"C:\Project/test.csproj"] = true;
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_TRAP_DIR"] = "";
@@ -715,9 +715,9 @@ namespace Semmle.Autobuild.CSharp.Tests
public void TestWindowCSharpMsBuild()
{
actions.RunProcess[@"cmd.exe /C C:\Project\.nuget\nuget.exe restore C:\Project\test1.sln -DisableParallelProcessing"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test1.sln /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /P:Fu=Bar"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test1.sln /p:UseSharedCompilation=false /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /p:MvcBuildViews=true /P:Fu=Bar"] = 0;
actions.RunProcess[@"cmd.exe /C C:\Project\.nuget\nuget.exe restore C:\Project\test2.sln -DisableParallelProcessing"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test2.sln /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /P:Fu=Bar"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test2.sln /p:UseSharedCompilation=false /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /p:MvcBuildViews=true /P:Fu=Bar"] = 0;
actions.FileExists["csharp.log"] = true;
actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe"] = false;
actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat"] = false;
@@ -746,9 +746,9 @@ namespace Semmle.Autobuild.CSharp.Tests
public void TestWindowCSharpMsBuildMultipleSolutions()
{
actions.RunProcess[@"cmd.exe /C nuget restore C:\Project\test1.csproj -DisableParallelProcessing"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test1.csproj /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /P:Fu=Bar"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test1.csproj /p:UseSharedCompilation=false /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /p:MvcBuildViews=true /P:Fu=Bar"] = 0;
actions.RunProcess[@"cmd.exe /C nuget restore C:\Project\test2.csproj -DisableParallelProcessing"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test2.csproj /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /P:Fu=Bar"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test2.csproj /p:UseSharedCompilation=false /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /p:MvcBuildViews=true /P:Fu=Bar"] = 0;
actions.FileExists["csharp.log"] = true;
actions.FileExists[@"C:\Project\test1.csproj"] = true;
actions.FileExists[@"C:\Project\test2.csproj"] = true;
@@ -791,7 +791,7 @@ namespace Semmle.Autobuild.CSharp.Tests
public void TestWindowCSharpMsBuildFailed()
{
actions.RunProcess[@"cmd.exe /C nuget restore C:\Project\test1.sln -DisableParallelProcessing"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test1.sln /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /P:Fu=Bar"] = 1;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test1.sln /p:UseSharedCompilation=false /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /p:MvcBuildViews=true /P:Fu=Bar"] = 1;
actions.FileExists["csharp.log"] = true;
actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe"] = false;
actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat"] = false;
@@ -817,8 +817,8 @@ namespace Semmle.Autobuild.CSharp.Tests
[Fact]
public void TestSkipNugetMsBuild()
{
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test1.sln /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /P:Fu=Bar"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test2.sln /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /P:Fu=Bar"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test1.sln /p:UseSharedCompilation=false /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /p:MvcBuildViews=true /P:Fu=Bar"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test2.sln /p:UseSharedCompilation=false /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /p:MvcBuildViews=true /P:Fu=Bar"] = 0;
actions.FileExists["csharp.log"] = true;
actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe"] = false;
actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat"] = false;
@@ -862,7 +862,7 @@ namespace Semmle.Autobuild.CSharp.Tests
actions.RunProcess["dotnet --info"] = 0;
actions.RunProcess[@"dotnet clean C:\Project/test.csproj"] = 0;
actions.RunProcess[@"dotnet restore C:\Project/test.csproj"] = 0;
actions.RunProcess[@"dotnet build --no-incremental --no-restore C:\Project/test.csproj"] = 0;
actions.RunProcess[@"dotnet build --no-incremental /p:UseSharedCompilation=false --no-restore C:\Project/test.csproj"] = 0;
actions.FileExists["csharp.log"] = true;
actions.FileExists[@"C:\Project/test.csproj"] = true;
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_TRAP_DIR"] = "";
@@ -894,7 +894,7 @@ namespace Semmle.Autobuild.CSharp.Tests
actions.RunProcess[@"C:\Project/.dotnet/dotnet --info"] = 0;
actions.RunProcess[@"C:\Project/.dotnet/dotnet clean C:\Project/test.csproj"] = 0;
actions.RunProcess[@"C:\Project/.dotnet/dotnet restore C:\Project/test.csproj"] = 0;
actions.RunProcess[@"C:\Project/.dotnet/dotnet build --no-incremental C:\Project/test.csproj"] = 0;
actions.RunProcess[@"C:\Project/.dotnet/dotnet build --no-incremental /p:UseSharedCompilation=false C:\Project/test.csproj"] = 0;
actions.FileExists["csharp.log"] = true;
actions.FileExists["test.csproj"] = true;
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_TRAP_DIR"] = "";
@@ -929,7 +929,7 @@ namespace Semmle.Autobuild.CSharp.Tests
actions.RunProcess[@"C:\Project/.dotnet/dotnet --info"] = 0;
actions.RunProcess[@"C:\Project/.dotnet/dotnet clean C:\Project/test.csproj"] = 0;
actions.RunProcess[@"C:\Project/.dotnet/dotnet restore C:\Project/test.csproj"] = 0;
actions.RunProcess[@"C:\Project/.dotnet/dotnet build --no-incremental C:\Project/test.csproj"] = 0;
actions.RunProcess[@"C:\Project/.dotnet/dotnet build --no-incremental /p:UseSharedCompilation=false C:\Project/test.csproj"] = 0;
actions.FileExists["csharp.log"] = true;
actions.FileExists["test.csproj"] = true;
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_TRAP_DIR"] = "";
@@ -960,7 +960,7 @@ namespace Semmle.Autobuild.CSharp.Tests
actions.RunProcess[@"cmd.exe /C C:\Project\.dotnet\dotnet --info"] = 0;
actions.RunProcess[@"cmd.exe /C C:\Project\.dotnet\dotnet clean C:\Project\test.csproj"] = 0;
actions.RunProcess[@"cmd.exe /C C:\Project\.dotnet\dotnet restore C:\Project\test.csproj"] = 0;
actions.RunProcess[@"cmd.exe /C C:\Project\.dotnet\dotnet build --no-incremental C:\Project\test.csproj"] = 0;
actions.RunProcess[@"cmd.exe /C C:\Project\.dotnet\dotnet build --no-incremental /p:UseSharedCompilation=false C:\Project\test.csproj"] = 0;
actions.FileExists["csharp.log"] = true;
actions.FileExists[@"C:\Project\test.csproj"] = true;
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_TRAP_DIR"] = "";
@@ -1008,7 +1008,7 @@ namespace Semmle.Autobuild.CSharp.Tests
{
actions.RunProcess[@"cmd.exe /C nuget restore C:\Project\dirs.proj -DisableParallelProcessing"] = 1;
actions.RunProcess[@"cmd.exe /C C:\Project\.nuget\nuget.exe restore C:\Project\dirs.proj -DisableParallelProcessing"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\dirs.proj /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /P:Fu=Bar"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\dirs.proj /p:UseSharedCompilation=false /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /p:MvcBuildViews=true /P:Fu=Bar"] = 0;
actions.FileExists["csharp.log"] = true;
actions.FileExists[@"C:\Project\a\test.csproj"] = true;
actions.FileExists[@"C:\Project\dirs.proj"] = true;
@@ -1052,7 +1052,7 @@ namespace Semmle.Autobuild.CSharp.Tests
{
actions.RunProcess[@"nuget restore C:\Project/dirs.proj -DisableParallelProcessing"] = 1;
actions.RunProcess[@"mono C:\Project/.nuget/nuget.exe restore C:\Project/dirs.proj -DisableParallelProcessing"] = 0;
actions.RunProcess[@"msbuild C:\Project/dirs.proj /t:rebuild"] = 0;
actions.RunProcess[@"msbuild C:\Project/dirs.proj /p:UseSharedCompilation=false /t:rebuild /p:MvcBuildViews=true"] = 0;
actions.FileExists["csharp.log"] = true;
actions.FileExists[@"C:\Project/a/test.csproj"] = true;
actions.FileExists[@"C:\Project/dirs.proj"] = true;

View File

@@ -5,6 +5,7 @@ using Newtonsoft.Json.Linq;
using System.Collections.Generic;
using System.IO;
using Semmle.Util;
using System.Text.RegularExpressions;
using Semmle.Autobuild.Shared;
namespace Semmle.Autobuild.CSharp
@@ -80,6 +81,9 @@ namespace Semmle.Autobuild.CSharp
env = null;
}
if (env is null)
env = new Dictionary<string, string>();
env.Add("UseSharedCompilation", "false");
return f(installDir, env);
});
}
@@ -241,7 +245,8 @@ namespace Semmle.Autobuild.CSharp
Argument("--no-incremental");
return
script.Argument(builder.Options.DotNetArguments).
script.Argument("/p:UseSharedCompilation=false").
Argument(builder.Options.DotNetArguments).
QuoteArgument(projOrSln).
Script;
}

View File

@@ -98,6 +98,8 @@ namespace Semmle.Autobuild.Shared
command.RunCommand(msBuild);
command.QuoteArgument(projectOrSolution.FullPath);
command.Argument("/p:UseSharedCompilation=false");
var target = builder.Options.MsBuildTarget ?? "rebuild";
var platform = builder.Options.MsBuildPlatform ?? (projectOrSolution is ISolution s1 ? s1.DefaultPlatformName : null);
var configuration = builder.Options.MsBuildConfiguration ?? (projectOrSolution is ISolution s2 ? s2.DefaultConfigurationName : null);
@@ -107,6 +109,7 @@ namespace Semmle.Autobuild.Shared
command.Argument(string.Format("/p:Platform=\"{0}\"", platform));
if (configuration is not null)
command.Argument(string.Format("/p:Configuration=\"{0}\"", configuration));
command.Argument("/p:MvcBuildViews=true");
command.Argument(builder.Options.MsBuildArguments);

View File

@@ -35,10 +35,3 @@ options:
the code (for example if it uses inaccessible dependencies).
type: string
pattern: "^(false|true)$"
cil:
title: Whether to enable CIL extraction.
description: >
A value indicating, whether CIL extraction should be enabled.
The default is 'true'.
type: string
pattern: "^(false|true)$"

View File

@@ -9,7 +9,7 @@ Microsoft.Extensions.Caching.Memory,,,46,,,,,,,,,,,,45,1
Microsoft.Extensions.Configuration,,,83,,,,,,,,,,,,80,3
Microsoft.Extensions.DependencyInjection,,,62,,,,,,,,,,,,62,
Microsoft.Extensions.DependencyModel,,,12,,,,,,,,,,,,12,
Microsoft.Extensions.FileProviders,,,16,,,,,,,,,,,,16,
Microsoft.Extensions.FileProviders,,,15,,,,,,,,,,,,15,
Microsoft.Extensions.FileSystemGlobbing,,,15,,,,,,,,,,,,13,2
Microsoft.Extensions.Hosting,,,17,,,,,,,,,,,,16,1
Microsoft.Extensions.Http,,,10,,,,,,,,,,,,10,
@@ -24,5 +24,5 @@ Microsoft.Win32,,,8,,,,,,,,,,,,8,
MySql.Data.MySqlClient,48,,,,,,,,,,48,,,,,
Newtonsoft.Json,,,91,,,,,,,,,,,,73,18
ServiceStack,194,,7,27,,,,,,75,92,,,,7,
System,65,4,12081,,8,8,9,,4,,33,3,1,3,10139,1942
System,43,4,11809,,1,1,1,,4,,33,3,1,3,9867,1942
Windows.Security.Cryptography.Core,1,,,,,,,1,,,,,,,,
1 package sink source summary sink:code sink:encryption-decryptor sink:encryption-encryptor sink:encryption-keyprop sink:encryption-symmetrickey sink:html sink:remote sink:sql sink:xss source:file source:local summary:taint summary:value
9 Microsoft.Extensions.Configuration 83 80 3
10 Microsoft.Extensions.DependencyInjection 62 62
11 Microsoft.Extensions.DependencyModel 12 12
12 Microsoft.Extensions.FileProviders 16 15 16 15
13 Microsoft.Extensions.FileSystemGlobbing 15 13 2
14 Microsoft.Extensions.Hosting 17 16 1
15 Microsoft.Extensions.Http 10 10
24 MySql.Data.MySqlClient 48 48
25 Newtonsoft.Json 91 73 18
26 ServiceStack 194 7 27 75 92 7
27 System 65 43 4 12081 11809 8 1 8 1 9 1 4 33 3 1 3 10139 9867 1942
28 Windows.Security.Cryptography.Core 1 1

View File

@@ -8,7 +8,7 @@ C# framework & library support
Framework / library,Package,Flow sources,Taint & value steps,Sinks (total),`CWE-079` :sub:`Cross-site scripting`
`ServiceStack <https://servicestack.net/>`_,"``ServiceStack.*``, ``ServiceStack``",,7,194,
System,"``System.*``, ``System``",4,12081,65,7
Others,"``Dapper``, ``JsonToItemsTaskFactory``, ``Microsoft.ApplicationBlocks.Data``, ``Microsoft.CSharp``, ``Microsoft.EntityFrameworkCore``, ``Microsoft.Extensions.Caching.Distributed``, ``Microsoft.Extensions.Caching.Memory``, ``Microsoft.Extensions.Configuration``, ``Microsoft.Extensions.DependencyInjection``, ``Microsoft.Extensions.DependencyModel``, ``Microsoft.Extensions.FileProviders``, ``Microsoft.Extensions.FileSystemGlobbing``, ``Microsoft.Extensions.Hosting``, ``Microsoft.Extensions.Http``, ``Microsoft.Extensions.Logging``, ``Microsoft.Extensions.Options``, ``Microsoft.Extensions.Primitives``, ``Microsoft.Interop``, ``Microsoft.NET.Build.Tasks``, ``Microsoft.NETCore.Platforms.BuildTasks``, ``Microsoft.VisualBasic``, ``Microsoft.Win32``, ``MySql.Data.MySqlClient``, ``Newtonsoft.Json``, ``Windows.Security.Cryptography.Core``",,555,138,
Totals,,4,12643,397,7
System,"``System.*``, ``System``",4,11809,43,7
Others,"``Dapper``, ``JsonToItemsTaskFactory``, ``Microsoft.ApplicationBlocks.Data``, ``Microsoft.CSharp``, ``Microsoft.EntityFrameworkCore``, ``Microsoft.Extensions.Caching.Distributed``, ``Microsoft.Extensions.Caching.Memory``, ``Microsoft.Extensions.Configuration``, ``Microsoft.Extensions.DependencyInjection``, ``Microsoft.Extensions.DependencyModel``, ``Microsoft.Extensions.FileProviders``, ``Microsoft.Extensions.FileSystemGlobbing``, ``Microsoft.Extensions.Hosting``, ``Microsoft.Extensions.Http``, ``Microsoft.Extensions.Logging``, ``Microsoft.Extensions.Options``, ``Microsoft.Extensions.Primitives``, ``Microsoft.Interop``, ``Microsoft.NET.Build.Tasks``, ``Microsoft.NETCore.Platforms.BuildTasks``, ``Microsoft.VisualBasic``, ``Microsoft.Win32``, ``MySql.Data.MySqlClient``, ``Newtonsoft.Json``, ``Windows.Security.Cryptography.Core``",,554,138,
Totals,,4,12370,375,7

View File

@@ -1,2 +0,0 @@
description: Introduce '--cil' flag in the comments. This does not make any changes to the dbscheme.
compatibility: full

View File

@@ -13,6 +13,31 @@ namespace Semmle.Extraction.CSharp
{
Extractor.SetInvariantCulture();
Console.WriteLine($"Semmle.Extraction.CSharp.Driver: called with {string.Join(", ", args)}");
if (args.Length > 0 && args[0] == "--dotnetexec")
{
var compilerRegEx = new Regex(@"csc\.exe|mcs\.exe|csc\.dll", RegexOptions.Compiled);
var cil = args.Length > 1 && args[1] == "--cil";
for (var i = cil ? 2 : 1; i < args.Length; i++)
{
if (compilerRegEx.IsMatch(args[i]))
{
var argsList = new List<string>();
if (cil)
argsList.Add("--cil");
argsList.Add("--compiler");
argsList.Add(args[i]);
if (i + 1 < args.Length)
argsList.AddRange(args[(i + 1)..]);
return (int)Extractor.Run(argsList.ToArray());
}
}
Console.WriteLine($"Semmle.Extraction.CSharp.Driver: not a compiler invocation");
return 0;
}
return (int)Extractor.Run(args);
}
}

View File

@@ -56,6 +56,7 @@ namespace Semmle.Extraction.CSharp.Standalone
CSharp.Extractor.SetInvariantCulture();
var options = Options.Create(args);
// options.CIL = true; // To do: Enable this
if (options.Help)
{

View File

@@ -22,7 +22,7 @@ namespace Semmle.Extraction.Tests
{
options = CSharp.Options.CreateWithEnvironment(Array.Empty<string>());
Assert.True(options.Cache);
Assert.True(options.CIL);
Assert.False(options.CIL);
Assert.Null(options.Framework);
Assert.Null(options.CompilerName);
Assert.Empty(options.CompilerArguments);
@@ -51,20 +51,10 @@ namespace Semmle.Extraction.Tests
[Fact]
public void CIL()
{
options = CSharp.Options.CreateWithEnvironment(Array.Empty<string>());
options = CSharp.Options.CreateWithEnvironment(new string[] { "--cil" });
Assert.True(options.CIL);
Environment.SetEnvironmentVariable("CODEQL_EXTRACTOR_CSHARP_OPTION_CIL", "false");
options = CSharp.Options.CreateWithEnvironment(Array.Empty<string>());
options = CSharp.Options.CreateWithEnvironment(new string[] { "--cil", "--nocil" });
Assert.False(options.CIL);
Environment.SetEnvironmentVariable("CODEQL_EXTRACTOR_CSHARP_OPTION_CIL", "true");
options = CSharp.Options.CreateWithEnvironment(Array.Empty<string>());
Assert.True(options.CIL);
Environment.SetEnvironmentVariable("CODEQL_EXTRACTOR_CSHARP_OPTION_CIL", null);
options = CSharp.Options.CreateWithEnvironment(Array.Empty<string>());
Assert.True(options.CIL);
}
[Fact]
@@ -131,6 +121,22 @@ namespace Semmle.Extraction.Tests
Assert.Equal("foo", options.Framework);
}
[Fact]
public void EnvironmentVariables()
{
Environment.SetEnvironmentVariable("LGTM_INDEX_EXTRACTOR", "--cil c");
options = CSharp.Options.CreateWithEnvironment(new string[] { "a", "b" });
Assert.True(options.CIL);
Assert.Equal("a", options.CompilerArguments[0]);
Assert.Equal("b", options.CompilerArguments[1]);
Assert.Equal("c", options.CompilerArguments[2]);
Environment.SetEnvironmentVariable("LGTM_INDEX_EXTRACTOR", "");
Environment.SetEnvironmentVariable("LGTM_INDEX_EXTRACTOR", "--nocil");
options = CSharp.Options.CreateWithEnvironment(new string[] { "--cil" });
Assert.False(options.CIL);
}
[Fact]
public void StandaloneDefaults()
{

View File

@@ -28,7 +28,7 @@ namespace Semmle.Extraction
/// <summary>
/// Holds if CIL should be extracted.
/// </summary>
public bool CIL { get; private set; } = true;
public bool CIL { get; private set; } = false;
/// <summary>
/// Holds if assemblies shouldn't be extracted twice.
@@ -50,6 +50,7 @@ namespace Semmle.Extraction
/// </summary>
public bool QlTest { get; private set; } = false;
/// <summary>
/// The compression algorithm used for trap files.
/// </summary>
@@ -72,9 +73,6 @@ namespace Semmle.Extraction
return true;
}
return false;
case "cil":
CIL = Boolean.Parse(value);
return true;
default:
return false;
}
@@ -99,6 +97,9 @@ namespace Semmle.Extraction
case "cache":
Cache = value;
return true;
case "cil":
CIL = value;
return true;
case "pdb":
PDB = value;
CIL = true;

View File

@@ -17,7 +17,7 @@ namespace Semmle.Util
bool HandleOption(string key, string value);
/// <summary>
/// Handle a flag of the form "--cache" or "--nocache"
/// Handle a flag of the form "--cil" or "--nocil"
/// </summary>
/// <param name="key">The name of the flag. This is case sensitive.</param>
/// <param name="value">True if set, or false if prefixed by "--no"</param>
@@ -40,7 +40,6 @@ namespace Semmle.Util
public static class OptionsExtensions
{
private static readonly string[] ExtractorOptions = new[] { "trap_compression", "cil" };
private static string? GetExtractorOption(string name) =>
Environment.GetEnvironmentVariable($"CODEQL_EXTRACTOR_CSHARP_OPTION_{name.ToUpper()}");
@@ -48,14 +47,12 @@ namespace Semmle.Util
{
var extractorOptions = new List<string>();
foreach (var option in ExtractorOptions)
var trapCompression = GetExtractorOption("trap_compression");
if (!string.IsNullOrEmpty(trapCompression))
{
var value = GetExtractorOption(option);
if (!string.IsNullOrEmpty(value))
{
extractorOptions.Add($"--{option}:{value}");
}
extractorOptions.Add($"--trap_compression:{trapCompression}");
}
return extractorOptions;
}

View File

@@ -1,5 +1,3 @@
## 1.2.4
## 1.2.3
## 1.2.2

View File

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

View File

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

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