Merge branch 'main' into rdmarsh2/dataflow-global-vars

This commit is contained in:
Robert Marsh
2022-08-01 14:55:45 -04:00
1402 changed files with 85612 additions and 54375 deletions

View File

@@ -0,0 +1,9 @@
# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.236.0/containers/cpp/.devcontainer/base.Dockerfile
# [Choice] Debian / Ubuntu version (use Debian 11, Ubuntu 18.04/22.04 on local arm64/Apple Silicon): debian-11, debian-10, ubuntu-22.04, ubuntu-20.04, ubuntu-18.04
FROM mcr.microsoft.com/vscode/devcontainers/cpp:0-ubuntu-22.04
USER root
ADD root.sh /tmp/root.sh
ADD update-codeql.sh /usr/local/bin/update-codeql
RUN bash /tmp/root.sh && rm /tmp/root.sh

View File

@@ -0,0 +1,25 @@
{
"extensions": [
"github.vscode-codeql",
"hbenl.vscode-test-explorer",
"ms-vscode.test-adapter-converter",
"slevesque.vscode-zipexplorer",
"ms-vscode.cpptools"
],
"settings": {
"files.watcherExclude": {
"**/target/**": true
},
"codeQL.runningQueries.memory": 2048
},
"build": {
"dockerfile": "Dockerfile",
},
"runArgs": [
"--cap-add=SYS_PTRACE",
"--security-opt",
"seccomp=unconfined"
],
"remoteUser": "vscode",
"onCreateCommand": ".devcontainer/swift/user.sh"
}

View File

@@ -0,0 +1,22 @@
set -xe
BAZELISK_VERSION=v1.12.0
BAZELISK_DOWNLOAD_SHA=6b0bcb2ea15bca16fffabe6fda75803440375354c085480fe361d2cbf32501db
apt-get update
export DEBIAN_FRONTEND=noninteractive
apt-get -y install --no-install-recommends \
zlib1g-dev \
uuid-dev \
python3-distutils \
python3-pip \
bash-completion
# Install Bazel
curl -fSsL -o /usr/local/bin/bazelisk https://github.com/bazelbuild/bazelisk/releases/download/${BAZELISK_VERSION}/bazelisk-linux-amd64
echo "${BAZELISK_DOWNLOAD_SHA} */usr/local/bin/bazelisk" | sha256sum --check -
chmod 0755 /usr/local/bin/bazelisk
ln -s bazelisk /usr/local/bin/bazel
# install latest codeql
update-codeql

View File

@@ -0,0 +1,20 @@
#!/bin/bash -e
URL=https://github.com/github/codeql-cli-binaries/releases
LATEST_VERSION=$(curl -L -s -H 'Accept: application/json' $URL/latest | sed -e 's/.*"tag_name":"\([^"]*\)".*/\1/')
CURRENT_VERSION=v$(codeql version 2>/dev/null | sed -ne 's/.*release \([0-9.]*\)\./\1/p')
if [[ $CURRENT_VERSION != $LATEST_VERSION ]]; then
if [[ $UID != 0 ]]; then
echo "update required, please run this script with sudo:"
echo " sudo $0"
exit 1
fi
ZIP=$(mktemp codeql.XXXX.zip)
curl -fSqL -o $ZIP $URL/download/$LATEST_VERSION/codeql-linux64.zip
unzip -q $ZIP -d /opt
rm $ZIP
ln -sf /opt/codeql/codeql /usr/local/bin/codeql
echo installed version $LATEST_VERSION
else
echo current version $CURRENT_VERSION is up-to-date
fi

13
.devcontainer/swift/user.sh Executable file
View File

@@ -0,0 +1,13 @@
set -xe
# add the workspace to the codeql search path
mkdir -p /home/vscode/.config/codeql
echo "--search-path /workspaces/codeql" > /home/vscode/.config/codeql/config
# create a swift extractor pack with the current state
cd /workspaces/codeql
bazel run swift/create-extractor-pack
#install and set up pre-commit
python3 -m pip install pre-commit --no-warn-script-location
$HOME/.local/bin/pre-commit install

View File

@@ -15,18 +15,22 @@ jobs:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: ./.github/actions/fetch-codeql - uses: ./.github/actions/fetch-codeql
- uses: bazelbuild/setup-bazelisk@v2 - uses: bazelbuild/setup-bazelisk@v2
- uses: actions/setup-python@v3
- uses: pre-commit/action@v3.0.0
name: Check that python code is properly formatted
with:
extra_args: autopep8 --all-files
- name: Run unit tests - name: Run unit tests
run: | run: |
bazel test //swift/codegen/test --test_output=errors bazel test //swift/codegen/test --test_output=errors
- name: Check that QL generated code was checked in - uses: pre-commit/action@v3.0.0
run: | name: Check that QL generated code was checked in
bazel run //swift/codegen with:
git add swift extra_args: swift-codegen --all-files
git diff --exit-code --stat HEAD
- name: Generate C++ files - name: Generate C++ files
run: | run: |
bazel run //swift/codegen:codegen -- --generate=trap,cpp --cpp-output=$PWD/swift-generated-headers bazel run //swift/codegen:codegen -- --generate=trap,cpp --cpp-output=$PWD/swift-generated-cpp-files
- uses: actions/upload-artifact@v3 - uses: actions/upload-artifact@v3
with: with:
name: swift-generated-headers name: swift-generated-cpp-files
path: swift-generated-headers/*.h path: swift-generated-cpp-files/**

3
.gitignore vendored
View File

@@ -58,3 +58,6 @@ go/main
# node_modules folders except in the JS test suite # node_modules folders except in the JS test suite
node_modules/ node_modules/
!/javascript/ql/test/**/node_modules/ !/javascript/ql/test/**/node_modules/
# Temporary folders for working with generated models
.model-temp

View File

@@ -15,6 +15,12 @@ repos:
- id: clang-format - id: clang-format
files: ^swift/.*\.(h|c|cpp)$ files: ^swift/.*\.(h|c|cpp)$
- repo: https://github.com/pre-commit/mirrors-autopep8
rev: v1.6.0
hooks:
- id: autopep8
files: ^swift/codegen/.*\.py
- repo: local - repo: local
hooks: hooks:
- id: codeql-format - id: codeql-format
@@ -40,7 +46,7 @@ repos:
name: Run Swift checked in code generation name: Run Swift checked in code generation
files: ^swift/(codegen/|.*/generated/|ql/lib/(swift\.dbscheme$|codeql/swift/elements)) files: ^swift/(codegen/|.*/generated/|ql/lib/(swift\.dbscheme$|codeql/swift/elements))
language: system language: system
entry: bazel run //swift/codegen entry: bazel run //swift/codegen -- --quiet
pass_filenames: false pass_filenames: false
- id: swift-codegen-unit-tests - id: swift-codegen-unit-tests

View File

@@ -75,7 +75,8 @@
"DataFlow Java/C# Flow Summaries": [ "DataFlow Java/C# Flow Summaries": [
"java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll", "java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll",
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll", "csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll",
"ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImpl.qll" "ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImpl.qll",
"swift/ql/lib/codeql/swift/dataflow/internal/FlowSummaryImpl.qll"
], ],
"SsaReadPosition Java/C#": [ "SsaReadPosition Java/C#": [
"java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/SsaReadPositionCommon.qll", "java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/SsaReadPositionCommon.qll",
@@ -527,7 +528,8 @@
"java/ql/lib/semmle/code/java/dataflow/internal/AccessPathSyntax.qll", "java/ql/lib/semmle/code/java/dataflow/internal/AccessPathSyntax.qll",
"javascript/ql/lib/semmle/javascript/frameworks/data/internal/AccessPathSyntax.qll", "javascript/ql/lib/semmle/javascript/frameworks/data/internal/AccessPathSyntax.qll",
"ruby/ql/lib/codeql/ruby/dataflow/internal/AccessPathSyntax.qll", "ruby/ql/lib/codeql/ruby/dataflow/internal/AccessPathSyntax.qll",
"python/ql/lib/semmle/python/frameworks/data/internal/AccessPathSyntax.qll" "python/ql/lib/semmle/python/frameworks/data/internal/AccessPathSyntax.qll",
"swift/ql/lib/codeql/swift/dataflow/internal/AccessPathSyntax.qll"
], ],
"IncompleteUrlSubstringSanitization": [ "IncompleteUrlSubstringSanitization": [
"javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.qll", "javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.qll",

View File

@@ -1,3 +1,9 @@
## 0.2.3
### New Features
* An `isBraced` predicate was added to the `Initializer` class which holds when a C++ braced initializer was used in the initialization.
## 0.2.2 ## 0.2.2
### Deprecated APIs ### Deprecated APIs

View File

@@ -0,0 +1,4 @@
---
category: deprecated
---
* The `BarrierGuard` class has been deprecated. Such barriers and sanitizers can now instead be created using the new `BarrierGuard` parameterized module.

View File

@@ -0,0 +1,4 @@
---
category: fix
---
* `UserType.getADeclarationEntry()` now yields all forward declarations when the user type is a `class`, `struct`, or `union`.

View File

@@ -0,0 +1,5 @@
## 0.2.3
### New Features
* An `isBraced` predicate was added to the `Initializer` class which holds when a C++ braced initializer was used in the initialization.

View File

@@ -1,2 +1,2 @@
--- ---
lastReleaseVersion: 0.2.2 lastReleaseVersion: 0.2.3

View File

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

View File

@@ -48,8 +48,8 @@ class UserType extends Type, Declaration, NameQualifyingElement, AccessHolder, @
} }
override TypeDeclarationEntry getADeclarationEntry() { override TypeDeclarationEntry getADeclarationEntry() {
if type_decls(_, underlyingElement(this), _) if type_decls(_, unresolveElement(this), _)
then type_decls(unresolveElement(result), underlyingElement(this), _) then type_decls(underlyingElement(result), unresolveElement(this), _)
else exists(Class t | this.(Class).isConstructedFrom(t) and result = t.getADeclarationEntry()) else exists(Class t | this.(Class).isConstructedFrom(t) and result = t.getADeclarationEntry())
} }

View File

@@ -90,14 +90,20 @@ abstract class Configuration extends string {
/** Holds if data flow out of `node` is prohibited. */ /** Holds if data flow out of `node` is prohibited. */
predicate isBarrierOut(Node node) { none() } predicate isBarrierOut(Node node) { none() }
/** Holds if data flow through nodes guarded by `guard` is prohibited. */ /**
predicate isBarrierGuard(BarrierGuard guard) { none() } * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited.
*/
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
/** /**
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited when * Holds if data flow through nodes guarded by `guard` is prohibited when
* the flow state is `state` * the flow state is `state`
*/ */
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() } deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
/** /**
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
@@ -335,6 +341,29 @@ private predicate outBarrier(NodeEx node, Configuration config) {
) )
} }
/** A bridge class to access the deprecated `isBarrierGuard`. */
private class BarrierGuardGuardedNodeBridge extends Unit {
abstract predicate guardedNode(Node n, Configuration config);
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
}
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
deprecated override predicate guardedNode(Node n, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
}
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
}
}
pragma[nomagic] pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) { private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n | exists(Node n | node.asNode() = n |
@@ -348,10 +377,7 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
not config.isSink(n) and not config.isSink(n) and
not config.isSink(n, _) not config.isSink(n, _)
or or
exists(BarrierGuard g | any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config)
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
) )
} }
@@ -360,10 +386,7 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
exists(Node n | node.asNode() = n | exists(Node n | node.asNode() = n |
config.isBarrier(n, state) config.isBarrier(n, state)
or or
exists(BarrierGuard g | any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config)
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
) )
} }

View File

@@ -90,14 +90,20 @@ abstract class Configuration extends string {
/** Holds if data flow out of `node` is prohibited. */ /** Holds if data flow out of `node` is prohibited. */
predicate isBarrierOut(Node node) { none() } predicate isBarrierOut(Node node) { none() }
/** Holds if data flow through nodes guarded by `guard` is prohibited. */ /**
predicate isBarrierGuard(BarrierGuard guard) { none() } * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited.
*/
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
/** /**
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited when * Holds if data flow through nodes guarded by `guard` is prohibited when
* the flow state is `state` * the flow state is `state`
*/ */
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() } deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
/** /**
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
@@ -335,6 +341,29 @@ private predicate outBarrier(NodeEx node, Configuration config) {
) )
} }
/** A bridge class to access the deprecated `isBarrierGuard`. */
private class BarrierGuardGuardedNodeBridge extends Unit {
abstract predicate guardedNode(Node n, Configuration config);
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
}
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
deprecated override predicate guardedNode(Node n, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
}
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
}
}
pragma[nomagic] pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) { private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n | exists(Node n | node.asNode() = n |
@@ -348,10 +377,7 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
not config.isSink(n) and not config.isSink(n) and
not config.isSink(n, _) not config.isSink(n, _)
or or
exists(BarrierGuard g | any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config)
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
) )
} }
@@ -360,10 +386,7 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
exists(Node n | node.asNode() = n | exists(Node n | node.asNode() = n |
config.isBarrier(n, state) config.isBarrier(n, state)
or or
exists(BarrierGuard g | any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config)
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
) )
} }

View File

@@ -90,14 +90,20 @@ abstract class Configuration extends string {
/** Holds if data flow out of `node` is prohibited. */ /** Holds if data flow out of `node` is prohibited. */
predicate isBarrierOut(Node node) { none() } predicate isBarrierOut(Node node) { none() }
/** Holds if data flow through nodes guarded by `guard` is prohibited. */ /**
predicate isBarrierGuard(BarrierGuard guard) { none() } * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited.
*/
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
/** /**
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited when * Holds if data flow through nodes guarded by `guard` is prohibited when
* the flow state is `state` * the flow state is `state`
*/ */
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() } deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
/** /**
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
@@ -335,6 +341,29 @@ private predicate outBarrier(NodeEx node, Configuration config) {
) )
} }
/** A bridge class to access the deprecated `isBarrierGuard`. */
private class BarrierGuardGuardedNodeBridge extends Unit {
abstract predicate guardedNode(Node n, Configuration config);
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
}
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
deprecated override predicate guardedNode(Node n, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
}
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
}
}
pragma[nomagic] pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) { private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n | exists(Node n | node.asNode() = n |
@@ -348,10 +377,7 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
not config.isSink(n) and not config.isSink(n) and
not config.isSink(n, _) not config.isSink(n, _)
or or
exists(BarrierGuard g | any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config)
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
) )
} }
@@ -360,10 +386,7 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
exists(Node n | node.asNode() = n | exists(Node n | node.asNode() = n |
config.isBarrier(n, state) config.isBarrier(n, state)
or or
exists(BarrierGuard g | any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config)
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
) )
} }

View File

@@ -90,14 +90,20 @@ abstract class Configuration extends string {
/** Holds if data flow out of `node` is prohibited. */ /** Holds if data flow out of `node` is prohibited. */
predicate isBarrierOut(Node node) { none() } predicate isBarrierOut(Node node) { none() }
/** Holds if data flow through nodes guarded by `guard` is prohibited. */ /**
predicate isBarrierGuard(BarrierGuard guard) { none() } * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited.
*/
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
/** /**
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited when * Holds if data flow through nodes guarded by `guard` is prohibited when
* the flow state is `state` * the flow state is `state`
*/ */
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() } deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
/** /**
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
@@ -335,6 +341,29 @@ private predicate outBarrier(NodeEx node, Configuration config) {
) )
} }
/** A bridge class to access the deprecated `isBarrierGuard`. */
private class BarrierGuardGuardedNodeBridge extends Unit {
abstract predicate guardedNode(Node n, Configuration config);
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
}
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
deprecated override predicate guardedNode(Node n, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
}
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
}
}
pragma[nomagic] pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) { private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n | exists(Node n | node.asNode() = n |
@@ -348,10 +377,7 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
not config.isSink(n) and not config.isSink(n) and
not config.isSink(n, _) not config.isSink(n, _)
or or
exists(BarrierGuard g | any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config)
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
) )
} }
@@ -360,10 +386,7 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
exists(Node n | node.asNode() = n | exists(Node n | node.asNode() = n |
config.isBarrier(n, state) config.isBarrier(n, state)
or or
exists(BarrierGuard g | any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config)
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
) )
} }

View File

@@ -90,14 +90,20 @@ abstract class Configuration extends string {
/** Holds if data flow out of `node` is prohibited. */ /** Holds if data flow out of `node` is prohibited. */
predicate isBarrierOut(Node node) { none() } predicate isBarrierOut(Node node) { none() }
/** Holds if data flow through nodes guarded by `guard` is prohibited. */ /**
predicate isBarrierGuard(BarrierGuard guard) { none() } * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited.
*/
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
/** /**
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited when * Holds if data flow through nodes guarded by `guard` is prohibited when
* the flow state is `state` * the flow state is `state`
*/ */
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() } deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
/** /**
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
@@ -335,6 +341,29 @@ private predicate outBarrier(NodeEx node, Configuration config) {
) )
} }
/** A bridge class to access the deprecated `isBarrierGuard`. */
private class BarrierGuardGuardedNodeBridge extends Unit {
abstract predicate guardedNode(Node n, Configuration config);
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
}
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
deprecated override predicate guardedNode(Node n, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
}
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
}
}
pragma[nomagic] pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) { private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n | exists(Node n | node.asNode() = n |
@@ -348,10 +377,7 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
not config.isSink(n) and not config.isSink(n) and
not config.isSink(n, _) not config.isSink(n, _)
or or
exists(BarrierGuard g | any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config)
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
) )
} }
@@ -360,10 +386,7 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
exists(Node n | node.asNode() = n | exists(Node n | node.asNode() = n |
config.isBarrier(n, state) config.isBarrier(n, state)
or or
exists(BarrierGuard g | any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config)
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
) )
} }

View File

@@ -850,6 +850,34 @@ class ContentSet instanceof Content {
} }
/** /**
* Holds if the guard `g` validates the expression `e` upon evaluating to `branch`.
*
* The expression `e` is expected to be a syntactic part of the guard `g`.
* For example, the guard `g` might be a call `isSafe(x)` and the expression `e`
* the argument `x`.
*/
signature predicate guardChecksSig(GuardCondition g, Expr e, boolean branch);
/**
* Provides a set of barrier nodes for a guard that validates an expression.
*
* This is expected to be used in `isBarrier`/`isSanitizer` definitions
* in data flow and taint tracking.
*/
module BarrierGuard<guardChecksSig/3 guardChecks> {
/** Gets a node that is safely guarded by the given guard check. */
ExprNode getABarrierNode() {
exists(GuardCondition g, SsaDefinition def, Variable v, boolean branch |
result.getExpr() = def.getAUse(v) and
guardChecks(g, def.getAUse(v), branch) and
g.controls(result.getExpr().getBasicBlock(), branch)
)
}
}
/**
* DEPRECATED: Use `BarrierGuard` module instead.
*
* A guard that validates some expression. * A guard that validates some expression.
* *
* To use this in a configuration, extend the class and provide a * To use this in a configuration, extend the class and provide a
@@ -858,7 +886,7 @@ class ContentSet instanceof Content {
* *
* It is important that all extending classes in scope are disjoint. * It is important that all extending classes in scope are disjoint.
*/ */
class BarrierGuard extends GuardCondition { deprecated class BarrierGuard extends GuardCondition {
/** Override this predicate to hold if this guard validates `e` upon evaluating to `b`. */ /** Override this predicate to hold if this guard validates `e` upon evaluating to `b`. */
abstract predicate checks(Expr e, boolean b); abstract predicate checks(Expr e, boolean b);

View File

@@ -47,12 +47,6 @@ predicate defaultImplicitTaintRead(DataFlow::Node node, DataFlow::Content c) { n
*/ */
predicate defaultTaintSanitizer(DataFlow::Node node) { none() } predicate defaultTaintSanitizer(DataFlow::Node node) { none() }
/**
* Holds if `guard` should be a sanitizer guard in all global taint flow configurations
* but not in local taint.
*/
predicate defaultTaintSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
/** /**
* Holds if taint can flow in one local step from `nodeFrom` to `nodeTo` excluding * Holds if taint can flow in one local step from `nodeFrom` to `nodeTo` excluding
* local data flow steps. That is, `nodeFrom` and `nodeTo` are likely to represent * local data flow steps. That is, `nodeFrom` and `nodeTo` are likely to represent

View File

@@ -116,20 +116,30 @@ abstract class Configuration extends DataFlow::Configuration {
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) } final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */ /**
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() } * DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
*
* Holds if taint propagation through nodes guarded by `guard` is prohibited.
*/
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { deprecated final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
this.isSanitizerGuard(guard) or defaultTaintSanitizerGuard(guard) this.isSanitizerGuard(guard)
} }
/** /**
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
*
* Holds if taint propagation through nodes guarded by `guard` is prohibited * Holds if taint propagation through nodes guarded by `guard` is prohibited
* when the flow state is `state`. * when the flow state is `state`.
*/ */
predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { none() } deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
none()
}
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { deprecated final override predicate isBarrierGuard(
DataFlow::BarrierGuard guard, DataFlow::FlowState state
) {
this.isSanitizerGuard(guard, state) this.isSanitizerGuard(guard, state)
} }

View File

@@ -116,20 +116,30 @@ abstract class Configuration extends DataFlow::Configuration {
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) } final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */ /**
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() } * DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
*
* Holds if taint propagation through nodes guarded by `guard` is prohibited.
*/
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { deprecated final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
this.isSanitizerGuard(guard) or defaultTaintSanitizerGuard(guard) this.isSanitizerGuard(guard)
} }
/** /**
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
*
* Holds if taint propagation through nodes guarded by `guard` is prohibited * Holds if taint propagation through nodes guarded by `guard` is prohibited
* when the flow state is `state`. * when the flow state is `state`.
*/ */
predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { none() } deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
none()
}
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { deprecated final override predicate isBarrierGuard(
DataFlow::BarrierGuard guard, DataFlow::FlowState state
) {
this.isSanitizerGuard(guard, state) this.isSanitizerGuard(guard, state)
} }

View File

@@ -4,11 +4,7 @@
* qualified. * qualified.
* *
* This file contains classes that mirror the standard AST classes for C++, but * This file contains classes that mirror the standard AST classes for C++, but
* these classes are only concerned with naming. The other difference is that * these classes are only concerned with naming.
* these classes don't use the `ResolveClass.qll` mechanisms like
* `unresolveElement` because these classes should eventually be part of the
* implementation of `ResolveClass.qll`, allowing it to match up classes when
* their qualified names and parameters match.
*/ */
private import semmle.code.cpp.Declaration as D private import semmle.code.cpp.Declaration as D

View File

@@ -115,15 +115,13 @@ private module Cached {
*/ */
cached cached
predicate isClass(@usertype t) { predicate isClass(@usertype t) {
( usertypes(t, _, 1) or
usertypes(t, _, 1) or usertypes(t, _, 2) or
usertypes(t, _, 2) or usertypes(t, _, 3) or
usertypes(t, _, 3) or usertypes(t, _, 6) or
usertypes(t, _, 6) or usertypes(t, _, 10) or
usertypes(t, _, 10) or usertypes(t, _, 11) or
usertypes(t, _, 11) or usertypes(t, _, 12)
usertypes(t, _, 12)
)
} }
cached cached

View File

@@ -90,14 +90,20 @@ abstract class Configuration extends string {
/** Holds if data flow out of `node` is prohibited. */ /** Holds if data flow out of `node` is prohibited. */
predicate isBarrierOut(Node node) { none() } predicate isBarrierOut(Node node) { none() }
/** Holds if data flow through nodes guarded by `guard` is prohibited. */ /**
predicate isBarrierGuard(BarrierGuard guard) { none() } * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited.
*/
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
/** /**
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited when * Holds if data flow through nodes guarded by `guard` is prohibited when
* the flow state is `state` * the flow state is `state`
*/ */
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() } deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
/** /**
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
@@ -335,6 +341,29 @@ private predicate outBarrier(NodeEx node, Configuration config) {
) )
} }
/** A bridge class to access the deprecated `isBarrierGuard`. */
private class BarrierGuardGuardedNodeBridge extends Unit {
abstract predicate guardedNode(Node n, Configuration config);
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
}
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
deprecated override predicate guardedNode(Node n, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
}
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
}
}
pragma[nomagic] pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) { private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n | exists(Node n | node.asNode() = n |
@@ -348,10 +377,7 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
not config.isSink(n) and not config.isSink(n) and
not config.isSink(n, _) not config.isSink(n, _)
or or
exists(BarrierGuard g | any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config)
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
) )
} }
@@ -360,10 +386,7 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
exists(Node n | node.asNode() = n | exists(Node n | node.asNode() = n |
config.isBarrier(n, state) config.isBarrier(n, state)
or or
exists(BarrierGuard g | any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config)
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
) )
} }

View File

@@ -90,14 +90,20 @@ abstract class Configuration extends string {
/** Holds if data flow out of `node` is prohibited. */ /** Holds if data flow out of `node` is prohibited. */
predicate isBarrierOut(Node node) { none() } predicate isBarrierOut(Node node) { none() }
/** Holds if data flow through nodes guarded by `guard` is prohibited. */ /**
predicate isBarrierGuard(BarrierGuard guard) { none() } * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited.
*/
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
/** /**
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited when * Holds if data flow through nodes guarded by `guard` is prohibited when
* the flow state is `state` * the flow state is `state`
*/ */
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() } deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
/** /**
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
@@ -335,6 +341,29 @@ private predicate outBarrier(NodeEx node, Configuration config) {
) )
} }
/** A bridge class to access the deprecated `isBarrierGuard`. */
private class BarrierGuardGuardedNodeBridge extends Unit {
abstract predicate guardedNode(Node n, Configuration config);
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
}
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
deprecated override predicate guardedNode(Node n, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
}
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
}
}
pragma[nomagic] pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) { private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n | exists(Node n | node.asNode() = n |
@@ -348,10 +377,7 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
not config.isSink(n) and not config.isSink(n) and
not config.isSink(n, _) not config.isSink(n, _)
or or
exists(BarrierGuard g | any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config)
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
) )
} }
@@ -360,10 +386,7 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
exists(Node n | node.asNode() = n | exists(Node n | node.asNode() = n |
config.isBarrier(n, state) config.isBarrier(n, state)
or or
exists(BarrierGuard g | any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config)
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
) )
} }

View File

@@ -90,14 +90,20 @@ abstract class Configuration extends string {
/** Holds if data flow out of `node` is prohibited. */ /** Holds if data flow out of `node` is prohibited. */
predicate isBarrierOut(Node node) { none() } predicate isBarrierOut(Node node) { none() }
/** Holds if data flow through nodes guarded by `guard` is prohibited. */ /**
predicate isBarrierGuard(BarrierGuard guard) { none() } * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited.
*/
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
/** /**
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited when * Holds if data flow through nodes guarded by `guard` is prohibited when
* the flow state is `state` * the flow state is `state`
*/ */
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() } deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
/** /**
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
@@ -335,6 +341,29 @@ private predicate outBarrier(NodeEx node, Configuration config) {
) )
} }
/** A bridge class to access the deprecated `isBarrierGuard`. */
private class BarrierGuardGuardedNodeBridge extends Unit {
abstract predicate guardedNode(Node n, Configuration config);
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
}
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
deprecated override predicate guardedNode(Node n, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
}
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
}
}
pragma[nomagic] pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) { private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n | exists(Node n | node.asNode() = n |
@@ -348,10 +377,7 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
not config.isSink(n) and not config.isSink(n) and
not config.isSink(n, _) not config.isSink(n, _)
or or
exists(BarrierGuard g | any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config)
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
) )
} }
@@ -360,10 +386,7 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
exists(Node n | node.asNode() = n | exists(Node n | node.asNode() = n |
config.isBarrier(n, state) config.isBarrier(n, state)
or or
exists(BarrierGuard g | any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config)
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
) )
} }

View File

@@ -90,14 +90,20 @@ abstract class Configuration extends string {
/** Holds if data flow out of `node` is prohibited. */ /** Holds if data flow out of `node` is prohibited. */
predicate isBarrierOut(Node node) { none() } predicate isBarrierOut(Node node) { none() }
/** Holds if data flow through nodes guarded by `guard` is prohibited. */ /**
predicate isBarrierGuard(BarrierGuard guard) { none() } * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited.
*/
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
/** /**
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited when * Holds if data flow through nodes guarded by `guard` is prohibited when
* the flow state is `state` * the flow state is `state`
*/ */
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() } deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
/** /**
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
@@ -335,6 +341,29 @@ private predicate outBarrier(NodeEx node, Configuration config) {
) )
} }
/** A bridge class to access the deprecated `isBarrierGuard`. */
private class BarrierGuardGuardedNodeBridge extends Unit {
abstract predicate guardedNode(Node n, Configuration config);
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
}
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
deprecated override predicate guardedNode(Node n, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
}
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
}
}
pragma[nomagic] pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) { private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n | exists(Node n | node.asNode() = n |
@@ -348,10 +377,7 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
not config.isSink(n) and not config.isSink(n) and
not config.isSink(n, _) not config.isSink(n, _)
or or
exists(BarrierGuard g | any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config)
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
) )
} }
@@ -360,10 +386,7 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
exists(Node n | node.asNode() = n | exists(Node n | node.asNode() = n |
config.isBarrier(n, state) config.isBarrier(n, state)
or or
exists(BarrierGuard g | any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config)
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
) )
} }

View File

@@ -1092,6 +1092,56 @@ class ContentSet instanceof Content {
} }
/** /**
* Holds if the guard `g` validates the expression `e` upon evaluating to `branch`.
*
* The expression `e` is expected to be a syntactic part of the guard `g`.
* For example, the guard `g` might be a call `isSafe(x)` and the expression `e`
* the argument `x`.
*/
signature predicate guardChecksSig(IRGuardCondition g, Expr e, boolean branch);
/**
* Provides a set of barrier nodes for a guard that validates an expression.
*
* This is expected to be used in `isBarrier`/`isSanitizer` definitions
* in data flow and taint tracking.
*/
module BarrierGuard<guardChecksSig/3 guardChecks> {
/** Gets a node that is safely guarded by the given guard check. */
ExprNode getABarrierNode() {
exists(IRGuardCondition g, ValueNumber value, boolean edge |
guardChecks(g, value.getAnInstruction().getConvertedResultExpression(), edge) and
result.asInstruction() = value.getAnInstruction() and
g.controls(result.asInstruction().getBlock(), edge)
)
}
}
/**
* Holds if the guard `g` validates the instruction `instr` upon evaluating to `branch`.
*/
signature predicate instructionGuardChecksSig(IRGuardCondition g, Instruction instr, boolean branch);
/**
* Provides a set of barrier nodes for a guard that validates an instruction.
*
* This is expected to be used in `isBarrier`/`isSanitizer` definitions
* in data flow and taint tracking.
*/
module InstructionBarrierGuard<instructionGuardChecksSig/3 instructionGuardChecks> {
/** Gets a node that is safely guarded by the given guard check. */
ExprNode getABarrierNode() {
exists(IRGuardCondition g, ValueNumber value, boolean edge |
instructionGuardChecks(g, value.getAnInstruction(), edge) and
result.asInstruction() = value.getAnInstruction() and
g.controls(result.asInstruction().getBlock(), edge)
)
}
}
/**
* DEPRECATED: Use `BarrierGuard` module instead.
*
* A guard that validates some instruction. * A guard that validates some instruction.
* *
* To use this in a configuration, extend the class and provide a * To use this in a configuration, extend the class and provide a
@@ -1100,7 +1150,7 @@ class ContentSet instanceof Content {
* *
* It is important that all extending classes in scope are disjoint. * It is important that all extending classes in scope are disjoint.
*/ */
class BarrierGuard extends IRGuardCondition { deprecated class BarrierGuard extends IRGuardCondition {
/** Override this predicate to hold if this guard validates `instr` upon evaluating to `b`. */ /** Override this predicate to hold if this guard validates `instr` upon evaluating to `b`. */
predicate checksInstr(Instruction instr, boolean b) { none() } predicate checksInstr(Instruction instr, boolean b) { none() }

View File

@@ -94,12 +94,6 @@ private string getNodeProperty(DataFlow::Node node, string key) {
any(DataFlow::Configuration cfg).isBarrierIn(node) and kind = "in" any(DataFlow::Configuration cfg).isBarrierIn(node) and kind = "in"
or or
any(DataFlow::Configuration cfg).isBarrierOut(node) and kind = "out" any(DataFlow::Configuration cfg).isBarrierOut(node) and kind = "out"
or
exists(DataFlow::BarrierGuard guard |
any(DataFlow::Configuration cfg).isBarrierGuard(guard) and
node = guard.getAGuardedNode() and
kind = "guard(" + guard.getResultId() + ")"
)
| |
kind, ", " kind, ", "
) )

View File

@@ -163,12 +163,6 @@ predicate defaultImplicitTaintRead(DataFlow::Node node, DataFlow::Content c) { n
*/ */
predicate defaultTaintSanitizer(DataFlow::Node node) { none() } predicate defaultTaintSanitizer(DataFlow::Node node) { none() }
/**
* Holds if `guard` should be a sanitizer guard in all global taint flow configurations
* but not in local taint.
*/
predicate defaultTaintSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
/** /**
* Holds if taint can flow from `instrIn` to `instrOut` through a call to a * Holds if taint can flow from `instrIn` to `instrOut` through a call to a
* modeled function. * modeled function.

View File

@@ -116,20 +116,30 @@ abstract class Configuration extends DataFlow::Configuration {
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) } final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */ /**
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() } * DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
*
* Holds if taint propagation through nodes guarded by `guard` is prohibited.
*/
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { deprecated final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
this.isSanitizerGuard(guard) or defaultTaintSanitizerGuard(guard) this.isSanitizerGuard(guard)
} }
/** /**
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
*
* Holds if taint propagation through nodes guarded by `guard` is prohibited * Holds if taint propagation through nodes guarded by `guard` is prohibited
* when the flow state is `state`. * when the flow state is `state`.
*/ */
predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { none() } deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
none()
}
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { deprecated final override predicate isBarrierGuard(
DataFlow::BarrierGuard guard, DataFlow::FlowState state
) {
this.isSanitizerGuard(guard, state) this.isSanitizerGuard(guard, state)
} }

View File

@@ -116,20 +116,30 @@ abstract class Configuration extends DataFlow::Configuration {
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) } final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */ /**
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() } * DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
*
* Holds if taint propagation through nodes guarded by `guard` is prohibited.
*/
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { deprecated final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
this.isSanitizerGuard(guard) or defaultTaintSanitizerGuard(guard) this.isSanitizerGuard(guard)
} }
/** /**
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
*
* Holds if taint propagation through nodes guarded by `guard` is prohibited * Holds if taint propagation through nodes guarded by `guard` is prohibited
* when the flow state is `state`. * when the flow state is `state`.
*/ */
predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { none() } deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
none()
}
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { deprecated final override predicate isBarrierGuard(
DataFlow::BarrierGuard guard, DataFlow::FlowState state
) {
this.isSanitizerGuard(guard, state) this.isSanitizerGuard(guard, state)
} }

View File

@@ -116,20 +116,30 @@ abstract class Configuration extends DataFlow::Configuration {
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) } final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */ /**
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() } * DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
*
* Holds if taint propagation through nodes guarded by `guard` is prohibited.
*/
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { deprecated final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
this.isSanitizerGuard(guard) or defaultTaintSanitizerGuard(guard) this.isSanitizerGuard(guard)
} }
/** /**
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
*
* Holds if taint propagation through nodes guarded by `guard` is prohibited * Holds if taint propagation through nodes guarded by `guard` is prohibited
* when the flow state is `state`. * when the flow state is `state`.
*/ */
predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { none() } deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
none()
}
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { deprecated final override predicate isBarrierGuard(
DataFlow::BarrierGuard guard, DataFlow::FlowState state
) {
this.isSanitizerGuard(guard, state) this.isSanitizerGuard(guard, state)
} }

View File

@@ -1,3 +1,5 @@
## 0.1.4
## 0.1.3 ## 0.1.3
### Minor Analysis Improvements ### Minor Analysis Improvements

View File

@@ -0,0 +1 @@
## 0.1.4

View File

@@ -1,2 +1,2 @@
--- ---
lastReleaseVersion: 0.1.3 lastReleaseVersion: 0.1.4

View File

@@ -0,0 +1,11 @@
...
SSL_shutdown(ssl);
SSL_shutdown(ssl); // BAD
...
switch ((ret = SSL_shutdown(ssl))) {
case 1:
break;
case 0:
ERR_clear_error();
if (-1 != (ret = SSL_shutdown(ssl))) break; // GOOD
...

View File

@@ -0,0 +1,27 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>Incorrect closing of the connection leads to the creation of different states for the server and client, which can be exploited by an attacker.</p>
</overview>
<example>
<p>The following example shows the incorrect and correct usage of function SSL_shutdown.</p>
<sample src="DangerousUseSSL_shutdown.cpp" />
</example>
<references>
<li>
CERT Coding Standard:
<a href="https://wiki.sei.cmu.edu/confluence/display/c/EXP12-C.+Do+not+ignore+values+returned+by+functions">EXP12-C. Do not ignore values returned by functions - SEI CERT C Coding Standard - Confluence</a>.
</li>
<li>
Openssl.org:
<a href="https://www.openssl.org/docs/man3.0/man3/SSL_shutdown.html">SSL_shutdown - shut down a TLS/SSL connection</a>.
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,33 @@
/**
* @name Dangerous use SSL_shutdown.
* @description Incorrect closing of the connection leads to the creation of different states for the server and client, which can be exploited by an attacker.
* @kind problem
* @id cpp/dangerous-use-of-ssl-shutdown
* @problem.severity warning
* @precision medium
* @tags correctness
* security
* external/cwe/cwe-670
*/
import cpp
import semmle.code.cpp.commons.Exclusions
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
from FunctionCall fc, FunctionCall fc1
where
fc != fc1 and
fc.getASuccessor+() = fc1 and
fc.getTarget().hasName("SSL_shutdown") and
fc1.getTarget().hasName("SSL_shutdown") and
fc1 instanceof ExprInVoidContext and
(
globalValueNumber(fc.getArgument(0)) = globalValueNumber(fc1.getArgument(0)) or
fc.getArgument(0).(VariableAccess).getTarget() = fc1.getArgument(0).(VariableAccess).getTarget()
) and
not exists(FunctionCall fctmp |
fctmp.getTarget().hasName("SSL_free") and
fc.getASuccessor+() = fctmp and
fctmp.getASuccessor+() = fc1
)
select fc, "You need to handle the return value SSL_shutdown"

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-queries name: codeql/cpp-queries
version: 0.1.4-dev version: 0.2.0-dev
groups: groups:
- cpp - cpp
- queries - queries

View File

@@ -239,12 +239,24 @@ private string getColumnString(TColumn column) {
/** /**
* RegEx pattern to match a single expected result, not including the leading `$`. It consists of one or * RegEx pattern to match a single expected result, not including the leading `$`. It consists of one or
* more comma-separated tags containing only letters, digits, `-` and `_` (note that the first character * more comma-separated tags optionally followed by `=` and the expected value.
* must not be a digit), optionally followed by `=` and the expected value. *
* Tags must be only letters, digits, `-` and `_` (note that the first character
* must not be a digit), but can contain anything enclosed in a single set of
* square brackets.
*
* Examples:
* - `tag`
* - `tag=value`
* - `tag,tag2=value`
* - `tag[foo bar]=value`
*
* Not allowed:
* - `tag[[[foo bar]`
*/ */
private string expectationPattern() { private string expectationPattern() {
exists(string tag, string tags, string value | exists(string tag, string tags, string value |
tag = "[A-Za-z-_][A-Za-z-_0-9]*" and tag = "[A-Za-z-_](?:[A-Za-z-_0-9]|\\[[^\\]\\]]*\\])*" and
tags = "((?:" + tag + ")(?:\\s*,\\s*" + tag + ")*)" and tags = "((?:" + tag + ")(?:\\s*,\\s*" + tag + ")*)" and
// In Python, we allow both `"` and `'` for strings, as well as the prefixes `bru`. // In Python, we allow both `"` and `'` for strings, as well as the prefixes `bru`.
// For example, `b"foo"`. // For example, `b"foo"`.

View File

@@ -0,0 +1,2 @@
| test.cpp:45:20:45:31 | call to SSL_shutdown | You need to handle the return value SSL_shutdown |
| test.cpp:61:11:61:22 | call to SSL_shutdown | You need to handle the return value SSL_shutdown |

View File

@@ -0,0 +1 @@
experimental/Security/CWE/CWE-670/DangerousUseSSL_shutdown.ql

View File

@@ -0,0 +1,75 @@
// it's not exact, but it's enough for an example
typedef int SSL;
int SSL_shutdown(SSL *ssl);
int SSL_get_error(const SSL *ssl, int ret);
void ERR_clear_error(void);
void print_error(char *buff,int code);
int gootTest1(SSL *ssl)
{
int ret;
switch ((ret = SSL_shutdown(ssl))) {
case 1:
break;
case 0:
ERR_clear_error();
if ((ret = SSL_shutdown(ssl)) == 1) break; // GOOD
default:
print_error("error shutdown",
SSL_get_error(ssl, ret));
return -1;
}
return 0;
}
int gootTest2(SSL *ssl)
{
int ret;
switch ((ret = SSL_shutdown(ssl))) {
case 1:
break;
case 0:
ERR_clear_error();
if (-1 != (ret = SSL_shutdown(ssl))) break; // GOOD
default:
print_error("error shutdown",
SSL_get_error(ssl, ret));
return -1;
}
return 0;
}
int badTest1(SSL *ssl)
{
int ret;
switch ((ret = SSL_shutdown(ssl))) {
case 1:
break;
case 0:
SSL_shutdown(ssl); // BAD
break;
default:
print_error("error shutdown",
SSL_get_error(ssl, ret));
return -1;
}
return 0;
}
int badTest2(SSL *ssl)
{
int ret;
ret = SSL_shutdown(ssl);
switch (ret) {
case 1:
break;
case 0:
SSL_shutdown(ssl); // BAD
break;
default:
print_error("error shutdown",
SSL_get_error(ssl, ret));
return -1;
}
return 0;
}

View File

@@ -220,10 +220,10 @@ postWithInFlow
| lambdas.cpp:20:11:20:11 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | | lambdas.cpp:20:11:20:11 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
| lambdas.cpp:20:11:20:11 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | | lambdas.cpp:20:11:20:11 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
| lambdas.cpp:20:11:20:11 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | | lambdas.cpp:20:11:20:11 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
| lambdas.cpp:23:3:23:3 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. |
| lambdas.cpp:23:3:23:14 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | | lambdas.cpp:23:3:23:14 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
| lambdas.cpp:23:3:23:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | | lambdas.cpp:23:3:23:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| lambdas.cpp:23:3:23:14 | v [post update] | PostUpdateNode should not be the target of local flow. | | lambdas.cpp:23:3:23:14 | v [post update] | PostUpdateNode should not be the target of local flow. |
| lambdas.cpp:23:15:23:15 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. |
| lambdas.cpp:28:7:28:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | | lambdas.cpp:28:7:28:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
| lambdas.cpp:28:10:31:2 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | | lambdas.cpp:28:10:31:2 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
| lambdas.cpp:28:10:31:2 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | | lambdas.cpp:28:10:31:2 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |

View File

@@ -2,19 +2,17 @@ import TestUtilities.dataflow.FlowTestCommon
module AstTest { module AstTest {
private import semmle.code.cpp.dataflow.DataFlow private import semmle.code.cpp.dataflow.DataFlow
private import semmle.code.cpp.controlflow.Guards
/** /**
* A `BarrierGuard` that stops flow to all occurrences of `x` within statement * A `BarrierGuard` that stops flow to all occurrences of `x` within statement
* S in `if (guarded(x)) S`. * S in `if (guarded(x)) S`.
*/ */
// This is tested in `BarrierGuard.cpp`. // This is tested in `BarrierGuard.cpp`.
class TestBarrierGuard extends DataFlow::BarrierGuard { predicate testBarrierGuard(GuardCondition g, Expr checked, boolean isTrue) {
TestBarrierGuard() { this.(FunctionCall).getTarget().getName() = "guarded" } g.(FunctionCall).getTarget().getName() = "guarded" and
checked = g.(FunctionCall).getArgument(0) and
override predicate checks(Expr checked, boolean isTrue) { isTrue = true
checked = this.(FunctionCall).getArgument(0) and
isTrue = true
}
} }
/** Common data flow configuration to be used by tests. */ /** Common data flow configuration to be used by tests. */
@@ -40,29 +38,26 @@ module AstTest {
} }
override predicate isBarrier(DataFlow::Node barrier) { override predicate isBarrier(DataFlow::Node barrier) {
barrier.asExpr().(VariableAccess).getTarget().hasName("barrier") barrier.asExpr().(VariableAccess).getTarget().hasName("barrier") or
barrier = DataFlow::BarrierGuard<testBarrierGuard/3>::getABarrierNode()
} }
override predicate isBarrierGuard(DataFlow::BarrierGuard bg) { bg instanceof TestBarrierGuard }
} }
} }
module IRTest { module IRTest {
private import semmle.code.cpp.ir.dataflow.DataFlow private import semmle.code.cpp.ir.dataflow.DataFlow
private import semmle.code.cpp.ir.IR private import semmle.code.cpp.ir.IR
private import semmle.code.cpp.controlflow.IRGuards
/** /**
* A `BarrierGuard` that stops flow to all occurrences of `x` within statement * A `BarrierGuard` that stops flow to all occurrences of `x` within statement
* S in `if (guarded(x)) S`. * S in `if (guarded(x)) S`.
*/ */
// This is tested in `BarrierGuard.cpp`. // This is tested in `BarrierGuard.cpp`.
class TestBarrierGuard extends DataFlow::BarrierGuard { predicate testBarrierGuard(IRGuardCondition g, Instruction checked, boolean isTrue) {
TestBarrierGuard() { this.(CallInstruction).getStaticCallTarget().getName() = "guarded" } g.(CallInstruction).getStaticCallTarget().getName() = "guarded" and
checked = g.(CallInstruction).getPositionalArgument(0) and
override predicate checksInstr(Instruction checked, boolean isTrue) { isTrue = true
checked = this.(CallInstruction).getPositionalArgument(0) and
isTrue = true
}
} }
/** Common data flow configuration to be used by tests. */ /** Common data flow configuration to be used by tests. */
@@ -93,10 +88,9 @@ module IRTest {
} }
override predicate isBarrier(DataFlow::Node barrier) { override predicate isBarrier(DataFlow::Node barrier) {
barrier.asExpr().(VariableAccess).getTarget().hasName("barrier") barrier.asExpr().(VariableAccess).getTarget().hasName("barrier") or
barrier = DataFlow::InstructionBarrierGuard<testBarrierGuard/3>::getABarrierNode()
} }
override predicate isBarrierGuard(DataFlow::BarrierGuard bg) { bg instanceof TestBarrierGuard }
} }
private predicate readsVariable(LoadInstruction load, Variable var) { private predicate readsVariable(LoadInstruction load, Variable var) {

View File

@@ -33,3 +33,11 @@ public:
myTemplateClass<int> mtc_int; myTemplateClass<int> mtc_int;
myTemplateClass<short> mtc_short; myTemplateClass<short> mtc_short;
// Class (UserType)
class myClass
{
public:
int myMemberVariable;
};

View File

@@ -27,5 +27,11 @@
| declarationEntry.cpp:31:4:31:19 | myMemberVariable | declarationEntry.cpp:31:4:31:19 | definition of myMemberVariable | 1 | 1 | | declarationEntry.cpp:31:4:31:19 | myMemberVariable | declarationEntry.cpp:31:4:31:19 | definition of myMemberVariable | 1 | 1 |
| declarationEntry.cpp:34:22:34:28 | mtc_int | declarationEntry.cpp:34:22:34:28 | definition of mtc_int | 1 | 1 | | declarationEntry.cpp:34:22:34:28 | mtc_int | declarationEntry.cpp:34:22:34:28 | definition of mtc_int | 1 | 1 |
| declarationEntry.cpp:35:24:35:32 | mtc_short | declarationEntry.cpp:35:24:35:32 | definition of mtc_short | 1 | 1 | | declarationEntry.cpp:35:24:35:32 | mtc_short | declarationEntry.cpp:35:24:35:32 | definition of mtc_short | 1 | 1 |
| declarationEntry.cpp:39:7:39:7 | operator= | declarationEntry.cpp:39:7:39:7 | declaration of operator= | 1 | 1 |
| declarationEntry.cpp:39:7:39:7 | operator= | declarationEntry.cpp:39:7:39:7 | declaration of operator= | 1 | 1 |
| declarationEntry.cpp:39:7:39:13 | myClass | declarationEntry.cpp:39:7:39:13 | definition of myClass | 1 | 1 |
| declarationEntry.cpp:39:7:39:13 | myClass | forwardDeclaration.cpp:1:7:1:13 | declaration of myClass | 1 | 1 |
| declarationEntry.cpp:42:6:42:21 | myMemberVariable | declarationEntry.cpp:42:6:42:21 | definition of myMemberVariable | 1 | 1 |
| forwardDeclaration.cpp:3:10:3:19 | myClassPtr | forwardDeclaration.cpp:3:10:3:19 | definition of myClassPtr | 1 | 1 |
| macro.c:2:1:2:3 | foo | macro.c:2:1:2:3 | declaration of foo | 1 | 1 | | macro.c:2:1:2:3 | foo | macro.c:2:1:2:3 | declaration of foo | 1 | 1 |
| macro.c:4:5:4:8 | main | macro.c:4:5:4:8 | definition of main | 1 | 1 | | macro.c:4:5:4:8 | main | macro.c:4:5:4:8 | definition of main | 1 | 1 |

View File

@@ -10,5 +10,7 @@
| declarationEntry.cpp:28:7:28:7 | declaration of operator= | | 0 | | | declarationEntry.cpp:28:7:28:7 | declaration of operator= | | 0 | |
| declarationEntry.cpp:28:7:28:7 | declaration of operator= | | 0 | | | declarationEntry.cpp:28:7:28:7 | declaration of operator= | | 0 | |
| declarationEntry.cpp:28:7:28:7 | declaration of operator= | | 0 | | | declarationEntry.cpp:28:7:28:7 | declaration of operator= | | 0 | |
| declarationEntry.cpp:39:7:39:7 | declaration of operator= | | 0 | |
| declarationEntry.cpp:39:7:39:7 | declaration of operator= | | 0 | |
| macro.c:2:1:2:3 | declaration of foo | | 2 | c_linkage, static | | macro.c:2:1:2:3 | declaration of foo | | 2 | c_linkage, static |
| macro.c:4:5:4:8 | definition of main | | 1 | c_linkage | | macro.c:4:5:4:8 | definition of main | | 1 | c_linkage |

View File

@@ -0,0 +1,3 @@
class myClass;
myClass *myClassPtr;

View File

@@ -0,0 +1,45 @@
| declarationEntry.c:2:6:2:20 | declaration of myFirstFunction | declarationEntry.c:2:6:2:20 | myFirstFunction | yes |
| declarationEntry.c:4:6:4:21 | definition of mySecondFunction | declarationEntry.c:4:6:4:21 | mySecondFunction | yes |
| declarationEntry.c:8:6:8:20 | definition of myThirdFunction | declarationEntry.c:8:6:8:20 | myThirdFunction | yes |
| declarationEntry.c:13:2:13:2 | declaration of myFourthFunction | declarationEntry.c:13:2:13:2 | myFourthFunction | yes |
| declarationEntry.c:13:2:13:2 | declaration of myFourthFunction | declarationEntry.c:17:6:17:21 | myFourthFunction | yes |
| declarationEntry.c:14:2:14:2 | declaration of myFifthFunction | declarationEntry.c:14:2:14:2 | myFifthFunction | yes |
| declarationEntry.c:17:6:17:21 | declaration of myFourthFunction | declarationEntry.c:13:2:13:2 | myFourthFunction | yes |
| declarationEntry.c:17:6:17:21 | declaration of myFourthFunction | declarationEntry.c:17:6:17:21 | myFourthFunction | yes |
| declarationEntry.cpp:3:12:3:21 | declaration of myVariable | declarationEntry.cpp:5:5:5:14 | myVariable | yes |
| declarationEntry.cpp:5:5:5:14 | definition of myVariable | declarationEntry.cpp:5:5:5:14 | myVariable | yes |
| declarationEntry.cpp:9:6:9:15 | declaration of myFunction | declarationEntry.cpp:11:6:11:15 | myFunction | yes |
| declarationEntry.cpp:9:21:9:31 | declaration of myParameter | declarationEntry.cpp:11:21:11:31 | myParameter | yes |
| declarationEntry.cpp:11:6:11:15 | definition of myFunction | declarationEntry.cpp:11:6:11:15 | myFunction | yes |
| declarationEntry.cpp:11:21:11:31 | definition of myParameter | declarationEntry.cpp:11:21:11:31 | myParameter | yes |
| declarationEntry.cpp:18:6:18:11 | declaration of myEnum | declarationEntry.cpp:20:6:20:11 | myEnum | yes |
| declarationEntry.cpp:20:6:20:11 | definition of myEnum | declarationEntry.cpp:20:6:20:11 | myEnum | yes |
| declarationEntry.cpp:27:20:27:20 | definition of T | declarationEntry.cpp:27:20:27:20 | T | yes |
| declarationEntry.cpp:28:7:28:7 | declaration of operator= | declarationEntry.cpp:28:7:28:7 | operator= | yes |
| declarationEntry.cpp:28:7:28:7 | declaration of operator= | declarationEntry.cpp:28:7:28:7 | operator= | yes |
| declarationEntry.cpp:28:7:28:7 | declaration of operator= | declarationEntry.cpp:28:7:28:7 | operator= | yes |
| declarationEntry.cpp:28:7:28:7 | declaration of operator= | declarationEntry.cpp:28:7:28:7 | operator= | yes |
| declarationEntry.cpp:28:7:28:21 | definition of myTemplateClass<T> | declarationEntry.cpp:28:7:28:21 | myTemplateClass<T> | yes |
| declarationEntry.cpp:31:4:31:19 | definition of myMemberVariable | declarationEntry.cpp:31:4:31:19 | myMemberVariable | yes |
| declarationEntry.cpp:31:4:31:19 | definition of myMemberVariable | declarationEntry.cpp:31:4:31:19 | myMemberVariable | yes |
| declarationEntry.cpp:31:4:31:19 | definition of myMemberVariable | declarationEntry.cpp:31:4:31:19 | myMemberVariable | yes |
| declarationEntry.cpp:34:22:34:28 | definition of mtc_int | declarationEntry.cpp:34:22:34:28 | mtc_int | yes |
| declarationEntry.cpp:35:24:35:32 | definition of mtc_short | declarationEntry.cpp:35:24:35:32 | mtc_short | yes |
| declarationEntry.cpp:39:7:39:7 | declaration of operator= | declarationEntry.cpp:39:7:39:7 | operator= | yes |
| declarationEntry.cpp:39:7:39:7 | declaration of operator= | declarationEntry.cpp:39:7:39:7 | operator= | yes |
| declarationEntry.cpp:39:7:39:13 | definition of myClass | declarationEntry.cpp:39:7:39:13 | myClass | yes |
| declarationEntry.cpp:42:6:42:21 | definition of myMemberVariable | declarationEntry.cpp:42:6:42:21 | myMemberVariable | yes |
| file://:0:0:0:0 | declaration of 1st parameter | file://:0:0:0:0 | (unnamed parameter 0) | yes |
| file://:0:0:0:0 | declaration of 1st parameter | file://:0:0:0:0 | (unnamed parameter 0) | yes |
| file://:0:0:0:0 | declaration of 1st parameter | file://:0:0:0:0 | (unnamed parameter 0) | yes |
| file://:0:0:0:0 | declaration of 1st parameter | file://:0:0:0:0 | (unnamed parameter 0) | yes |
| file://:0:0:0:0 | declaration of 1st parameter | file://:0:0:0:0 | (unnamed parameter 0) | yes |
| file://:0:0:0:0 | declaration of 1st parameter | file://:0:0:0:0 | (unnamed parameter 0) | yes |
| file://:0:0:0:0 | definition of fp_offset | file://:0:0:0:0 | fp_offset | yes |
| file://:0:0:0:0 | definition of gp_offset | file://:0:0:0:0 | gp_offset | yes |
| file://:0:0:0:0 | definition of overflow_arg_area | file://:0:0:0:0 | overflow_arg_area | yes |
| file://:0:0:0:0 | definition of reg_save_area | file://:0:0:0:0 | reg_save_area | yes |
| forwardDeclaration.cpp:1:7:1:13 | declaration of myClass | declarationEntry.cpp:39:7:39:13 | myClass | yes |
| forwardDeclaration.cpp:3:10:3:19 | definition of myClassPtr | forwardDeclaration.cpp:3:10:3:19 | myClassPtr | yes |
| macro.c:2:1:2:3 | declaration of foo | macro.c:2:1:2:3 | foo | yes |
| macro.c:4:5:4:8 | definition of main | macro.c:4:5:4:8 | main | yes |

View File

@@ -0,0 +1,7 @@
import cpp
from DeclarationEntry de, Declaration d, string canRoundTrip
where
d = de.getDeclaration() and
if d.getADeclarationEntry() = de then canRoundTrip = "yes" else canRoundTrip = "no"
select de, d, canRoundTrip

View File

@@ -4841,6 +4841,9 @@
| ir.cpp:1043:24:1043:24 | SideEffect | ~m1043_20 | | ir.cpp:1043:24:1043:24 | SideEffect | ~m1043_20 |
| ir.cpp:1043:31:1043:31 | Address | &:r1043_9 | | ir.cpp:1043:31:1043:31 | Address | &:r1043_9 |
| ir.cpp:1043:36:1043:55 | Address | &:r1043_11 | | ir.cpp:1043:36:1043:55 | Address | &:r1043_11 |
| ir.cpp:1043:43:1043:43 | Address | &:r1043_16 |
| ir.cpp:1043:43:1043:43 | Arg(this) | this:r1043_16 |
| ir.cpp:1043:43:1043:43 | SideEffect | ~m1043_20 |
| ir.cpp:1043:43:1043:54 | Address | &:r1043_22 | | ir.cpp:1043:43:1043:54 | Address | &:r1043_22 |
| ir.cpp:1043:43:1043:54 | Address | &:r1043_24 | | ir.cpp:1043:43:1043:54 | Address | &:r1043_24 |
| ir.cpp:1043:43:1043:54 | Address | &:r1043_25 | | ir.cpp:1043:43:1043:54 | Address | &:r1043_25 |
@@ -4861,11 +4864,8 @@
| ir.cpp:1043:45:1043:49 | SideEffect | ~m1043_4 | | ir.cpp:1043:45:1043:49 | SideEffect | ~m1043_4 |
| ir.cpp:1043:45:1043:49 | Unary | r1043_13 | | ir.cpp:1043:45:1043:49 | Unary | r1043_13 |
| ir.cpp:1043:45:1043:49 | Unary | r1043_15 | | ir.cpp:1043:45:1043:49 | Unary | r1043_15 |
| ir.cpp:1043:52:1043:52 | Address | &:r1043_16 | | ir.cpp:1043:53:1043:53 | Load | ~m1043_20 |
| ir.cpp:1043:52:1043:52 | Arg(this) | this:r1043_16 | | ir.cpp:1043:53:1043:53 | Right | r1043_26 |
| ir.cpp:1043:52:1043:52 | SideEffect | ~m1043_20 |
| ir.cpp:1043:54:1043:54 | Load | ~m1043_20 |
| ir.cpp:1043:54:1043:54 | Right | r1043_26 |
| ir.cpp:1043:58:1043:58 | ChiPartial | partial:m1043_9 | | ir.cpp:1043:58:1043:58 | ChiPartial | partial:m1043_9 |
| ir.cpp:1043:58:1043:58 | ChiTotal | total:m1043_3 | | ir.cpp:1043:58:1043:58 | ChiTotal | total:m1043_3 |
| ir.cpp:1043:58:1043:58 | StoreValue | r1043_8 | | ir.cpp:1043:58:1043:58 | StoreValue | r1043_8 |
@@ -4980,6 +4980,9 @@
| ir.cpp:1047:34:1047:34 | SideEffect | ~m1047_20 | | ir.cpp:1047:34:1047:34 | SideEffect | ~m1047_20 |
| ir.cpp:1047:41:1047:41 | Address | &:r1047_9 | | ir.cpp:1047:41:1047:41 | Address | &:r1047_9 |
| ir.cpp:1047:46:1047:65 | Address | &:r1047_11 | | ir.cpp:1047:46:1047:65 | Address | &:r1047_11 |
| ir.cpp:1047:53:1047:53 | Address | &:r1047_16 |
| ir.cpp:1047:53:1047:53 | Arg(this) | this:r1047_16 |
| ir.cpp:1047:53:1047:53 | SideEffect | ~m1047_20 |
| ir.cpp:1047:53:1047:64 | Address | &:r1047_23 | | ir.cpp:1047:53:1047:64 | Address | &:r1047_23 |
| ir.cpp:1047:53:1047:64 | Load | ~m1047_20 | | ir.cpp:1047:53:1047:64 | Load | ~m1047_20 |
| ir.cpp:1047:53:1047:64 | StoreValue | r1047_24 | | ir.cpp:1047:53:1047:64 | StoreValue | r1047_24 |
@@ -4994,9 +4997,6 @@
| ir.cpp:1047:55:1047:59 | SideEffect | ~m1047_4 | | ir.cpp:1047:55:1047:59 | SideEffect | ~m1047_4 |
| ir.cpp:1047:55:1047:59 | Unary | r1047_13 | | ir.cpp:1047:55:1047:59 | Unary | r1047_13 |
| ir.cpp:1047:55:1047:59 | Unary | r1047_15 | | ir.cpp:1047:55:1047:59 | Unary | r1047_15 |
| ir.cpp:1047:62:1047:62 | Address | &:r1047_16 |
| ir.cpp:1047:62:1047:62 | Arg(this) | this:r1047_16 |
| ir.cpp:1047:62:1047:62 | SideEffect | ~m1047_20 |
| ir.cpp:1047:63:1047:63 | Right | r1047_22 | | ir.cpp:1047:63:1047:63 | Right | r1047_22 |
| ir.cpp:1047:68:1047:68 | StoreValue | r1047_8 | | ir.cpp:1047:68:1047:68 | StoreValue | r1047_8 |
| ir.cpp:1047:68:1047:68 | Unary | r1047_7 | | ir.cpp:1047:68:1047:68 | Unary | r1047_7 |
@@ -5105,6 +5105,9 @@
| ir.cpp:1051:39:1051:39 | SideEffect | ~m1051_20 | | ir.cpp:1051:39:1051:39 | SideEffect | ~m1051_20 |
| ir.cpp:1051:46:1051:46 | Address | &:r1051_9 | | ir.cpp:1051:46:1051:46 | Address | &:r1051_9 |
| ir.cpp:1051:51:1051:70 | Address | &:r1051_11 | | ir.cpp:1051:51:1051:70 | Address | &:r1051_11 |
| ir.cpp:1051:58:1051:58 | Address | &:r1051_16 |
| ir.cpp:1051:58:1051:58 | Arg(this) | this:r1051_16 |
| ir.cpp:1051:58:1051:58 | SideEffect | ~m1051_20 |
| ir.cpp:1051:58:1051:69 | Address | &:r1051_22 | | ir.cpp:1051:58:1051:69 | Address | &:r1051_22 |
| ir.cpp:1051:58:1051:69 | Address | &:r1051_24 | | ir.cpp:1051:58:1051:69 | Address | &:r1051_24 |
| ir.cpp:1051:58:1051:69 | Address | &:r1051_26 | | ir.cpp:1051:58:1051:69 | Address | &:r1051_26 |
@@ -5125,9 +5128,6 @@
| ir.cpp:1051:60:1051:64 | SideEffect | ~m1051_4 | | ir.cpp:1051:60:1051:64 | SideEffect | ~m1051_4 |
| ir.cpp:1051:60:1051:64 | Unary | r1051_13 | | ir.cpp:1051:60:1051:64 | Unary | r1051_13 |
| ir.cpp:1051:60:1051:64 | Unary | r1051_15 | | ir.cpp:1051:60:1051:64 | Unary | r1051_15 |
| ir.cpp:1051:67:1051:67 | Address | &:r1051_16 |
| ir.cpp:1051:67:1051:67 | Arg(this) | this:r1051_16 |
| ir.cpp:1051:67:1051:67 | SideEffect | ~m1051_20 |
| ir.cpp:1051:73:1051:73 | ChiPartial | partial:m1051_9 | | ir.cpp:1051:73:1051:73 | ChiPartial | partial:m1051_9 |
| ir.cpp:1051:73:1051:73 | ChiTotal | total:m1051_3 | | ir.cpp:1051:73:1051:73 | ChiTotal | total:m1051_3 |
| ir.cpp:1051:73:1051:73 | StoreValue | r1051_8 | | ir.cpp:1051:73:1051:73 | StoreValue | r1051_8 |
@@ -5192,6 +5192,9 @@
| ir.cpp:1054:49:1054:49 | SideEffect | ~m1054_20 | | ir.cpp:1054:49:1054:49 | SideEffect | ~m1054_20 |
| ir.cpp:1054:56:1054:56 | Address | &:r1054_9 | | ir.cpp:1054:56:1054:56 | Address | &:r1054_9 |
| ir.cpp:1054:61:1054:88 | Address | &:r1054_11 | | ir.cpp:1054:61:1054:88 | Address | &:r1054_11 |
| ir.cpp:1054:68:1054:68 | Address | &:r1054_16 |
| ir.cpp:1054:68:1054:68 | Arg(this) | this:r1054_16 |
| ir.cpp:1054:68:1054:68 | SideEffect | ~m1054_20 |
| ir.cpp:1054:68:1054:87 | Address | &:r1054_37 | | ir.cpp:1054:68:1054:87 | Address | &:r1054_37 |
| ir.cpp:1054:68:1054:87 | Load | ~m1054_20 | | ir.cpp:1054:68:1054:87 | Load | ~m1054_20 |
| ir.cpp:1054:68:1054:87 | StoreValue | r1054_38 | | ir.cpp:1054:68:1054:87 | StoreValue | r1054_38 |
@@ -5206,9 +5209,6 @@
| ir.cpp:1054:70:1054:74 | SideEffect | ~m1054_4 | | ir.cpp:1054:70:1054:74 | SideEffect | ~m1054_4 |
| ir.cpp:1054:70:1054:74 | Unary | r1054_13 | | ir.cpp:1054:70:1054:74 | Unary | r1054_13 |
| ir.cpp:1054:70:1054:74 | Unary | r1054_15 | | ir.cpp:1054:70:1054:74 | Unary | r1054_15 |
| ir.cpp:1054:77:1054:77 | Address | &:r1054_16 |
| ir.cpp:1054:77:1054:77 | Arg(this) | this:r1054_16 |
| ir.cpp:1054:77:1054:77 | SideEffect | ~m1054_20 |
| ir.cpp:1054:78:1054:82 | Address | &:r1054_22 | | ir.cpp:1054:78:1054:82 | Address | &:r1054_22 |
| ir.cpp:1054:78:1054:82 | Address | &:r1054_24 | | ir.cpp:1054:78:1054:82 | Address | &:r1054_24 |
| ir.cpp:1054:78:1054:82 | Left | r1054_25 | | ir.cpp:1054:78:1054:82 | Left | r1054_25 |

View File

@@ -156,10 +156,10 @@
| captures.cpp:23:12:23:16 | x | | captures.cpp:23:12:23:16 | x |
| captures.cpp:23:12:23:16 | y | | captures.cpp:23:12:23:16 | y |
| captures.cpp:23:12:23:20 | ... + ... | | captures.cpp:23:12:23:20 | ... + ... |
| captures.cpp:23:16:23:16 | (reference dereference) |
| captures.cpp:23:16:23:16 | definition of y | | captures.cpp:23:16:23:16 | definition of y |
| captures.cpp:23:16:23:16 | y | | captures.cpp:23:16:23:16 | y |
| captures.cpp:23:16:23:16 | y | | captures.cpp:23:16:23:16 | y |
| captures.cpp:23:18:23:18 | (reference dereference) |
| captures.cpp:23:20:23:20 | z | | captures.cpp:23:20:23:20 | z |
| captures.cpp:26:3:26:24 | return ... | | captures.cpp:26:3:26:24 | return ... |
| captures.cpp:26:10:26:17 | (const lambda [] type at line 22, col. 19)... | | captures.cpp:26:10:26:17 | (const lambda [] type at line 22, col. 19)... |

View File

@@ -1,3 +1,4 @@
#include "a.h" #include "a.h"
#include "c.h"

View File

@@ -0,0 +1,12 @@
int js[] = { 1, 2, 3, 4 };
int ks[4] = { 1, 2, 3, 4 };
int ls[4] = { 1, 2, 3, 4 };
int iss[4][2] = { { 1, 2 }, { 3, 4 }, { 1, 2 }, { 3, 4 } };
typedef int int_alias;
int_alias i;

View File

@@ -0,0 +1,10 @@
extern int js[];
extern int ks[];
extern int ls[4];
extern int iss[][2];
extern int i;

View File

@@ -0,0 +1,4 @@
namespace aNameSpace {
int xs[] = { 1, 2 };
}

View File

@@ -0,0 +1,4 @@
namespace aNameSpace {
extern int xs[2];
}

View File

@@ -0,0 +1,2 @@
#include "d.h"

View File

@@ -1,5 +1,17 @@
| a.c:4:5:4:6 | definition of is | array of {int} | 1 | | a.c:4:5:4:6 | definition of is | array of {int} | 1 |
| a.h:2:12:2:13 | declaration of is | array of 4 {int} | 1 | | a.h:2:12:2:13 | declaration of is | array of 4 {int} | 1 |
| c.c:2:5:2:6 | definition of js | array of {int} | 1 |
| c.c:4:5:4:6 | definition of ks | array of 4 {int} | 1 |
| c.c:6:5:6:6 | definition of ls | array of 4 {int} | 1 |
| c.c:8:5:8:7 | definition of iss | array of 4 {array of 2 {int}} | 1 |
| c.c:12:11:12:11 | definition of i | typedef {int} as "int_alias" | 1 |
| c.h:2:12:2:13 | declaration of js | array of {int} | 1 |
| c.h:4:12:4:13 | declaration of ks | array of {int} | 1 |
| c.h:6:12:6:13 | declaration of ls | array of 4 {int} | 1 |
| c.h:8:12:8:14 | declaration of iss | array of {array of 2 {int}} | 1 |
| c.h:10:12:10:12 | declaration of i | int | 1 |
| d.cpp:3:7:3:8 | definition of xs | array of {int} | 1 |
| d.h:3:14:3:15 | declaration of xs | array of 2 {int} | 1 |
| file://:0:0:0:0 | definition of fp_offset | unsigned int | 1 | | file://:0:0:0:0 | definition of fp_offset | unsigned int | 1 |
| file://:0:0:0:0 | definition of gp_offset | unsigned int | 1 | | file://:0:0:0:0 | definition of gp_offset | unsigned int | 1 |
| file://:0:0:0:0 | definition of overflow_arg_area | pointer to {void} | 1 | | file://:0:0:0:0 | definition of overflow_arg_area | pointer to {void} | 1 |

View File

@@ -1,4 +1,16 @@
| a.c:4:5:4:6 | is | array of {int} | 1 | | a.c:4:5:4:6 | is | array of {int} | 1 |
| c.c:2:5:2:6 | js | array of {int} | 1 |
| c.c:4:5:4:6 | ks | array of 4 {int} | 1 |
| c.c:6:5:6:6 | ls | array of 4 {int} | 1 |
| c.c:8:5:8:7 | iss | array of 4 {array of 2 {int}} | 1 |
| c.c:12:11:12:11 | i | typedef {int} as "int_alias" | 1 |
| c.h:4:12:4:13 | ks | array of {int} | 1 |
| c.h:8:12:8:14 | iss | array of {array of 2 {int}} | 1 |
| c.h:10:12:10:12 | i | int | 1 |
| d.cpp:3:7:3:8 | xs | array of {int} | 1 |
| d.h:3:14:3:15 | xs | array of 2 {int} | 1 |
| file://:0:0:0:0 | (unnamed parameter 0) | reference to {const {struct __va_list_tag}} | 1 |
| file://:0:0:0:0 | (unnamed parameter 0) | rvalue reference to {struct __va_list_tag} | 1 |
| file://:0:0:0:0 | fp_offset | unsigned int | 1 | | file://:0:0:0:0 | fp_offset | unsigned int | 1 |
| file://:0:0:0:0 | gp_offset | unsigned int | 1 | | file://:0:0:0:0 | gp_offset | unsigned int | 1 |
| file://:0:0:0:0 | overflow_arg_area | pointer to {void} | 1 | | file://:0:0:0:0 | overflow_arg_area | pointer to {void} | 1 |

View File

@@ -0,0 +1,36 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.CSharp.Entities.Statements;
using System.Collections.Generic;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities
{
internal class ImplicitMainMethod : OrdinaryMethod
{
private readonly List<GlobalStatementSyntax> globalStatements;
public ImplicitMainMethod(Context cx, IMethodSymbol symbol, List<GlobalStatementSyntax> globalStatements)
: base(cx, symbol)
{
this.globalStatements = globalStatements;
}
protected override void PopulateMethodBody(TextWriter trapFile)
{
GlobalStatementsBlock.Create(Context, this, globalStatements);
}
public static ImplicitMainMethod Create(Context cx, IMethodSymbol method, List<GlobalStatementSyntax> globalStatements)
{
return ImplicitMainMethodFactory.Instance.CreateEntity(cx, method, (method, globalStatements));
}
private class ImplicitMainMethodFactory : CachedEntityFactory<(IMethodSymbol, List<GlobalStatementSyntax>), ImplicitMainMethod>
{
public static ImplicitMainMethodFactory Instance { get; } = new ImplicitMainMethodFactory();
public override ImplicitMainMethod Create(Context cx, (IMethodSymbol, List<GlobalStatementSyntax>) init) => new ImplicitMainMethod(cx, init.Item1, init.Item2);
}
}
}

View File

@@ -46,7 +46,7 @@ namespace Semmle.Extraction.CSharp.Entities
// so there's nothing to extract. // so there's nothing to extract.
} }
private void PopulateMethodBody(TextWriter trapFile) protected virtual void PopulateMethodBody(TextWriter trapFile)
{ {
if (!IsSourceDeclaration) if (!IsSourceDeclaration)
return; return;

View File

@@ -8,7 +8,7 @@ namespace Semmle.Extraction.CSharp.Entities
{ {
internal class OrdinaryMethod : Method internal class OrdinaryMethod : Method
{ {
private OrdinaryMethod(Context cx, IMethodSymbol init) protected OrdinaryMethod(Context cx, IMethodSymbol init)
: base(cx, init) { } : base(cx, init) { }
public override string Name => Symbol.GetName(); public override string Name => Symbol.GetName();

View File

@@ -2,17 +2,22 @@ using Semmle.Extraction.Kinds;
using System.Linq; using System.Linq;
using System.IO; using System.IO;
using Semmle.Extraction.Entities; using Semmle.Extraction.Entities;
using System.Collections.Generic;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System;
namespace Semmle.Extraction.CSharp.Entities.Statements namespace Semmle.Extraction.CSharp.Entities.Statements
{ {
internal class GlobalStatementsBlock : Statement internal class GlobalStatementsBlock : Statement
{ {
private readonly Method parent; private readonly Method parent;
private readonly List<GlobalStatementSyntax> globalStatements;
private GlobalStatementsBlock(Context cx, Method parent) private GlobalStatementsBlock(Context cx, Method parent, List<GlobalStatementSyntax> globalStatements)
: base(cx, StmtKind.BLOCK, parent, 0) : base(cx, StmtKind.BLOCK, parent, 0)
{ {
this.parent = parent; this.parent = parent;
this.globalStatements = globalStatements;
} }
public override Microsoft.CodeAnalysis.Location? ReportingLocation public override Microsoft.CodeAnalysis.Location? ReportingLocation
@@ -27,9 +32,9 @@ namespace Semmle.Extraction.CSharp.Entities.Statements
} }
} }
public static GlobalStatementsBlock Create(Context cx, Method parent) public static GlobalStatementsBlock Create(Context cx, Method parent, List<GlobalStatementSyntax> globalStatements)
{ {
var ret = new GlobalStatementsBlock(cx, parent); var ret = new GlobalStatementsBlock(cx, parent, globalStatements);
ret.TryPopulate(); ret.TryPopulate();
return ret; return ret;
} }
@@ -37,6 +42,14 @@ namespace Semmle.Extraction.CSharp.Entities.Statements
protected override void PopulateStatement(TextWriter trapFile) protected override void PopulateStatement(TextWriter trapFile)
{ {
trapFile.stmt_location(this, Context.CreateLocation(ReportingLocation)); trapFile.stmt_location(this, Context.CreateLocation(ReportingLocation));
for (var i = 0; i < globalStatements.Count; i++)
{
if (globalStatements[i].Statement is not null)
{
Statement.Create(Context, globalStatements[i].Statement, this, i);
}
}
} }
} }
} }

View File

@@ -3,7 +3,6 @@ using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Util.Logging; using Semmle.Util.Logging;
using Semmle.Extraction.CSharp.Entities; using Semmle.Extraction.CSharp.Entities;
using Semmle.Extraction.CSharp.Entities.Statements;
using System.Linq; using System.Linq;
namespace Semmle.Extraction.CSharp.Populators namespace Semmle.Extraction.CSharp.Populators
@@ -60,23 +59,14 @@ namespace Semmle.Extraction.CSharp.Populators
} }
var entryPoint = Cx.Compilation.GetEntryPoint(System.Threading.CancellationToken.None); var entryPoint = Cx.Compilation.GetEntryPoint(System.Threading.CancellationToken.None);
var entryMethod = Method.Create(Cx, entryPoint); if (entryPoint is null)
if (entryMethod is null)
{ {
Cx.ExtractionError("No entry method found. Skipping the extraction of global statements.", Cx.ExtractionError("No entry method found. Skipping the extraction of global statements.",
null, Cx.CreateLocation(globalStatements[0].GetLocation()), null, Severity.Info); null, Cx.CreateLocation(globalStatements[0].GetLocation()), null, Severity.Info);
return; return;
} }
var block = GlobalStatementsBlock.Create(Cx, entryMethod); ImplicitMainMethod.Create(Cx, entryPoint, globalStatements);
for (var i = 0; i < globalStatements.Count; i++)
{
if (globalStatements[i].Statement is not null)
{
Statement.Create(Cx, globalStatements[i].Statement, block, i);
}
}
} }
} }
} }

View File

@@ -1,3 +1,5 @@
## 1.1.4
## 1.1.3 ## 1.1.3
## 1.1.2 ## 1.1.2

View File

@@ -0,0 +1 @@
## 1.1.4

View File

@@ -1,2 +1,2 @@
--- ---
lastReleaseVersion: 1.1.3 lastReleaseVersion: 1.1.4

View File

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

View File

@@ -1,3 +1,5 @@
## 1.1.4
## 1.1.3 ## 1.1.3
## 1.1.2 ## 1.1.2

View File

@@ -0,0 +1 @@
## 1.1.4

View File

@@ -1,2 +1,2 @@
--- ---
lastReleaseVersion: 1.1.3 lastReleaseVersion: 1.1.4

View File

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

View File

@@ -1,3 +1,5 @@
## 0.2.3
## 0.2.2 ## 0.2.2
## 0.2.1 ## 0.2.1

View File

@@ -0,0 +1,4 @@
---
category: deprecated
---
* The `BarrierGuard` class has been deprecated. Such barriers and sanitizers can now instead be created using the new `BarrierGuard` parameterized module.

View File

@@ -0,0 +1 @@
## 0.2.3

View File

@@ -1,2 +1,2 @@
--- ---
lastReleaseVersion: 0.2.2 lastReleaseVersion: 0.2.3

View File

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

View File

@@ -69,6 +69,12 @@
* sources "remote" indicates a default remote flow source, and for summaries * sources "remote" indicates a default remote flow source, and for summaries
* "taint" indicates a default additional taint step and "value" indicates a * "taint" indicates a default additional taint step and "value" indicates a
* globally applicable value-preserving step. * globally applicable value-preserving step.
* 9. The `provenance` column is a tag to indicate the origin of the summary.
* There are two supported values: "generated" and "manual". "generated" means that
* the model has been emitted by the model generator tool and "manual" means
* that the model has been written by hand. This information is used in a heuristic
* for dataflow analysis to determine, if a model or source code should be used for
* determining flow.
*/ */
import csharp import csharp
@@ -163,17 +169,10 @@ private predicate sinkModel(string row) { any(SinkModelCsv s).row(row) }
private predicate summaryModel(string row) { any(SummaryModelCsv s).row(row) } private predicate summaryModel(string row) { any(SummaryModelCsv s).row(row) }
bindingset[input]
private predicate getKind(string input, string kind, boolean generated) {
input.splitAt(":", 0) = "generated" and kind = input.splitAt(":", 1) and generated = true
or
not input.matches("%:%") and kind = input and generated = false
}
/** Holds if a source model exists for the given parameters. */ /** Holds if a source model exists for the given parameters. */
predicate sourceModel( predicate sourceModel(
string namespace, string type, boolean subtypes, string name, string signature, string ext, string namespace, string type, boolean subtypes, string name, string signature, string ext,
string output, string kind, boolean generated string output, string kind, string provenance
) { ) {
exists(string row | exists(string row |
sourceModel(row) and sourceModel(row) and
@@ -185,14 +184,15 @@ predicate sourceModel(
row.splitAt(";", 4) = signature and row.splitAt(";", 4) = signature and
row.splitAt(";", 5) = ext and row.splitAt(";", 5) = ext and
row.splitAt(";", 6) = output and row.splitAt(";", 6) = output and
exists(string k | row.splitAt(";", 7) = k and getKind(k, kind, generated)) row.splitAt(";", 7) = kind and
row.splitAt(";", 8) = provenance
) )
} }
/** Holds if a sink model exists for the given parameters. */ /** Holds if a sink model exists for the given parameters. */
predicate sinkModel( predicate sinkModel(
string namespace, string type, boolean subtypes, string name, string signature, string ext, string namespace, string type, boolean subtypes, string name, string signature, string ext,
string input, string kind, boolean generated string input, string kind, string provenance
) { ) {
exists(string row | exists(string row |
sinkModel(row) and sinkModel(row) and
@@ -204,14 +204,15 @@ predicate sinkModel(
row.splitAt(";", 4) = signature and row.splitAt(";", 4) = signature and
row.splitAt(";", 5) = ext and row.splitAt(";", 5) = ext and
row.splitAt(";", 6) = input and row.splitAt(";", 6) = input and
exists(string k | row.splitAt(";", 7) = k and getKind(k, kind, generated)) row.splitAt(";", 7) = kind and
row.splitAt(";", 8) = provenance
) )
} }
/** Holds if a summary model exists for the given parameters. */ /** Holds if a summary model exists for the given parameters. */
predicate summaryModel( predicate summaryModel(
string namespace, string type, boolean subtypes, string name, string signature, string ext, string namespace, string type, boolean subtypes, string name, string signature, string ext,
string input, string output, string kind, boolean generated string input, string output, string kind, string provenance
) { ) {
exists(string row | exists(string row |
summaryModel(row) and summaryModel(row) and
@@ -224,7 +225,8 @@ predicate summaryModel(
row.splitAt(";", 5) = ext and row.splitAt(";", 5) = ext and
row.splitAt(";", 6) = input and row.splitAt(";", 6) = input and
row.splitAt(";", 7) = output and row.splitAt(";", 7) = output and
exists(string k | row.splitAt(";", 8) = k and getKind(k, kind, generated)) row.splitAt(";", 8) = kind and
row.splitAt(";", 9) = provenance
) )
} }
@@ -259,25 +261,25 @@ predicate modelCoverage(string namespace, int namespaces, string kind, string pa
part = "source" and part = "source" and
n = n =
strictcount(string subns, string type, boolean subtypes, string name, string signature, strictcount(string subns, string type, boolean subtypes, string name, string signature,
string ext, string output, boolean generated | string ext, string output, string provenance |
canonicalNamespaceLink(namespace, subns) and canonicalNamespaceLink(namespace, subns) and
sourceModel(subns, type, subtypes, name, signature, ext, output, kind, generated) sourceModel(subns, type, subtypes, name, signature, ext, output, kind, provenance)
) )
or or
part = "sink" and part = "sink" and
n = n =
strictcount(string subns, string type, boolean subtypes, string name, string signature, strictcount(string subns, string type, boolean subtypes, string name, string signature,
string ext, string input, boolean generated | string ext, string input, string provenance |
canonicalNamespaceLink(namespace, subns) and canonicalNamespaceLink(namespace, subns) and
sinkModel(subns, type, subtypes, name, signature, ext, input, kind, generated) sinkModel(subns, type, subtypes, name, signature, ext, input, kind, provenance)
) )
or or
part = "summary" and part = "summary" and
n = n =
strictcount(string subns, string type, boolean subtypes, string name, string signature, strictcount(string subns, string type, boolean subtypes, string name, string signature,
string ext, string input, string output, boolean generated | string ext, string input, string output, string provenance |
canonicalNamespaceLink(namespace, subns) and canonicalNamespaceLink(namespace, subns) and
summaryModel(subns, type, subtypes, name, signature, ext, input, output, kind, generated) summaryModel(subns, type, subtypes, name, signature, ext, input, output, kind, provenance)
) )
) )
} }
@@ -286,12 +288,16 @@ predicate modelCoverage(string namespace, int namespaces, string kind, string pa
module CsvValidation { module CsvValidation {
/** Holds if some row in a CSV-based flow model appears to contain typos. */ /** Holds if some row in a CSV-based flow model appears to contain typos. */
query predicate invalidModelRow(string msg) { query predicate invalidModelRow(string msg) {
exists(string pred, string namespace, string type, string name, string signature, string ext | exists(
sourceModel(namespace, type, _, name, signature, ext, _, _, _) and pred = "source" string pred, string namespace, string type, string name, string signature, string ext,
string provenance
|
sourceModel(namespace, type, _, name, signature, ext, _, _, provenance) and pred = "source"
or or
sinkModel(namespace, type, _, name, signature, ext, _, _, _) and pred = "sink" sinkModel(namespace, type, _, name, signature, ext, _, _, provenance) and pred = "sink"
or or
summaryModel(namespace, type, _, name, signature, ext, _, _, _, _) and pred = "summary" summaryModel(namespace, type, _, name, signature, ext, _, _, _, provenance) and
pred = "summary"
| |
not namespace.regexpMatch("[a-zA-Z0-9_\\.]+") and not namespace.regexpMatch("[a-zA-Z0-9_\\.]+") and
msg = "Dubious namespace \"" + namespace + "\" in " + pred + " model." msg = "Dubious namespace \"" + namespace + "\" in " + pred + " model."
@@ -307,6 +313,9 @@ module CsvValidation {
or or
not ext.regexpMatch("|Attribute") and not ext.regexpMatch("|Attribute") and
msg = "Unrecognized extra API graph element \"" + ext + "\" in " + pred + " model." msg = "Unrecognized extra API graph element \"" + ext + "\" in " + pred + " model."
or
not provenance = ["manual", "generated"] and
msg = "Unrecognized provenance description \"" + provenance + "\" in " + pred + " model."
) )
or or
exists(string pred, AccessPath input, string part | exists(string pred, AccessPath input, string part |
@@ -338,18 +347,18 @@ module CsvValidation {
) )
or or
exists(string pred, string row, int expect | exists(string pred, string row, int expect |
sourceModel(row) and expect = 8 and pred = "source" sourceModel(row) and expect = 9 and pred = "source"
or or
sinkModel(row) and expect = 8 and pred = "sink" sinkModel(row) and expect = 9 and pred = "sink"
or or
summaryModel(row) and expect = 9 and pred = "summary" summaryModel(row) and expect = 10 and pred = "summary"
| |
exists(int cols | exists(int cols |
cols = 1 + max(int n | exists(row.splitAt(";", n))) and cols = 1 + max(int n | exists(row.splitAt(";", n))) and
cols != expect and cols != expect and
msg = msg =
"Wrong number of columns in " + pred + " model row, expected " + expect + ", got " + cols + "Wrong number of columns in " + pred + " model row, expected " + expect + ", got " + cols +
"." " in " + row + "."
) )
or or
exists(string b | exists(string b |
@@ -359,23 +368,20 @@ module CsvValidation {
) )
) )
or or
exists(string row, string k, string kind | summaryModel(row) | exists(string row, string kind | summaryModel(row) |
k = row.splitAt(";", 8) and kind = row.splitAt(";", 8) and
getKind(k, kind, _) and
not kind = ["taint", "value"] and not kind = ["taint", "value"] and
msg = "Invalid kind \"" + kind + "\" in summary model." msg = "Invalid kind \"" + kind + "\" in summary model."
) )
or or
exists(string row, string k, string kind | sinkModel(row) | exists(string row, string kind | sinkModel(row) |
k = row.splitAt(";", 7) and kind = row.splitAt(";", 7) and
getKind(k, kind, _) and
not kind = ["code", "sql", "xss", "remote", "html"] and not kind = ["code", "sql", "xss", "remote", "html"] and
msg = "Invalid kind \"" + kind + "\" in sink model." msg = "Invalid kind \"" + kind + "\" in sink model."
) )
or or
exists(string row, string k, string kind | sourceModel(row) | exists(string row, string kind | sourceModel(row) |
k = row.splitAt(";", 7) and kind = row.splitAt(";", 7) and
getKind(k, kind, _) and
not kind = "local" and not kind = "local" and
msg = "Invalid kind \"" + kind + "\" in source model." msg = "Invalid kind \"" + kind + "\" in source model."
) )

View File

@@ -90,14 +90,20 @@ abstract class Configuration extends string {
/** Holds if data flow out of `node` is prohibited. */ /** Holds if data flow out of `node` is prohibited. */
predicate isBarrierOut(Node node) { none() } predicate isBarrierOut(Node node) { none() }
/** Holds if data flow through nodes guarded by `guard` is prohibited. */ /**
predicate isBarrierGuard(BarrierGuard guard) { none() } * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited.
*/
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
/** /**
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited when * Holds if data flow through nodes guarded by `guard` is prohibited when
* the flow state is `state` * the flow state is `state`
*/ */
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() } deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
/** /**
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
@@ -335,6 +341,29 @@ private predicate outBarrier(NodeEx node, Configuration config) {
) )
} }
/** A bridge class to access the deprecated `isBarrierGuard`. */
private class BarrierGuardGuardedNodeBridge extends Unit {
abstract predicate guardedNode(Node n, Configuration config);
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
}
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
deprecated override predicate guardedNode(Node n, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
}
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
}
}
pragma[nomagic] pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) { private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n | exists(Node n | node.asNode() = n |
@@ -348,10 +377,7 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
not config.isSink(n) and not config.isSink(n) and
not config.isSink(n, _) not config.isSink(n, _)
or or
exists(BarrierGuard g | any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config)
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
) )
} }
@@ -360,10 +386,7 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
exists(Node n | node.asNode() = n | exists(Node n | node.asNode() = n |
config.isBarrier(n, state) config.isBarrier(n, state)
or or
exists(BarrierGuard g | any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config)
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
) )
} }

View File

@@ -90,14 +90,20 @@ abstract class Configuration extends string {
/** Holds if data flow out of `node` is prohibited. */ /** Holds if data flow out of `node` is prohibited. */
predicate isBarrierOut(Node node) { none() } predicate isBarrierOut(Node node) { none() }
/** Holds if data flow through nodes guarded by `guard` is prohibited. */ /**
predicate isBarrierGuard(BarrierGuard guard) { none() } * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited.
*/
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
/** /**
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited when * Holds if data flow through nodes guarded by `guard` is prohibited when
* the flow state is `state` * the flow state is `state`
*/ */
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() } deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
/** /**
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
@@ -335,6 +341,29 @@ private predicate outBarrier(NodeEx node, Configuration config) {
) )
} }
/** A bridge class to access the deprecated `isBarrierGuard`. */
private class BarrierGuardGuardedNodeBridge extends Unit {
abstract predicate guardedNode(Node n, Configuration config);
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
}
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
deprecated override predicate guardedNode(Node n, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
}
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
}
}
pragma[nomagic] pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) { private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n | exists(Node n | node.asNode() = n |
@@ -348,10 +377,7 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
not config.isSink(n) and not config.isSink(n) and
not config.isSink(n, _) not config.isSink(n, _)
or or
exists(BarrierGuard g | any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config)
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
) )
} }
@@ -360,10 +386,7 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
exists(Node n | node.asNode() = n | exists(Node n | node.asNode() = n |
config.isBarrier(n, state) config.isBarrier(n, state)
or or
exists(BarrierGuard g | any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config)
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
) )
} }

View File

@@ -90,14 +90,20 @@ abstract class Configuration extends string {
/** Holds if data flow out of `node` is prohibited. */ /** Holds if data flow out of `node` is prohibited. */
predicate isBarrierOut(Node node) { none() } predicate isBarrierOut(Node node) { none() }
/** Holds if data flow through nodes guarded by `guard` is prohibited. */ /**
predicate isBarrierGuard(BarrierGuard guard) { none() } * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited.
*/
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
/** /**
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited when * Holds if data flow through nodes guarded by `guard` is prohibited when
* the flow state is `state` * the flow state is `state`
*/ */
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() } deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
/** /**
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
@@ -335,6 +341,29 @@ private predicate outBarrier(NodeEx node, Configuration config) {
) )
} }
/** A bridge class to access the deprecated `isBarrierGuard`. */
private class BarrierGuardGuardedNodeBridge extends Unit {
abstract predicate guardedNode(Node n, Configuration config);
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
}
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
deprecated override predicate guardedNode(Node n, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
}
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
}
}
pragma[nomagic] pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) { private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n | exists(Node n | node.asNode() = n |
@@ -348,10 +377,7 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
not config.isSink(n) and not config.isSink(n) and
not config.isSink(n, _) not config.isSink(n, _)
or or
exists(BarrierGuard g | any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config)
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
) )
} }
@@ -360,10 +386,7 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
exists(Node n | node.asNode() = n | exists(Node n | node.asNode() = n |
config.isBarrier(n, state) config.isBarrier(n, state)
or or
exists(BarrierGuard g | any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config)
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
) )
} }

View File

@@ -90,14 +90,20 @@ abstract class Configuration extends string {
/** Holds if data flow out of `node` is prohibited. */ /** Holds if data flow out of `node` is prohibited. */
predicate isBarrierOut(Node node) { none() } predicate isBarrierOut(Node node) { none() }
/** Holds if data flow through nodes guarded by `guard` is prohibited. */ /**
predicate isBarrierGuard(BarrierGuard guard) { none() } * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited.
*/
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
/** /**
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited when * Holds if data flow through nodes guarded by `guard` is prohibited when
* the flow state is `state` * the flow state is `state`
*/ */
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() } deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
/** /**
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
@@ -335,6 +341,29 @@ private predicate outBarrier(NodeEx node, Configuration config) {
) )
} }
/** A bridge class to access the deprecated `isBarrierGuard`. */
private class BarrierGuardGuardedNodeBridge extends Unit {
abstract predicate guardedNode(Node n, Configuration config);
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
}
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
deprecated override predicate guardedNode(Node n, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
}
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
}
}
pragma[nomagic] pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) { private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n | exists(Node n | node.asNode() = n |
@@ -348,10 +377,7 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
not config.isSink(n) and not config.isSink(n) and
not config.isSink(n, _) not config.isSink(n, _)
or or
exists(BarrierGuard g | any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config)
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
) )
} }
@@ -360,10 +386,7 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
exists(Node n | node.asNode() = n | exists(Node n | node.asNode() = n |
config.isBarrier(n, state) config.isBarrier(n, state)
or or
exists(BarrierGuard g | any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config)
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
) )
} }

View File

@@ -90,14 +90,20 @@ abstract class Configuration extends string {
/** Holds if data flow out of `node` is prohibited. */ /** Holds if data flow out of `node` is prohibited. */
predicate isBarrierOut(Node node) { none() } predicate isBarrierOut(Node node) { none() }
/** Holds if data flow through nodes guarded by `guard` is prohibited. */ /**
predicate isBarrierGuard(BarrierGuard guard) { none() } * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited.
*/
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
/** /**
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited when * Holds if data flow through nodes guarded by `guard` is prohibited when
* the flow state is `state` * the flow state is `state`
*/ */
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() } deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
/** /**
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
@@ -335,6 +341,29 @@ private predicate outBarrier(NodeEx node, Configuration config) {
) )
} }
/** A bridge class to access the deprecated `isBarrierGuard`. */
private class BarrierGuardGuardedNodeBridge extends Unit {
abstract predicate guardedNode(Node n, Configuration config);
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
}
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
deprecated override predicate guardedNode(Node n, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
}
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
}
}
pragma[nomagic] pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) { private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n | exists(Node n | node.asNode() = n |
@@ -348,10 +377,7 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
not config.isSink(n) and not config.isSink(n) and
not config.isSink(n, _) not config.isSink(n, _)
or or
exists(BarrierGuard g | any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config)
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
) )
} }
@@ -360,10 +386,7 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
exists(Node n | node.asNode() = n | exists(Node n | node.asNode() = n |
config.isBarrier(n, state) config.isBarrier(n, state)
or or
exists(BarrierGuard g | any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config)
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
) )
} }

View File

@@ -90,14 +90,20 @@ abstract class Configuration extends string {
/** Holds if data flow out of `node` is prohibited. */ /** Holds if data flow out of `node` is prohibited. */
predicate isBarrierOut(Node node) { none() } predicate isBarrierOut(Node node) { none() }
/** Holds if data flow through nodes guarded by `guard` is prohibited. */ /**
predicate isBarrierGuard(BarrierGuard guard) { none() } * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited.
*/
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
/** /**
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
*
* Holds if data flow through nodes guarded by `guard` is prohibited when * Holds if data flow through nodes guarded by `guard` is prohibited when
* the flow state is `state` * the flow state is `state`
*/ */
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() } deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
/** /**
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
@@ -335,6 +341,29 @@ private predicate outBarrier(NodeEx node, Configuration config) {
) )
} }
/** A bridge class to access the deprecated `isBarrierGuard`. */
private class BarrierGuardGuardedNodeBridge extends Unit {
abstract predicate guardedNode(Node n, Configuration config);
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
}
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
deprecated override predicate guardedNode(Node n, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
}
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
}
}
pragma[nomagic] pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) { private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n | exists(Node n | node.asNode() = n |
@@ -348,10 +377,7 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
not config.isSink(n) and not config.isSink(n) and
not config.isSink(n, _) not config.isSink(n, _)
or or
exists(BarrierGuard g | any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config)
config.isBarrierGuard(g) and
n = g.getAGuardedNode()
)
) )
} }
@@ -360,10 +386,7 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
exists(Node n | node.asNode() = n | exists(Node n | node.asNode() = n |
config.isBarrier(n, state) config.isBarrier(n, state)
or or
exists(BarrierGuard g | any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config)
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
) )
} }

View File

@@ -173,6 +173,33 @@ abstract class NonLocalJumpNode extends Node {
} }
/** /**
* Holds if the guard `g` validates the expression `e` upon evaluating to `v`.
*
* The expression `e` is expected to be a syntactic part of the guard `g`.
* For example, the guard `g` might be a call `isSafe(x)` and the expression `e`
* the argument `x`.
*/
signature predicate guardChecksSig(Guard g, Expr e, AbstractValue v);
/**
* Provides a set of barrier nodes for a guard that validates an expression.
*
* This is expected to be used in `isBarrier`/`isSanitizer` definitions
* in data flow and taint tracking.
*/
module BarrierGuard<guardChecksSig/3 guardChecks> {
/** Gets a node that is safely guarded by the given guard check. */
ExprNode getABarrierNode() {
exists(Guard g, Expr e, AbstractValue v |
guardChecks(g, e, v) and
g.controlsNode(result.getControlFlowNode(), e, v)
)
}
}
/**
* DEPRECATED: Use `BarrierGuard` module instead.
*
* A guard that validates some expression. * A guard that validates some expression.
* *
* To use this in a configuration, extend the class and provide a * To use this in a configuration, extend the class and provide a
@@ -181,7 +208,7 @@ abstract class NonLocalJumpNode extends Node {
* *
* It is important that all extending classes in scope are disjoint. * It is important that all extending classes in scope are disjoint.
*/ */
class BarrierGuard extends Guard { deprecated class BarrierGuard extends Guard {
/** Holds if this guard validates `e` upon evaluating to `v`. */ /** Holds if this guard validates `e` upon evaluating to `v`. */
abstract predicate checks(Expr e, AbstractValue v); abstract predicate checks(Expr e, AbstractValue v);

View File

@@ -1116,13 +1116,13 @@ module Private {
preservesValue = false and result = "taint" preservesValue = false and result = "taint"
} }
private string renderGenerated(RelevantSummarizedCallable c) { private string renderProvenance(RelevantSummarizedCallable c) {
if c.(SummarizedCallable).isAutoGenerated() then result = "generated:" else result = "" if c.(SummarizedCallable).isAutoGenerated() then result = "generated" else result = "manual"
} }
/** /**
* A query predicate for outputting flow summaries in semi-colon separated format in QL tests. * A query predicate for outputting flow summaries in semi-colon separated format in QL tests.
* The syntax is: "namespace;type;overrides;name;signature;ext;inputspec;outputspec;(generated:)?kind", * The syntax is: "namespace;type;overrides;name;signature;ext;inputspec;outputspec;kind;provenance"",
* ext is hardcoded to empty. * ext is hardcoded to empty.
*/ */
query predicate summary(string csv) { query predicate summary(string csv) {
@@ -1133,7 +1133,7 @@ module Private {
c.relevantSummary(input, output, preservesValue) and c.relevantSummary(input, output, preservesValue) and
csv = csv =
c.getCallableCsv() + getComponentStackCsv(input) + ";" + getComponentStackCsv(output) + c.getCallableCsv() + getComponentStackCsv(input) + ";" + getComponentStackCsv(output) +
";" + renderGenerated(c) + renderKind(preservesValue) ";" + renderKind(preservesValue) + ";" + renderProvenance(c)
) )
} }
} }

View File

@@ -91,6 +91,13 @@ DataFlowType getCallbackReturnType(DataFlowType t, ReturnKind rk) {
) )
} }
bindingset[provenance]
private boolean isGenerated(string provenance) {
provenance = "generated" and result = true
or
provenance != "generated" and result = false
}
/** /**
* Holds if an external flow summary exists for `c` with input specification * Holds if an external flow summary exists for `c` with input specification
* `input`, output specification `output`, kind `kind`, and a flag `generated` * `input`, output specification `output`, kind `kind`, and a flag `generated`
@@ -98,9 +105,11 @@ DataFlowType getCallbackReturnType(DataFlowType t, ReturnKind rk) {
*/ */
predicate summaryElement(Callable c, string input, string output, string kind, boolean generated) { predicate summaryElement(Callable c, string input, string output, string kind, boolean generated) {
exists( exists(
string namespace, string type, boolean subtypes, string name, string signature, string ext string namespace, string type, boolean subtypes, string name, string signature, string ext,
string provenance
| |
summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind, generated) and summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind, provenance) and
generated = isGenerated(provenance) and
c = interpretElement(namespace, type, subtypes, name, signature, ext) c = interpretElement(namespace, type, subtypes, name, signature, ext)
) )
} }
@@ -112,9 +121,11 @@ predicate summaryElement(Callable c, string input, string output, string kind, b
*/ */
predicate sourceElement(Element e, string output, string kind, boolean generated) { predicate sourceElement(Element e, string output, string kind, boolean generated) {
exists( exists(
string namespace, string type, boolean subtypes, string name, string signature, string ext string namespace, string type, boolean subtypes, string name, string signature, string ext,
string provenance
| |
sourceModel(namespace, type, subtypes, name, signature, ext, output, kind, generated) and sourceModel(namespace, type, subtypes, name, signature, ext, output, kind, provenance) and
generated = isGenerated(provenance) and
e = interpretElement(namespace, type, subtypes, name, signature, ext) e = interpretElement(namespace, type, subtypes, name, signature, ext)
) )
} }
@@ -126,9 +137,11 @@ predicate sourceElement(Element e, string output, string kind, boolean generated
*/ */
predicate sinkElement(Element e, string input, string kind, boolean generated) { predicate sinkElement(Element e, string input, string kind, boolean generated) {
exists( exists(
string namespace, string type, boolean subtypes, string name, string signature, string ext string namespace, string type, boolean subtypes, string name, string signature, string ext,
string provenance
| |
sinkModel(namespace, type, subtypes, name, signature, ext, input, kind, generated) and sinkModel(namespace, type, subtypes, name, signature, ext, input, kind, provenance) and
generated = isGenerated(provenance) and
e = interpretElement(namespace, type, subtypes, name, signature, ext) e = interpretElement(namespace, type, subtypes, name, signature, ext)
) )
} }

View File

@@ -19,12 +19,6 @@ private import semmle.code.csharp.frameworks.WCF
*/ */
predicate defaultTaintSanitizer(DataFlow::Node node) { none() } predicate defaultTaintSanitizer(DataFlow::Node node) { none() }
/**
* Holds if `guard` should be a sanitizer guard in all global taint flow configurations
* but not in local taint.
*/
predicate defaultTaintSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
/** /**
* Holds if default `TaintTracking::Configuration`s should allow implicit reads * Holds if default `TaintTracking::Configuration`s should allow implicit reads
* of `c` at sinks and inputs to additional taint steps. * of `c` at sinks and inputs to additional taint steps.

View File

@@ -116,20 +116,30 @@ abstract class Configuration extends DataFlow::Configuration {
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) } final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */ /**
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() } * DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
*
* Holds if taint propagation through nodes guarded by `guard` is prohibited.
*/
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { deprecated final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
this.isSanitizerGuard(guard) or defaultTaintSanitizerGuard(guard) this.isSanitizerGuard(guard)
} }
/** /**
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
*
* Holds if taint propagation through nodes guarded by `guard` is prohibited * Holds if taint propagation through nodes guarded by `guard` is prohibited
* when the flow state is `state`. * when the flow state is `state`.
*/ */
predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { none() } deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
none()
}
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { deprecated final override predicate isBarrierGuard(
DataFlow::BarrierGuard guard, DataFlow::FlowState state
) {
this.isSanitizerGuard(guard, state) this.isSanitizerGuard(guard, state)
} }

View File

@@ -116,20 +116,30 @@ abstract class Configuration extends DataFlow::Configuration {
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) } final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */ /**
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() } * DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
*
* Holds if taint propagation through nodes guarded by `guard` is prohibited.
*/
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { deprecated final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
this.isSanitizerGuard(guard) or defaultTaintSanitizerGuard(guard) this.isSanitizerGuard(guard)
} }
/** /**
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
*
* Holds if taint propagation through nodes guarded by `guard` is prohibited * Holds if taint propagation through nodes guarded by `guard` is prohibited
* when the flow state is `state`. * when the flow state is `state`.
*/ */
predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { none() } deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
none()
}
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { deprecated final override predicate isBarrierGuard(
DataFlow::BarrierGuard guard, DataFlow::FlowState state
) {
this.isSanitizerGuard(guard, state) this.isSanitizerGuard(guard, state)
} }

View File

@@ -116,20 +116,30 @@ abstract class Configuration extends DataFlow::Configuration {
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) } final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */ /**
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() } * DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
*
* Holds if taint propagation through nodes guarded by `guard` is prohibited.
*/
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { deprecated final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
this.isSanitizerGuard(guard) or defaultTaintSanitizerGuard(guard) this.isSanitizerGuard(guard)
} }
/** /**
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
*
* Holds if taint propagation through nodes guarded by `guard` is prohibited * Holds if taint propagation through nodes guarded by `guard` is prohibited
* when the flow state is `state`. * when the flow state is `state`.
*/ */
predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { none() } deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
none()
}
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { deprecated final override predicate isBarrierGuard(
DataFlow::BarrierGuard guard, DataFlow::FlowState state
) {
this.isSanitizerGuard(guard, state) this.isSanitizerGuard(guard, state)
} }

View File

@@ -116,20 +116,30 @@ abstract class Configuration extends DataFlow::Configuration {
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) } final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */ /**
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() } * DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
*
* Holds if taint propagation through nodes guarded by `guard` is prohibited.
*/
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { deprecated final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
this.isSanitizerGuard(guard) or defaultTaintSanitizerGuard(guard) this.isSanitizerGuard(guard)
} }
/** /**
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
*
* Holds if taint propagation through nodes guarded by `guard` is prohibited * Holds if taint propagation through nodes guarded by `guard` is prohibited
* when the flow state is `state`. * when the flow state is `state`.
*/ */
predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { none() } deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
none()
}
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { deprecated final override predicate isBarrierGuard(
DataFlow::BarrierGuard guard, DataFlow::FlowState state
) {
this.isSanitizerGuard(guard, state) this.isSanitizerGuard(guard, state)
} }

View File

@@ -116,20 +116,30 @@ abstract class Configuration extends DataFlow::Configuration {
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) } final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */ /**
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() } * DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
*
* Holds if taint propagation through nodes guarded by `guard` is prohibited.
*/
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { deprecated final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
this.isSanitizerGuard(guard) or defaultTaintSanitizerGuard(guard) this.isSanitizerGuard(guard)
} }
/** /**
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
*
* Holds if taint propagation through nodes guarded by `guard` is prohibited * Holds if taint propagation through nodes guarded by `guard` is prohibited
* when the flow state is `state`. * when the flow state is `state`.
*/ */
predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { none() } deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
none()
}
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { deprecated final override predicate isBarrierGuard(
DataFlow::BarrierGuard guard, DataFlow::FlowState state
) {
this.isSanitizerGuard(guard, state) this.isSanitizerGuard(guard, state)
} }

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