Compare commits

..

7 Commits

Author SHA1 Message Date
Nick Rolfe
b8146a1089 Merge remote-tracking branch 'origin/main' into nickrolfe/extractor-performance 2022-01-27 15:06:05 +00:00
Nick Rolfe
ea5d696d55 Ruby: use IndexMap
This is the same idea as Java's LinkedHashMap: it gives the same O(1)
insertion and lookup as HashMap, but preserves insertion order for
iteration.
2021-11-23 11:08:18 +00:00
Nick Rolfe
6908a0dc12 Ruby: avoid repeated construction of table name strings 2021-11-23 11:08:18 +00:00
Nick Rolfe
189e75bfe2 Sort TRAP output
First, emit labels with fresh ids. Then other labels. Then tuples,
grouped by name. Hopefully this will help both with the compression
ratio but also with branch prediction in the TRAP importer.
2021-11-23 11:08:18 +00:00
Nick Rolfe
b502e68783 Ruby: compute path string only once 2021-11-23 11:08:18 +00:00
Nick Rolfe
6d28e87f57 Ruby: separate trap-writer into its own module 2021-11-23 11:08:18 +00:00
Nick Rolfe
5cada400f1 Ruby: pre-compute set of valid types for each field
We were previously doing this during extraction, i.e. for each field
node we encouter, which meant we were repeating a lot of work. The
`type_matches_set` function was a fairly significant hot-spot in
profiling results, so this should improve performance.
2021-11-23 11:08:18 +00:00
517 changed files with 17603 additions and 178512 deletions

View File

@@ -6,7 +6,6 @@
"*/ql/examples/qlpack.yml",
"cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/qlpack.yml",
"javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml",
"javascript/ql/experimental/adaptivethreatmodeling/modelbuilding/qlpack.yml",
"javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml",
"csharp/ql/campaigns/Solorigate/lib/qlpack.yml",
"csharp/ql/campaigns/Solorigate/src/qlpack.yml",

7
.gitattributes vendored
View File

@@ -50,9 +50,4 @@
*.pdb -text
java/ql/test/stubs/**/*.java linguist-generated=true
java/ql/test/experimental/stubs/**/*.java linguist-generated=true
# Generated test files - these are synced from the standard JavaScript libraries using
# `javascript/ql/experimental/adaptivethreatmodeling/test/update_endpoint_test_files.py`.
javascript/ql/experimental/adaptivethreatmodeling/test/endpoint_large_scale/autogenerated/**/*.js linguist-generated=true -merge
javascript/ql/experimental/adaptivethreatmodeling/test/endpoint_large_scale/autogenerated/**/*.ts linguist-generated=true -merge
java/ql/test/experimental/stubs/**/*.java linguist-generated=true

View File

@@ -27,11 +27,6 @@ jobs:
pull-requests: read
steps:
- name: Setup dotnet
uses: actions/setup-dotnet@v1
with:
dotnet-version: 6.0.101
- name: Checkout repository
uses: actions/checkout@v2
@@ -56,7 +51,7 @@ jobs:
# uses a compiled language
- run: |
dotnet build csharp /p:UseSharedCompilation=false
dotnet build csharp
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@main

View File

@@ -1,67 +0,0 @@
name: JS ML-powered queries tests
on:
push:
paths:
- "javascript/ql/experimental/adaptivethreatmodeling/**"
- .github/workflows/js-ml-tests.yml
branches:
- main
- "rc/*"
pull_request:
paths:
- "javascript/ql/experimental/adaptivethreatmodeling/**"
- .github/workflows/js-ml-tests.yml
defaults:
run:
working-directory: javascript/ql/experimental/adaptivethreatmodeling
jobs:
qlformat:
name: Check QL formatting
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ./.github/actions/fetch-codeql
- name: Check QL formatting
run: |
find . "(" -name "*.ql" -or -name "*.qll" ")" -print0 | \
xargs -0 codeql query format --check-only
qlcompile:
name: Check QL compilation
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ./.github/actions/fetch-codeql
- name: Check QL compilation
run: |
codeql query compile \
--check-only \
--ram 5120 \
--additional-packs "${{ github.workspace }}" \
--threads=0 \
-- \
lib modelbuilding src
qltest:
name: Run QL tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ./.github/actions/fetch-codeql
- name: Run QL tests
run: |
codeql test run \
--threads=0 \
--ram 5120 \
--additional-packs "${{ github.workspace }}" \
-- \
test

View File

@@ -1,103 +0,0 @@
name: Models as Data - Diff
on:
workflow_dispatch:
inputs:
projects:
description: "The projects to generate models for"
required: true
default: '["netty/netty"]'
pull_request:
branches:
- main
paths:
- "java/ql/src/utils/model-generator/**/*.*"
- ".github/workflows/mad_modelDiff.yml"
permissions:
contents: read
jobs:
model-diff:
name: Model Difference
runs-on: ubuntu-latest
if: github.repository == 'github/codeql'
strategy:
matrix:
slug: ${{fromJson(github.event.inputs.projects || '["apache/commons-codec", "apache/commons-io", "apache/commons-beanutils", "apache/commons-logging", "apache/commons-fileupload", "apache/commons-lang", "apache/commons-validator", "apache/commons-csv", "apache/dubbo"]' )}}
steps:
- name: Clone github/codeql from PR
uses: actions/checkout@v2
if: github.event.pull_request
with:
path: codeql-pr
- name: Clone github/codeql from main
uses: actions/checkout@v2
with:
path: codeql-main
ref: main
- uses: ./codeql-main/.github/actions/fetch-codeql
- name: Download database
env:
SLUG: ${{ matrix.slug }}
run: |
set -x
mkdir lib-dbs
SHORTNAME=${SLUG//[^a-zA-Z0-9_]/}
projectId=`curl -s https://lgtm.com/api/v1.0/projects/g/${SLUG} | jq .id`
curl -L "https://lgtm.com/api/v1.0/snapshots/$projectId/java" -o "$SHORTNAME.zip"
unzip -q -d "${SHORTNAME}-db" "${SHORTNAME}.zip"
mkdir "lib-dbs/$SHORTNAME/"
mv "${SHORTNAME}-db/"$(ls -1 "${SHORTNAME}"-db)/* "lib-dbs/${SHORTNAME}/"
- name: Generate Models (PR and main)
run: |
set -x
mkdir tmp-models
MODELS=`pwd`/tmp-models
DATABASES=`pwd`/lib-dbs
analyzeDatabaseWithCheckout() {
QL_VARIANT=$1
DATABASE=$2
cd codeql-$QL_VARIANT
SHORTNAME=`basename $DATABASE`
python java/ql/src/utils/model-generator/GenerateFlowModel.py $DATABASE $MODELS/${SHORTNAME}.qll
mv $MODELS/${SHORTNAME}.qll $MODELS/${SHORTNAME}Generated_${QL_VARIANT}.qll
cd ..
}
for d in $DATABASES/*/ ; do
ls -1 "$d"
analyzeDatabaseWithCheckout "main" $d
if [[ "$GITHUB_EVENT_NAME" == "pull_request" ]]
then
analyzeDatabaseWithCheckout "pr" $d
fi
done
- name: Install diff2html
if: github.event.pull_request
run: |
npm install -g diff2html-cli
- name: Generate Model Diff
if: github.event.pull_request
run: |
set -x
MODELS=`pwd`/tmp-models
ls -1 tmp-models/
for m in $MODELS/*_main.qll ; do
t="${m/main/"pr"}"
basename=`basename $m`
name="diff_${basename/_main.qll/""}"
(diff -w -u $m $t | diff2html -i stdin -F $MODELS/$name.html) || true
done
- uses: actions/upload-artifact@v2
with:
name: models
path: tmp-models/*.qll
retention-days: 20
- uses: actions/upload-artifact@v2
with:
name: diffs
path: tmp-models/*.html
retention-days: 20

View File

@@ -1,62 +0,0 @@
name: Regenerate framework models
on:
workflow_dispatch:
schedule:
- cron: "30 2 * * *"
pull_request:
branches:
- main
paths:
- ".github/workflows/mad_regenerate-models.yml"
jobs:
regenerate-models:
runs-on: ubuntu-latest
strategy:
matrix:
# placeholder required for each axis, excluded below, replaced by the actual combinations (see include)
slug: ["placeholder"]
ref: ["placeholder"]
include:
- slug: "apache/commons-io"
ref: "8985de8fe74f6622a419b37a6eed0dbc484dc128"
exclude:
- slug: "placeholder"
ref: "placeholder"
steps:
- name: Clone self (github/codeql)
uses: actions/checkout@v2
- name: Setup CodeQL binaries
uses: ./.github/actions/fetch-codeql
- name: Clone repositories
uses: actions/checkout@v2
with:
path: repos/${{ matrix.ref }}
ref: ${{ matrix.ref }}
repository: ${{ matrix.slug }}
- name: Build database
env:
SLUG: ${{ matrix.slug }}
REF: ${{ matrix.ref }}
run: |
mkdir dbs
cd repos/${REF}
SHORTNAME=${SLUG//[^a-zA-Z0-9_]/}
codeql database create --language=java ../../dbs/${SHORTNAME}
- name: Regenerate models in-place
env:
SLUG: ${{ matrix.slug }}
run: |
SHORTNAME=${SLUG//[^a-zA-Z0-9_]/}
java/ql/src/utils/model-generator/RegenerateModels.py "${SLUG}" dbs/${SHORTNAME}
- name: Stage changes
run: |
find java -name "*.qll" -print0 | xargs -0 git add
git status
git diff --cached > models.patch
- uses: actions/upload-artifact@v2
with:
name: patch
path: models.patch
retention-days: 7

View File

@@ -189,11 +189,4 @@ jobs:
uses: github/codeql-action/analyze@erik-krogh/ql
with:
category: "ql-for-ql-${{ matrix.folder }}"
- name: Copy sarif file to CWD
run: cp ../results/ql.sarif ./${{ matrix.folder }}.sarif
- name: Sarif as artifact
uses: actions/upload-artifact@v2
with:
name: ${{ matrix.folder }}.sarif
path: ${{ matrix.folder }}.sarif

View File

@@ -17,7 +17,7 @@ jobs:
CODEQL_THREADS: 4 # TODO: remove this once it's set by the CLI
strategy:
matrix:
repo:
repo:
- github/codeql
- github/codeql-go
runs-on: ubuntu-latest
@@ -35,7 +35,7 @@ jobs:
~/.cargo/registry
~/.cargo/git
ql/target
key: ${{ runner.os }}-qltest-cargo-${{ hashFiles('ql/**/Cargo.lock') }}
key: ${{ runner.os }}-qltest-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Build Extractor
run: cd ql; env "PATH=$PATH:`dirname ${CODEQL}`" ./create-extractor-pack.sh
env:

View File

@@ -29,24 +29,24 @@ jobs:
~/.cargo/registry
~/.cargo/git
ql/target
key: ${{ runner.os }}-qltest-cargo-${{ hashFiles('ql/**/Cargo.lock') }}
key: ${{ runner.os }}-qltest-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Build extractor
run: |
cd ql;
codeqlpath=$(dirname ${{ steps.find-codeql.outputs.codeql-path }});
env "PATH=$PATH:$codeqlpath" ./create-extractor-pack.sh
- name: Run QL tests
run: |
run: |
"${CODEQL}" test run --check-databases --check-unused-labels --check-repeated-labels --check-redefined-labels --check-use-before-definition --search-path "${{ github.workspace }}/ql/extractor-pack" --consistency-queries ql/ql/consistency-queries ql/ql/test
env:
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
- name: Check QL formatting
run: |
run: |
find ql/ql "(" -name "*.ql" -or -name "*.qll" ")" -print0 | xargs -0 "${CODEQL}" query format --check-only
env:
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
- name: Check QL compilation
run: |
run: |
"${CODEQL}" query compile --check-only --threads=4 --warnings=error --search-path "${{ github.workspace }}/ql/extractor-pack" "ql/ql/src" "ql/ql/examples"
env:
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}

View File

@@ -50,7 +50,7 @@ jobs:
~/.cargo/registry
~/.cargo/git
ruby/target
key: ${{ runner.os }}-ruby-rust-cargo-${{ hashFiles('ruby/rust-toolchain.toml', 'ruby/**/Cargo.lock') }}
key: ${{ runner.os }}-rust-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Check formatting
run: cargo fmt --all -- --check
- name: Build

View File

@@ -24,45 +24,27 @@ defaults:
working-directory: ruby
jobs:
qlformat:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ./.github/actions/fetch-codeql
- name: Check QL formatting
run: find ql "(" -name "*.ql" -or -name "*.qll" ")" -print0 | xargs -0 codeql query format --check-only
qlcompile:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ./.github/actions/fetch-codeql
- name: Check QL compilation
run: |
codeql query compile --check-only --threads=0 --ram 5000 --warnings=error "ql/src" "ql/examples"
env:
GITHUB_TOKEN: ${{ github.token }}
qlupgrade:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ./.github/actions/fetch-codeql
- name: Check DB upgrade scripts
run: |
echo >empty.trap
codeql dataset import -S ql/lib/upgrades/initial/ruby.dbscheme testdb empty.trap
codeql dataset upgrade testdb --additional-packs ql/lib
diff -q testdb/ruby.dbscheme ql/lib/ruby.dbscheme
qltest:
runs-on: ubuntu-latest
strategy:
matrix:
slice: ["1/2", "2/2"]
steps:
- uses: actions/checkout@v2
- uses: ./.github/actions/fetch-codeql
- uses: ./ruby/actions/create-extractor-pack
- name: Run QL tests
run: |
codeql test run --threads=0 --ram 5000 --slice ${{ matrix.slice }} --search-path "${{ github.workspace }}/ruby/extractor-pack" --check-databases --check-unused-labels --check-repeated-labels --check-redefined-labels --check-use-before-definition --consistency-queries ql/consistency-queries ql/test
codeql test run --threads=0 --ram 5000 --search-path "${{ github.workspace }}/ruby/extractor-pack" --check-databases --check-unused-labels --check-repeated-labels --check-redefined-labels --check-use-before-definition --consistency-queries ql/consistency-queries ql/test
env:
GITHUB_TOKEN: ${{ github.token }}
- name: Check QL formatting
run: find ql "(" -name "*.ql" -or -name "*.qll" ")" -print0 | xargs -0 codeql query format --check-only
- name: Check QL compilation
run: |
codeql query compile --check-only --threads=0 --ram 5000 --warnings=error "ql/src" "ql/examples"
env:
GITHUB_TOKEN: ${{ github.token }}
- name: Check DB upgrade scripts
run: |
echo >empty.trap
codeql dataset import -S ql/lib/upgrades/initial/ruby.dbscheme testdb empty.trap
codeql dataset upgrade testdb --additional-packs ql/lib
diff -q testdb/ruby.dbscheme ql/lib/ruby.dbscheme

View File

@@ -1,51 +0,0 @@
# benjamin-buttons.md
This file describes the changes that have been applied to
the library to make it behave as if it was younger.
## TaintedPath.ql
Sinks added between 2020-01-01 and 2020-10-06 have been removed. Found by looking at:
- the commit titles of https://github.com/github/codeql/commits/main/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected
- the PR titles of https://github.com/github/codeql/pulls?page=2&q=is%3Apr+label%3AJS+is%3Aclosed+sink
Sinks added between 2018-08-02 and 2020-01-01 have been removed. Found by looking at:
- the commit titles of https://github.com/github/codeql/commits/main/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected
- the PR titles of https://github.com/github/codeql/pulls?page=2&q=is%3Apr+label%3AJS+is%3Aclosed+sink
- the PR titles of https://github.com/github/codeql/pulls?page=2&q=is%3Apr+label%3AJS+is%3Aclosed+pathinjection
- the PR titles of https://github.com/github/codeql/pulls?page=2&q=is%3Apr+label%3AJS+is%3Aclosed+tainted-path
Sinks from the "graceful-fs" and "fs-extra" (added before the open-sourcing squash).
## Xss.ql
Sinks added between 2020-01-01 and 2020-10-06 have been removed. Found by looking at:
- the commit titles of https://github.com/github/codeql/commits/main/javascript/ql/test/query-tests/Security/CWE-079/Xss.expected
- the PR titles of https://github.com/github/codeql/pulls?page=2&q=is%3Apr+label%3AJS+is%3Aclosed+sink
- recursive type tracking for `jQuery::dollar`, `DOM::domValueRef`.
## SqlInjection.ql
Sinks added between 2020-01-01 and 2020-10-06 have been removed. Found by looking at:
- the commit titles of https://github.com/github/codeql/commits/main/javascript/ql/test/query-tests/Security/CWE-089
- the PR titles of https://github.com/github/codeql/pulls?page=2&q=is%3Apr+label%3AJS+is%3Aclosed+sink
Sinks added between 2018-08-02 and 2020-01-01 have been removed. Found by looking at:
- the commit titles of https://github.com/github/codeql/commits/main/javascript/ql/test/query-tests/Security/CWE-089
- the PR titles of https://github.com/github/codeql/pulls?page=2&q=is%3Apr+label%3AJS+is%3Aclosed+sink
- the PR titles of https://github.com/github/codeql/pulls?page=2&q=is%3Apr+label%3AJS+is%3Aclosed+sql
TypeTracking in SQL.qll (added before the open-sourcing squash)
The model of `mssql` and `sequelize` (added before the open-sourcing squash)
## PseudoProperties
Pseudo-properties (`$name$`) used in type-tracking and global dataflow configurations have been disabled.
Found by searching for `"\$.*\$"`.

View File

@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
<Nullable>enable</Nullable>

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<AssemblyName>Semmle.Autobuild.Cpp</AssemblyName>
<RootNamespace>Semmle.Autobuild.Cpp</RootNamespace>
<ApplicationIcon />

View File

@@ -1,6 +1,4 @@
name: codeql/cpp-examples
groups:
- cpp
- examples
version: 0.0.2
dependencies:
codeql/cpp-all: "*"

View File

@@ -1290,7 +1290,7 @@ class DataFlowCallOption extends TDataFlowCallOption {
}
}
/** A `Content` tagged with the type of a containing object. */
/** Content tagged with the type of a containing object. */
class TypedContent extends MkTypedContent {
private Content c;
private DataFlowType t;

View File

@@ -592,14 +592,12 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
* Holds if data flows from `source` to `sink` in zero or more local
* (intra-procedural) steps.
*/
pragma[inline]
predicate localFlow(Node source, Node sink) { localFlowStep*(source, sink) }
/**
* Holds if data can flow from `e1` to `e2` in zero or more
* local (intra-procedural) steps.
*/
pragma[inline]
predicate localExprFlow(Expr e1, Expr e2) { localFlow(exprNode(e1), exprNode(e2)) }
/**

View File

@@ -124,14 +124,12 @@ predicate localAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeT
* Holds if taint may propagate from `source` to `sink` in zero or more local
* (intra-procedural) steps.
*/
pragma[inline]
predicate localTaint(DataFlow::Node source, DataFlow::Node sink) { localTaintStep*(source, sink) }
/**
* Holds if taint can flow from `e1` to `e2` in zero or more
* local (intra-procedural) steps.
*/
pragma[inline]
predicate localExprTaint(Expr e1, Expr e2) {
localTaint(DataFlow::exprNode(e1), DataFlow::exprNode(e2))
}

View File

@@ -1290,7 +1290,7 @@ class DataFlowCallOption extends TDataFlowCallOption {
}
}
/** A `Content` tagged with the type of a containing object. */
/** Content tagged with the type of a containing object. */
class TypedContent extends MkTypedContent {
private Content c;
private DataFlowType t;

View File

@@ -1032,14 +1032,12 @@ SideEffectInstruction getSideEffectFor(CallInstruction call, int argument) {
* Holds if data flows from `source` to `sink` in zero or more local
* (intra-procedural) steps.
*/
pragma[inline]
predicate localFlow(Node source, Node sink) { localFlowStep*(source, sink) }
/**
* Holds if data can flow from `i1` to `i2` in zero or more
* local (intra-procedural) steps.
*/
pragma[inline]
predicate localInstructionFlow(Instruction e1, Instruction e2) {
localFlow(instructionNode(e1), instructionNode(e2))
}
@@ -1048,7 +1046,6 @@ predicate localInstructionFlow(Instruction e1, Instruction e2) {
* Holds if data can flow from `e1` to `e2` in zero or more
* local (intra-procedural) steps.
*/
pragma[inline]
predicate localExprFlow(Expr e1, Expr e2) { localFlow(exprNode(e1), exprNode(e2)) }
private newtype TContent =

View File

@@ -121,14 +121,12 @@ private predicate operandToInstructionTaintStep(Operand opFrom, Instruction inst
* Holds if taint may propagate from `source` to `sink` in zero or more local
* (intra-procedural) steps.
*/
pragma[inline]
predicate localTaint(DataFlow::Node source, DataFlow::Node sink) { localTaintStep*(source, sink) }
/**
* Holds if taint can flow from `i1` to `i2` in zero or more
* local (intra-procedural) steps.
*/
pragma[inline]
predicate localInstructionTaint(Instruction i1, Instruction i2) {
localTaint(DataFlow::instructionNode(i1), DataFlow::instructionNode(i2))
}
@@ -137,7 +135,6 @@ predicate localInstructionTaint(Instruction i1, Instruction i2) {
* Holds if taint can flow from `e1` to `e2` in zero or more
* local (intra-procedural) steps.
*/
pragma[inline]
predicate localExprTaint(Expr e1, Expr e2) {
localTaint(DataFlow::exprNode(e1), DataFlow::exprNode(e2))
}

View File

@@ -567,13 +567,6 @@ newtype TTranslatedElement =
} or
// The initialization of a base class from within a constructor.
TTranslatedConstructorBaseInit(ConstructorBaseInit init) { not ignoreExpr(init) } or
// Workaround for a case where no base constructor is generated but a targetless base
// constructor call is present.
TTranslatedConstructorBareInit(ConstructorInit init) {
not ignoreExpr(init) and
not init instanceof ConstructorBaseInit and
not init instanceof ConstructorFieldInit
} or
// The destruction of a base class from within a destructor.
TTranslatedDestructorBaseDestruction(DestructorBaseDestruction destruction) {
not ignoreExpr(destruction)

View File

@@ -573,11 +573,6 @@ class TranslatedConstructorInitList extends TranslatedElement, InitializationCon
baseInit = func.(Constructor).getInitializer(id) and
result = getTranslatedConstructorBaseInit(baseInit)
)
or
exists(ConstructorInit bareInit |
bareInit = func.(Constructor).getInitializer(id) and
result = getTranslatedConstructorBareInit(bareInit)
)
}
override Instruction getFirstInstruction() {

View File

@@ -917,36 +917,3 @@ class TranslatedDestructorBaseDestruction extends TranslatedBaseStructorCall,
final override string toString() { result = "destroy base: " + call.toString() }
}
/**
* A constructor base init call where no base constructor has been generated.
*
* Workaround for an extractor issue.
*/
class TranslatedConstructorBareInit extends TranslatedElement, TTranslatedConstructorBareInit {
ConstructorInit init;
TranslatedConstructorBareInit() { this = TTranslatedConstructorBareInit(init) }
override Locatable getAST() { result = init }
final override string toString() { result = "construct base (no constructor)" }
override Instruction getFirstInstruction() { result = getParent().getChildSuccessor(this) }
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
none()
}
override TranslatedElement getChild(int id) { none() }
override Function getFunction() { result = getParent().getFunction() }
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
override Instruction getChildSuccessor(TranslatedElement child) { none() }
}
TranslatedConstructorBareInit getTranslatedConstructorBareInit(ConstructorInit init) {
result.getAST() = init
}

View File

@@ -11,14 +11,15 @@ import semmle.code.cpp.models.interfaces.SideEffect
import semmle.code.cpp.models.interfaces.FlowSource
/**
* The standard functions `fgets` and `fgetws`.
* The standard functions `gets` and `fgets`.
*/
private class FgetsFunction extends DataFlowFunction, TaintFunction, ArrayFunction, AliasFunction,
private class GetsFunction extends DataFlowFunction, TaintFunction, ArrayFunction, AliasFunction,
SideEffectFunction, RemoteFlowSourceFunction {
FgetsFunction() {
GetsFunction() {
// gets(str)
// fgets(str, num, stream)
// fgetws(wstr, num, stream)
this.hasGlobalOrStdOrBslName(["fgets", "fgetws"])
this.hasGlobalOrStdOrBslName(["gets", "fgets", "fgetws"])
}
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
@@ -50,61 +51,20 @@ private class FgetsFunction extends DataFlowFunction, TaintFunction, ArrayFuncti
override predicate hasRemoteFlowSource(FunctionOutput output, string description) {
output.isParameterDeref(0) and
description = "String read by " + this.getName()
or
output.isReturnValue() and
description = "String read by " + this.getName()
}
override predicate hasArrayWithVariableSize(int bufParam, int countParam) {
not this.hasName("gets") and
bufParam = 0 and
countParam = 1
}
override predicate hasArrayWithUnknownSize(int bufParam) {
this.hasName("gets") and
bufParam = 0
}
override predicate hasArrayOutput(int bufParam) { bufParam = 0 }
override predicate hasSocketInput(FunctionInput input) { input.isParameterDeref(2) }
}
/**
* The standard functions `gets`.
*/
private class GetsFunction extends DataFlowFunction, ArrayFunction, AliasFunction,
SideEffectFunction, LocalFlowSourceFunction {
GetsFunction() {
// gets(str)
this.hasGlobalOrStdOrBslName("gets")
}
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
input.isParameter(0) and
output.isReturnValue()
}
override predicate parameterNeverEscapes(int index) { none() }
override predicate parameterEscapesOnlyViaReturn(int index) { index = 0 }
override predicate parameterIsAlwaysReturned(int index) { index = 0 }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = 0 and
buffer = true and
mustWrite = true
}
override predicate hasLocalFlowSource(FunctionOutput output, string description) {
output.isParameterDeref(0) and
description = "String read by " + this.getName()
or
output.isReturnValue() and
description = "String read by " + this.getName()
}
override predicate hasArrayWithUnknownSize(int bufParam) { bufParam = 0 }
override predicate hasArrayOutput(int bufParam) { bufParam = 0 }
override predicate hasSocketInput(FunctionInput input) { input.isParameter(2) }
}

View File

@@ -6,22 +6,122 @@
*/
class Person extends string {
Person() {
this =
[
"Ronil", "Dina", "Ravi", "Bruce", "Jo", "Aida", "Esme", "Charlie", "Fred", "Meera", "Maya",
"Chad", "Tiana", "Laura", "George", "Will", "Mary", "Almira", "Susannah", "Rhoda",
"Cynthia", "Eunice", "Olive", "Virginia", "Angeline", "Helen", "Cornelia", "Harriet",
"Mahala", "Abby", "Margaret", "Deb", "Minerva", "Severus", "Lavina", "Adeline", "Cath",
"Elisa", "Lucretia", "Anne", "Eleanor", "Joanna", "Adam", "Agnes", "Rosanna", "Clara",
"Melissa", "Amy", "Isabel", "Jemima", "Cordelia", "Melinda", "Delila", "Jeremiah", "Elijah",
"Hester", "Walter", "Oliver", "Hugh", "Aaron", "Reuben", "Eli", "Amos", "Augustus",
"Theodore", "Ira", "Timothy", "Cyrus", "Horace", "Simon", "Asa", "Frank", "Nelson",
"Leonard", "Harrison", "Anthony", "Louis", "Milton", "Noah", "Cornelius", "Abdul", "Warren",
"Harvey", "Dennis", "Wesley", "Sylvester", "Gilbert", "Sullivan", "Edmund", "Wilson",
"Perry", "Matthew", "Simba", "Nala", "Rafiki", "Shenzi", "Ernest", "Gertrude", "Oscar",
"Lilian", "Raymond", "Elgar", "Elmer", "Herbert", "Maude", "Mae", "Otto", "Edwin",
"Ophelia", "Parsley", "Sage", "Rosemary", "Thyme", "Garfunkel", "King Basil", "Stephen"
]
this = "Ronil" or
this = "Dina" or
this = "Ravi" or
this = "Bruce" or
this = "Jo" or
this = "Aida" or
this = "Esme" or
this = "Charlie" or
this = "Fred" or
this = "Meera" or
this = "Maya" or
this = "Chad" or
this = "Tiana" or
this = "Laura" or
this = "George" or
this = "Will" or
this = "Mary" or
this = "Almira" or
this = "Susannah" or
this = "Rhoda" or
this = "Cynthia" or
this = "Eunice" or
this = "Olive" or
this = "Virginia" or
this = "Angeline" or
this = "Helen" or
this = "Cornelia" or
this = "Harriet" or
this = "Mahala" or
this = "Abby" or
this = "Margaret" or
this = "Deb" or
this = "Minerva" or
this = "Severus" or
this = "Lavina" or
this = "Adeline" or
this = "Cath" or
this = "Elisa" or
this = "Lucretia" or
this = "Anne" or
this = "Eleanor" or
this = "Joanna" or
this = "Adam" or
this = "Agnes" or
this = "Rosanna" or
this = "Clara" or
this = "Melissa" or
this = "Amy" or
this = "Isabel" or
this = "Jemima" or
this = "Cordelia" or
this = "Melinda" or
this = "Delila" or
this = "Jeremiah" or
this = "Elijah" or
this = "Hester" or
this = "Walter" or
this = "Oliver" or
this = "Hugh" or
this = "Aaron" or
this = "Reuben" or
this = "Eli" or
this = "Amos" or
this = "Augustus" or
this = "Theodore" or
this = "Ira" or
this = "Timothy" or
this = "Cyrus" or
this = "Horace" or
this = "Simon" or
this = "Asa" or
this = "Frank" or
this = "Nelson" or
this = "Leonard" or
this = "Harrison" or
this = "Anthony" or
this = "Louis" or
this = "Milton" or
this = "Noah" or
this = "Cornelius" or
this = "Abdul" or
this = "Warren" or
this = "Harvey" or
this = "Dennis" or
this = "Wesley" or
this = "Sylvester" or
this = "Gilbert" or
this = "Sullivan" or
this = "Edmund" or
this = "Wilson" or
this = "Perry" or
this = "Matthew" or
this = "Simba" or
this = "Nala" or
this = "Rafiki" or
this = "Shenzi" or
this = "Ernest" or
this = "Gertrude" or
this = "Oscar" or
this = "Lilian" or
this = "Raymond" or
this = "Elgar" or
this = "Elmer" or
this = "Herbert" or
this = "Maude" or
this = "Mae" or
this = "Otto" or
this = "Edwin" or
this = "Ophelia" or
this = "Parsley" or
this = "Sage" or
this = "Rosemary" or
this = "Thyme" or
this = "Garfunkel" or
this = "King Basil" or
this = "Stephen"
}
/** Gets the hair color of the person. If the person is bald, there is no result. */
@@ -836,12 +936,25 @@ class Person extends string {
/** Holds if the person is deceased. */
predicate isDeceased() {
this =
[
"Ernest", "Gertrude", "Oscar", "Lilian", "Edwin", "Raymond", "Elgar", "Elmer", "Herbert",
"Maude", "Mae", "Otto", "Ophelia", "Parsley", "Sage", "Rosemary", "Thyme", "Garfunkel",
"King Basil"
]
this = "Ernest" or
this = "Gertrude" or
this = "Oscar" or
this = "Lilian" or
this = "Edwin" or
this = "Raymond" or
this = "Elgar" or
this = "Elmer" or
this = "Herbert" or
this = "Maude" or
this = "Mae" or
this = "Otto" or
this = "Ophelia" or
this = "Parsley" or
this = "Sage" or
this = "Rosemary" or
this = "Thyme" or
this = "Garfunkel" or
this = "King Basil"
}
/** Gets a parent of the person (alive or deceased). */
@@ -1082,7 +1195,12 @@ class Person extends string {
}
/** Holds if the person is allowed in the region. Initially, all villagers are allowed in every region. */
predicate isAllowedIn(string region) { region = ["north", "south", "east", "west"] }
predicate isAllowedIn(string region) {
region = "north" or
region = "south" or
region = "east" or
region = "west"
}
}
/** Returns a parent of the person. */

View File

@@ -14,9 +14,6 @@
*/
import cpp
// We don't actually use the global value numbering library in this query, but without it we end up
// recomputing the IR.
private import semmle.code.cpp.valuenumbering.GlobalValueNumbering
import semmle.code.cpp.ir.IR
import semmle.code.cpp.ir.dataflow.DataFlow::DataFlow

View File

@@ -65,7 +65,6 @@ where
midNode.getNode().asExpr() = mid and
mid = w.getASource() and
dest = w.getDest() and
not dest.(VariableAccess).getTarget().getName() = ["stdin", "stdout", "stderr"] and // exclude calls with standard streams
not isFileName(globalValueNumber(source)) and // file names are not passwords
not exists(string convChar | convChar = w.getSourceConvChar(mid) | not convChar = ["s", "S"]) // ignore things written with other conversion characters
select w, sourceNode, midNode,

View File

@@ -5,7 +5,7 @@
* @kind path-problem
* @problem.severity warning
* @security-severity 7.5
* @precision high
* @precision medium
* @id cpp/cleartext-transmission
* @tags security
* external/cwe/cwe-319
@@ -14,8 +14,8 @@
import cpp
import semmle.code.cpp.security.SensitiveExprs
import semmle.code.cpp.dataflow.TaintTracking
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
import semmle.code.cpp.models.interfaces.FlowSource
import semmle.code.cpp.commons.File
import DataFlow::PathGraph
/**
@@ -27,7 +27,6 @@ class SensitiveNode extends DataFlow::Node {
this.asExpr() = any(SensitiveVariable sv).getInitializer().getExpr() or
this.asExpr().(VariableAccess).getTarget() =
any(SensitiveVariable sv).(GlobalOrNamespaceVariable) or
this.asExpr().(VariableAccess).getTarget() = any(SensitiveVariable v | v instanceof Field) or
this.asUninitialized() instanceof SensitiveVariable or
this.asParameter() instanceof SensitiveVariable or
this.asExpr().(FunctionCall).getTarget() instanceof SensitiveFunction
@@ -59,10 +58,7 @@ class Send extends SendRecv instanceof RemoteFlowSinkFunction {
call.getTarget() = this and
exists(FunctionInput input, int arg |
super.hasSocketInput(input) and
(
input.isParameter(arg) or
input.isParameterDeref(arg)
) and
input.isParameter(arg) and
result = call.getArgument(arg)
)
}
@@ -85,10 +81,7 @@ class Recv extends SendRecv instanceof RemoteFlowSourceFunction {
call.getTarget() = this and
exists(FunctionInput input, int arg |
super.hasSocketInput(input) and
(
input.isParameter(arg) or
input.isParameterDeref(arg)
) and
input.isParameter(arg) and
result = call.getArgument(arg)
)
}
@@ -121,32 +114,24 @@ abstract class NetworkSendRecv extends FunctionCall {
NetworkSendRecv() {
this.getTarget() = target and
// exclude calls based on the socket...
not exists(DataFlow::Node src, DataFlow::Node dest |
DataFlow::localFlow(src, dest) and
dest.asExpr() = target.getSocketExpr(this) and
not exists(GVN g |
g = globalValueNumber(target.getSocketExpr(this)) and
(
// literal constant
src.asExpr() instanceof Literal
globalValueNumber(any(Literal l)) = g
or
// variable (such as a global) initialized to a literal constant
exists(Variable v |
v.getInitializer().getExpr() instanceof Literal and
src.asExpr() = v.getAnAccess()
g = globalValueNumber(v.getAnAccess())
)
or
// result of a function call with literal inputs (likely constant)
forex(Expr arg | arg = src.asExpr().(FunctionCall).getAnArgument() | arg instanceof Literal)
or
// variable called `stdin`, `stdout` or `stderr`
src.asExpr().(VariableAccess).getTarget().getName() = ["stdin", "stdout", "stderr"]
or
// open of `"/dev/tty"`
exists(FunctionCall fc |
fopenCall(fc) and
fc.getAnArgument().getValue() = "/dev/tty" and
src.asExpr() = fc
forex(Expr arg | arg = fc.getAnArgument() | arg instanceof Literal) and
g = globalValueNumber(fc)
)
// (this is not exhaustive)
// (this is far from exhaustive)
)
)
}

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* The "Cleartext transmission of sensitive information" (`cpp/cleartext-transmission`) query now finds more results, where a password is stored in a struct field or class member variable.

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* The `cpp/cleartext-storage-file` query has been improved, removing false positives where data is written to a standard output stream.

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* The "Cleartext transmission of sensitive information" (`cpp/cleartext-transmission`) query has been further improved to reduce false positive results, and upgraded from `medium` to `high` precision.

View File

@@ -1,9 +0,0 @@
void test(){
int a = 8;
int b = 9;
//Useless NonEquals
if(a==8 && a != 7) {}
while(a==8 && a!=7){}
}

View File

@@ -1,18 +0,0 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>Comparison operations like <code>a==8 &amp;&amp; a!=7</code> contain a useless part : the non-equal part. This rule finds tests of this kind within an <code>if</code> or a <code>while</code> statement</p>
</overview>
<recommendation>
<p>Remove the useless comparisons</p>
</recommendation>
<example>
<sample src="UselessTest.cpp" />
</example>
</qhelp>

View File

@@ -1,43 +0,0 @@
/**
* @name Useless Test
* @description A boolean condition that is guaranteed to never be evaluated should be deleted.
* @kind problem
* @problem.severity warning
* @id cpp/uselesstest
* @tags reliability
* readability
*/
import cpp
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
predicate sameExpr(Expr e1, Expr e2) { globalValueNumber(e1).getAnExpr() = e2 }
Element nearestParent(Expr e) {
if
e.getParent().(Expr).getConversion*() instanceof ParenthesisExpr or
e.getParent() instanceof IfStmt or
e.getParent() instanceof WhileStmt
then result = e.getParent()
else result = nearestParent(e.getParent())
}
from LogicalAndExpr b, EQExpr eq, NEExpr ne
where
(
b.getAChild*() = eq and
b.getAChild*() = ne and
eq.getParent() instanceof LogicalAndExpr and
ne.getParent() instanceof LogicalAndExpr
) and
(
eq.getLeftOperand() instanceof VariableAccess and ne.getLeftOperand() instanceof VariableAccess
or
eq.getLeftOperand() instanceof PointerDereferenceExpr and
ne.getLeftOperand() instanceof PointerDereferenceExpr
) and
eq.getRightOperand() instanceof Literal and
ne.getRightOperand() instanceof Literal and
nearestParent(eq) = nearestParent(ne) and
sameExpr(eq.getLeftOperand(), ne.getLeftOperand())
select ne, "Useless Test"

View File

@@ -1,8 +1,6 @@
name: codeql/cpp-queries
version: 0.0.8-dev
groups:
- cpp
- queries
groups: cpp
dependencies:
codeql/cpp-all: "*"
codeql/suite-helpers: "*"

View File

@@ -93,7 +93,7 @@
private import InlineExpectationsTestPrivate
/**
* The base class for tests with inline expectations. The test extends this class to provide the actual
* Base class for tests with inline expectations. The test extends this class to provide the actual
* results of the query, which are then compared with the expected results in comments to produce a
* list of failure messages that point out where the actual results differ from the expected
* results.
@@ -123,15 +123,6 @@ abstract class InlineExpectationsTest extends string {
*/
abstract predicate hasActualResult(Location location, string element, string tag, string value);
/**
* Like `hasActualResult`, but returns results that do not require a matching annotation.
* A failure will still arise if there is an annotation that does not match any results, but not vice versa.
* Override this predicate to specify optional results.
*/
predicate hasOptionalResult(Location location, string element, string tag, string value) {
none()
}
final predicate hasFailureMessage(FailureLocatable element, string message) {
exists(ActualResult actualResult |
actualResult.getTest() = this and
@@ -143,8 +134,7 @@ abstract class InlineExpectationsTest extends string {
)
or
not exists(ValidExpectation expectation | expectation.matchesActualResult(actualResult)) and
message = "Unexpected result: " + actualResult.getExpectationText() and
not actualResult.isOptional()
message = "Unexpected result: " + actualResult.getExpectationText()
)
)
or
@@ -253,13 +243,9 @@ private string expectationPattern() {
private newtype TFailureLocatable =
TActualResult(
InlineExpectationsTest test, Location location, string element, string tag, string value,
boolean optional
InlineExpectationsTest test, Location location, string element, string tag, string value
) {
test.hasActualResult(location, element, tag, value) and
optional = false
or
test.hasOptionalResult(location, element, tag, value) and optional = true
test.hasActualResult(location, element, tag, value)
} or
TValidExpectation(ExpectationComment comment, string tag, string value, string knownFailure) {
exists(TColumn column, string tags |
@@ -291,9 +277,8 @@ class ActualResult extends FailureLocatable, TActualResult {
string element;
string tag;
string value;
boolean optional;
ActualResult() { this = TActualResult(test, location, element, tag, value, optional) }
ActualResult() { this = TActualResult(test, location, element, tag, value) }
override string toString() { result = element }
@@ -304,8 +289,6 @@ class ActualResult extends FailureLocatable, TActualResult {
override string getTag() { result = tag }
override string getValue() { result = value }
predicate isOptional() { optional = true }
}
abstract private class Expectation extends FailureLocatable {

View File

@@ -11332,64 +11332,6 @@ ir.cpp:
# 1447| Type = [Struct] POD_Derived
# 1447| ValueCategory = prvalue
# 1448| getStmt(4): [ReturnStmt] return ...
# 1450| [CopyAssignmentOperator] Inheritance_Test_B& Inheritance_Test_B::operator=(Inheritance_Test_B const&)
# 1450| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const Inheritance_Test_B &
# 1450| [Constructor] void Inheritance_Test_B::Inheritance_Test_B()
# 1450| <params>:
# 1451| [Destructor] void Inheritance_Test_B::~Inheritance_Test_B()
# 1451| <params>:
# 1451| getEntryPoint(): [BlockStmt] { ... }
# 1451| getStmt(0): [ReturnStmt] return ...
# 1451| <destructions>:
# 1454| [CopyAssignmentOperator] Inheritance_Test_A& Inheritance_Test_A::operator=(Inheritance_Test_A const&)
# 1454| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const Inheritance_Test_A &
# 1454| [MoveAssignmentOperator] Inheritance_Test_A& Inheritance_Test_A::operator=(Inheritance_Test_A&&)
# 1454| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [RValueReferenceType] Inheritance_Test_A &&
# 1454| [CopyConstructor] void Inheritance_Test_A::Inheritance_Test_A(Inheritance_Test_A const&)
# 1454| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const Inheritance_Test_A &
# 1454| [MoveConstructor] void Inheritance_Test_A::Inheritance_Test_A(Inheritance_Test_A&&)
# 1454| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [RValueReferenceType] Inheritance_Test_A &&
# 1454| [Destructor] void Inheritance_Test_A::~Inheritance_Test_A()
# 1454| <params>:
# 1457| [Constructor] void Inheritance_Test_A::Inheritance_Test_A()
# 1457| <params>:
# 1457| <initializations>:
# 1457| getInitializer(0): (no string representation)
# 1457| Type = [Struct] Inheritance_Test_B
# 1457| ValueCategory = prvalue
# 1457| getInitializer(1): [ConstructorFieldInit] constructor init of field x
# 1457| Type = [IntType] int
# 1457| ValueCategory = prvalue
# 1457| getExpr(): [Literal] 42
# 1457| Type = [IntType] int
# 1457| Value = [Literal] 42
# 1457| ValueCategory = prvalue
# 1457| getEntryPoint(): [BlockStmt] { ... }
# 1458| getStmt(0): [ExprStmt] ExprStmt
# 1458| getExpr(): [AssignExpr] ... = ...
# 1458| Type = [IntType] int
# 1458| ValueCategory = lvalue
# 1458| getLValue(): [PointerFieldAccess] y
# 1458| Type = [IntType] int
# 1458| ValueCategory = lvalue
# 1458| getQualifier(): [ThisExpr] this
# 1458| Type = [PointerType] Inheritance_Test_A *
# 1458| ValueCategory = prvalue(load)
# 1458| getRValue(): [Literal] 3
# 1458| Type = [IntType] int
# 1458| Value = [Literal] 3
# 1458| ValueCategory = prvalue
# 1459| getStmt(1): [ReturnStmt] return ...
perf-regression.cpp:
# 4| [CopyAssignmentOperator] Big& Big::operator=(Big const&)
# 4| <params>:

View File

@@ -1447,15 +1447,4 @@ void temporary_hierarchy() {
float f = (returnValue<POD_Derived>()).f();
}
struct Inheritance_Test_B {
~Inheritance_Test_B() {}
};
struct Inheritance_Test_A : public Inheritance_Test_B {
int x;
int y;
Inheritance_Test_A() : x(42) {
y = 3;
}
};
// semmle-extractor-options: -std=c++17 --clang

View File

@@ -6626,36 +6626,6 @@
| ir.cpp:1447:44:1447:44 | ChiTotal | total:m1447_5 |
| ir.cpp:1447:44:1447:44 | SideEffect | ~m1447_5 |
| ir.cpp:1447:44:1447:44 | StoreValue | r1447_8 |
| ir.cpp:1451:3:1451:21 | Address | &:r1451_5 |
| ir.cpp:1451:3:1451:21 | Address | &:r1451_5 |
| ir.cpp:1451:3:1451:21 | Address | &:r1451_7 |
| ir.cpp:1451:3:1451:21 | Address | &:r1451_7 |
| ir.cpp:1451:3:1451:21 | ChiPartial | partial:m1451_3 |
| ir.cpp:1451:3:1451:21 | ChiTotal | total:m1451_2 |
| ir.cpp:1451:3:1451:21 | Load | m1451_6 |
| ir.cpp:1451:3:1451:21 | SideEffect | m1451_3 |
| ir.cpp:1451:3:1451:21 | SideEffect | m1451_8 |
| ir.cpp:1457:3:1457:20 | Address | &:r1457_5 |
| ir.cpp:1457:3:1457:20 | Address | &:r1457_5 |
| ir.cpp:1457:3:1457:20 | Address | &:r1457_7 |
| ir.cpp:1457:3:1457:20 | Address | &:r1457_7 |
| ir.cpp:1457:3:1457:20 | ChiPartial | partial:m1457_3 |
| ir.cpp:1457:3:1457:20 | ChiTotal | total:m1457_2 |
| ir.cpp:1457:3:1457:20 | Load | m1457_6 |
| ir.cpp:1457:3:1457:20 | SideEffect | m1457_3 |
| ir.cpp:1457:3:1457:20 | SideEffect | m1458_6 |
| ir.cpp:1457:3:1457:20 | Unary | m1457_6 |
| ir.cpp:1457:26:1457:30 | Address | &:r1457_9 |
| ir.cpp:1457:26:1457:30 | ChiPartial | partial:m1457_11 |
| ir.cpp:1457:26:1457:30 | ChiTotal | total:m1457_8 |
| ir.cpp:1457:26:1457:30 | StoreValue | r1457_10 |
| ir.cpp:1458:5:1458:5 | Address | &:r1458_2 |
| ir.cpp:1458:5:1458:5 | Address | &:r1458_4 |
| ir.cpp:1458:5:1458:5 | Load | m1457_6 |
| ir.cpp:1458:5:1458:5 | Unary | r1458_3 |
| ir.cpp:1458:5:1458:9 | ChiPartial | partial:m1458_5 |
| ir.cpp:1458:5:1458:9 | ChiTotal | total:m1457_12 |
| ir.cpp:1458:9:1458:9 | StoreValue | r1458_1 |
| perf-regression.cpp:6:3:6:5 | Address | &:r6_5 |
| perf-regression.cpp:6:3:6:5 | Address | &:r6_5 |
| perf-regression.cpp:6:3:6:5 | Address | &:r6_7 |

View File

@@ -7858,44 +7858,6 @@ ir.cpp:
# 1443| v1443_5(void) = AliasedUse : ~m?
# 1443| v1443_6(void) = ExitFunction :
# 1451| void Inheritance_Test_B::~Inheritance_Test_B()
# 1451| Block 0
# 1451| v1451_1(void) = EnterFunction :
# 1451| mu1451_2(unknown) = AliasedDefinition :
# 1451| mu1451_3(unknown) = InitializeNonLocal :
# 1451| r1451_4(glval<unknown>) = VariableAddress[#this] :
# 1451| mu1451_5(glval<Inheritance_Test_B>) = InitializeParameter[#this] : &:r1451_4
# 1451| r1451_6(glval<Inheritance_Test_B>) = Load[#this] : &:r1451_4, ~m?
# 1451| mu1451_7(Inheritance_Test_B) = InitializeIndirection[#this] : &:r1451_6
# 1451| v1451_8(void) = NoOp :
# 1451| v1451_9(void) = ReturnIndirection[#this] : &:r1451_6, ~m?
# 1451| v1451_10(void) = ReturnVoid :
# 1451| v1451_11(void) = AliasedUse : ~m?
# 1451| v1451_12(void) = ExitFunction :
# 1457| void Inheritance_Test_A::Inheritance_Test_A()
# 1457| Block 0
# 1457| v1457_1(void) = EnterFunction :
# 1457| mu1457_2(unknown) = AliasedDefinition :
# 1457| mu1457_3(unknown) = InitializeNonLocal :
# 1457| r1457_4(glval<unknown>) = VariableAddress[#this] :
# 1457| mu1457_5(glval<Inheritance_Test_A>) = InitializeParameter[#this] : &:r1457_4
# 1457| r1457_6(glval<Inheritance_Test_A>) = Load[#this] : &:r1457_4, ~m?
# 1457| mu1457_7(Inheritance_Test_A) = InitializeIndirection[#this] : &:r1457_6
# 1457| r1457_8(glval<int>) = FieldAddress[x] : mu1457_5
# 1457| r1457_9(int) = Constant[42] :
# 1457| mu1457_10(int) = Store[?] : &:r1457_8, r1457_9
# 1458| r1458_1(int) = Constant[3] :
# 1458| r1458_2(glval<unknown>) = VariableAddress[#this] :
# 1458| r1458_3(Inheritance_Test_A *) = Load[#this] : &:r1458_2, ~m?
# 1458| r1458_4(glval<int>) = FieldAddress[y] : r1458_3
# 1458| mu1458_5(int) = Store[?] : &:r1458_4, r1458_1
# 1459| v1459_1(void) = NoOp :
# 1457| v1457_11(void) = ReturnIndirection[#this] : &:r1457_6, ~m?
# 1457| v1457_12(void) = ReturnVoid :
# 1457| v1457_13(void) = AliasedUse : ~m?
# 1457| v1457_14(void) = ExitFunction :
perf-regression.cpp:
# 6| void Big::Big()
# 6| Block 0

View File

@@ -1,10 +1,8 @@
edges
| test.cpp:54:17:54:20 | argv | test.cpp:58:25:58:29 | input |
nodes
| test2.cpp:110:3:110:6 | call to gets | semmle.label | call to gets |
| test.cpp:54:17:54:20 | argv | semmle.label | argv |
| test.cpp:58:25:58:29 | input | semmle.label | input |
subpaths
#select
| test2.cpp:110:3:110:6 | call to gets | test2.cpp:110:3:110:6 | call to gets | test2.cpp:110:3:110:6 | call to gets | This write into buffer 'password' may contain unencrypted data from $@ | test2.cpp:110:3:110:6 | call to gets | user input (String read by gets) |
| test.cpp:58:3:58:9 | call to sprintf | test.cpp:54:17:54:20 | argv | test.cpp:58:25:58:29 | input | This write into buffer 'passwd' may contain unencrypted data from $@ | test.cpp:54:17:54:20 | argv | user input (a command-line argument) |

View File

@@ -1,5 +1,4 @@
edges
| test2.cpp:63:24:63:31 | password | test2.cpp:63:16:63:20 | call to crypt |
| test3.cpp:17:28:17:36 | password1 | test3.cpp:22:15:22:23 | password1 |
| test3.cpp:17:51:17:59 | password2 | test3.cpp:26:15:26:23 | password2 |
| test3.cpp:45:8:45:15 | password | test3.cpp:47:15:47:22 | password |
@@ -90,16 +89,11 @@ edges
| test3.cpp:398:18:398:25 | password | test3.cpp:400:15:400:23 | & ... |
| test3.cpp:398:18:398:25 | password | test3.cpp:400:16:400:23 | password |
| test3.cpp:398:18:398:25 | password | test3.cpp:400:33:400:40 | password |
| test3.cpp:421:21:421:28 | password | test3.cpp:421:3:421:17 | call to decrypt_inplace |
| test3.cpp:429:7:429:14 | password | test3.cpp:431:8:431:15 | password |
| test.cpp:41:23:41:43 | cleartext password! | test.cpp:48:21:48:27 | call to encrypt |
| test.cpp:41:23:41:43 | cleartext password! | test.cpp:48:29:48:39 | thePassword |
| test.cpp:66:23:66:43 | cleartext password! | test.cpp:76:21:76:27 | call to encrypt |
| test.cpp:66:23:66:43 | cleartext password! | test.cpp:76:29:76:39 | thePassword |
nodes
| test2.cpp:63:16:63:20 | call to crypt | semmle.label | call to crypt |
| test2.cpp:63:24:63:31 | password | semmle.label | password |
| test2.cpp:63:24:63:31 | password | semmle.label | password |
| test3.cpp:17:28:17:36 | password1 | semmle.label | password1 |
| test3.cpp:17:51:17:59 | password2 | semmle.label | password2 |
| test3.cpp:22:15:22:23 | password1 | semmle.label | password1 |
@@ -214,13 +208,6 @@ nodes
| test3.cpp:400:15:400:23 | & ... | semmle.label | & ... |
| test3.cpp:400:16:400:23 | password | semmle.label | password |
| test3.cpp:400:33:400:40 | password | semmle.label | password |
| test3.cpp:414:17:414:24 | password | semmle.label | password |
| test3.cpp:420:17:420:24 | password | semmle.label | password |
| test3.cpp:421:3:421:17 | call to decrypt_inplace | semmle.label | call to decrypt_inplace |
| test3.cpp:421:21:421:28 | password | semmle.label | password |
| test3.cpp:421:21:421:28 | password | semmle.label | password |
| test3.cpp:429:7:429:14 | password | semmle.label | password |
| test3.cpp:431:8:431:15 | password | semmle.label | password |
| test.cpp:41:23:41:43 | cleartext password! | semmle.label | cleartext password! |
| test.cpp:48:21:48:27 | call to encrypt | semmle.label | call to encrypt |
| test.cpp:48:29:48:39 | thePassword | semmle.label | thePassword |
@@ -251,6 +238,3 @@ subpaths
| test3.cpp:300:2:300:5 | call to send | test3.cpp:308:58:308:66 | password2 | test3.cpp:300:14:300:17 | data | This operation transmits 'data', which may contain unencrypted sensitive data from $@ | test3.cpp:308:58:308:66 | password2 | password2 |
| test3.cpp:341:4:341:7 | call to recv | test3.cpp:339:9:339:16 | password | test3.cpp:341:16:341:23 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:339:9:339:16 | password | password |
| test3.cpp:388:3:388:6 | call to recv | test3.cpp:386:8:386:15 | password | test3.cpp:388:15:388:22 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:386:8:386:15 | password | password |
| test3.cpp:414:3:414:6 | call to recv | test3.cpp:414:17:414:24 | password | test3.cpp:414:17:414:24 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:414:17:414:24 | password | password |
| test3.cpp:420:3:420:6 | call to recv | test3.cpp:420:17:420:24 | password | test3.cpp:420:17:420:24 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:420:17:420:24 | password | password |
| test3.cpp:431:2:431:6 | call to fgets | test3.cpp:429:7:429:14 | password | test3.cpp:431:8:431:15 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:429:7:429:14 | password | password |

View File

@@ -99,14 +99,3 @@ void tests(FILE *log, myStruct &s)
fprintf(log, "log: %s", buffer); // BAD
}
}
char *gets(char *s);
void test_gets()
{
{
char password[1024];
gets(password); // BAD
}
}

View File

@@ -411,66 +411,13 @@ void test_member_password()
{
packet p;
recv(val(), p.password, 256, val()); // BAD: not encrypted
recv(val(), p.password, 256, val()); // BAD: not encrypted [NOT DETECTED]
}
{
packet p;
recv(val(), p.password, 256, val()); // GOOD: password is encrypted [FALSE POSITIVE]
recv(val(), p.password, 256, val()); // GOOD: password is encrypted
decrypt_inplace(p.password); // proof that `password` was in fact encrypted
}
}
extern FILE *stdin;
void test_stdin_param(FILE *stream)
{
char password[128];
fgets(password, 128, stream); // GOOD: from standard input (see call below) [FALSE POSITIVE]
}
void test_stdin()
{
char password[128];
FILE *f = stdin;
fgets(password, 128, stdin); // GOOD: from standard input
fgets(password, 128, f); // GOOD: from standard input
test_stdin_param(stdin);
}
int open(const char *filename, int b);
void test_tty()
{
{
char password[256];
int f;
f = open("/dev/tty", val());
recv(f, password, 256, val()); // GOOD: from terminal
}
{
char password[256];
int f;
f = STDIN_FILENO;
recv(f, password, 256, val()); // GOOD: from stdin
}
{
char password[256];
int f;
f = open("/dev/tty", val());
if (f == -1)
{
f = STDIN_FILENO;
}
recv(f, password, 256, val()); // GOOD: from terminal or stdin
}
}

View File

@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
<Nullable>enable</Nullable>

View File

@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<AssemblyName>Semmle.Autobuild.CSharp</AssemblyName>
<RootNamespace>Semmle.Autobuild.CSharp</RootNamespace>
<ApplicationIcon/>

View File

@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<AssemblyName>Semmle.Autobuild.Shared</AssemblyName>
<RootNamespace>Semmle.Autobuild.Shared</RootNamespace>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>

View File

@@ -1,3 +0,0 @@
description: Remove 'kind' from 'attributes'.
compatability: full
attributes.rel: reorder attributes.rel (int id, int kind, int type_id, int target) id type_id target

View File

@@ -1,2 +0,0 @@
description: Support for compiler-generated event accessors.
compatibility: backwards

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<AssemblyName>Semmle.Extraction.CIL.Driver</AssemblyName>
<RootNamespace>Semmle.Extraction.CIL.Driver</RootNamespace>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<AssemblyName>Semmle.Extraction.CIL</AssemblyName>
<RootNamespace>Semmle.Extraction.CIL</RootNamespace>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>

View File

@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<AssemblyName>Semmle.Extraction.CSharp.Driver</AssemblyName>
<RootNamespace>Semmle.Extraction.CSharp.Driver</RootNamespace>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>

View File

@@ -146,7 +146,7 @@ namespace Semmle.BuildAnalyser
* loading the same assembly from different locations.
*/
using var pereader = new System.Reflection.PortableExecutable.PEReader(new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read));
using var sha1 = SHA1.Create();
using var sha1 = new SHA1CryptoServiceProvider();
var metadata = pereader.GetMetadata();
unsafe
{

View File

@@ -160,7 +160,7 @@ namespace Semmle.BuildAnalyser
{
var bytes = Encoding.Unicode.GetBytes(srcDir);
using var sha1 = SHA1.Create();
using var sha1 = new SHA1CryptoServiceProvider();
var sha = sha1.ComputeHash(bytes);
var sb = new StringBuilder();
foreach (var b in sha.Take(8))

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<AssemblyName>Semmle.Extraction.CSharp.Standalone</AssemblyName>
<RootNamespace>Semmle.Extraction.CSharp.Standalone</RootNamespace>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>

View File

@@ -6,15 +6,11 @@ namespace Semmle.Extraction.CSharp.Entities
{
internal class Accessor : Method
{
private readonly IPropertySymbol property;
protected Accessor(Context cx, IMethodSymbol init, IPropertySymbol property)
: base(cx, init)
{
this.property = property;
}
protected Accessor(Context cx, IMethodSymbol init)
: base(cx, init) { }
/// <summary>
/// Gets the property symbol associated with accessor `symbol`, or `null`
/// Gets the property symbol associated accessor `symbol`, or `null`
/// if there is no associated symbol.
/// </summary>
public static IPropertySymbol? GetPropertySymbol(IMethodSymbol symbol)
@@ -30,26 +26,39 @@ namespace Semmle.Extraction.CSharp.Entities
return props.SingleOrDefault();
}
/// <summary>
/// Gets the property symbol associated with this accessor.
/// </summary>
private IPropertySymbol? PropertySymbol => GetPropertySymbol(Symbol);
public new Accessor OriginalDefinition => Create(Context, Symbol.OriginalDefinition);
public override void Populate(TextWriter trapFile)
{
PopulateMethod(trapFile);
PopulateModifiers(trapFile);
ContainingType!.PopulateGenerics();
var parent = Property.Create(Context, property);
var prop = PropertySymbol;
if (prop is null)
{
var type = Symbol.AssociatedSymbol?.GetType().ToString() ?? "null";
Context.ModelError(Symbol, $"Unhandled accessor associated symbol of type {type}");
return;
}
var parent = Property.Create(Context, prop);
int kind;
Accessor unboundAccessor;
if (SymbolEqualityComparer.Default.Equals(Symbol, property.GetMethod))
if (SymbolEqualityComparer.Default.Equals(Symbol, prop.GetMethod))
{
kind = 1;
var orig = property.OriginalDefinition;
unboundAccessor = Create(Context, orig.GetMethod!, orig);
unboundAccessor = Create(Context, prop.OriginalDefinition.GetMethod!);
}
else if (SymbolEqualityComparer.Default.Equals(Symbol, property.SetMethod))
else if (SymbolEqualityComparer.Default.Equals(Symbol, prop.SetMethod))
{
kind = 2;
var orig = property.OriginalDefinition;
unboundAccessor = Create(Context, orig.SetMethod!, orig);
unboundAccessor = Create(Context, prop.OriginalDefinition.SetMethod!);
}
else
{
@@ -75,14 +84,14 @@ namespace Semmle.Extraction.CSharp.Entities
}
}
public static Accessor Create(Context cx, IMethodSymbol symbol, IPropertySymbol prop) =>
AccessorFactory.Instance.CreateEntity(cx, symbol, (symbol, prop));
public static new Accessor Create(Context cx, IMethodSymbol symbol) =>
AccessorFactory.Instance.CreateEntityFromSymbol(cx, symbol);
private class AccessorFactory : CachedEntityFactory<(IMethodSymbol, IPropertySymbol), Accessor>
private class AccessorFactory : CachedEntityFactory<IMethodSymbol, Accessor>
{
public static AccessorFactory Instance { get; } = new AccessorFactory();
public override Accessor Create(Context cx, (IMethodSymbol, IPropertySymbol) init) => new(cx, init.Item1, init.Item2);
public override Accessor Create(Context cx, IMethodSymbol init) => new Accessor(cx, init);
}
}
}

View File

@@ -1,5 +1,3 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.CodeAnalysis;
@@ -8,28 +6,18 @@ using Semmle.Extraction.Entities;
namespace Semmle.Extraction.CSharp.Entities
{
internal enum AttributeKind
{
Default = 0,
Return = 1,
Assembly = 2,
Module = 3,
}
internal class Attribute : CachedEntity<AttributeData>, IExpressionParentEntity
{
bool IExpressionParentEntity.IsTopLevelParent => true;
private readonly AttributeSyntax? attributeSyntax;
private readonly IEntity entity;
private readonly AttributeKind kind;
private Attribute(Context cx, AttributeData attributeData, IEntity entity, AttributeKind kind)
private Attribute(Context cx, AttributeData attributeData, IEntity entity)
: base(cx, attributeData)
{
this.attributeSyntax = attributeData.ApplicationSyntaxReference?.GetSyntax() as AttributeSyntax;
this.entity = entity;
this.kind = kind;
}
public override void WriteId(EscapingTextWriter trapFile)
@@ -60,7 +48,7 @@ namespace Semmle.Extraction.CSharp.Entities
public override void Populate(TextWriter trapFile)
{
var type = Type.Create(Context, Symbol.AttributeClass);
trapFile.attributes(this, kind, type.TypeRef, entity);
trapFile.attributes(this, type.TypeRef, entity);
trapFile.attribute_location(this, Location);
if (attributeSyntax is not null)
@@ -137,36 +125,26 @@ namespace Semmle.Extraction.CSharp.Entities
public override bool NeedsPopulation => true;
private static void ExtractAttributes(Context cx, IEnumerable<AttributeData> attributes, IEntity entity, AttributeKind kind)
{
foreach (var attribute in attributes)
{
Create(cx, attribute, entity, kind);
}
}
public static void ExtractAttributes(Context cx, ISymbol symbol, IEntity entity)
{
ExtractAttributes(cx, symbol.GetAttributes(), entity, AttributeKind.Default);
if (symbol is IMethodSymbol method)
foreach (var attribute in symbol.GetAttributes())
{
ExtractAttributes(cx, method.GetReturnTypeAttributes(), entity, AttributeKind.Return);
Create(cx, attribute, entity);
}
}
public static Attribute Create(Context cx, AttributeData attributeData, IEntity entity, AttributeKind kind)
public static Attribute Create(Context cx, AttributeData attributeData, IEntity entity)
{
var init = (attributeData, entity, kind);
var init = (attributeData, entity);
return AttributeFactory.Instance.CreateEntity(cx, attributeData, init);
}
private class AttributeFactory : CachedEntityFactory<(AttributeData attributeData, IEntity receiver, AttributeKind kind), Attribute>
private class AttributeFactory : CachedEntityFactory<(AttributeData attributeData, IEntity receiver), Attribute>
{
public static readonly AttributeFactory Instance = new AttributeFactory();
public override Attribute Create(Context cx, (AttributeData attributeData, IEntity receiver, AttributeKind kind) init) =>
new Attribute(cx, init.attributeData, init.receiver, init.kind);
public override Attribute Create(Context cx, (AttributeData attributeData, IEntity receiver) init) =>
new Attribute(cx, init.attributeData, init.receiver);
}
}
}

View File

@@ -3,46 +3,45 @@ using System.IO;
namespace Semmle.Extraction.CSharp.Entities
{
internal class EventAccessor : Method
internal class EventAccessor : Accessor
{
private readonly IEventSymbol @event;
private EventAccessor(Context cx, IMethodSymbol init, IEventSymbol @event)
: base(cx, init)
{
this.@event = @event;
}
private EventAccessor(Context cx, IMethodSymbol init)
: base(cx, init) { }
/// <summary>
/// Gets the event symbol associated with accessor `symbol`, or `null`
/// if there is no associated symbol.
/// Gets the event symbol associated with this accessor.
/// </summary>
public static IEventSymbol? GetEventSymbol(IMethodSymbol symbol) =>
symbol.AssociatedSymbol as IEventSymbol;
private IEventSymbol? EventSymbol => Symbol.AssociatedSymbol as IEventSymbol;
public override void Populate(TextWriter trapFile)
{
PopulateMethod(trapFile);
ContainingType!.PopulateGenerics();
var @event = EventSymbol;
if (@event is null)
{
var type = Symbol.AssociatedSymbol?.GetType().ToString() ?? "null";
Context.ModelError(Symbol, $"Unhandled event accessor associated symbol of type {type}");
return;
}
var parent = Event.Create(Context, @event);
int kind;
EventAccessor unboundAccessor;
if (SymbolEqualityComparer.Default.Equals(Symbol, @event.AddMethod))
{
kind = 1;
var orig = @event.OriginalDefinition;
unboundAccessor = Create(Context, orig.AddMethod!, orig);
unboundAccessor = Create(Context, @event.OriginalDefinition.AddMethod!);
}
else if (SymbolEqualityComparer.Default.Equals(Symbol, @event.RemoveMethod))
{
kind = 2;
var orig = @event.OriginalDefinition;
unboundAccessor = Create(Context, orig.RemoveMethod!, orig);
unboundAccessor = Create(Context, @event.OriginalDefinition.RemoveMethod!);
}
else
{
Context.ModelError(Symbol, $"Undhandled event accessor kind {Symbol.ToDisplayString()}");
Context.ModelError(Symbol, "Undhandled event accessor kind");
return;
}
@@ -52,21 +51,16 @@ namespace Semmle.Extraction.CSharp.Entities
trapFile.event_accessor_location(this, l);
Overrides(trapFile);
if (Symbol.FromSource() && Block is null)
{
trapFile.compiler_generated(this);
}
}
public static EventAccessor Create(Context cx, IMethodSymbol symbol, IEventSymbol @event) =>
EventAccessorFactory.Instance.CreateEntity(cx, symbol, (symbol, @event));
public static new EventAccessor Create(Context cx, IMethodSymbol symbol) =>
EventAccessorFactory.Instance.CreateEntityFromSymbol(cx, symbol);
private class EventAccessorFactory : CachedEntityFactory<(IMethodSymbol, IEventSymbol), EventAccessor>
private class EventAccessorFactory : CachedEntityFactory<IMethodSymbol, EventAccessor>
{
public static EventAccessorFactory Instance { get; } = new EventAccessorFactory();
public override EventAccessor Create(Context cx, (IMethodSymbol, IEventSymbol) init) => new EventAccessor(cx, init.Item1, init.Item2);
public override EventAccessor Create(Context cx, IMethodSymbol init) => new EventAccessor(cx, init);
}
}
}

View File

@@ -1,5 +1,3 @@
using System;
using System.Collections.Generic;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
using Semmle.Extraction.Entities;
@@ -12,69 +10,17 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
base(new ExpressionInfo(cx, null, cx.CreateLocation(pp.GetLocation()), ExprKind.PROPERTY_PATTERN, parent, child, false, null))
{
child = 0;
var trapFile = cx.TrapWriter.Writer;
foreach (var sub in pp.Subpatterns)
{
if (sub.ExpressionColon is null)
var p = Expressions.Pattern.Create(cx, sub.Pattern, this, child++);
if (sub.NameColon is null)
{
Context.ModelError(sub, "Expected to find 'Expression:' in pattern.");
Context.ModelError(sub, "Expected to find 'Name:' in pattern.");
continue;
}
MakeExpressions(cx, this, sub, child++);
trapFile.exprorstmt_name(p, sub.NameColon.Name.ToString());
}
}
private record AccessStep(string Identifier, Microsoft.CodeAnalysis.Location Location);
private class AccessStepPack
{
public readonly List<AccessStep> Prefix = new List<AccessStep>();
public AccessStep Last { get; private set; }
public AccessStepPack Add(string identifier, Microsoft.CodeAnalysis.Location location)
{
Prefix.Add(Last);
Last = new AccessStep(identifier, location);
return this;
}
public AccessStepPack(string identifier, Microsoft.CodeAnalysis.Location location) =>
Last = new AccessStep(identifier, location);
}
private static AccessStepPack GetAccessStepPack(ExpressionSyntax syntax) =>
syntax switch
{
MemberAccessExpressionSyntax memberAccess => GetAccessStepPack(memberAccess.Expression).Add(memberAccess.Name.Identifier.ValueText, memberAccess.Name.Identifier.GetLocation()),
IdentifierNameSyntax identifier => new AccessStepPack(identifier.Identifier.Text, identifier.GetLocation()),
_ => throw new InternalError(syntax, "Unexpected expression syntax in property patterns."),
};
private static AccessStepPack GetAccessStepPack(BaseExpressionColonSyntax syntax) =>
syntax switch
{
NameColonSyntax ncs => new AccessStepPack(ncs.Name.ToString(), ncs.Name.GetLocation()),
ExpressionColonSyntax ecs => GetAccessStepPack(ecs.Expression),
_ => throw new InternalError(syntax, "Unsupported expression colon in property pattern."),
};
private static Expression CreateSyntheticExp(Context cx, Microsoft.CodeAnalysis.Location location, IExpressionParentEntity parent, int child) =>
new Expression(new ExpressionInfo(cx, null, cx.CreateLocation(location), ExprKind.PROPERTY_PATTERN, parent, child, false, null));
private static void MakeExpressions(Context cx, IExpressionParentEntity parent, SubpatternSyntax syntax, int child)
{
var trapFile = cx.TrapWriter.Writer;
var pack = GetAccessStepPack(syntax.ExpressionColon!);
foreach (var step in pack.Prefix)
{
var exp = CreateSyntheticExp(cx, step.Location, parent, child);
trapFile.exprorstmt_name(exp, step.Identifier);
parent = exp;
child = 0;
}
var p = Expressions.Pattern.Create(cx, syntax.Pattern, parent, child);
trapFile.exprorstmt_name(p, pack.Last.Identifier);
}
}
}

View File

@@ -262,10 +262,10 @@ namespace Semmle.Extraction.CSharp.Entities
return Destructor.Create(cx, methodDecl);
case MethodKind.PropertyGet:
case MethodKind.PropertySet:
return Accessor.GetPropertySymbol(methodDecl) is IPropertySymbol prop ? Accessor.Create(cx, methodDecl, prop) : OrdinaryMethod.Create(cx, methodDecl);
return Accessor.GetPropertySymbol(methodDecl) is null ? OrdinaryMethod.Create(cx, methodDecl) : (Method)Accessor.Create(cx, methodDecl);
case MethodKind.EventAdd:
case MethodKind.EventRemove:
return EventAccessor.GetEventSymbol(methodDecl) is IEventSymbol @event ? EventAccessor.Create(cx, methodDecl, @event) : OrdinaryMethod.Create(cx, methodDecl);
return EventAccessor.Create(cx, methodDecl);
case MethodKind.UserDefinedOperator:
case MethodKind.BuiltinOperator:
return UserOperator.Create(cx, methodDecl);

View File

@@ -1,5 +1,7 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Entities;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -19,9 +21,33 @@ namespace Semmle.Extraction.CSharp.Entities
public override void Populate(TextWriter trapFile)
{
trapFile.types(this, Kinds.TypeKind.TYPE_PARAMETER, Symbol.Name);
var constraints = new TypeParameterConstraints(Context);
trapFile.type_parameter_constraints(constraints, this);
TypeParameterConstraints.Create(Context, this);
if (Symbol.HasReferenceTypeConstraint)
trapFile.general_type_parameter_constraints(constraints, 1);
if (Symbol.HasValueTypeConstraint)
trapFile.general_type_parameter_constraints(constraints, 2);
if (Symbol.HasConstructorConstraint)
trapFile.general_type_parameter_constraints(constraints, 3);
if (Symbol.HasUnmanagedTypeConstraint)
trapFile.general_type_parameter_constraints(constraints, 4);
if (Symbol.ReferenceTypeConstraintNullableAnnotation == NullableAnnotation.Annotated)
trapFile.general_type_parameter_constraints(constraints, 5);
foreach (var abase in Symbol.GetAnnotatedTypeConstraints())
{
var t = Create(Context, abase.Symbol);
trapFile.specific_type_parameter_constraints(constraints, t.TypeRef);
if (!abase.HasObliviousNullability())
trapFile.specific_type_parameter_nullability(constraints, t.TypeRef, NullabilityEntity.Create(Context, Nullability.Create(abase)));
}
trapFile.types(this, Kinds.TypeKind.TYPE_PARAMETER, Symbol.Name);
var parentNs = Namespace.Create(Context, Symbol.TypeParameterKind == TypeParameterKind.Method ? Context.Compilation.GlobalNamespace : Symbol.ContainingNamespace);
trapFile.parent_namespace(this, parentNs);

View File

@@ -1,65 +1,14 @@
using Microsoft.CodeAnalysis;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities
{
internal class TypeParameterConstraints : CachedEntity<ITypeParameterSymbol>
internal class TypeParameterConstraints : FreshEntity
{
private readonly TypeParameter parent;
public TypeParameterConstraints(Context cx)
: base(cx) { }
public TypeParameterConstraints(Context cx, TypeParameter parent)
: base(cx, parent.Symbol)
protected override void Populate(TextWriter trapFile)
{
this.parent = parent;
}
public override void WriteId(EscapingTextWriter trapFile)
{
trapFile.WriteSubId(parent);
trapFile.Write(";typeparameterconstraints");
}
public override bool NeedsPopulation => true;
public override void Populate(TextWriter trapFile)
{
trapFile.type_parameter_constraints(this, parent);
if (Symbol.HasReferenceTypeConstraint)
trapFile.general_type_parameter_constraints(this, 1);
if (Symbol.HasValueTypeConstraint)
trapFile.general_type_parameter_constraints(this, 2);
if (Symbol.HasConstructorConstraint)
trapFile.general_type_parameter_constraints(this, 3);
if (Symbol.HasUnmanagedTypeConstraint)
trapFile.general_type_parameter_constraints(this, 4);
if (Symbol.ReferenceTypeConstraintNullableAnnotation == NullableAnnotation.Annotated)
trapFile.general_type_parameter_constraints(this, 5);
foreach (var abase in Symbol.GetAnnotatedTypeConstraints())
{
var t = Type.Create(Context, abase.Symbol);
trapFile.specific_type_parameter_constraints(this, t.TypeRef);
if (!abase.HasObliviousNullability())
trapFile.specific_type_parameter_nullability(this, t.TypeRef, NullabilityEntity.Create(Context, Nullability.Create(abase)));
}
}
public override Location? ReportingLocation => null;
public static TypeParameterConstraints Create(Context cx, TypeParameter p) =>
TypeParameterConstraintsFactory.Instance.CreateEntity(cx, (typeof(TypeParameterConstraints), p), p);
private class TypeParameterConstraintsFactory : CachedEntityFactory<TypeParameter, TypeParameterConstraints>
{
public static TypeParameterConstraintsFactory Instance { get; } = new TypeParameterConstraintsFactory();
public override TypeParameterConstraints Create(Context cx, TypeParameter init) => new(cx, init);
}
}
}

View File

@@ -178,9 +178,6 @@ namespace Semmle.Extraction.CSharp.Entities
/// <returns>The converted name.</returns>
private static string OperatorSymbol(Context cx, IMethodSymbol method)
{
if (method.ExplicitInterfaceImplementations.Any())
return OperatorSymbol(cx, method.ExplicitInterfaceImplementations.First());
var methodName = method.Name;
if (!OperatorSymbol(methodName, out var result))
cx.ModelError(method, $"Unhandled operator name in OperatorSymbol(): '{methodName}'");

View File

@@ -86,17 +86,11 @@ namespace Semmle.Extraction.CSharp.Populators
return;
var outputAssembly = Assembly.CreateOutputAssembly(Cx);
var kind = node.Target?.Identifier.Kind() switch
{
SyntaxKind.AssemblyKeyword => Entities.AttributeKind.Assembly,
SyntaxKind.ModuleKeyword => Entities.AttributeKind.Module,
_ => throw new InternalError(node, "Unhandled global target")
};
foreach (var attribute in node.Attributes)
{
if (attributeLookup.Value(attribute) is AttributeData attributeData)
{
var ae = Entities.Attribute.Create(Cx, attributeData, outputAssembly, kind);
var ae = Entities.Attribute.Create(Cx, attributeData, outputAssembly);
Cx.BindComments(ae, attribute.GetLocation());
}
}

View File

@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<AssemblyName>Semmle.Extraction.CSharp</AssemblyName>
<RootNamespace>Semmle.Extraction.CSharp</RootNamespace>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>

View File

@@ -32,8 +32,8 @@ namespace Semmle.Extraction.CSharp
internal static void array_element_type(this TextWriter trapFile, ArrayType array, int dimension, int rank, Type elementType) =>
trapFile.WriteTuple("array_element_type", array, dimension, rank, elementType);
internal static void attributes(this TextWriter trapFile, Attribute attribute, AttributeKind kind, Type attributeType, IEntity entity) =>
trapFile.WriteTuple("attributes", attribute, kind, attributeType, entity);
internal static void attributes(this TextWriter trapFile, Attribute attribute, Type attributeType, IEntity entity) =>
trapFile.WriteTuple("attributes", attribute, attributeType, entity);
internal static void attribute_location(this TextWriter trapFile, Attribute attribute, Location location) =>
trapFile.WriteTuple("attribute_location", attribute, location);

View File

@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
<Nullable>enable</Nullable>

View File

@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<AssemblyName>Semmle.Extraction</AssemblyName>
<RootNamespace>Semmle.Extraction</RootNamespace>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>

View File

@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
<Nullable>enable</Nullable>

View File

@@ -84,7 +84,7 @@ namespace Semmle.Util
public static string ComputeFileHash(string filePath)
{
using var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
using var shaAlg = SHA256.Create();
using var shaAlg = new SHA256Managed();
var sha = shaAlg.ComputeHash(fileStream);
var hex = new StringBuilder(sha.Length * 2);
foreach (var b in sha)

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<AssemblyName>Semmle.Util</AssemblyName>
<RootNamespace>Semmle.Util</RootNamespace>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>

View File

@@ -1,6 +1,4 @@
name: codeql/csharp-examples
groups:
- csharp
- examples
version: 0.0.2
dependencies:
codeql/csharp-all: "*"

View File

@@ -1,5 +0,0 @@
---
category: majorAnalysis
---
* Return value attributes are extracted.
* The QL `Attribute` class now has subclasses for each kind of attribute.

View File

@@ -1,4 +0,0 @@
---
category: majorAnalysis
---
* Added support for C# 10 [Extended property patterns](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-10#extended-property-patterns).

View File

@@ -36,12 +36,6 @@ class Attributable extends @attributable {
}
}
private string getAttributeName(Attribute a) {
exists(string type | type = a.getType().getName() |
if type.matches("%Attribute") then result = type.prefix(type.length() - 9) else result = type
)
}
/**
* An attribute, for example `[...]` on line 1 in
*
@@ -56,10 +50,10 @@ private string getAttributeName(Attribute a) {
*/
class Attribute extends TopLevelExprParent, @attribute {
/** Gets the type of this attribute. */
Class getType() { attributes(this, _, getTypeRef(result), _) }
Class getType() { attributes(this, getTypeRef(result), _) }
/** Gets the element that this attribute is attached to. */
Attributable getTarget() { attributes(this, _, _, result) }
Attributable getTarget() { attributes(this, _, result) }
/**
* Gets the `i`th argument of this attribute. This includes both constructor
@@ -94,55 +88,12 @@ class Attribute extends TopLevelExprParent, @attribute {
override Location getALocation() { attribute_location(this, result) }
override string toString() { result = "[" + getAttributeName(this) + "(...)]" }
override string toString() {
exists(string type, string name | type = this.getType().getName() |
(if type.matches("%Attribute") then name = type.prefix(type.length() - 9) else name = type) and
result = "[" + name + "(...)]"
)
}
override string getAPrimaryQlClass() { result = "Attribute" }
}
/**
* An attribute with default kind, for example `[...]` on line 1 in
* ```csharp
* [MyAttribute(0)]
* int SomeMethod() { return 1; }
* ```
*/
class DefaultAttribute extends Attribute, @attribute_default {
override string getAPrimaryQlClass() { result = "DefaultAttribute" }
}
/**
* An attribute with return kind, for example `[...]` on line 1 in
* ```csharp
* [return: MyAttribute(0)]
* int SomeMethod() { return 1; }
* ```
*/
class ReturnAttribute extends Attribute, @attribute_return {
override string toString() { result = "[return: " + getAttributeName(this) + "(...)]" }
override string getAPrimaryQlClass() { result = "ReturnAttribute" }
}
/**
* An attribute with assembly kind, for example `[...]` on line 1 in
* ```csharp
* [assembly: MyAttribute(0)]
* ```
*/
class AssemblyAttribute extends Attribute, @attribute_assembly {
override string toString() { result = "[assembly: " + getAttributeName(this) + "(...)]" }
override string getAPrimaryQlClass() { result = "AssemblyAttribute" }
}
/**
* An attribute with module kind, for example `[...]` on line 1 in
* ```csharp
* [module: MyAttribute(0)]
* ```
*/
class ModuleAttribute extends Attribute, @attribute_module {
override string toString() { result = "[module: " + getAttributeName(this) + "(...)]" }
override string getAPrimaryQlClass() { result = "ModuleAttribute" }
}

View File

@@ -214,7 +214,7 @@ abstract class SplitKind extends SplitKindBase {
abstract string toString();
}
/** An interface for implementing an entity to split on. */
/** Provides the interface for implementing an entity to split on. */
abstract class SplitImpl extends Split {
/** Gets the kind of this split. */
abstract SplitKind getKind();
@@ -894,31 +894,16 @@ module TestOutput {
p
order by
l.getFile().getBaseName(), l.getFile().getAbsolutePath(), l.getStartLine(),
l.getStartColumn(), l.getEndLine(), l.getEndColumn(), p.toString()
l.getStartColumn()
)
).toString()
}
query predicate edges(RelevantNode pred, RelevantNode succ, string attr, string val) {
attr = "semmle.label" and
exists(SuccessorType t | succ = getASuccessor(pred, t) |
attr = "semmle.label" and
if successorTypeIsSimple(t) then val = "" else val = t.toString()
)
or
attr = "semmle.order" and
val =
any(int i |
succ =
rank[i](RelevantNode s, SuccessorType t, Location l |
s = getASuccessor(pred, t) and
l = s.getLocation()
|
s
order by
l.getFile().getBaseName(), l.getFile().getAbsolutePath(), l.getStartLine(),
l.getStartColumn(), l.getEndLine(), l.getEndColumn(), t.toString()
)
).toString()
}
}

View File

@@ -1290,7 +1290,7 @@ class DataFlowCallOption extends TDataFlowCallOption {
}
}
/** A `Content` tagged with the type of a containing object. */
/** Content tagged with the type of a containing object. */
class TypedContent extends MkTypedContent {
private Content c;
private DataFlowType t;

View File

@@ -160,7 +160,6 @@ predicate localFlow(Node source, Node sink) { localFlowStep*(source, sink) }
* Holds if data can flow from `e1` to `e2` in zero or more
* local (intra-procedural) steps.
*/
pragma[inline]
predicate localExprFlow(Expr e1, Expr e2) { localFlow(exprNode(e1), exprNode(e2)) }
/**

View File

@@ -90,9 +90,7 @@ module Public {
predicate contains(SummaryComponent c) { c = this.drop(_).head() }
/** Gets the bottom element of this stack. */
SummaryComponent bottom() {
this = TSingletonSummaryComponentStack(result) or result = this.tail().bottom()
}
SummaryComponent bottom() { result = this.drop(this.length() - 1).head() }
/** Gets a textual representation of this stack. */
string toString() {

View File

@@ -5,14 +5,12 @@ private import TaintTrackingPrivate
* Holds if taint propagates from `source` to `sink` in zero or more local
* (intra-procedural) steps.
*/
pragma[inline]
predicate localTaint(DataFlow::Node source, DataFlow::Node sink) { localTaintStep*(source, sink) }
/**
* Holds if taint can flow from `e1` to `e2` in zero or more
* local (intra-procedural) steps.
*/
pragma[inline]
predicate localExprTaint(Expr e1, Expr e2) {
localTaint(DataFlow::exprNode(e1), DataFlow::exprNode(e2))
}

View File

@@ -520,17 +520,9 @@ tuple_element(
attributes(
unique int id: @attribute,
int kind: int ref,
int type_id: @type_or_ref ref,
int target: @attributable ref);
case @attribute.kind of
0 = @attribute_default
| 1 = @attribute_return
| 2 = @attribute_assembly
| 3 = @attribute_module
;
attribute_location(
int id: @attribute ref,
int loc: @location ref);
@@ -656,7 +648,7 @@ has_modifiers(
int id: @modifiable_direct ref,
int mod_id: @modifier ref);
compiler_generated(unique int id: @modifiable ref);
compiler_generated(unique int id: @modifiable_direct ref);
/** MEMBERS **/

File diff suppressed because it is too large Load Diff

View File

@@ -6,22 +6,122 @@
*/
class Person extends string {
Person() {
this =
[
"Ronil", "Dina", "Ravi", "Bruce", "Jo", "Aida", "Esme", "Charlie", "Fred", "Meera", "Maya",
"Chad", "Tiana", "Laura", "George", "Will", "Mary", "Almira", "Susannah", "Rhoda",
"Cynthia", "Eunice", "Olive", "Virginia", "Angeline", "Helen", "Cornelia", "Harriet",
"Mahala", "Abby", "Margaret", "Deb", "Minerva", "Severus", "Lavina", "Adeline", "Cath",
"Elisa", "Lucretia", "Anne", "Eleanor", "Joanna", "Adam", "Agnes", "Rosanna", "Clara",
"Melissa", "Amy", "Isabel", "Jemima", "Cordelia", "Melinda", "Delila", "Jeremiah", "Elijah",
"Hester", "Walter", "Oliver", "Hugh", "Aaron", "Reuben", "Eli", "Amos", "Augustus",
"Theodore", "Ira", "Timothy", "Cyrus", "Horace", "Simon", "Asa", "Frank", "Nelson",
"Leonard", "Harrison", "Anthony", "Louis", "Milton", "Noah", "Cornelius", "Abdul", "Warren",
"Harvey", "Dennis", "Wesley", "Sylvester", "Gilbert", "Sullivan", "Edmund", "Wilson",
"Perry", "Matthew", "Simba", "Nala", "Rafiki", "Shenzi", "Ernest", "Gertrude", "Oscar",
"Lilian", "Raymond", "Elgar", "Elmer", "Herbert", "Maude", "Mae", "Otto", "Edwin",
"Ophelia", "Parsley", "Sage", "Rosemary", "Thyme", "Garfunkel", "King Basil", "Stephen"
]
this = "Ronil" or
this = "Dina" or
this = "Ravi" or
this = "Bruce" or
this = "Jo" or
this = "Aida" or
this = "Esme" or
this = "Charlie" or
this = "Fred" or
this = "Meera" or
this = "Maya" or
this = "Chad" or
this = "Tiana" or
this = "Laura" or
this = "George" or
this = "Will" or
this = "Mary" or
this = "Almira" or
this = "Susannah" or
this = "Rhoda" or
this = "Cynthia" or
this = "Eunice" or
this = "Olive" or
this = "Virginia" or
this = "Angeline" or
this = "Helen" or
this = "Cornelia" or
this = "Harriet" or
this = "Mahala" or
this = "Abby" or
this = "Margaret" or
this = "Deb" or
this = "Minerva" or
this = "Severus" or
this = "Lavina" or
this = "Adeline" or
this = "Cath" or
this = "Elisa" or
this = "Lucretia" or
this = "Anne" or
this = "Eleanor" or
this = "Joanna" or
this = "Adam" or
this = "Agnes" or
this = "Rosanna" or
this = "Clara" or
this = "Melissa" or
this = "Amy" or
this = "Isabel" or
this = "Jemima" or
this = "Cordelia" or
this = "Melinda" or
this = "Delila" or
this = "Jeremiah" or
this = "Elijah" or
this = "Hester" or
this = "Walter" or
this = "Oliver" or
this = "Hugh" or
this = "Aaron" or
this = "Reuben" or
this = "Eli" or
this = "Amos" or
this = "Augustus" or
this = "Theodore" or
this = "Ira" or
this = "Timothy" or
this = "Cyrus" or
this = "Horace" or
this = "Simon" or
this = "Asa" or
this = "Frank" or
this = "Nelson" or
this = "Leonard" or
this = "Harrison" or
this = "Anthony" or
this = "Louis" or
this = "Milton" or
this = "Noah" or
this = "Cornelius" or
this = "Abdul" or
this = "Warren" or
this = "Harvey" or
this = "Dennis" or
this = "Wesley" or
this = "Sylvester" or
this = "Gilbert" or
this = "Sullivan" or
this = "Edmund" or
this = "Wilson" or
this = "Perry" or
this = "Matthew" or
this = "Simba" or
this = "Nala" or
this = "Rafiki" or
this = "Shenzi" or
this = "Ernest" or
this = "Gertrude" or
this = "Oscar" or
this = "Lilian" or
this = "Raymond" or
this = "Elgar" or
this = "Elmer" or
this = "Herbert" or
this = "Maude" or
this = "Mae" or
this = "Otto" or
this = "Edwin" or
this = "Ophelia" or
this = "Parsley" or
this = "Sage" or
this = "Rosemary" or
this = "Thyme" or
this = "Garfunkel" or
this = "King Basil" or
this = "Stephen"
}
/** Gets the hair color of the person. If the person is bald, there is no result. */
@@ -836,12 +936,25 @@ class Person extends string {
/** Holds if the person is deceased. */
predicate isDeceased() {
this =
[
"Ernest", "Gertrude", "Oscar", "Lilian", "Edwin", "Raymond", "Elgar", "Elmer", "Herbert",
"Maude", "Mae", "Otto", "Ophelia", "Parsley", "Sage", "Rosemary", "Thyme", "Garfunkel",
"King Basil"
]
this = "Ernest" or
this = "Gertrude" or
this = "Oscar" or
this = "Lilian" or
this = "Edwin" or
this = "Raymond" or
this = "Elgar" or
this = "Elmer" or
this = "Herbert" or
this = "Maude" or
this = "Mae" or
this = "Otto" or
this = "Ophelia" or
this = "Parsley" or
this = "Sage" or
this = "Rosemary" or
this = "Thyme" or
this = "Garfunkel" or
this = "King Basil"
}
/** Gets a parent of the person (alive or deceased). */
@@ -1082,7 +1195,12 @@ class Person extends string {
}
/** Holds if the person is allowed in the region. Initially, all villagers are allowed in every region. */
predicate isAllowedIn(string region) { region = ["north", "south", "east", "west"] }
predicate isAllowedIn(string region) {
region = "north" or
region = "south" or
region = "east" or
region = "west"
}
}
/** Returns a parent of the person. */

View File

@@ -1,2 +0,0 @@
description: Support for compiler-generated event accessors.
compatibility: backwards

View File

@@ -1,15 +0,0 @@
class Attribute extends @attribute {
string toString() { none() }
}
class Attributable extends @attributable {
string toString() { none() }
}
class TypeOrRef extends @type_or_ref {
string toString() { none() }
}
from Attribute id, TypeOrRef type_id, Attributable target
where attributes(id, type_id, target)
select id, 0, type_id, target

View File

@@ -1,3 +0,0 @@
description: Add 'kind' to 'attributes'.
compatability: backwards
attributes.rel: run attribute_kind.ql

View File

@@ -1,24 +0,0 @@
/**
* @name Extractor diagnostics
* @description This query is for internal use only and may change without notice.
* @kind table
* @id csharp/extractor-diagnostics
*/
import csharp
bindingset[i]
private float getCompilationTimeSum(int i) {
result = sum(float f | compilation_time(_, _, i, f) | f)
}
select getCompilationTimeSum(0) as sum_frontend_cpu_seconds,
getCompilationTimeSum(1) as sum_frontend_elapsed_seconds,
getCompilationTimeSum(4) as sum_frontend_user_seconds,
getCompilationTimeSum(2) as sum_extractor_cpu_seconds,
getCompilationTimeSum(3) as sum_extractor_elapsed_seconds,
getCompilationTimeSum(5) as sum_extractor_user_seconds,
sum(float f | compilation_finished(_, f, _) | f) as sum_total_cpu_seconds,
sum(float f | compilation_finished(_, _, f) | f) as sum_total_elapsed_seconds,
getCompilationTimeSum(6) as sum_peak_working_set_mb,
max(float f | compilation_time(_, _, 6, f) | f) as max_peak_working_set_mb

View File

@@ -8,7 +8,7 @@ import shutil
def write_csproj_prefix(ioWrapper):
ioWrapper.write('<Project Sdk="Microsoft.NET.Sdk">\n')
ioWrapper.write(' <PropertyGroup>\n')
ioWrapper.write(' <TargetFramework>net6.0</TargetFramework>\n')
ioWrapper.write(' <TargetFramework>net5.0</TargetFramework>\n')
ioWrapper.write(' <AllowUnsafeBlocks>true</AllowUnsafeBlocks>\n')
ioWrapper.write(' <OutputPath>bin\</OutputPath>\n')
ioWrapper.write(
@@ -60,7 +60,7 @@ jsonFile = os.path.join(rawOutputDir, outputName + '.json')
version = helpers.get_argv(2, "latest")
print("\n* Creating new input project")
run_cmd(['dotnet', 'new', 'classlib', "-f", "net6.0", "--language", "C#", '--name',
run_cmd(['dotnet', 'new', 'classlib', "-f", "net5.0", "--language", "C#", '--name',
projectNameIn, '--output', projectDirIn])
helpers.remove_files(projectDirIn, '.cs')
@@ -71,7 +71,7 @@ if (version != "latest"):
cmd.append(version)
run_cmd(cmd)
sdk_version = '6.0.101'
sdk_version = '5.0.402'
print("\n* Creating new global.json file and setting SDK to " + sdk_version)
run_cmd(['dotnet', 'new', 'globaljson', '--force', '--sdk-version', sdk_version, '--output', workDir])

View File

@@ -1,8 +1,6 @@
name: codeql/csharp-queries
version: 0.0.8-dev
groups:
- csharp
- queries
groups: csharp
suites: codeql-suites
extractor: csharp
defaultSuiteFile: codeql-suites/csharp-code-scanning.qls

View File

@@ -93,7 +93,7 @@
private import InlineExpectationsTestPrivate
/**
* The base class for tests with inline expectations. The test extends this class to provide the actual
* Base class for tests with inline expectations. The test extends this class to provide the actual
* results of the query, which are then compared with the expected results in comments to produce a
* list of failure messages that point out where the actual results differ from the expected
* results.
@@ -123,15 +123,6 @@ abstract class InlineExpectationsTest extends string {
*/
abstract predicate hasActualResult(Location location, string element, string tag, string value);
/**
* Like `hasActualResult`, but returns results that do not require a matching annotation.
* A failure will still arise if there is an annotation that does not match any results, but not vice versa.
* Override this predicate to specify optional results.
*/
predicate hasOptionalResult(Location location, string element, string tag, string value) {
none()
}
final predicate hasFailureMessage(FailureLocatable element, string message) {
exists(ActualResult actualResult |
actualResult.getTest() = this and
@@ -143,8 +134,7 @@ abstract class InlineExpectationsTest extends string {
)
or
not exists(ValidExpectation expectation | expectation.matchesActualResult(actualResult)) and
message = "Unexpected result: " + actualResult.getExpectationText() and
not actualResult.isOptional()
message = "Unexpected result: " + actualResult.getExpectationText()
)
)
or
@@ -253,13 +243,9 @@ private string expectationPattern() {
private newtype TFailureLocatable =
TActualResult(
InlineExpectationsTest test, Location location, string element, string tag, string value,
boolean optional
InlineExpectationsTest test, Location location, string element, string tag, string value
) {
test.hasActualResult(location, element, tag, value) and
optional = false
or
test.hasOptionalResult(location, element, tag, value) and optional = true
test.hasActualResult(location, element, tag, value)
} or
TValidExpectation(ExpectationComment comment, string tag, string value, string knownFailure) {
exists(TColumn column, string tags |
@@ -291,9 +277,8 @@ class ActualResult extends FailureLocatable, TActualResult {
string element;
string tag;
string value;
boolean optional;
ActualResult() { this = TActualResult(test, location, element, tag, value, optional) }
ActualResult() { this = TActualResult(test, location, element, tag, value) }
override string toString() { result = element }
@@ -304,8 +289,6 @@ class ActualResult extends FailureLocatable, TActualResult {
override string getTag() { result = tag }
override string getValue() { result = value }
predicate isOptional() { optional = true }
}
abstract private class Expectation extends FailureLocatable {

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