mirror of
https://github.com/github/codeql.git
synced 2025-12-20 10:46:30 +01:00
Merge branch 'main' of github.com:github/codeql into python-port-stacktrace-exosure
This commit is contained in:
21
.github/workflows/check-change-note.yml
vendored
Normal file
21
.github/workflows/check-change-note.yml
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [labeled, unlabeled, opened, synchronize, reopened, ready_for_review]
|
||||
paths:
|
||||
- "*/ql/src/**/*.ql"
|
||||
- "*/ql/src/**/*.qll"
|
||||
- "!**/experimental/**"
|
||||
|
||||
jobs:
|
||||
check-change-note:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Fail if no change note found. To fix, either add one, or add the `no-change-note-required` label.
|
||||
if: |
|
||||
github.event.pull_request.draft == false &&
|
||||
!contains(github.event.pull_request.labels.*.name, 'no-change-note-required')
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
gh api 'repos/${{github.repository}}/pulls/${{github.event.number}}/files' --paginate |
|
||||
jq 'any(.[].filename ; test("/change-notes/.*[.]md$"))' --exit-status
|
||||
4
.github/workflows/codeql-analysis.yml
vendored
4
.github/workflows/codeql-analysis.yml
vendored
@@ -5,10 +5,14 @@ on:
|
||||
branches:
|
||||
- main
|
||||
- 'rc/*'
|
||||
paths:
|
||||
- 'csharp/**'
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
- 'rc/*'
|
||||
paths:
|
||||
- 'csharp/**'
|
||||
schedule:
|
||||
- cron: '0 9 * * 1'
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ jobs:
|
||||
uses: ammaraskar/sphinx-action@8b4f60114d7fd1faeba1a712269168508d4750d2 # v0.4
|
||||
with:
|
||||
docs-folder: "query-help/"
|
||||
pre-build-command: "python -m pip install --upgrade recommonmark"
|
||||
pre-build-command: "python -m pip install --upgrade recommonmark && python -m pip install --upgrade sphinx-markdown-tables"
|
||||
build-command: "sphinx-build -b dirhtml . _build"
|
||||
- name: Upload HTML artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
|
||||
15
CODEOWNERS
15
CODEOWNERS
@@ -3,18 +3,3 @@
|
||||
/java/ @github/codeql-java
|
||||
/javascript/ @github/codeql-javascript
|
||||
/python/ @github/codeql-python
|
||||
|
||||
# Assign query help for docs review
|
||||
/cpp/**/*.qhelp @hubwriter
|
||||
/csharp/**/*.qhelp @jf205
|
||||
/java/**/*.qhelp @felicitymay
|
||||
/javascript/**/*.qhelp @mchammer01
|
||||
/python/**/*.qhelp @felicitymay
|
||||
/docs/language/ @shati-patel @jf205
|
||||
|
||||
# Exclude help for experimental queries from docs review
|
||||
/cpp/**/experimental/**/*.qhelp @github/codeql-c-analysis
|
||||
/csharp/**/experimental/**/*.qhelp @github/codeql-csharp
|
||||
/java/**/experimental/**/*.qhelp @github/codeql-java
|
||||
/javascript/**/experimental/**/*.qhelp @github/codeql-javascript
|
||||
/python/**/experimental/**/*.qhelp @github/codeql-python
|
||||
|
||||
@@ -49,7 +49,11 @@ If you have an idea for a query that you would like to share with other CodeQL u
|
||||
|
||||
- The query must have at least one true positive result on some revision of a real project.
|
||||
|
||||
Experimental queries and libraries may not be actively maintained as the [supported](docs/supported-queries.md) libraries evolve. They may also be changed in backwards-incompatible ways or may be removed entirely in the future without deprecation warnings.
|
||||
6. **Query help files and unit tests**
|
||||
|
||||
- Query help (`.qhelp`) files and unit tests are optional (but strongly encouraged!) for queries in the `experimental` directories. For more information about contributing query help files and unit tests, see [Supported CodeQL queries and libraries](docs/supported-queries.md).
|
||||
|
||||
Experimental queries and libraries may not be actively maintained as the supported libraries evolve. They may also be changed in backwards-incompatible ways or may be removed entirely in the future without deprecation warnings.
|
||||
|
||||
After the experimental query is merged, we welcome pull requests to improve it. Before a query can be moved out of the `experimental` subdirectory, it must satisfy [the requirements for being a supported query](docs/supported-queries.md).
|
||||
|
||||
|
||||
@@ -356,6 +356,7 @@
|
||||
],
|
||||
"Inline Test Expectations": [
|
||||
"cpp/ql/test/TestUtilities/InlineExpectationsTest.qll",
|
||||
"java/ql/test/TestUtilities/InlineExpectationsTest.qll",
|
||||
"python/ql/test/TestUtilities/InlineExpectationsTest.qll"
|
||||
],
|
||||
"C++ ExternalAPIs": [
|
||||
|
||||
@@ -46,7 +46,7 @@ class UntrustedDataToExternalAPIConfig extends TaintTracking::Configuration {
|
||||
UntrustedDataToExternalAPIConfig() { this = "UntrustedDataToExternalAPIConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
exists(RemoteFlowFunction remoteFlow |
|
||||
exists(RemoteFlowSourceFunction remoteFlow |
|
||||
remoteFlow = source.asExpr().(Call).getTarget() and
|
||||
remoteFlow.hasRemoteFlowSource(_, _)
|
||||
)
|
||||
|
||||
@@ -34,6 +34,10 @@ class Configuration extends TaintTrackingConfiguration {
|
||||
override predicate isSink(Element tainted) {
|
||||
exists(PrintStdoutCall call | call.getAnArgument() = tainted)
|
||||
}
|
||||
|
||||
override predicate isBarrier(Expr e) {
|
||||
super.isBarrier(e) or e.getUnspecifiedType() instanceof IntegralType
|
||||
}
|
||||
}
|
||||
|
||||
from QueryString query, Element printedArg, PathNode sourceNode, PathNode sinkNode
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
* @tags reliability
|
||||
* security
|
||||
* external/cwe/cwe-242
|
||||
* external/cwe/cwe-676
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
@@ -139,6 +139,19 @@ class Declaration extends Locatable, @declaration {
|
||||
this.hasQualifiedName("std", "", name)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this declaration has the given name in the global namespace,
|
||||
* the `std` namespace or the `bsl` namespace.
|
||||
* We treat `std` and `bsl` as the same in some of our models.
|
||||
*/
|
||||
predicate hasGlobalOrStdOrBslName(string name) {
|
||||
this.hasGlobalName(name)
|
||||
or
|
||||
this.hasQualifiedName("std", "", name)
|
||||
or
|
||||
this.hasQualifiedName("bsl", "", name)
|
||||
}
|
||||
|
||||
/** Gets a specifier of this declaration. */
|
||||
Specifier getASpecifier() { none() } // overridden in subclasses
|
||||
|
||||
|
||||
@@ -467,7 +467,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
|
||||
// ... and likewise for destructors.
|
||||
this.(Destructor).getADestruction().mayBeGloballyImpure()
|
||||
else
|
||||
// Unless it's a function that we know is side-effect-free, it may
|
||||
// Unless it's a function that we know is side-effect free, it may
|
||||
// have side-effects.
|
||||
not this.hasGlobalOrStdName([
|
||||
"strcmp", "wcscmp", "_mbscmp", "strlen", "wcslen", "_mbslen", "_mbslen_l", "_mbstrlen",
|
||||
@@ -680,7 +680,7 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl {
|
||||
|
||||
/**
|
||||
* A C/C++ non-member function (a function that is not a member of any
|
||||
* class). For example the in the following code, `MyFunction` is a
|
||||
* class). For example, in the following code, `MyFunction` is a
|
||||
* `TopLevelFunction` but `MyMemberFunction` is not:
|
||||
* ```
|
||||
* void MyFunction() {
|
||||
|
||||
@@ -34,10 +34,10 @@ class Scanf extends ScanfFunction {
|
||||
Scanf() {
|
||||
this instanceof TopLevelFunction and
|
||||
(
|
||||
hasName("scanf") or // scanf(format, args...)
|
||||
hasName("wscanf") or // wscanf(format, args...)
|
||||
hasName("_scanf_l") or // _scanf_l(format, locale, args...)
|
||||
hasName("_wscanf_l") // _wscanf_l(format, locale, args...)
|
||||
hasGlobalOrStdOrBslName("scanf") or // scanf(format, args...)
|
||||
hasGlobalOrStdOrBslName("wscanf") or // wscanf(format, args...)
|
||||
hasGlobalName("_scanf_l") or // _scanf_l(format, locale, args...)
|
||||
hasGlobalName("_wscanf_l") // _wscanf_l(format, locale, args...)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -53,10 +53,10 @@ class Fscanf extends ScanfFunction {
|
||||
Fscanf() {
|
||||
this instanceof TopLevelFunction and
|
||||
(
|
||||
hasName("fscanf") or // fscanf(src_stream, format, args...)
|
||||
hasName("fwscanf") or // fwscanf(src_stream, format, args...)
|
||||
hasName("_fscanf_l") or // _fscanf_l(src_stream, format, locale, args...)
|
||||
hasName("_fwscanf_l") // _fwscanf_l(src_stream, format, locale, args...)
|
||||
hasGlobalOrStdOrBslName("fscanf") or // fscanf(src_stream, format, args...)
|
||||
hasGlobalOrStdOrBslName("fwscanf") or // fwscanf(src_stream, format, args...)
|
||||
hasGlobalName("_fscanf_l") or // _fscanf_l(src_stream, format, locale, args...)
|
||||
hasGlobalName("_fwscanf_l") // _fwscanf_l(src_stream, format, locale, args...)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -72,10 +72,10 @@ class Sscanf extends ScanfFunction {
|
||||
Sscanf() {
|
||||
this instanceof TopLevelFunction and
|
||||
(
|
||||
hasName("sscanf") or // sscanf(src_stream, format, args...)
|
||||
hasName("swscanf") or // swscanf(src, format, args...)
|
||||
hasName("_sscanf_l") or // _sscanf_l(src, format, locale, args...)
|
||||
hasName("_swscanf_l") // _swscanf_l(src, format, locale, args...)
|
||||
hasGlobalOrStdOrBslName("sscanf") or // sscanf(src_stream, format, args...)
|
||||
hasGlobalOrStdOrBslName("swscanf") or // swscanf(src, format, args...)
|
||||
hasGlobalName("_sscanf_l") or // _sscanf_l(src, format, locale, args...)
|
||||
hasGlobalName("_swscanf_l") // _swscanf_l(src, format, locale, args...)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -91,10 +91,10 @@ class Snscanf extends ScanfFunction {
|
||||
Snscanf() {
|
||||
this instanceof TopLevelFunction and
|
||||
(
|
||||
hasName("_snscanf") or // _snscanf(src, max_amount, format, args...)
|
||||
hasName("_snwscanf") or // _snwscanf(src, max_amount, format, args...)
|
||||
hasName("_snscanf_l") or // _snscanf_l(src, max_amount, format, locale, args...)
|
||||
hasName("_snwscanf_l") // _snwscanf_l(src, max_amount, format, locale, args...)
|
||||
hasGlobalName("_snscanf") or // _snscanf(src, max_amount, format, args...)
|
||||
hasGlobalName("_snwscanf") or // _snwscanf(src, max_amount, format, args...)
|
||||
hasGlobalName("_snscanf_l") or // _snscanf_l(src, max_amount, format, locale, args...)
|
||||
hasGlobalName("_snwscanf_l") // _snwscanf_l(src, max_amount, format, locale, args...)
|
||||
// note that the max_amount is not a limit on the output length, it's an input length
|
||||
// limit used with non null-terminated strings.
|
||||
)
|
||||
|
||||
@@ -131,7 +131,22 @@ private predicate lvalueToUpdate(Expr lvalue, Expr outer, ControlFlowNode node)
|
||||
exists(Call call | node = call |
|
||||
outer = call.getQualifier().getFullyConverted() and
|
||||
outer.getUnspecifiedType() instanceof Class and
|
||||
not call.getTarget().hasSpecifier("const")
|
||||
not (
|
||||
call.getTarget().hasSpecifier("const") and
|
||||
// Given the following program:
|
||||
// ```
|
||||
// struct C {
|
||||
// void* data_;
|
||||
// void* data() const { return data; }
|
||||
// };
|
||||
// C c;
|
||||
// memcpy(c.data(), source, 16)
|
||||
// ```
|
||||
// the data pointed to by `c.data_` is potentially modified by the call to `memcpy` even though
|
||||
// `C::data` has a const specifier. So we further place the restriction that the type returned
|
||||
// by `call` should not be of the form `const T*` (for some deeply const type `T`).
|
||||
call.getType().isDeeplyConstBelow()
|
||||
)
|
||||
)
|
||||
or
|
||||
assignmentTo(outer, node)
|
||||
@@ -170,7 +185,11 @@ private predicate pointerToUpdate(Expr pointer, Expr outer, ControlFlowNode node
|
||||
or
|
||||
outer = call.getQualifier().getFullyConverted() and
|
||||
outer.getUnspecifiedType() instanceof PointerType and
|
||||
not call.getTarget().hasSpecifier("const")
|
||||
not (
|
||||
call.getTarget().hasSpecifier("const") and
|
||||
// See the `lvalueToUpdate` case for an explanation of this conjunct.
|
||||
call.getType().isDeeplyConstBelow()
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(PointerFieldAccess fa |
|
||||
|
||||
@@ -3598,6 +3598,7 @@ private module FlowExploration {
|
||||
or
|
||||
exists(PartialPathNodeRev mid |
|
||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
||||
not clearsContent(node, ap.getHead()) and
|
||||
not fullBarrier(node, config) and
|
||||
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
)
|
||||
@@ -3611,6 +3612,7 @@ private module FlowExploration {
|
||||
exists(PartialPathNodeFwd mid |
|
||||
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
||||
not fullBarrier(node, config) and
|
||||
not clearsContent(node, ap.getHead().getContent()) and
|
||||
if node instanceof CastingNode
|
||||
then compatibleTypes(getNodeType(node), ap.getType())
|
||||
else any()
|
||||
|
||||
@@ -3598,6 +3598,7 @@ private module FlowExploration {
|
||||
or
|
||||
exists(PartialPathNodeRev mid |
|
||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
||||
not clearsContent(node, ap.getHead()) and
|
||||
not fullBarrier(node, config) and
|
||||
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
)
|
||||
@@ -3611,6 +3612,7 @@ private module FlowExploration {
|
||||
exists(PartialPathNodeFwd mid |
|
||||
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
||||
not fullBarrier(node, config) and
|
||||
not clearsContent(node, ap.getHead().getContent()) and
|
||||
if node instanceof CastingNode
|
||||
then compatibleTypes(getNodeType(node), ap.getType())
|
||||
else any()
|
||||
|
||||
@@ -3598,6 +3598,7 @@ private module FlowExploration {
|
||||
or
|
||||
exists(PartialPathNodeRev mid |
|
||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
||||
not clearsContent(node, ap.getHead()) and
|
||||
not fullBarrier(node, config) and
|
||||
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
)
|
||||
@@ -3611,6 +3612,7 @@ private module FlowExploration {
|
||||
exists(PartialPathNodeFwd mid |
|
||||
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
||||
not fullBarrier(node, config) and
|
||||
not clearsContent(node, ap.getHead().getContent()) and
|
||||
if node instanceof CastingNode
|
||||
then compatibleTypes(getNodeType(node), ap.getType())
|
||||
else any()
|
||||
|
||||
@@ -3598,6 +3598,7 @@ private module FlowExploration {
|
||||
or
|
||||
exists(PartialPathNodeRev mid |
|
||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
||||
not clearsContent(node, ap.getHead()) and
|
||||
not fullBarrier(node, config) and
|
||||
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
)
|
||||
@@ -3611,6 +3612,7 @@ private module FlowExploration {
|
||||
exists(PartialPathNodeFwd mid |
|
||||
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
||||
not fullBarrier(node, config) and
|
||||
not clearsContent(node, ap.getHead().getContent()) and
|
||||
if node instanceof CastingNode
|
||||
then compatibleTypes(getNodeType(node), ap.getType())
|
||||
else any()
|
||||
|
||||
@@ -3598,6 +3598,7 @@ private module FlowExploration {
|
||||
or
|
||||
exists(PartialPathNodeRev mid |
|
||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
||||
not clearsContent(node, ap.getHead()) and
|
||||
not fullBarrier(node, config) and
|
||||
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
)
|
||||
@@ -3611,6 +3612,7 @@ private module FlowExploration {
|
||||
exists(PartialPathNodeFwd mid |
|
||||
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
||||
not fullBarrier(node, config) and
|
||||
not clearsContent(node, ap.getHead().getContent()) and
|
||||
if node instanceof CastingNode
|
||||
then compatibleTypes(getNodeType(node), ap.getType())
|
||||
else any()
|
||||
|
||||
@@ -3598,6 +3598,7 @@ private module FlowExploration {
|
||||
or
|
||||
exists(PartialPathNodeRev mid |
|
||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
||||
not clearsContent(node, ap.getHead()) and
|
||||
not fullBarrier(node, config) and
|
||||
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
)
|
||||
@@ -3611,6 +3612,7 @@ private module FlowExploration {
|
||||
exists(PartialPathNodeFwd mid |
|
||||
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
||||
not fullBarrier(node, config) and
|
||||
not clearsContent(node, ap.getHead().getContent()) and
|
||||
if node instanceof CastingNode
|
||||
then compatibleTypes(getNodeType(node), ap.getType())
|
||||
else any()
|
||||
|
||||
@@ -3598,6 +3598,7 @@ private module FlowExploration {
|
||||
or
|
||||
exists(PartialPathNodeRev mid |
|
||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
||||
not clearsContent(node, ap.getHead()) and
|
||||
not fullBarrier(node, config) and
|
||||
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
)
|
||||
@@ -3611,6 +3612,7 @@ private module FlowExploration {
|
||||
exists(PartialPathNodeFwd mid |
|
||||
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
||||
not fullBarrier(node, config) and
|
||||
not clearsContent(node, ap.getHead().getContent()) and
|
||||
if node instanceof CastingNode
|
||||
then compatibleTypes(getNodeType(node), ap.getType())
|
||||
else any()
|
||||
|
||||
@@ -3598,6 +3598,7 @@ private module FlowExploration {
|
||||
or
|
||||
exists(PartialPathNodeRev mid |
|
||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
||||
not clearsContent(node, ap.getHead()) and
|
||||
not fullBarrier(node, config) and
|
||||
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
)
|
||||
@@ -3611,6 +3612,7 @@ private module FlowExploration {
|
||||
exists(PartialPathNodeFwd mid |
|
||||
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
||||
not fullBarrier(node, config) and
|
||||
not clearsContent(node, ap.getHead().getContent()) and
|
||||
if node instanceof CastingNode
|
||||
then compatibleTypes(getNodeType(node), ap.getType())
|
||||
else any()
|
||||
|
||||
@@ -3598,6 +3598,7 @@ private module FlowExploration {
|
||||
or
|
||||
exists(PartialPathNodeRev mid |
|
||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
||||
not clearsContent(node, ap.getHead()) and
|
||||
not fullBarrier(node, config) and
|
||||
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
)
|
||||
@@ -3611,6 +3612,7 @@ private module FlowExploration {
|
||||
exists(PartialPathNodeFwd mid |
|
||||
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
||||
not fullBarrier(node, config) and
|
||||
not clearsContent(node, ap.getHead().getContent()) and
|
||||
if node instanceof CastingNode
|
||||
then compatibleTypes(getNodeType(node), ap.getType())
|
||||
else any()
|
||||
|
||||
@@ -28,3 +28,8 @@ private import implementations.Swap
|
||||
private import implementations.GetDelim
|
||||
private import implementations.SmartPointer
|
||||
private import implementations.Sscanf
|
||||
private import implementations.Send
|
||||
private import implementations.Recv
|
||||
private import implementations.Accept
|
||||
private import implementations.Poll
|
||||
private import implementations.Select
|
||||
|
||||
56
cpp/ql/src/semmle/code/cpp/models/implementations/Accept.qll
Normal file
56
cpp/ql/src/semmle/code/cpp/models/implementations/Accept.qll
Normal file
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Provides implementation classes modeling `accept` and various similar
|
||||
* functions. See `semmle.code.cpp.models.Models` for usage information.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.Function
|
||||
import semmle.code.cpp.models.interfaces.ArrayFunction
|
||||
import semmle.code.cpp.models.interfaces.Taint
|
||||
import semmle.code.cpp.models.interfaces.Alias
|
||||
import semmle.code.cpp.models.interfaces.SideEffect
|
||||
|
||||
/**
|
||||
* The function `accept` and its assorted variants
|
||||
*/
|
||||
private class Accept extends ArrayFunction, AliasFunction, TaintFunction, SideEffectFunction {
|
||||
Accept() { this.hasGlobalName(["accept", "accept4", "WSAAccept"]) }
|
||||
|
||||
override predicate hasArrayWithVariableSize(int bufParam, int countParam) {
|
||||
bufParam = 1 and countParam = 2
|
||||
}
|
||||
|
||||
override predicate hasArrayInput(int bufParam) { bufParam = 1 }
|
||||
|
||||
override predicate hasArrayOutput(int bufParam) { bufParam = 1 }
|
||||
|
||||
override predicate parameterNeverEscapes(int index) { exists(this.getParameter(index)) }
|
||||
|
||||
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||
|
||||
override predicate parameterIsAlwaysReturned(int index) { none() }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
(input.isParameter(0) or input.isParameterDeref(1)) and
|
||||
(output.isReturnValue() or output.isParameterDeref(1))
|
||||
}
|
||||
|
||||
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||
i = 1 and buffer = true and mustWrite = false
|
||||
or
|
||||
i = 2 and buffer = false and mustWrite = false
|
||||
}
|
||||
|
||||
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||
i = 0 and buffer = true
|
||||
or
|
||||
i = 1 and buffer = false
|
||||
}
|
||||
|
||||
override ParameterIndex getParameterSizeIndex(ParameterIndex i) { i = 1 and result = 2 }
|
||||
|
||||
// NOTE: We implement thse two predicates as none because we can't model the low-level changes made to
|
||||
// the structure pointed to by the file-descriptor argument.
|
||||
override predicate hasOnlySpecificReadSideEffects() { none() }
|
||||
|
||||
override predicate hasOnlySpecificWriteSideEffects() { none() }
|
||||
}
|
||||
@@ -15,7 +15,7 @@ private class MallocAllocationFunction extends AllocationFunction {
|
||||
|
||||
MallocAllocationFunction() {
|
||||
// --- C library allocation
|
||||
hasGlobalOrStdName("malloc") and // malloc(size)
|
||||
hasGlobalOrStdOrBslName("malloc") and // malloc(size)
|
||||
sizeArg = 0
|
||||
or
|
||||
hasGlobalName([
|
||||
@@ -104,7 +104,7 @@ private class CallocAllocationFunction extends AllocationFunction {
|
||||
|
||||
CallocAllocationFunction() {
|
||||
// --- C library allocation
|
||||
hasGlobalOrStdName("calloc") and // calloc(num, size)
|
||||
hasGlobalOrStdOrBslName("calloc") and // calloc(num, size)
|
||||
sizeArg = 1 and
|
||||
multArg = 0
|
||||
}
|
||||
@@ -124,7 +124,7 @@ private class ReallocAllocationFunction extends AllocationFunction {
|
||||
|
||||
ReallocAllocationFunction() {
|
||||
// --- C library allocation
|
||||
hasGlobalOrStdName("realloc") and // realloc(ptr, size)
|
||||
hasGlobalOrStdOrBslName("realloc") and // realloc(ptr, size)
|
||||
sizeArg = 1 and
|
||||
reallocArg = 0
|
||||
or
|
||||
|
||||
@@ -13,9 +13,13 @@ private class StandardDeallocationFunction extends DeallocationFunction {
|
||||
int freedArg;
|
||||
|
||||
StandardDeallocationFunction() {
|
||||
hasGlobalName([
|
||||
hasGlobalOrStdOrBslName([
|
||||
// --- C library allocation
|
||||
"free", "realloc",
|
||||
"free", "realloc"
|
||||
]) and
|
||||
freedArg = 0
|
||||
or
|
||||
hasGlobalName([
|
||||
// --- OpenSSL memory allocation
|
||||
"CRYPTO_free", "CRYPTO_secure_free"
|
||||
]) and
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import semmle.code.cpp.models.interfaces.Alias
|
||||
import semmle.code.cpp.models.interfaces.FlowSource
|
||||
|
||||
private class Fread extends AliasFunction, RemoteFlowFunction {
|
||||
Fread() { this.hasGlobalName("fread") }
|
||||
private class Fread extends AliasFunction, RemoteFlowSourceFunction {
|
||||
Fread() { this.hasGlobalOrStdOrBslName("fread") }
|
||||
|
||||
override predicate parameterNeverEscapes(int n) {
|
||||
n = 0 or
|
||||
|
||||
@@ -7,7 +7,7 @@ import semmle.code.cpp.models.interfaces.FlowSource
|
||||
* The standard functions `getdelim`, `getwdelim` and the glibc variant `__getdelim`.
|
||||
*/
|
||||
private class GetDelimFunction extends TaintFunction, AliasFunction, SideEffectFunction,
|
||||
RemoteFlowFunction {
|
||||
RemoteFlowSourceFunction {
|
||||
GetDelimFunction() { hasGlobalName(["getdelim", "getwdelim", "__getdelim"]) }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput i, FunctionOutput o) {
|
||||
|
||||
@@ -8,8 +8,8 @@ import semmle.code.cpp.models.interfaces.FlowSource
|
||||
/**
|
||||
* The POSIX function `getenv`.
|
||||
*/
|
||||
class Getenv extends LocalFlowFunction {
|
||||
Getenv() { this.hasGlobalName("getenv") }
|
||||
class Getenv extends LocalFlowSourceFunction {
|
||||
Getenv() { this.hasGlobalOrStdOrBslName("getenv") }
|
||||
|
||||
override predicate hasLocalFlowSource(FunctionOutput output, string description) {
|
||||
(
|
||||
|
||||
@@ -14,12 +14,12 @@ import semmle.code.cpp.models.interfaces.FlowSource
|
||||
* The standard functions `gets` and `fgets`.
|
||||
*/
|
||||
private class GetsFunction extends DataFlowFunction, TaintFunction, ArrayFunction, AliasFunction,
|
||||
SideEffectFunction, RemoteFlowFunction {
|
||||
SideEffectFunction, RemoteFlowSourceFunction {
|
||||
GetsFunction() {
|
||||
// gets(str)
|
||||
// fgets(str, num, stream)
|
||||
// fgetws(wstr, num, stream)
|
||||
hasGlobalOrStdName(["gets", "fgets", "fgetws"])
|
||||
hasGlobalOrStdOrBslName(["gets", "fgets", "fgetws"])
|
||||
}
|
||||
|
||||
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
|
||||
@@ -54,13 +54,13 @@ private class GetsFunction extends DataFlowFunction, TaintFunction, ArrayFunctio
|
||||
}
|
||||
|
||||
override predicate hasArrayWithVariableSize(int bufParam, int countParam) {
|
||||
not hasGlobalOrStdName("gets") and
|
||||
not hasName("gets") and
|
||||
bufParam = 0 and
|
||||
countParam = 1
|
||||
}
|
||||
|
||||
override predicate hasArrayWithUnknownSize(int bufParam) {
|
||||
hasGlobalOrStdName("gets") and
|
||||
hasName("gets") and
|
||||
bufParam = 0
|
||||
}
|
||||
|
||||
|
||||
@@ -6,12 +6,9 @@ import semmle.code.cpp.models.interfaces.SideEffect
|
||||
/**
|
||||
* The standard function templates `std::move` and `std::forward`.
|
||||
*/
|
||||
private class IdentityFunction extends DataFlowFunction, SideEffectFunction, AliasFunction {
|
||||
IdentityFunction() {
|
||||
this.getNamespace().getParentNamespace() instanceof GlobalNamespace and
|
||||
this.getNamespace().getName() = "std" and
|
||||
this.getName() = ["move", "forward"]
|
||||
}
|
||||
private class IdentityFunction extends DataFlowFunction, SideEffectFunction, AliasFunction,
|
||||
FunctionTemplateInstantiation {
|
||||
IdentityFunction() { this.hasQualifiedName("std", ["move", "forward"]) }
|
||||
|
||||
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ import semmle.code.cpp.models.interfaces.Iterator
|
||||
*/
|
||||
private class IteratorTraits extends Class {
|
||||
IteratorTraits() {
|
||||
this.hasQualifiedName("std", "iterator_traits") and
|
||||
this.hasQualifiedName(["std", "bsl"], "iterator_traits") and
|
||||
not this instanceof TemplateClass and
|
||||
exists(TypedefType t |
|
||||
this.getAMember() = t and
|
||||
@@ -26,6 +26,14 @@ private class IteratorTraits extends Class {
|
||||
Type getIteratorType() { result = this.getTemplateArgument(0) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A type that is deduced to be an iterator because there is a corresponding
|
||||
* `std::iterator_traits` instantiation for it.
|
||||
*/
|
||||
private class IteratorByTraits extends Iterator {
|
||||
IteratorByTraits() { exists(IteratorTraits it | it.getIteratorType() = this) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A type which has the typedefs expected for an iterator.
|
||||
*/
|
||||
@@ -36,7 +44,7 @@ private class IteratorByTypedefs extends Iterator, Class {
|
||||
this.getAMember().(TypedefType).hasName("pointer") and
|
||||
this.getAMember().(TypedefType).hasName("reference") and
|
||||
this.getAMember().(TypedefType).hasName("iterator_category") and
|
||||
not this.hasQualifiedName("std", "iterator_traits")
|
||||
not this.hasQualifiedName(["std", "bsl"], "iterator_traits")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,17 +52,13 @@ private class IteratorByTypedefs extends Iterator, Class {
|
||||
* The `std::iterator` class.
|
||||
*/
|
||||
private class StdIterator extends Iterator, Class {
|
||||
StdIterator() { this.hasQualifiedName("std", "iterator") }
|
||||
StdIterator() { this.hasQualifiedName(["std", "bsl"], "iterator") }
|
||||
}
|
||||
|
||||
/**
|
||||
* A type that is deduced to be an iterator because there is a corresponding
|
||||
* `std::iterator_traits` instantiation for it.
|
||||
* Gets the `FunctionInput` corresponding to an iterator parameter to
|
||||
* user-defined operator `op`, at `index`.
|
||||
*/
|
||||
private class IteratorByTraits extends Iterator {
|
||||
IteratorByTraits() { exists(IteratorTraits it | it.getIteratorType() = this) }
|
||||
}
|
||||
|
||||
private FunctionInput getIteratorArgumentInput(Operator op, int index) {
|
||||
exists(Type t |
|
||||
t =
|
||||
@@ -155,17 +159,21 @@ private class IteratorSubOperator extends Operator, TaintFunction {
|
||||
private class IteratorAssignArithmeticOperator extends Operator, DataFlowFunction, TaintFunction {
|
||||
IteratorAssignArithmeticOperator() {
|
||||
this.hasName(["operator+=", "operator-="]) and
|
||||
this.getDeclaringType() instanceof Iterator
|
||||
exists(getIteratorArgumentInput(this, 0))
|
||||
}
|
||||
|
||||
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
|
||||
input.isParameter(0) and
|
||||
output.isReturnValue()
|
||||
or
|
||||
input.isParameterDeref(0) and output.isReturnValueDeref()
|
||||
}
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
input.isParameterDeref(0) and output.isReturnValueDeref()
|
||||
or
|
||||
// reverse flow from returned reference to the object referenced by the first parameter
|
||||
input.isReturnValueDeref() and
|
||||
output.isParameterDeref(0)
|
||||
or
|
||||
input.isParameterDeref(1) and
|
||||
output.isParameterDeref(0)
|
||||
}
|
||||
@@ -177,8 +185,7 @@ private class IteratorAssignArithmeticOperator extends Operator, DataFlowFunctio
|
||||
class IteratorPointerDereferenceMemberOperator extends MemberFunction, TaintFunction,
|
||||
IteratorReferenceFunction {
|
||||
IteratorPointerDereferenceMemberOperator() {
|
||||
this.hasName("operator*") and
|
||||
this.getDeclaringType() instanceof Iterator
|
||||
this.getClassAndName("operator*") instanceof Iterator
|
||||
}
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
@@ -195,8 +202,7 @@ class IteratorPointerDereferenceMemberOperator extends MemberFunction, TaintFunc
|
||||
*/
|
||||
private class IteratorCrementMemberOperator extends MemberFunction, DataFlowFunction, TaintFunction {
|
||||
IteratorCrementMemberOperator() {
|
||||
this.hasName(["operator++", "operator--"]) and
|
||||
this.getDeclaringType() instanceof Iterator
|
||||
this.getClassAndName(["operator++", "operator--"]) instanceof Iterator
|
||||
}
|
||||
|
||||
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
|
||||
@@ -220,10 +226,7 @@ private class IteratorCrementMemberOperator extends MemberFunction, DataFlowFunc
|
||||
* A member `operator->` function for an iterator type.
|
||||
*/
|
||||
private class IteratorFieldMemberOperator extends Operator, TaintFunction {
|
||||
IteratorFieldMemberOperator() {
|
||||
this.hasName("operator->") and
|
||||
this.getDeclaringType() instanceof Iterator
|
||||
}
|
||||
IteratorFieldMemberOperator() { this.getClassAndName("operator->") instanceof Iterator }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
input.isQualifierObject() and
|
||||
@@ -236,8 +239,7 @@ private class IteratorFieldMemberOperator extends Operator, TaintFunction {
|
||||
*/
|
||||
private class IteratorBinaryArithmeticMemberOperator extends MemberFunction, TaintFunction {
|
||||
IteratorBinaryArithmeticMemberOperator() {
|
||||
this.hasName(["operator+", "operator-"]) and
|
||||
this.getDeclaringType() instanceof Iterator
|
||||
this.getClassAndName(["operator+", "operator-"]) instanceof Iterator
|
||||
}
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
@@ -252,21 +254,24 @@ private class IteratorBinaryArithmeticMemberOperator extends MemberFunction, Tai
|
||||
private class IteratorAssignArithmeticMemberOperator extends MemberFunction, DataFlowFunction,
|
||||
TaintFunction {
|
||||
IteratorAssignArithmeticMemberOperator() {
|
||||
this.hasName(["operator+=", "operator-="]) and
|
||||
this.getDeclaringType() instanceof Iterator
|
||||
this.getClassAndName(["operator+=", "operator-="]) instanceof Iterator
|
||||
}
|
||||
|
||||
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
|
||||
input.isQualifierAddress() and
|
||||
output.isReturnValue()
|
||||
or
|
||||
input.isReturnValueDeref() and
|
||||
output.isQualifierObject()
|
||||
}
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
input.isQualifierObject() and
|
||||
output.isReturnValueDeref()
|
||||
or
|
||||
// reverse flow from returned reference to the qualifier
|
||||
input.isReturnValueDeref() and
|
||||
output.isQualifierObject()
|
||||
or
|
||||
input.isParameterDeref(0) and
|
||||
output.isQualifierObject()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,10 +280,7 @@ private class IteratorAssignArithmeticMemberOperator extends MemberFunction, Dat
|
||||
*/
|
||||
private class IteratorArrayMemberOperator extends MemberFunction, TaintFunction,
|
||||
IteratorReferenceFunction {
|
||||
IteratorArrayMemberOperator() {
|
||||
this.hasName("operator[]") and
|
||||
this.getDeclaringType() instanceof Iterator
|
||||
}
|
||||
IteratorArrayMemberOperator() { this.getClassAndName("operator[]") instanceof Iterator }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
input.isQualifierObject() and
|
||||
@@ -295,8 +297,7 @@ private class IteratorArrayMemberOperator extends MemberFunction, TaintFunction,
|
||||
*/
|
||||
private class IteratorAssignmentMemberOperator extends MemberFunction, TaintFunction {
|
||||
IteratorAssignmentMemberOperator() {
|
||||
this.hasName("operator=") and
|
||||
this.getDeclaringType() instanceof Iterator and
|
||||
this.getClassAndName("operator=") instanceof Iterator and
|
||||
not this instanceof CopyAssignmentOperator and
|
||||
not this instanceof MoveAssignmentOperator
|
||||
}
|
||||
@@ -337,7 +338,7 @@ private class BeginOrEndFunction extends MemberFunction, TaintFunction, GetItera
|
||||
*/
|
||||
private class InserterIteratorFunction extends GetIteratorFunction {
|
||||
InserterIteratorFunction() {
|
||||
this.hasQualifiedName("std", ["front_inserter", "inserter", "back_inserter"])
|
||||
this.hasQualifiedName(["std", "bsl"], ["front_inserter", "inserter", "back_inserter"])
|
||||
}
|
||||
|
||||
override predicate getsIterator(FunctionInput input, FunctionOutput output) {
|
||||
|
||||
@@ -20,7 +20,7 @@ private class MemcpyFunction extends ArrayFunction, DataFlowFunction, SideEffect
|
||||
// memcpy(dest, src, num)
|
||||
// memmove(dest, src, num)
|
||||
// memmove(dest, src, num, remaining)
|
||||
this.hasGlobalOrStdName(["memcpy", "memmove"])
|
||||
this.hasGlobalOrStdOrBslName(["memcpy", "memmove"])
|
||||
or
|
||||
// bcopy(src, dest, num)
|
||||
// mempcpy(dest, src, num)
|
||||
|
||||
@@ -15,7 +15,9 @@ import semmle.code.cpp.models.interfaces.SideEffect
|
||||
private class MemsetFunction extends ArrayFunction, DataFlowFunction, AliasFunction,
|
||||
SideEffectFunction {
|
||||
MemsetFunction() {
|
||||
this.hasGlobalOrStdName(["memset", "wmemset"])
|
||||
this.hasGlobalOrStdOrBslName("memset")
|
||||
or
|
||||
this.hasGlobalOrStdName("wmemset")
|
||||
or
|
||||
this.hasGlobalName([bzero(), "__builtin_memset", "__builtin_memset_chk"])
|
||||
}
|
||||
|
||||
44
cpp/ql/src/semmle/code/cpp/models/implementations/Poll.qll
Normal file
44
cpp/ql/src/semmle/code/cpp/models/implementations/Poll.qll
Normal file
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Provides implementation classes modeling `poll` and various similar
|
||||
* functions. See `semmle.code.cpp.models.Models` for usage information.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.Function
|
||||
import semmle.code.cpp.models.interfaces.ArrayFunction
|
||||
import semmle.code.cpp.models.interfaces.Alias
|
||||
import semmle.code.cpp.models.interfaces.SideEffect
|
||||
|
||||
/**
|
||||
* The function `poll` and its assorted variants
|
||||
*/
|
||||
private class Poll extends ArrayFunction, AliasFunction, SideEffectFunction {
|
||||
Poll() { this.hasGlobalName(["poll", "ppoll", "WSAPoll"]) }
|
||||
|
||||
override predicate hasArrayWithVariableSize(int bufParam, int countParam) {
|
||||
bufParam = 0 and countParam = 1
|
||||
}
|
||||
|
||||
override predicate hasArrayInput(int bufParam) { bufParam = 0 }
|
||||
|
||||
override predicate hasArrayOutput(int bufParam) { bufParam = 0 }
|
||||
|
||||
override predicate parameterNeverEscapes(int index) { exists(this.getParameter(index)) }
|
||||
|
||||
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||
|
||||
override predicate parameterIsAlwaysReturned(int index) { none() }
|
||||
|
||||
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||
i = 0 and buffer = true and mustWrite = false
|
||||
}
|
||||
|
||||
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||
i = 0 and buffer = true
|
||||
or
|
||||
this.hasGlobalName("ppoll") and i = [2, 3] and buffer = false
|
||||
}
|
||||
|
||||
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||
|
||||
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||
}
|
||||
@@ -15,7 +15,7 @@ private class Printf extends FormattingFunction, AliasFunction {
|
||||
Printf() {
|
||||
this instanceof TopLevelFunction and
|
||||
(
|
||||
hasGlobalOrStdName(["printf", "wprintf"]) or
|
||||
hasGlobalOrStdOrBslName(["printf", "wprintf"]) or
|
||||
hasGlobalName(["printf_s", "wprintf_s", "g_printf"])
|
||||
) and
|
||||
not exists(getDefinition().getFile().getRelativePath())
|
||||
@@ -23,10 +23,7 @@ private class Printf extends FormattingFunction, AliasFunction {
|
||||
|
||||
override int getFormatParameterIndex() { result = 0 }
|
||||
|
||||
deprecated override predicate isWideCharDefault() {
|
||||
hasGlobalOrStdName("wprintf") or
|
||||
hasGlobalName("wprintf_s")
|
||||
}
|
||||
deprecated override predicate isWideCharDefault() { hasName(["wprintf", "wprintf_s"]) }
|
||||
|
||||
override predicate isOutputGlobal() { any() }
|
||||
|
||||
@@ -44,7 +41,7 @@ private class Fprintf extends FormattingFunction {
|
||||
Fprintf() {
|
||||
this instanceof TopLevelFunction and
|
||||
(
|
||||
hasGlobalOrStdName(["fprintf", "fwprintf"]) or
|
||||
hasGlobalOrStdOrBslName(["fprintf", "fwprintf"]) or
|
||||
hasGlobalName("g_fprintf")
|
||||
) and
|
||||
not exists(getDefinition().getFile().getRelativePath())
|
||||
@@ -52,7 +49,7 @@ private class Fprintf extends FormattingFunction {
|
||||
|
||||
override int getFormatParameterIndex() { result = 1 }
|
||||
|
||||
deprecated override predicate isWideCharDefault() { hasGlobalOrStdName("fwprintf") }
|
||||
deprecated override predicate isWideCharDefault() { hasName("fwprintf") }
|
||||
|
||||
override int getOutputParameterIndex(boolean isStream) { result = 0 and isStream = true }
|
||||
}
|
||||
@@ -64,7 +61,7 @@ private class Sprintf extends FormattingFunction {
|
||||
Sprintf() {
|
||||
this instanceof TopLevelFunction and
|
||||
(
|
||||
hasGlobalOrStdName([
|
||||
hasGlobalOrStdOrBslName([
|
||||
"sprintf", // sprintf(dst, format, args...)
|
||||
"wsprintf" // wsprintf(dst, format, args...)
|
||||
])
|
||||
@@ -90,22 +87,20 @@ private class Sprintf extends FormattingFunction {
|
||||
}
|
||||
|
||||
override int getFormatParameterIndex() {
|
||||
hasGlobalName("g_strdup_printf") and result = 0
|
||||
hasName("g_strdup_printf") and result = 0
|
||||
or
|
||||
hasGlobalName("__builtin___sprintf_chk") and result = 3
|
||||
hasName("__builtin___sprintf_chk") and result = 3
|
||||
or
|
||||
not getName() = ["g_strdup_printf", "__builtin___sprintf_chk"] and
|
||||
result = 1
|
||||
}
|
||||
|
||||
override int getOutputParameterIndex(boolean isStream) {
|
||||
not hasGlobalName("g_strdup_printf") and result = 0 and isStream = false
|
||||
not hasName("g_strdup_printf") and result = 0 and isStream = false
|
||||
}
|
||||
|
||||
override int getFirstFormatArgumentIndex() {
|
||||
if hasGlobalName("__builtin___sprintf_chk")
|
||||
then result = 4
|
||||
else result = getNumberOfParameters()
|
||||
if hasName("__builtin___sprintf_chk") then result = 4 else result = getNumberOfParameters()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,7 +111,7 @@ private class SnprintfImpl extends Snprintf {
|
||||
SnprintfImpl() {
|
||||
this instanceof TopLevelFunction and
|
||||
(
|
||||
hasGlobalOrStdName([
|
||||
hasGlobalOrStdOrBslName([
|
||||
"snprintf", // C99 defines snprintf
|
||||
"swprintf" // The s version of wide-char printf is also always the n version
|
||||
])
|
||||
@@ -163,10 +158,7 @@ private class SnprintfImpl extends Snprintf {
|
||||
}
|
||||
|
||||
override predicate returnsFullFormatLength() {
|
||||
(
|
||||
hasGlobalOrStdName("snprintf") or
|
||||
hasGlobalName(["g_snprintf", "__builtin___snprintf_chk", "snprintf_s"])
|
||||
) and
|
||||
hasName(["snprintf", "g_snprintf", "__builtin___snprintf_chk", "snprintf_s"]) and
|
||||
not exists(getDefinition().getFile().getRelativePath())
|
||||
}
|
||||
|
||||
|
||||
@@ -3,11 +3,14 @@ import semmle.code.cpp.models.interfaces.Taint
|
||||
import semmle.code.cpp.models.interfaces.Alias
|
||||
import semmle.code.cpp.models.interfaces.SideEffect
|
||||
|
||||
/** Pure string functions. */
|
||||
/**
|
||||
* A function that operates on strings and is pure. That is, its evaluation is
|
||||
* guaranteed to be side-effect free.
|
||||
*/
|
||||
private class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunction,
|
||||
SideEffectFunction {
|
||||
PureStrFunction() {
|
||||
hasGlobalOrStdName([
|
||||
hasGlobalOrStdOrBslName([
|
||||
atoi(), "strcasestr", "strchnul", "strchr", "strchrnul", "strstr", "strpbrk", "strrchr",
|
||||
"strspn", strtol(), strrev(), strcmp(), strlwr(), strupr()
|
||||
])
|
||||
@@ -89,10 +92,12 @@ private string strcmp() {
|
||||
]
|
||||
}
|
||||
|
||||
/** String standard `strlen` function, and related functions for computing string lengths. */
|
||||
/**
|
||||
* A function such as `strlen` that returns the length of the given string.
|
||||
*/
|
||||
private class StrLenFunction extends AliasFunction, ArrayFunction, SideEffectFunction {
|
||||
StrLenFunction() {
|
||||
hasGlobalOrStdName(["strlen", "strnlen", "wcslen"])
|
||||
hasGlobalOrStdOrBslName(["strlen", "strnlen", "wcslen"])
|
||||
or
|
||||
hasGlobalName(["_mbslen", "_mbslen_l", "_mbstrlen", "_mbstrlen_l"])
|
||||
}
|
||||
@@ -123,9 +128,12 @@ private class StrLenFunction extends AliasFunction, ArrayFunction, SideEffectFun
|
||||
}
|
||||
}
|
||||
|
||||
/** Pure functions. */
|
||||
/**
|
||||
* A function that is pure, that is, its evaluation is guaranteed to be
|
||||
* side-effect free. Excludes functions modeled by `PureStrFunction` and `PureMemFunction`.
|
||||
*/
|
||||
private class PureFunction extends TaintFunction, SideEffectFunction {
|
||||
PureFunction() { hasGlobalOrStdName(["abs", "labs"]) }
|
||||
PureFunction() { hasGlobalOrStdOrBslName(["abs", "labs"]) }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
exists(ParameterIndex i |
|
||||
@@ -140,11 +148,14 @@ private class PureFunction extends TaintFunction, SideEffectFunction {
|
||||
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||
}
|
||||
|
||||
/** Pure raw-memory functions. */
|
||||
/**
|
||||
* A function that operates on memory buffers and is pure. That is, its
|
||||
* evaluation is guaranteed to be side-effect free.
|
||||
*/
|
||||
private class PureMemFunction extends AliasFunction, ArrayFunction, TaintFunction,
|
||||
SideEffectFunction {
|
||||
PureMemFunction() {
|
||||
hasGlobalOrStdName([
|
||||
hasGlobalOrStdOrBslName([
|
||||
"memchr", "__builtin_memchr", "memrchr", "rawmemchr", "memcmp", "__builtin_memcmp", "memmem"
|
||||
]) or
|
||||
this.hasGlobalName("memfrob")
|
||||
|
||||
88
cpp/ql/src/semmle/code/cpp/models/implementations/Recv.qll
Normal file
88
cpp/ql/src/semmle/code/cpp/models/implementations/Recv.qll
Normal file
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
* Provides implementation classes modeling `recv` and various similar
|
||||
* functions. See `semmle.code.cpp.models.Models` for usage information.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.models.interfaces.Taint
|
||||
import semmle.code.cpp.models.interfaces.ArrayFunction
|
||||
import semmle.code.cpp.models.interfaces.Alias
|
||||
import semmle.code.cpp.models.interfaces.FlowSource
|
||||
import semmle.code.cpp.models.interfaces.SideEffect
|
||||
|
||||
/** The function `recv` and its assorted variants */
|
||||
private class Recv extends AliasFunction, ArrayFunction, SideEffectFunction,
|
||||
RemoteFlowSourceFunction {
|
||||
Recv() {
|
||||
this.hasGlobalName([
|
||||
"recv", // recv(socket, dest, len, flags)
|
||||
"recvfrom", // recvfrom(socket, dest, len, flags, from, fromlen)
|
||||
"recvmsg", // recvmsg(socket, msg, flags)
|
||||
"read", // read(socket, dest, len)
|
||||
"pread", // pread(socket, dest, len, offset)
|
||||
"readv", // readv(socket, dest, len)
|
||||
"preadv", // readv(socket, dest, len, offset)
|
||||
"preadv2" // readv2(socket, dest, len, offset, flags)
|
||||
])
|
||||
}
|
||||
|
||||
override predicate parameterNeverEscapes(int index) {
|
||||
this.getParameter(index).getUnspecifiedType() instanceof PointerType
|
||||
}
|
||||
|
||||
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||
|
||||
override predicate parameterIsAlwaysReturned(int index) { none() }
|
||||
|
||||
override predicate hasArrayWithVariableSize(int bufParam, int countParam) {
|
||||
not this.hasGlobalName("recvmsg") and
|
||||
bufParam = 1 and
|
||||
countParam = 2
|
||||
}
|
||||
|
||||
override predicate hasArrayInput(int bufParam) { this.hasGlobalName("recvfrom") and bufParam = 4 }
|
||||
|
||||
override predicate hasArrayOutput(int bufParam) {
|
||||
bufParam = 1
|
||||
or
|
||||
this.hasGlobalName("recvfrom") and bufParam = 4
|
||||
}
|
||||
|
||||
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||
this.hasGlobalName("recvfrom") and
|
||||
(
|
||||
i = 4 and buffer = true
|
||||
or
|
||||
i = 5 and buffer = false
|
||||
)
|
||||
or
|
||||
this.hasGlobalName("recvmsg") and
|
||||
i = 1 and
|
||||
buffer = true
|
||||
}
|
||||
|
||||
override ParameterIndex getParameterSizeIndex(ParameterIndex i) { i = 1 and result = 2 }
|
||||
|
||||
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||
i = 1 and buffer = true and mustWrite = false
|
||||
or
|
||||
this.hasGlobalName("recvfrom") and
|
||||
(
|
||||
i = 4 and buffer = true and mustWrite = false
|
||||
or
|
||||
i = 5 and buffer = false and mustWrite = false
|
||||
)
|
||||
}
|
||||
|
||||
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||
|
||||
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||
|
||||
override predicate hasRemoteFlowSource(FunctionOutput output, string description) {
|
||||
(
|
||||
output.isParameterDeref(1)
|
||||
or
|
||||
this.hasGlobalName("recvfrom") and output.isParameterDeref([4, 5])
|
||||
) and
|
||||
description = "Buffer read by " + this.getName()
|
||||
}
|
||||
}
|
||||
40
cpp/ql/src/semmle/code/cpp/models/implementations/Select.qll
Normal file
40
cpp/ql/src/semmle/code/cpp/models/implementations/Select.qll
Normal file
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Provides implementation classes modeling `select` and various similar
|
||||
* functions. See `semmle.code.cpp.models.Models` for usage information.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.Function
|
||||
import semmle.code.cpp.models.interfaces.ArrayFunction
|
||||
import semmle.code.cpp.models.interfaces.Alias
|
||||
import semmle.code.cpp.models.interfaces.SideEffect
|
||||
|
||||
/**
|
||||
* The function `select` and its assorted variants
|
||||
*/
|
||||
private class Select extends ArrayFunction, AliasFunction, SideEffectFunction {
|
||||
Select() { this.hasGlobalName(["select", "pselect"]) }
|
||||
|
||||
override predicate hasArrayWithUnknownSize(int bufParam) { bufParam = [1 .. 3] }
|
||||
|
||||
override predicate hasArrayInput(int bufParam) { bufParam = [1 .. 3] }
|
||||
|
||||
override predicate hasArrayOutput(int bufParam) { bufParam = [1 .. 3] }
|
||||
|
||||
override predicate parameterNeverEscapes(int index) { exists(this.getParameter(index)) }
|
||||
|
||||
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||
|
||||
override predicate parameterIsAlwaysReturned(int index) { none() }
|
||||
|
||||
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||
i = [1 .. 3] and buffer = true and mustWrite = false
|
||||
}
|
||||
|
||||
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||
i = [1 .. 5] and buffer = true
|
||||
}
|
||||
|
||||
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||
|
||||
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||
}
|
||||
63
cpp/ql/src/semmle/code/cpp/models/implementations/Send.qll
Normal file
63
cpp/ql/src/semmle/code/cpp/models/implementations/Send.qll
Normal file
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* Provides implementation classes modeling `send` and various similar
|
||||
* functions. See `semmle.code.cpp.models.Models` for usage information.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.models.interfaces.Taint
|
||||
import semmle.code.cpp.models.interfaces.ArrayFunction
|
||||
import semmle.code.cpp.models.interfaces.Alias
|
||||
import semmle.code.cpp.models.interfaces.FlowSource
|
||||
import semmle.code.cpp.models.interfaces.SideEffect
|
||||
|
||||
/** The function `send` and its assorted variants */
|
||||
private class Send extends AliasFunction, ArrayFunction, SideEffectFunction, RemoteFlowSinkFunction {
|
||||
Send() {
|
||||
this.hasGlobalName([
|
||||
"send", // send(socket, buf, len, flags)
|
||||
"sendto", // sendto(socket, buf, len, flags, to, tolen)
|
||||
"sendmsg", // sendmsg(socket, msg, flags)
|
||||
"write", // write(socket, buf, len)
|
||||
"writev", // writev(socket, buf, len)
|
||||
"pwritev", // pwritev(socket, buf, len, offset)
|
||||
"pwritev2" // pwritev2(socket, buf, len, offset, flags)
|
||||
])
|
||||
}
|
||||
|
||||
override predicate parameterNeverEscapes(int index) {
|
||||
this.getParameter(index).getUnspecifiedType() instanceof PointerType
|
||||
}
|
||||
|
||||
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||
|
||||
override predicate parameterIsAlwaysReturned(int index) { none() }
|
||||
|
||||
override predicate hasArrayWithVariableSize(int bufParam, int countParam) {
|
||||
not this.hasGlobalName("sendmsg") and
|
||||
bufParam = 1 and
|
||||
countParam = 2
|
||||
}
|
||||
|
||||
override predicate hasArrayInput(int bufParam) { bufParam = 1 }
|
||||
|
||||
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||
|
||||
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||
|
||||
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||
none()
|
||||
}
|
||||
|
||||
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||
i = 1 and buffer = true
|
||||
or
|
||||
this.hasGlobalName("sendto") and i = 4 and buffer = false
|
||||
or
|
||||
this.hasGlobalName("sendmsg") and i = 1 and buffer = true
|
||||
}
|
||||
|
||||
override ParameterIndex getParameterSizeIndex(ParameterIndex i) { i = 1 and result = 2 }
|
||||
|
||||
override predicate hasRemoteFlowSink(FunctionInput input, string description) {
|
||||
input.isParameterDeref(1) and description = "Buffer sent by " + this.getName()
|
||||
}
|
||||
}
|
||||
@@ -4,14 +4,14 @@ import semmle.code.cpp.models.interfaces.Taint
|
||||
* The `std::shared_ptr` and `std::unique_ptr` template classes.
|
||||
*/
|
||||
private class UniqueOrSharedPtr extends Class {
|
||||
UniqueOrSharedPtr() { this.hasQualifiedName("std", ["shared_ptr", "unique_ptr"]) }
|
||||
UniqueOrSharedPtr() { this.hasQualifiedName(["std", "bsl"], ["shared_ptr", "unique_ptr"]) }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `std::make_shared` and `std::make_unique` template functions.
|
||||
*/
|
||||
private class MakeUniqueOrShared extends TaintFunction {
|
||||
MakeUniqueOrShared() { this.hasQualifiedName("std", ["make_shared", "make_unique"]) }
|
||||
MakeUniqueOrShared() { this.hasQualifiedName(["bsl", "std"], ["make_shared", "make_unique"]) }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
// Exclude the specializations of `std::make_shared` and `std::make_unique` that allocate arrays
|
||||
|
||||
@@ -5,6 +5,41 @@
|
||||
import semmle.code.cpp.models.interfaces.Taint
|
||||
import semmle.code.cpp.models.interfaces.Iterator
|
||||
|
||||
/**
|
||||
* The `std::array` template class.
|
||||
*/
|
||||
private class Array extends Class {
|
||||
Array() { this.hasQualifiedName(["std", "bsl"], "array") }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `std::deque` template class.
|
||||
*/
|
||||
private class Deque extends Class {
|
||||
Deque() { this.hasQualifiedName(["std", "bsl"], "deque") }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `std::forward_list` template class.
|
||||
*/
|
||||
private class ForwardList extends Class {
|
||||
ForwardList() { this.hasQualifiedName(["std", "bsl"], "forward_list") }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `std::list` template class.
|
||||
*/
|
||||
private class List extends Class {
|
||||
List() { this.hasQualifiedName(["std", "bsl"], "list") }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `std::vector` template class.
|
||||
*/
|
||||
private class Vector extends Class {
|
||||
Vector() { this.hasQualifiedName(["std", "bsl"], "vector") }
|
||||
}
|
||||
|
||||
/**
|
||||
* Additional model for standard container constructors that reference the
|
||||
* value type of the container (that is, the `T` in `std::vector<T>`). For
|
||||
@@ -15,7 +50,10 @@ import semmle.code.cpp.models.interfaces.Iterator
|
||||
*/
|
||||
private class StdSequenceContainerConstructor extends Constructor, TaintFunction {
|
||||
StdSequenceContainerConstructor() {
|
||||
this.getDeclaringType().hasQualifiedName("std", ["vector", "deque", "list", "forward_list"])
|
||||
this.getDeclaringType() instanceof Vector or
|
||||
this.getDeclaringType() instanceof Deque or
|
||||
this.getDeclaringType() instanceof List or
|
||||
this.getDeclaringType() instanceof ForwardList
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -50,7 +88,10 @@ private class StdSequenceContainerConstructor extends Constructor, TaintFunction
|
||||
* The standard container function `data`.
|
||||
*/
|
||||
private class StdSequenceContainerData extends TaintFunction {
|
||||
StdSequenceContainerData() { this.hasQualifiedName("std", ["array", "vector"], "data") }
|
||||
StdSequenceContainerData() {
|
||||
this.getClassAndName("data") instanceof Array or
|
||||
this.getClassAndName("data") instanceof Vector
|
||||
}
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
// flow from container itself (qualifier) to return value
|
||||
@@ -69,8 +110,10 @@ private class StdSequenceContainerData extends TaintFunction {
|
||||
*/
|
||||
private class StdSequenceContainerPush extends TaintFunction {
|
||||
StdSequenceContainerPush() {
|
||||
this.hasQualifiedName("std", ["vector", "deque", "list"], "push_back") or
|
||||
this.hasQualifiedName("std", ["deque", "list", "forward_list"], "push_front")
|
||||
this.getClassAndName("push_back") instanceof Vector or
|
||||
this.getClassAndName(["push_back", "push_front"]) instanceof Deque or
|
||||
this.getClassAndName("push_front") instanceof ForwardList or
|
||||
this.getClassAndName(["push_back", "push_front"]) instanceof List
|
||||
}
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
@@ -85,8 +128,11 @@ private class StdSequenceContainerPush extends TaintFunction {
|
||||
*/
|
||||
private class StdSequenceContainerFrontBack extends TaintFunction {
|
||||
StdSequenceContainerFrontBack() {
|
||||
this.hasQualifiedName("std", ["array", "vector", "deque", "list", "forward_list"], "front") or
|
||||
this.hasQualifiedName("std", ["array", "vector", "deque", "list"], "back")
|
||||
this.getClassAndName(["front", "back"]) instanceof Array or
|
||||
this.getClassAndName(["front", "back"]) instanceof Deque or
|
||||
this.getClassAndName("front") instanceof ForwardList or
|
||||
this.getClassAndName(["front", "back"]) instanceof List or
|
||||
this.getClassAndName(["front", "back"]) instanceof Vector
|
||||
}
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
@@ -101,8 +147,10 @@ private class StdSequenceContainerFrontBack extends TaintFunction {
|
||||
*/
|
||||
private class StdSequenceContainerInsert extends TaintFunction {
|
||||
StdSequenceContainerInsert() {
|
||||
this.hasQualifiedName("std", ["vector", "deque", "list"], "insert") or
|
||||
this.hasQualifiedName("std", "forward_list", "insert_after")
|
||||
this.getClassAndName("insert") instanceof Deque or
|
||||
this.getClassAndName("insert") instanceof List or
|
||||
this.getClassAndName("insert") instanceof Vector or
|
||||
this.getClassAndName("insert_after") instanceof ForwardList
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -138,7 +186,10 @@ private class StdSequenceContainerInsert extends TaintFunction {
|
||||
*/
|
||||
private class StdSequenceContainerAssign extends TaintFunction {
|
||||
StdSequenceContainerAssign() {
|
||||
this.hasQualifiedName("std", ["vector", "deque", "list", "forward_list"], "assign")
|
||||
this.getClassAndName("assign") instanceof Deque or
|
||||
this.getClassAndName("assign") instanceof ForwardList or
|
||||
this.getClassAndName("assign") instanceof List or
|
||||
this.getClassAndName("assign") instanceof Vector
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -170,7 +221,9 @@ private class StdSequenceContainerAssign extends TaintFunction {
|
||||
*/
|
||||
private class StdSequenceContainerAt extends TaintFunction {
|
||||
StdSequenceContainerAt() {
|
||||
this.hasQualifiedName("std", ["vector", "array", "deque"], ["at", "operator[]"])
|
||||
this.getClassAndName(["at", "operator[]"]) instanceof Array or
|
||||
this.getClassAndName(["at", "operator[]"]) instanceof Deque or
|
||||
this.getClassAndName(["at", "operator[]"]) instanceof Vector
|
||||
}
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
@@ -188,7 +241,7 @@ private class StdSequenceContainerAt extends TaintFunction {
|
||||
* The standard vector `emplace` function.
|
||||
*/
|
||||
class StdVectorEmplace extends TaintFunction {
|
||||
StdVectorEmplace() { this.hasQualifiedName("std", "vector", "emplace") }
|
||||
StdVectorEmplace() { this.getClassAndName("emplace") instanceof Vector }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
// flow from any parameter except the position iterator to qualifier and return value
|
||||
@@ -205,7 +258,7 @@ class StdVectorEmplace extends TaintFunction {
|
||||
* The standard vector `emplace_back` function.
|
||||
*/
|
||||
class StdVectorEmplaceBack extends TaintFunction {
|
||||
StdVectorEmplaceBack() { this.hasQualifiedName("std", "vector", "emplace_back") }
|
||||
StdVectorEmplaceBack() { this.getClassAndName("emplace_back") instanceof Vector }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
// flow from any parameter to qualifier
|
||||
|
||||
@@ -5,14 +5,18 @@
|
||||
import semmle.code.cpp.models.interfaces.Taint
|
||||
import semmle.code.cpp.models.interfaces.Iterator
|
||||
|
||||
/**
|
||||
* The `std::map` and `std::unordered_map` template classes.
|
||||
*/
|
||||
private class MapOrUnorderedMap extends Class {
|
||||
MapOrUnorderedMap() { this.hasQualifiedName(["std", "bsl"], ["map", "unordered_map"]) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Additional model for map constructors using iterator inputs.
|
||||
*/
|
||||
private class StdMapConstructor extends Constructor, TaintFunction {
|
||||
StdMapConstructor() {
|
||||
this.hasQualifiedName("std", "map", "map") or
|
||||
this.hasQualifiedName("std", "unordered_map", "unordered_map")
|
||||
}
|
||||
StdMapConstructor() { this.getDeclaringType() instanceof MapOrUnorderedMap }
|
||||
|
||||
/**
|
||||
* Gets the index of a parameter to this function that is an iterator.
|
||||
@@ -37,7 +41,7 @@ private class StdMapConstructor extends Constructor, TaintFunction {
|
||||
*/
|
||||
private class StdMapInsert extends TaintFunction {
|
||||
StdMapInsert() {
|
||||
this.hasQualifiedName("std", ["map", "unordered_map"], ["insert", "insert_or_assign"])
|
||||
this.getClassAndName(["insert", "insert_or_assign"]) instanceof MapOrUnorderedMap
|
||||
}
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
@@ -55,9 +59,7 @@ private class StdMapInsert extends TaintFunction {
|
||||
* The standard map `emplace` and `emplace_hint` functions.
|
||||
*/
|
||||
private class StdMapEmplace extends TaintFunction {
|
||||
StdMapEmplace() {
|
||||
this.hasQualifiedName("std", ["map", "unordered_map"], ["emplace", "emplace_hint"])
|
||||
}
|
||||
StdMapEmplace() { this.getClassAndName(["emplace", "emplace_hint"]) instanceof MapOrUnorderedMap }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
// flow from the last parameter (which may be the value part used to
|
||||
@@ -79,7 +81,7 @@ private class StdMapEmplace extends TaintFunction {
|
||||
* The standard map `try_emplace` function.
|
||||
*/
|
||||
private class StdMapTryEmplace extends TaintFunction {
|
||||
StdMapTryEmplace() { this.hasQualifiedName("std", ["map", "unordered_map"], "try_emplace") }
|
||||
StdMapTryEmplace() { this.getClassAndName("try_emplace") instanceof MapOrUnorderedMap }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
// flow from any parameter apart from the key to qualifier and return value
|
||||
@@ -106,7 +108,7 @@ private class StdMapTryEmplace extends TaintFunction {
|
||||
* The standard map `merge` function.
|
||||
*/
|
||||
private class StdMapMerge extends TaintFunction {
|
||||
StdMapMerge() { this.hasQualifiedName("std", ["map", "unordered_map"], "merge") }
|
||||
StdMapMerge() { this.getClassAndName("merge") instanceof MapOrUnorderedMap }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
// container1.merge(container2)
|
||||
@@ -119,7 +121,7 @@ private class StdMapMerge extends TaintFunction {
|
||||
* The standard map functions `at` and `operator[]`.
|
||||
*/
|
||||
private class StdMapAt extends TaintFunction {
|
||||
StdMapAt() { this.hasQualifiedName("std", ["map", "unordered_map"], ["at", "operator[]"]) }
|
||||
StdMapAt() { this.getClassAndName(["at", "operator[]"]) instanceof MapOrUnorderedMap }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
// flow from qualifier to referenced return value
|
||||
@@ -136,7 +138,7 @@ private class StdMapAt extends TaintFunction {
|
||||
* The standard map `find` function.
|
||||
*/
|
||||
private class StdMapFind extends TaintFunction {
|
||||
StdMapFind() { this.hasQualifiedName("std", ["map", "unordered_map"], "find") }
|
||||
StdMapFind() { this.getClassAndName("find") instanceof MapOrUnorderedMap }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
input.isQualifierObject() and
|
||||
@@ -148,7 +150,7 @@ private class StdMapFind extends TaintFunction {
|
||||
* The standard map `erase` function.
|
||||
*/
|
||||
private class StdMapErase extends TaintFunction {
|
||||
StdMapErase() { this.hasQualifiedName("std", ["map", "unordered_map"], "erase") }
|
||||
StdMapErase() { this.getClassAndName("erase") instanceof MapOrUnorderedMap }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
// flow from qualifier to iterator return value
|
||||
@@ -163,8 +165,7 @@ private class StdMapErase extends TaintFunction {
|
||||
*/
|
||||
private class StdMapEqualRange extends TaintFunction {
|
||||
StdMapEqualRange() {
|
||||
this.hasQualifiedName("std", ["map", "unordered_map"],
|
||||
["lower_bound", "upper_bound", "equal_range"])
|
||||
this.getClassAndName(["lower_bound", "upper_bound", "equal_range"]) instanceof MapOrUnorderedMap
|
||||
}
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
|
||||
@@ -7,10 +7,16 @@ import semmle.code.cpp.models.interfaces.Taint
|
||||
/**
|
||||
* An instantiation of `std::pair<T1, T2>`.
|
||||
*/
|
||||
class StdPairClass extends ClassTemplateInstantiation {
|
||||
StdPairClass() { getTemplate().hasQualifiedName("std", "pair") }
|
||||
private class StdPair extends ClassTemplateInstantiation {
|
||||
StdPair() { this.hasQualifiedName(["std", "bsl"], "pair") }
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: This is now called `StdPair` and is a private part of the
|
||||
* library implementation.
|
||||
*/
|
||||
deprecated class StdPairClass = StdPair;
|
||||
|
||||
/**
|
||||
* Any of the single-parameter constructors of `std::pair` that takes a reference to an
|
||||
* instantiation of `std::pair`. These constructors allow conversion between pair types when the
|
||||
@@ -18,9 +24,9 @@ class StdPairClass extends ClassTemplateInstantiation {
|
||||
*/
|
||||
class StdPairCopyishConstructor extends Constructor, TaintFunction {
|
||||
StdPairCopyishConstructor() {
|
||||
this.getDeclaringType() instanceof StdPairClass and
|
||||
this.getDeclaringType() instanceof StdPair and
|
||||
this.getNumberOfParameters() = 1 and
|
||||
this.getParameter(0).getUnspecifiedType().(ReferenceType).getBaseType() instanceof StdPairClass
|
||||
this.getParameter(0).getUnspecifiedType().(ReferenceType).getBaseType() instanceof StdPair
|
||||
}
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
@@ -38,7 +44,7 @@ class StdPairCopyishConstructor extends Constructor, TaintFunction {
|
||||
* Additional model for `std::pair` constructors.
|
||||
*/
|
||||
private class StdPairConstructor extends Constructor, TaintFunction {
|
||||
StdPairConstructor() { this.hasQualifiedName("std", "pair", "pair") }
|
||||
StdPairConstructor() { this.getDeclaringType() instanceof StdPair }
|
||||
|
||||
/**
|
||||
* Gets the index of a parameter to this function that is a reference to
|
||||
|
||||
@@ -5,14 +5,18 @@
|
||||
import semmle.code.cpp.models.interfaces.Taint
|
||||
import semmle.code.cpp.models.interfaces.Iterator
|
||||
|
||||
/**
|
||||
* An instantiation of `std::set` or `std::unordered_set`.
|
||||
*/
|
||||
private class StdSet extends ClassTemplateInstantiation {
|
||||
StdSet() { this.hasQualifiedName(["std", "bsl"], ["set", "unordered_set"]) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Additional model for set constructors using iterator inputs.
|
||||
*/
|
||||
private class StdSetConstructor extends Constructor, TaintFunction {
|
||||
StdSetConstructor() {
|
||||
this.hasQualifiedName("std", "set", "set") or
|
||||
this.hasQualifiedName("std", "unordered_set", "unordered_set")
|
||||
}
|
||||
StdSetConstructor() { this.getDeclaringType() instanceof StdSet }
|
||||
|
||||
/**
|
||||
* Gets the index of a parameter to this function that is an iterator.
|
||||
@@ -36,7 +40,7 @@ private class StdSetConstructor extends Constructor, TaintFunction {
|
||||
* The standard set `insert` and `insert_or_assign` functions.
|
||||
*/
|
||||
private class StdSetInsert extends TaintFunction {
|
||||
StdSetInsert() { this.hasQualifiedName("std", ["set", "unordered_set"], "insert") }
|
||||
StdSetInsert() { this.getClassAndName("insert") instanceof StdSet }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
// flow from last parameter to qualifier and return value
|
||||
@@ -53,9 +57,7 @@ private class StdSetInsert extends TaintFunction {
|
||||
* The standard set `emplace` and `emplace_hint` functions.
|
||||
*/
|
||||
private class StdSetEmplace extends TaintFunction {
|
||||
StdSetEmplace() {
|
||||
this.hasQualifiedName("std", ["set", "unordered_set"], ["emplace", "emplace_hint"])
|
||||
}
|
||||
StdSetEmplace() { this.getClassAndName(["emplace", "emplace_hint"]) instanceof StdSet }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
// flow from any parameter to qualifier and return value
|
||||
@@ -76,7 +78,7 @@ private class StdSetEmplace extends TaintFunction {
|
||||
* The standard set `merge` function.
|
||||
*/
|
||||
private class StdSetMerge extends TaintFunction {
|
||||
StdSetMerge() { this.hasQualifiedName("std", ["set", "unordered_set"], "merge") }
|
||||
StdSetMerge() { this.getClassAndName("merge") instanceof StdSet }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
// container1.merge(container2)
|
||||
@@ -89,7 +91,7 @@ private class StdSetMerge extends TaintFunction {
|
||||
* The standard set `find` function.
|
||||
*/
|
||||
private class StdSetFind extends TaintFunction {
|
||||
StdSetFind() { this.hasQualifiedName("std", ["set", "unordered_set"], "find") }
|
||||
StdSetFind() { this.getClassAndName("find") instanceof StdSet }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
input.isQualifierObject() and
|
||||
@@ -101,7 +103,7 @@ private class StdSetFind extends TaintFunction {
|
||||
* The standard set `erase` function.
|
||||
*/
|
||||
private class StdSetErase extends TaintFunction {
|
||||
StdSetErase() { this.hasQualifiedName("std", ["set", "unordered_set"], "erase") }
|
||||
StdSetErase() { this.getClassAndName("erase") instanceof StdSet }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
// flow from qualifier to iterator return value
|
||||
@@ -116,8 +118,7 @@ private class StdSetErase extends TaintFunction {
|
||||
*/
|
||||
private class StdSetEqualRange extends TaintFunction {
|
||||
StdSetEqualRange() {
|
||||
this.hasQualifiedName("std", ["set", "unordered_set"],
|
||||
["lower_bound", "upper_bound", "equal_range"])
|
||||
this.getClassAndName(["lower_bound", "upper_bound", "equal_range"]) instanceof StdSet
|
||||
}
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
|
||||
@@ -12,7 +12,7 @@ import semmle.code.cpp.models.interfaces.DataFlow
|
||||
* The `std::basic_string` template class instantiations.
|
||||
*/
|
||||
private class StdBasicString extends ClassTemplateInstantiation {
|
||||
StdBasicString() { this.hasQualifiedName("std", "basic_string") }
|
||||
StdBasicString() { this.hasQualifiedName(["std", "bsl"], "basic_string") }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -127,7 +127,7 @@ private class StdStringFrontBack extends TaintFunction {
|
||||
*/
|
||||
private class StdStringPlus extends TaintFunction {
|
||||
StdStringPlus() {
|
||||
this.hasQualifiedName("std", "operator+") and
|
||||
this.hasQualifiedName(["std", "bsl"], "operator+") and
|
||||
this.getUnspecifiedType() instanceof StdBasicString
|
||||
}
|
||||
|
||||
@@ -252,13 +252,6 @@ private class StdStringSubstr extends TaintFunction {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The `std::basic_stringstream` template class instantiations.
|
||||
*/
|
||||
private class StdBasicStringStream extends ClassTemplateInstantiation {
|
||||
StdBasicStringStream() { this.hasQualifiedName("std", "basic_stringstream") }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `std::string` functions `at` and `operator[]`.
|
||||
*/
|
||||
@@ -280,7 +273,7 @@ private class StdStringAt extends TaintFunction {
|
||||
* The `std::basic_istream` template class instantiations.
|
||||
*/
|
||||
private class StdBasicIStream extends ClassTemplateInstantiation {
|
||||
StdBasicIStream() { this.hasQualifiedName("std", "basic_istream") }
|
||||
StdBasicIStream() { this.hasQualifiedName(["std", "bsl"], "basic_istream") }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -314,7 +307,7 @@ private class StdIStreamIn extends DataFlowFunction, TaintFunction {
|
||||
*/
|
||||
private class StdIStreamInNonMember extends DataFlowFunction, TaintFunction {
|
||||
StdIStreamInNonMember() {
|
||||
this.hasQualifiedName("std", "operator>>") and
|
||||
this.hasQualifiedName(["std", "bsl"], "operator>>") and
|
||||
this.getUnspecifiedType().(ReferenceType).getBaseType() instanceof StdBasicIStream
|
||||
}
|
||||
|
||||
@@ -462,7 +455,7 @@ private class StdIStreamGetLine extends DataFlowFunction, TaintFunction {
|
||||
* The (non-member) function `std::getline`.
|
||||
*/
|
||||
private class StdGetLine extends DataFlowFunction, TaintFunction {
|
||||
StdGetLine() { this.hasQualifiedName("std", "getline") }
|
||||
StdGetLine() { this.hasQualifiedName(["std", "bsl"], "getline") }
|
||||
|
||||
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
|
||||
// flow from first parameter to return value
|
||||
@@ -488,7 +481,7 @@ private class StdGetLine extends DataFlowFunction, TaintFunction {
|
||||
* The `std::basic_ostream` template class instantiations.
|
||||
*/
|
||||
private class StdBasicOStream extends ClassTemplateInstantiation {
|
||||
StdBasicOStream() { this.hasQualifiedName("std", "basic_ostream") }
|
||||
StdBasicOStream() { this.hasQualifiedName(["std", "bsl"], "basic_ostream") }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -535,7 +528,7 @@ private class StdOStreamOut extends DataFlowFunction, TaintFunction {
|
||||
*/
|
||||
private class StdOStreamOutNonMember extends DataFlowFunction, TaintFunction {
|
||||
StdOStreamOutNonMember() {
|
||||
this.hasQualifiedName("std", "operator<<") and
|
||||
this.hasQualifiedName(["std", "bsl"], "operator<<") and
|
||||
this.getUnspecifiedType().(ReferenceType).getBaseType() instanceof StdBasicOStream
|
||||
}
|
||||
|
||||
@@ -563,6 +556,13 @@ private class StdOStreamOutNonMember extends DataFlowFunction, TaintFunction {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The `std::basic_stringstream` template class instantiations.
|
||||
*/
|
||||
private class StdBasicStringStream extends ClassTemplateInstantiation {
|
||||
StdBasicStringStream() { this.hasQualifiedName(["std", "bsl"], "basic_stringstream") }
|
||||
}
|
||||
|
||||
/**
|
||||
* Additional model for `std::stringstream` constructors that take a string
|
||||
* input parameter.
|
||||
@@ -609,7 +609,7 @@ private class StdStringStreamStr extends TaintFunction {
|
||||
* The `std::basic_ios` template class instantiations.
|
||||
*/
|
||||
private class StdBasicIOS extends ClassTemplateInstantiation {
|
||||
StdBasicIOS() { this.hasQualifiedName("std", "basic_ios") }
|
||||
StdBasicIOS() { this.hasQualifiedName(["std", "bsl"], "basic_ios") }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,7 +13,7 @@ import semmle.code.cpp.models.interfaces.SideEffect
|
||||
*/
|
||||
class StrcatFunction extends TaintFunction, DataFlowFunction, ArrayFunction, SideEffectFunction {
|
||||
StrcatFunction() {
|
||||
this.hasGlobalOrStdName([
|
||||
this.hasGlobalOrStdOrBslName([
|
||||
"strcat", // strcat(dst, src)
|
||||
"strncat", // strncat(dst, src, max_amount)
|
||||
"wcscat", // wcscat(dst, src)
|
||||
|
||||
@@ -13,7 +13,7 @@ import semmle.code.cpp.models.interfaces.SideEffect
|
||||
*/
|
||||
class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction, SideEffectFunction {
|
||||
StrcpyFunction() {
|
||||
this.hasGlobalOrStdName([
|
||||
this.hasGlobalOrStdOrBslName([
|
||||
"strcpy", // strcpy(dst, src)
|
||||
"wcscpy", // wcscpy(dst, src)
|
||||
"strncpy", // strncpy(dst, src, max_amount)
|
||||
|
||||
@@ -15,7 +15,7 @@ import semmle.code.cpp.models.interfaces.Taint
|
||||
*/
|
||||
private class Strtok extends ArrayFunction, AliasFunction, TaintFunction, SideEffectFunction {
|
||||
Strtok() {
|
||||
this.hasGlobalOrStdName("strtok") or
|
||||
this.hasGlobalOrStdOrBslName("strtok") or
|
||||
this.hasGlobalName(["strtok_r", "_strtok_l", "wcstok", "_wcstok_l", "_mbstok", "_mbstok_l"])
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import semmle.code.cpp.models.interfaces.Alias
|
||||
* ```
|
||||
*/
|
||||
private class Swap extends DataFlowFunction {
|
||||
Swap() { this.hasQualifiedName("std", "swap") }
|
||||
Swap() { this.hasQualifiedName(["std", "bsl"], "swap") }
|
||||
|
||||
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
|
||||
input.isParameterDeref(0) and
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/**
|
||||
* Provides a class for modeling functions that return data from potentially untrusted sources. To use
|
||||
* this QL library, create a QL class extending `DataFlowFunction` with a
|
||||
* Provides classes for modeling functions that return data from (or send data to) potentially untrusted
|
||||
* sources. To use this QL library, create a QL class extending `DataFlowFunction` with a
|
||||
* characteristic predicate that selects the function or set of functions you
|
||||
* are modeling. Within that class, override the predicates provided by
|
||||
* `RemoteFlowFunction` to match the flow within that function.
|
||||
* `RemoteFlowSourceFunction` or `RemoteFlowSinkFunction` to match the flow within that function.
|
||||
*/
|
||||
|
||||
import cpp
|
||||
@@ -13,19 +13,42 @@ import semmle.code.cpp.models.Models
|
||||
/**
|
||||
* A library function that returns data that may be read from a network connection.
|
||||
*/
|
||||
abstract class RemoteFlowFunction extends Function {
|
||||
abstract class RemoteFlowSourceFunction extends Function {
|
||||
/**
|
||||
* Holds if remote data described by `description` flows from `output` of a call to this function.
|
||||
*/
|
||||
abstract predicate hasRemoteFlowSource(FunctionOutput output, string description);
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `RemoteFlowSourceFunction` instead.
|
||||
*
|
||||
* A library function that returns data that may be read from a network connection.
|
||||
*/
|
||||
deprecated class RemoteFlowFunction = RemoteFlowSourceFunction;
|
||||
|
||||
/**
|
||||
* A library function that returns data that is directly controlled by a user.
|
||||
*/
|
||||
abstract class LocalFlowFunction extends Function {
|
||||
abstract class LocalFlowSourceFunction extends Function {
|
||||
/**
|
||||
* Holds if data described by `description` flows from `output` of a call to this function.
|
||||
*/
|
||||
abstract predicate hasLocalFlowSource(FunctionOutput output, string description);
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `LocalFlowSourceFunction` instead.
|
||||
*
|
||||
* A library function that returns data that is directly controlled by a user.
|
||||
*/
|
||||
deprecated class LocalFlowFunction = LocalFlowSourceFunction;
|
||||
|
||||
/** A library function that sends data over a network connection. */
|
||||
abstract class RemoteFlowSinkFunction extends Function {
|
||||
/**
|
||||
* Holds if data described by `description` flows into `input` to a call to this function, and is then
|
||||
* send over a network connection.
|
||||
*/
|
||||
abstract predicate hasRemoteFlowSink(FunctionInput input, string description);
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ private class RemoteReturnSource extends RemoteFlowSource {
|
||||
string sourceType;
|
||||
|
||||
RemoteReturnSource() {
|
||||
exists(RemoteFlowFunction func, CallInstruction instr, FunctionOutput output |
|
||||
exists(RemoteFlowSourceFunction func, CallInstruction instr, FunctionOutput output |
|
||||
asInstruction() = instr and
|
||||
instr.getStaticCallTarget() = func and
|
||||
func.hasRemoteFlowSource(output, sourceType) and
|
||||
@@ -42,7 +42,7 @@ private class RemoteParameterSource extends RemoteFlowSource {
|
||||
string sourceType;
|
||||
|
||||
RemoteParameterSource() {
|
||||
exists(RemoteFlowFunction func, WriteSideEffectInstruction instr, FunctionOutput output |
|
||||
exists(RemoteFlowSourceFunction func, WriteSideEffectInstruction instr, FunctionOutput output |
|
||||
asInstruction() = instr and
|
||||
instr.getPrimaryInstruction().(CallInstruction).getStaticCallTarget() = func and
|
||||
func.hasRemoteFlowSource(output, sourceType) and
|
||||
@@ -57,7 +57,7 @@ private class LocalReturnSource extends LocalFlowSource {
|
||||
string sourceType;
|
||||
|
||||
LocalReturnSource() {
|
||||
exists(LocalFlowFunction func, CallInstruction instr, FunctionOutput output |
|
||||
exists(LocalFlowSourceFunction func, CallInstruction instr, FunctionOutput output |
|
||||
asInstruction() = instr and
|
||||
instr.getStaticCallTarget() = func and
|
||||
func.hasLocalFlowSource(output, sourceType) and
|
||||
@@ -76,7 +76,7 @@ private class LocalParameterSource extends LocalFlowSource {
|
||||
string sourceType;
|
||||
|
||||
LocalParameterSource() {
|
||||
exists(LocalFlowFunction func, WriteSideEffectInstruction instr, FunctionOutput output |
|
||||
exists(LocalFlowSourceFunction func, WriteSideEffectInstruction instr, FunctionOutput output |
|
||||
asInstruction() = instr and
|
||||
instr.getPrimaryInstruction().(CallInstruction).getStaticCallTarget() = func and
|
||||
func.hasLocalFlowSource(output, sourceType) and
|
||||
@@ -98,3 +98,31 @@ private class ArgvSource extends LocalFlowSource {
|
||||
|
||||
override string getSourceType() { result = "a command-line argument" }
|
||||
}
|
||||
|
||||
/** A remote data flow sink. */
|
||||
abstract class RemoteFlowSink extends DataFlow::Node {
|
||||
/** Gets a string that describes the type of this flow sink. */
|
||||
abstract string getSinkType();
|
||||
}
|
||||
|
||||
private class RemoteParameterSink extends RemoteFlowSink {
|
||||
string sourceType;
|
||||
|
||||
RemoteParameterSink() {
|
||||
exists(RemoteFlowSinkFunction func, FunctionInput input, CallInstruction call, int index |
|
||||
func.hasRemoteFlowSink(input, sourceType) and call.getStaticCallTarget() = func
|
||||
|
|
||||
exists(ReadSideEffectInstruction read |
|
||||
call = read.getPrimaryInstruction() and
|
||||
read.getIndex() = index and
|
||||
this.asOperand() = read.getSideEffectOperand() and
|
||||
input.isParameterDerefOrQualifierObject(index)
|
||||
)
|
||||
or
|
||||
input.isParameterOrQualifierAddress(index) and
|
||||
this.asOperand() = call.getArgumentOperand(index)
|
||||
)
|
||||
}
|
||||
|
||||
override string getSinkType() { result = sourceType }
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import semmle.code.cpp.exprs.Expr
|
||||
import semmle.code.cpp.commons.Environment
|
||||
import semmle.code.cpp.security.SecurityOptions
|
||||
import semmle.code.cpp.models.interfaces.FlowSource
|
||||
|
||||
/**
|
||||
* Extend this class to customize the security queries for
|
||||
@@ -59,14 +60,14 @@ class SecurityOptions extends string {
|
||||
or
|
||||
functionCall.getTarget().hasGlobalName(fname) and
|
||||
exists(functionCall.getArgument(arg)) and
|
||||
(
|
||||
fname = ["read", "recv", "recvmsg"] and arg = 1
|
||||
or
|
||||
fname = "getaddrinfo" and arg = 3
|
||||
or
|
||||
fname = "recvfrom" and
|
||||
(arg = 1 or arg = 4 or arg = 5)
|
||||
fname = "getaddrinfo" and
|
||||
arg = 3
|
||||
)
|
||||
or
|
||||
exists(RemoteFlowSourceFunction remote, FunctionOutput output |
|
||||
functionCall.getTarget() = remote and
|
||||
output.isParameterDerefOrQualifierObject(arg) and
|
||||
remote.hasRemoteFlowSource(output, _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -81,6 +82,12 @@ class SecurityOptions extends string {
|
||||
userInputReturn(fname)
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(RemoteFlowSourceFunction remote, FunctionOutput output |
|
||||
functionCall.getTarget() = remote and
|
||||
(output.isReturnValue() or output.isReturnValueDeref()) and
|
||||
remote.hasRemoteFlowSource(output, _)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# C/C++ CodeQL tests
|
||||
|
||||
This document provides additional information about the C/C++ CodeQL Tests located in `cpp/ql/test`. See [Contributing to CodeQL](/CONTRIBUTING.md) for general information about contributing to this repository.
|
||||
This document provides additional information about the C/C++ CodeQL tests located in `cpp/ql/test`. The principles under "Copying code", below, also apply to any other C/C++ code in this repository, such as examples linked from query `.qhelp` files in `cpp/ql/src`. For more general information about contributing to this repository, see [Contributing to CodeQL](/CONTRIBUTING.md).
|
||||
|
||||
The tests can be run through Visual Studio Code. Advanced users may also use the `codeql test run` command.
|
||||
|
||||
|
||||
@@ -216,3 +216,46 @@ void test_pointers2()
|
||||
sink(ptr4); // clean
|
||||
sink(*ptr4); // $ MISSING: ast,ir
|
||||
}
|
||||
|
||||
// --- recv ---
|
||||
|
||||
int recv(int s, char* buf, int len, int flags);
|
||||
|
||||
void test_recv() {
|
||||
char buffer[1024];
|
||||
recv(0, buffer, sizeof(buffer), 0);
|
||||
sink(buffer); // $ ast,ir
|
||||
sink(*buffer); // $ ast,ir
|
||||
}
|
||||
|
||||
// --- send and related functions ---
|
||||
|
||||
int send(int, const void*, int, int);
|
||||
|
||||
void test_send(char* buffer, int length) {
|
||||
send(0, buffer, length, 0); // $ remote
|
||||
}
|
||||
|
||||
struct iovec {
|
||||
void *iov_base;
|
||||
unsigned iov_len;
|
||||
};
|
||||
|
||||
int readv(int, const struct iovec*, int);
|
||||
int writev(int, const struct iovec*, int);
|
||||
|
||||
void sink(const iovec* iovs);
|
||||
void sink(iovec);
|
||||
|
||||
int test_readv_and_writev(iovec* iovs) {
|
||||
readv(0, iovs, 16);
|
||||
sink(iovs); // $ast,ir
|
||||
sink(iovs[0]); // $ast MISSING: ir
|
||||
sink(*iovs); // $ast MISSING: ir
|
||||
|
||||
char* p = (char*)iovs[1].iov_base;
|
||||
sink(p); // $ MISSING: ast,ir
|
||||
sink(*p); // $ MISSING: ast,ir
|
||||
|
||||
writev(0, iovs, 16); // $ remote
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
/** This tests that we are able to detect remote flow sinks. */
|
||||
|
||||
import cpp
|
||||
import TestUtilities.InlineExpectationsTest
|
||||
import semmle.code.cpp.security.FlowSources
|
||||
|
||||
class RemoteFlowSinkTest extends InlineExpectationsTest {
|
||||
RemoteFlowSinkTest() { this = "RemoteFlowSinkTest" }
|
||||
|
||||
override string getARelevantTag() { result = "remote" }
|
||||
|
||||
override predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
tag = "remote" and
|
||||
value = "" and
|
||||
exists(RemoteFlowSink node |
|
||||
location = node.getLocation() and
|
||||
element = node.toString()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -36,9 +36,6 @@ argHasPostUpdate
|
||||
| arrays.cpp:10:8:10:15 | * ... | ArgumentNode is missing PostUpdateNode. |
|
||||
| arrays.cpp:16:8:16:13 | access to array | ArgumentNode is missing PostUpdateNode. |
|
||||
| arrays.cpp:17:8:17:13 | access to array | ArgumentNode is missing PostUpdateNode. |
|
||||
| by_reference.cpp:51:8:51:8 | s | ArgumentNode is missing PostUpdateNode. |
|
||||
| by_reference.cpp:57:8:57:8 | s | ArgumentNode is missing PostUpdateNode. |
|
||||
| by_reference.cpp:63:8:63:8 | s | ArgumentNode is missing PostUpdateNode. |
|
||||
postWithInFlow
|
||||
| A.cpp:25:13:25:13 | c [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| A.cpp:27:28:27:28 | c [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
|
||||
@@ -227,14 +227,18 @@
|
||||
| by_reference.cpp:20:23:20:27 | value | AST only |
|
||||
| by_reference.cpp:24:19:24:22 | this | AST only |
|
||||
| by_reference.cpp:24:25:24:29 | value | AST only |
|
||||
| by_reference.cpp:40:12:40:15 | this | AST only |
|
||||
| by_reference.cpp:50:3:50:3 | s | AST only |
|
||||
| by_reference.cpp:50:17:50:26 | call to user_input | AST only |
|
||||
| by_reference.cpp:51:8:51:8 | s | AST only |
|
||||
| by_reference.cpp:51:10:51:20 | call to getDirectly | AST only |
|
||||
| by_reference.cpp:56:3:56:3 | s | AST only |
|
||||
| by_reference.cpp:56:19:56:28 | call to user_input | AST only |
|
||||
| by_reference.cpp:57:8:57:8 | s | AST only |
|
||||
| by_reference.cpp:57:10:57:22 | call to getIndirectly | AST only |
|
||||
| by_reference.cpp:62:3:62:3 | s | AST only |
|
||||
| by_reference.cpp:62:25:62:34 | call to user_input | AST only |
|
||||
| by_reference.cpp:63:8:63:8 | s | AST only |
|
||||
| by_reference.cpp:63:10:63:28 | call to getThroughNonMember | AST only |
|
||||
| by_reference.cpp:68:17:68:18 | & ... | AST only |
|
||||
| by_reference.cpp:68:21:68:30 | call to user_input | AST only |
|
||||
|
||||
@@ -266,14 +266,18 @@
|
||||
| by_reference.cpp:20:23:20:27 | value |
|
||||
| by_reference.cpp:24:19:24:22 | this |
|
||||
| by_reference.cpp:24:25:24:29 | value |
|
||||
| by_reference.cpp:40:12:40:15 | this |
|
||||
| by_reference.cpp:50:3:50:3 | s |
|
||||
| by_reference.cpp:50:17:50:26 | call to user_input |
|
||||
| by_reference.cpp:51:8:51:8 | s |
|
||||
| by_reference.cpp:51:10:51:20 | call to getDirectly |
|
||||
| by_reference.cpp:56:3:56:3 | s |
|
||||
| by_reference.cpp:56:19:56:28 | call to user_input |
|
||||
| by_reference.cpp:57:8:57:8 | s |
|
||||
| by_reference.cpp:57:10:57:22 | call to getIndirectly |
|
||||
| by_reference.cpp:62:3:62:3 | s |
|
||||
| by_reference.cpp:62:25:62:34 | call to user_input |
|
||||
| by_reference.cpp:63:8:63:8 | s |
|
||||
| by_reference.cpp:63:10:63:28 | call to getThroughNonMember |
|
||||
| by_reference.cpp:68:17:68:18 | & ... |
|
||||
| by_reference.cpp:68:21:68:30 | call to user_input |
|
||||
|
||||
24
cpp/ql/test/library-tests/dataflow/taint-tests/bsd.cpp
Normal file
24
cpp/ql/test/library-tests/dataflow/taint-tests/bsd.cpp
Normal file
@@ -0,0 +1,24 @@
|
||||
void sink(...);
|
||||
int source();
|
||||
|
||||
// --- accept ---
|
||||
|
||||
struct sockaddr {
|
||||
unsigned char length;
|
||||
int sa_family;
|
||||
char* sa_data;
|
||||
};
|
||||
|
||||
int accept(int, const sockaddr*, int*);
|
||||
|
||||
void sink(sockaddr);
|
||||
|
||||
void test_accept() {
|
||||
int s = source();
|
||||
sockaddr addr;
|
||||
int size = sizeof(sockaddr);
|
||||
int a = accept(s, &addr, &size);
|
||||
|
||||
sink(a); // $ ast=17:11 SPURIOUS: ast=18:12 MISSING: ir
|
||||
sink(addr); // $ ast MISSING: ir
|
||||
}
|
||||
@@ -135,6 +135,17 @@
|
||||
| arrayassignment.cpp:145:12:145:12 | 5 | arrayassignment.cpp:145:7:145:13 | access to array | TAINT |
|
||||
| arrayassignment.cpp:146:7:146:10 | arr3 | arrayassignment.cpp:146:7:146:13 | access to array | |
|
||||
| arrayassignment.cpp:146:12:146:12 | 5 | arrayassignment.cpp:146:7:146:13 | access to array | TAINT |
|
||||
| bsd.cpp:17:11:17:16 | call to source | bsd.cpp:20:18:20:18 | s | |
|
||||
| bsd.cpp:18:12:18:15 | addr | bsd.cpp:20:22:20:25 | addr | |
|
||||
| bsd.cpp:18:12:18:15 | addr | bsd.cpp:23:8:23:11 | addr | |
|
||||
| bsd.cpp:19:14:19:29 | sizeof(sockaddr) | bsd.cpp:20:29:20:32 | size | |
|
||||
| bsd.cpp:20:11:20:16 | call to accept | bsd.cpp:22:8:22:8 | a | |
|
||||
| bsd.cpp:20:18:20:18 | s | bsd.cpp:20:11:20:16 | call to accept | TAINT |
|
||||
| bsd.cpp:20:21:20:25 | & ... | bsd.cpp:20:11:20:16 | call to accept | TAINT |
|
||||
| bsd.cpp:20:22:20:25 | addr | bsd.cpp:20:11:20:16 | call to accept | TAINT |
|
||||
| bsd.cpp:20:22:20:25 | addr | bsd.cpp:20:21:20:25 | & ... | |
|
||||
| bsd.cpp:20:28:20:32 | ref arg & ... | bsd.cpp:20:29:20:32 | size [inner post update] | |
|
||||
| bsd.cpp:20:29:20:32 | size | bsd.cpp:20:28:20:32 | & ... | |
|
||||
| constructor_delegation.cpp:8:2:8:8 | this | constructor_delegation.cpp:8:20:8:24 | constructor init of field x [pre-this] | |
|
||||
| constructor_delegation.cpp:8:14:8:15 | _x | constructor_delegation.cpp:8:22:8:23 | _x | |
|
||||
| constructor_delegation.cpp:8:22:8:23 | _x | constructor_delegation.cpp:8:20:8:24 | constructor init of field x | TAINT |
|
||||
@@ -796,8 +807,23 @@
|
||||
| map.cpp:146:40:146:41 | ref arg i1 | map.cpp:150:8:150:9 | i1 | |
|
||||
| map.cpp:148:8:148:8 | call to operator* | map.cpp:148:8:148:10 | call to pair | TAINT |
|
||||
| map.cpp:148:9:148:10 | i1 | map.cpp:148:8:148:8 | call to operator* | TAINT |
|
||||
| map.cpp:148:9:148:10 | ref arg i1 | map.cpp:146:24:146:25 | i1 | |
|
||||
| map.cpp:148:9:148:10 | ref arg i1 | map.cpp:146:40:146:41 | i1 | |
|
||||
| map.cpp:148:9:148:10 | ref arg i1 | map.cpp:148:9:148:10 | i1 | |
|
||||
| map.cpp:148:9:148:10 | ref arg i1 | map.cpp:149:8:149:9 | i1 | |
|
||||
| map.cpp:148:9:148:10 | ref arg i1 | map.cpp:150:8:150:9 | i1 | |
|
||||
| map.cpp:149:8:149:9 | i1 | map.cpp:149:10:149:10 | call to operator-> | TAINT |
|
||||
| map.cpp:149:8:149:9 | ref arg i1 | map.cpp:146:24:146:25 | i1 | |
|
||||
| map.cpp:149:8:149:9 | ref arg i1 | map.cpp:146:40:146:41 | i1 | |
|
||||
| map.cpp:149:8:149:9 | ref arg i1 | map.cpp:148:9:148:10 | i1 | |
|
||||
| map.cpp:149:8:149:9 | ref arg i1 | map.cpp:149:8:149:9 | i1 | |
|
||||
| map.cpp:149:8:149:9 | ref arg i1 | map.cpp:150:8:150:9 | i1 | |
|
||||
| map.cpp:150:8:150:9 | i1 | map.cpp:150:10:150:10 | call to operator-> | TAINT |
|
||||
| map.cpp:150:8:150:9 | ref arg i1 | map.cpp:146:24:146:25 | i1 | |
|
||||
| map.cpp:150:8:150:9 | ref arg i1 | map.cpp:146:40:146:41 | i1 | |
|
||||
| map.cpp:150:8:150:9 | ref arg i1 | map.cpp:148:9:148:10 | i1 | |
|
||||
| map.cpp:150:8:150:9 | ref arg i1 | map.cpp:149:8:149:9 | i1 | |
|
||||
| map.cpp:150:8:150:9 | ref arg i1 | map.cpp:150:8:150:9 | i1 | |
|
||||
| map.cpp:152:12:152:13 | m2 | map.cpp:152:15:152:19 | call to begin | TAINT |
|
||||
| map.cpp:152:12:152:13 | ref arg m2 | map.cpp:152:30:152:31 | m2 | |
|
||||
| map.cpp:152:12:152:13 | ref arg m2 | map.cpp:182:7:182:8 | m2 | |
|
||||
@@ -830,8 +856,23 @@
|
||||
| map.cpp:152:40:152:41 | ref arg i2 | map.cpp:156:8:156:9 | i2 | |
|
||||
| map.cpp:154:8:154:8 | call to operator* | map.cpp:154:8:154:10 | call to pair | TAINT |
|
||||
| map.cpp:154:9:154:10 | i2 | map.cpp:154:8:154:8 | call to operator* | TAINT |
|
||||
| map.cpp:154:9:154:10 | ref arg i2 | map.cpp:152:24:152:25 | i2 | |
|
||||
| map.cpp:154:9:154:10 | ref arg i2 | map.cpp:152:40:152:41 | i2 | |
|
||||
| map.cpp:154:9:154:10 | ref arg i2 | map.cpp:154:9:154:10 | i2 | |
|
||||
| map.cpp:154:9:154:10 | ref arg i2 | map.cpp:155:8:155:9 | i2 | |
|
||||
| map.cpp:154:9:154:10 | ref arg i2 | map.cpp:156:8:156:9 | i2 | |
|
||||
| map.cpp:155:8:155:9 | i2 | map.cpp:155:10:155:10 | call to operator-> | TAINT |
|
||||
| map.cpp:155:8:155:9 | ref arg i2 | map.cpp:152:24:152:25 | i2 | |
|
||||
| map.cpp:155:8:155:9 | ref arg i2 | map.cpp:152:40:152:41 | i2 | |
|
||||
| map.cpp:155:8:155:9 | ref arg i2 | map.cpp:154:9:154:10 | i2 | |
|
||||
| map.cpp:155:8:155:9 | ref arg i2 | map.cpp:155:8:155:9 | i2 | |
|
||||
| map.cpp:155:8:155:9 | ref arg i2 | map.cpp:156:8:156:9 | i2 | |
|
||||
| map.cpp:156:8:156:9 | i2 | map.cpp:156:10:156:10 | call to operator-> | TAINT |
|
||||
| map.cpp:156:8:156:9 | ref arg i2 | map.cpp:152:24:152:25 | i2 | |
|
||||
| map.cpp:156:8:156:9 | ref arg i2 | map.cpp:152:40:152:41 | i2 | |
|
||||
| map.cpp:156:8:156:9 | ref arg i2 | map.cpp:154:9:154:10 | i2 | |
|
||||
| map.cpp:156:8:156:9 | ref arg i2 | map.cpp:155:8:155:9 | i2 | |
|
||||
| map.cpp:156:8:156:9 | ref arg i2 | map.cpp:156:8:156:9 | i2 | |
|
||||
| map.cpp:158:12:158:13 | m3 | map.cpp:158:15:158:19 | call to begin | TAINT |
|
||||
| map.cpp:158:12:158:13 | ref arg m3 | map.cpp:158:30:158:31 | m3 | |
|
||||
| map.cpp:158:12:158:13 | ref arg m3 | map.cpp:252:1:252:1 | m3 | |
|
||||
@@ -852,8 +893,23 @@
|
||||
| map.cpp:158:40:158:41 | ref arg i3 | map.cpp:162:8:162:9 | i3 | |
|
||||
| map.cpp:160:8:160:8 | call to operator* | map.cpp:160:8:160:10 | call to pair | TAINT |
|
||||
| map.cpp:160:9:160:10 | i3 | map.cpp:160:8:160:8 | call to operator* | TAINT |
|
||||
| map.cpp:160:9:160:10 | ref arg i3 | map.cpp:158:24:158:25 | i3 | |
|
||||
| map.cpp:160:9:160:10 | ref arg i3 | map.cpp:158:40:158:41 | i3 | |
|
||||
| map.cpp:160:9:160:10 | ref arg i3 | map.cpp:160:9:160:10 | i3 | |
|
||||
| map.cpp:160:9:160:10 | ref arg i3 | map.cpp:161:8:161:9 | i3 | |
|
||||
| map.cpp:160:9:160:10 | ref arg i3 | map.cpp:162:8:162:9 | i3 | |
|
||||
| map.cpp:161:8:161:9 | i3 | map.cpp:161:10:161:10 | call to operator-> | TAINT |
|
||||
| map.cpp:161:8:161:9 | ref arg i3 | map.cpp:158:24:158:25 | i3 | |
|
||||
| map.cpp:161:8:161:9 | ref arg i3 | map.cpp:158:40:158:41 | i3 | |
|
||||
| map.cpp:161:8:161:9 | ref arg i3 | map.cpp:160:9:160:10 | i3 | |
|
||||
| map.cpp:161:8:161:9 | ref arg i3 | map.cpp:161:8:161:9 | i3 | |
|
||||
| map.cpp:161:8:161:9 | ref arg i3 | map.cpp:162:8:162:9 | i3 | |
|
||||
| map.cpp:162:8:162:9 | i3 | map.cpp:162:10:162:10 | call to operator-> | TAINT |
|
||||
| map.cpp:162:8:162:9 | ref arg i3 | map.cpp:158:24:158:25 | i3 | |
|
||||
| map.cpp:162:8:162:9 | ref arg i3 | map.cpp:158:40:158:41 | i3 | |
|
||||
| map.cpp:162:8:162:9 | ref arg i3 | map.cpp:160:9:160:10 | i3 | |
|
||||
| map.cpp:162:8:162:9 | ref arg i3 | map.cpp:161:8:161:9 | i3 | |
|
||||
| map.cpp:162:8:162:9 | ref arg i3 | map.cpp:162:8:162:9 | i3 | |
|
||||
| map.cpp:166:27:166:29 | call to map | map.cpp:167:7:167:9 | m10 | |
|
||||
| map.cpp:166:27:166:29 | call to map | map.cpp:171:7:171:9 | m10 | |
|
||||
| map.cpp:166:27:166:29 | call to map | map.cpp:252:1:252:1 | m10 | |
|
||||
@@ -1460,8 +1516,23 @@
|
||||
| map.cpp:298:40:298:41 | ref arg i1 | map.cpp:302:8:302:9 | i1 | |
|
||||
| map.cpp:300:8:300:8 | call to operator* | map.cpp:300:8:300:10 | call to pair | TAINT |
|
||||
| map.cpp:300:9:300:10 | i1 | map.cpp:300:8:300:8 | call to operator* | TAINT |
|
||||
| map.cpp:300:9:300:10 | ref arg i1 | map.cpp:298:24:298:25 | i1 | |
|
||||
| map.cpp:300:9:300:10 | ref arg i1 | map.cpp:298:40:298:41 | i1 | |
|
||||
| map.cpp:300:9:300:10 | ref arg i1 | map.cpp:300:9:300:10 | i1 | |
|
||||
| map.cpp:300:9:300:10 | ref arg i1 | map.cpp:301:8:301:9 | i1 | |
|
||||
| map.cpp:300:9:300:10 | ref arg i1 | map.cpp:302:8:302:9 | i1 | |
|
||||
| map.cpp:301:8:301:9 | i1 | map.cpp:301:10:301:10 | call to operator-> | TAINT |
|
||||
| map.cpp:301:8:301:9 | ref arg i1 | map.cpp:298:24:298:25 | i1 | |
|
||||
| map.cpp:301:8:301:9 | ref arg i1 | map.cpp:298:40:298:41 | i1 | |
|
||||
| map.cpp:301:8:301:9 | ref arg i1 | map.cpp:300:9:300:10 | i1 | |
|
||||
| map.cpp:301:8:301:9 | ref arg i1 | map.cpp:301:8:301:9 | i1 | |
|
||||
| map.cpp:301:8:301:9 | ref arg i1 | map.cpp:302:8:302:9 | i1 | |
|
||||
| map.cpp:302:8:302:9 | i1 | map.cpp:302:10:302:10 | call to operator-> | TAINT |
|
||||
| map.cpp:302:8:302:9 | ref arg i1 | map.cpp:298:24:298:25 | i1 | |
|
||||
| map.cpp:302:8:302:9 | ref arg i1 | map.cpp:298:40:298:41 | i1 | |
|
||||
| map.cpp:302:8:302:9 | ref arg i1 | map.cpp:300:9:300:10 | i1 | |
|
||||
| map.cpp:302:8:302:9 | ref arg i1 | map.cpp:301:8:301:9 | i1 | |
|
||||
| map.cpp:302:8:302:9 | ref arg i1 | map.cpp:302:8:302:9 | i1 | |
|
||||
| map.cpp:304:12:304:13 | m2 | map.cpp:304:15:304:19 | call to begin | TAINT |
|
||||
| map.cpp:304:12:304:13 | ref arg m2 | map.cpp:304:30:304:31 | m2 | |
|
||||
| map.cpp:304:12:304:13 | ref arg m2 | map.cpp:334:7:334:8 | m2 | |
|
||||
@@ -1488,8 +1559,23 @@
|
||||
| map.cpp:304:40:304:41 | ref arg i2 | map.cpp:308:8:308:9 | i2 | |
|
||||
| map.cpp:306:8:306:8 | call to operator* | map.cpp:306:8:306:10 | call to pair | TAINT |
|
||||
| map.cpp:306:9:306:10 | i2 | map.cpp:306:8:306:8 | call to operator* | TAINT |
|
||||
| map.cpp:306:9:306:10 | ref arg i2 | map.cpp:304:24:304:25 | i2 | |
|
||||
| map.cpp:306:9:306:10 | ref arg i2 | map.cpp:304:40:304:41 | i2 | |
|
||||
| map.cpp:306:9:306:10 | ref arg i2 | map.cpp:306:9:306:10 | i2 | |
|
||||
| map.cpp:306:9:306:10 | ref arg i2 | map.cpp:307:8:307:9 | i2 | |
|
||||
| map.cpp:306:9:306:10 | ref arg i2 | map.cpp:308:8:308:9 | i2 | |
|
||||
| map.cpp:307:8:307:9 | i2 | map.cpp:307:10:307:10 | call to operator-> | TAINT |
|
||||
| map.cpp:307:8:307:9 | ref arg i2 | map.cpp:304:24:304:25 | i2 | |
|
||||
| map.cpp:307:8:307:9 | ref arg i2 | map.cpp:304:40:304:41 | i2 | |
|
||||
| map.cpp:307:8:307:9 | ref arg i2 | map.cpp:306:9:306:10 | i2 | |
|
||||
| map.cpp:307:8:307:9 | ref arg i2 | map.cpp:307:8:307:9 | i2 | |
|
||||
| map.cpp:307:8:307:9 | ref arg i2 | map.cpp:308:8:308:9 | i2 | |
|
||||
| map.cpp:308:8:308:9 | i2 | map.cpp:308:10:308:10 | call to operator-> | TAINT |
|
||||
| map.cpp:308:8:308:9 | ref arg i2 | map.cpp:304:24:304:25 | i2 | |
|
||||
| map.cpp:308:8:308:9 | ref arg i2 | map.cpp:304:40:304:41 | i2 | |
|
||||
| map.cpp:308:8:308:9 | ref arg i2 | map.cpp:306:9:306:10 | i2 | |
|
||||
| map.cpp:308:8:308:9 | ref arg i2 | map.cpp:307:8:307:9 | i2 | |
|
||||
| map.cpp:308:8:308:9 | ref arg i2 | map.cpp:308:8:308:9 | i2 | |
|
||||
| map.cpp:310:12:310:13 | m3 | map.cpp:310:15:310:19 | call to begin | TAINT |
|
||||
| map.cpp:310:12:310:13 | ref arg m3 | map.cpp:310:30:310:31 | m3 | |
|
||||
| map.cpp:310:12:310:13 | ref arg m3 | map.cpp:438:1:438:1 | m3 | |
|
||||
@@ -1510,8 +1596,23 @@
|
||||
| map.cpp:310:40:310:41 | ref arg i3 | map.cpp:314:8:314:9 | i3 | |
|
||||
| map.cpp:312:8:312:8 | call to operator* | map.cpp:312:8:312:10 | call to pair | TAINT |
|
||||
| map.cpp:312:9:312:10 | i3 | map.cpp:312:8:312:8 | call to operator* | TAINT |
|
||||
| map.cpp:312:9:312:10 | ref arg i3 | map.cpp:310:24:310:25 | i3 | |
|
||||
| map.cpp:312:9:312:10 | ref arg i3 | map.cpp:310:40:310:41 | i3 | |
|
||||
| map.cpp:312:9:312:10 | ref arg i3 | map.cpp:312:9:312:10 | i3 | |
|
||||
| map.cpp:312:9:312:10 | ref arg i3 | map.cpp:313:8:313:9 | i3 | |
|
||||
| map.cpp:312:9:312:10 | ref arg i3 | map.cpp:314:8:314:9 | i3 | |
|
||||
| map.cpp:313:8:313:9 | i3 | map.cpp:313:10:313:10 | call to operator-> | TAINT |
|
||||
| map.cpp:313:8:313:9 | ref arg i3 | map.cpp:310:24:310:25 | i3 | |
|
||||
| map.cpp:313:8:313:9 | ref arg i3 | map.cpp:310:40:310:41 | i3 | |
|
||||
| map.cpp:313:8:313:9 | ref arg i3 | map.cpp:312:9:312:10 | i3 | |
|
||||
| map.cpp:313:8:313:9 | ref arg i3 | map.cpp:313:8:313:9 | i3 | |
|
||||
| map.cpp:313:8:313:9 | ref arg i3 | map.cpp:314:8:314:9 | i3 | |
|
||||
| map.cpp:314:8:314:9 | i3 | map.cpp:314:10:314:10 | call to operator-> | TAINT |
|
||||
| map.cpp:314:8:314:9 | ref arg i3 | map.cpp:310:24:310:25 | i3 | |
|
||||
| map.cpp:314:8:314:9 | ref arg i3 | map.cpp:310:40:310:41 | i3 | |
|
||||
| map.cpp:314:8:314:9 | ref arg i3 | map.cpp:312:9:312:10 | i3 | |
|
||||
| map.cpp:314:8:314:9 | ref arg i3 | map.cpp:313:8:313:9 | i3 | |
|
||||
| map.cpp:314:8:314:9 | ref arg i3 | map.cpp:314:8:314:9 | i3 | |
|
||||
| map.cpp:318:37:318:39 | call to unordered_map | map.cpp:319:7:319:9 | m10 | |
|
||||
| map.cpp:318:37:318:39 | call to unordered_map | map.cpp:323:7:323:9 | m10 | |
|
||||
| map.cpp:318:37:318:39 | call to unordered_map | map.cpp:438:1:438:1 | m10 | |
|
||||
@@ -2347,6 +2448,9 @@
|
||||
| set.cpp:55:40:55:41 | ref arg i1 | set.cpp:55:40:55:41 | i1 | |
|
||||
| set.cpp:55:40:55:41 | ref arg i1 | set.cpp:57:9:57:10 | i1 | |
|
||||
| set.cpp:57:9:57:10 | i1 | set.cpp:57:8:57:8 | call to operator* | TAINT |
|
||||
| set.cpp:57:9:57:10 | ref arg i1 | set.cpp:55:24:55:25 | i1 | |
|
||||
| set.cpp:57:9:57:10 | ref arg i1 | set.cpp:55:40:55:41 | i1 | |
|
||||
| set.cpp:57:9:57:10 | ref arg i1 | set.cpp:57:9:57:10 | i1 | |
|
||||
| set.cpp:59:12:59:13 | ref arg s2 | set.cpp:59:30:59:31 | s2 | |
|
||||
| set.cpp:59:12:59:13 | ref arg s2 | set.cpp:126:1:126:1 | s2 | |
|
||||
| set.cpp:59:12:59:13 | s2 | set.cpp:59:15:59:19 | call to begin | TAINT |
|
||||
@@ -2362,6 +2466,9 @@
|
||||
| set.cpp:59:40:59:41 | ref arg i2 | set.cpp:59:40:59:41 | i2 | |
|
||||
| set.cpp:59:40:59:41 | ref arg i2 | set.cpp:61:9:61:10 | i2 | |
|
||||
| set.cpp:61:9:61:10 | i2 | set.cpp:61:8:61:8 | call to operator* | TAINT |
|
||||
| set.cpp:61:9:61:10 | ref arg i2 | set.cpp:59:24:59:25 | i2 | |
|
||||
| set.cpp:61:9:61:10 | ref arg i2 | set.cpp:59:40:59:41 | i2 | |
|
||||
| set.cpp:61:9:61:10 | ref arg i2 | set.cpp:61:9:61:10 | i2 | |
|
||||
| set.cpp:65:19:65:21 | call to set | set.cpp:66:2:66:4 | s11 | |
|
||||
| set.cpp:65:19:65:21 | call to set | set.cpp:67:2:67:4 | s11 | |
|
||||
| set.cpp:65:19:65:21 | call to set | set.cpp:68:2:68:4 | s11 | |
|
||||
@@ -2845,6 +2952,9 @@
|
||||
| set.cpp:169:40:169:41 | ref arg i1 | set.cpp:169:40:169:41 | i1 | |
|
||||
| set.cpp:169:40:169:41 | ref arg i1 | set.cpp:171:9:171:10 | i1 | |
|
||||
| set.cpp:171:9:171:10 | i1 | set.cpp:171:8:171:8 | call to operator* | TAINT |
|
||||
| set.cpp:171:9:171:10 | ref arg i1 | set.cpp:169:24:169:25 | i1 | |
|
||||
| set.cpp:171:9:171:10 | ref arg i1 | set.cpp:169:40:169:41 | i1 | |
|
||||
| set.cpp:171:9:171:10 | ref arg i1 | set.cpp:171:9:171:10 | i1 | |
|
||||
| set.cpp:173:12:173:13 | ref arg s2 | set.cpp:173:30:173:31 | s2 | |
|
||||
| set.cpp:173:12:173:13 | ref arg s2 | set.cpp:238:1:238:1 | s2 | |
|
||||
| set.cpp:173:12:173:13 | s2 | set.cpp:173:15:173:19 | call to begin | TAINT |
|
||||
@@ -2860,6 +2970,9 @@
|
||||
| set.cpp:173:40:173:41 | ref arg i2 | set.cpp:173:40:173:41 | i2 | |
|
||||
| set.cpp:173:40:173:41 | ref arg i2 | set.cpp:175:9:175:10 | i2 | |
|
||||
| set.cpp:175:9:175:10 | i2 | set.cpp:175:8:175:8 | call to operator* | TAINT |
|
||||
| set.cpp:175:9:175:10 | ref arg i2 | set.cpp:173:24:173:25 | i2 | |
|
||||
| set.cpp:175:9:175:10 | ref arg i2 | set.cpp:173:40:173:41 | i2 | |
|
||||
| set.cpp:175:9:175:10 | ref arg i2 | set.cpp:175:9:175:10 | i2 | |
|
||||
| set.cpp:179:29:179:31 | call to unordered_set | set.cpp:180:2:180:4 | s11 | |
|
||||
| set.cpp:179:29:179:31 | call to unordered_set | set.cpp:181:2:181:4 | s11 | |
|
||||
| set.cpp:179:29:179:31 | call to unordered_set | set.cpp:182:2:182:4 | s11 | |
|
||||
@@ -3111,21 +3224,27 @@
|
||||
| smart_pointer.cpp:11:30:11:50 | call to make_shared | smart_pointer.cpp:13:10:13:10 | p | |
|
||||
| smart_pointer.cpp:11:52:11:57 | call to source | smart_pointer.cpp:11:30:11:50 | call to make_shared | TAINT |
|
||||
| smart_pointer.cpp:12:11:12:11 | p | smart_pointer.cpp:12:10:12:10 | call to operator* | TAINT |
|
||||
| smart_pointer.cpp:12:11:12:11 | ref arg p | smart_pointer.cpp:13:10:13:10 | p | |
|
||||
| smart_pointer.cpp:17:32:17:54 | call to make_shared | smart_pointer.cpp:18:11:18:11 | p | |
|
||||
| smart_pointer.cpp:17:32:17:54 | call to make_shared | smart_pointer.cpp:19:10:19:10 | p | |
|
||||
| smart_pointer.cpp:18:11:18:11 | p | smart_pointer.cpp:18:10:18:10 | call to operator* | TAINT |
|
||||
| smart_pointer.cpp:18:11:18:11 | ref arg p | smart_pointer.cpp:19:10:19:10 | p | |
|
||||
| smart_pointer.cpp:23:30:23:50 | call to make_unique | smart_pointer.cpp:24:11:24:11 | p | |
|
||||
| smart_pointer.cpp:23:30:23:50 | call to make_unique | smart_pointer.cpp:25:10:25:10 | p | |
|
||||
| smart_pointer.cpp:23:52:23:57 | call to source | smart_pointer.cpp:23:30:23:50 | call to make_unique | TAINT |
|
||||
| smart_pointer.cpp:24:11:24:11 | p | smart_pointer.cpp:24:10:24:10 | call to operator* | TAINT |
|
||||
| smart_pointer.cpp:24:11:24:11 | ref arg p | smart_pointer.cpp:25:10:25:10 | p | |
|
||||
| smart_pointer.cpp:29:32:29:54 | call to make_unique | smart_pointer.cpp:30:11:30:11 | p | |
|
||||
| smart_pointer.cpp:29:32:29:54 | call to make_unique | smart_pointer.cpp:31:10:31:10 | p | |
|
||||
| smart_pointer.cpp:30:11:30:11 | p | smart_pointer.cpp:30:10:30:10 | call to operator* | TAINT |
|
||||
| smart_pointer.cpp:30:11:30:11 | ref arg p | smart_pointer.cpp:31:10:31:10 | p | |
|
||||
| smart_pointer.cpp:35:30:35:50 | call to make_shared | smart_pointer.cpp:37:6:37:6 | p | |
|
||||
| smart_pointer.cpp:35:30:35:50 | call to make_shared | smart_pointer.cpp:38:10:38:10 | p | |
|
||||
| smart_pointer.cpp:35:30:35:50 | call to make_shared | smart_pointer.cpp:39:11:39:11 | p | |
|
||||
| smart_pointer.cpp:37:5:37:17 | ... = ... | smart_pointer.cpp:37:5:37:5 | call to operator* [post update] | |
|
||||
| smart_pointer.cpp:37:6:37:6 | p | smart_pointer.cpp:37:5:37:5 | call to operator* | TAINT |
|
||||
| smart_pointer.cpp:37:6:37:6 | ref arg p | smart_pointer.cpp:38:10:38:10 | p | |
|
||||
| smart_pointer.cpp:37:6:37:6 | ref arg p | smart_pointer.cpp:39:11:39:11 | p | |
|
||||
| smart_pointer.cpp:37:10:37:15 | call to source | smart_pointer.cpp:37:5:37:17 | ... = ... | |
|
||||
| smart_pointer.cpp:38:10:38:10 | ref arg p | smart_pointer.cpp:39:11:39:11 | p | |
|
||||
| smart_pointer.cpp:39:11:39:11 | p | smart_pointer.cpp:39:10:39:10 | call to operator* | TAINT |
|
||||
@@ -3134,6 +3253,8 @@
|
||||
| smart_pointer.cpp:43:29:43:51 | call to unique_ptr | smart_pointer.cpp:47:11:47:11 | p | |
|
||||
| smart_pointer.cpp:45:5:45:17 | ... = ... | smart_pointer.cpp:45:5:45:5 | call to operator* [post update] | |
|
||||
| smart_pointer.cpp:45:6:45:6 | p | smart_pointer.cpp:45:5:45:5 | call to operator* | TAINT |
|
||||
| smart_pointer.cpp:45:6:45:6 | ref arg p | smart_pointer.cpp:46:10:46:10 | p | |
|
||||
| smart_pointer.cpp:45:6:45:6 | ref arg p | smart_pointer.cpp:47:11:47:11 | p | |
|
||||
| smart_pointer.cpp:45:10:45:15 | call to source | smart_pointer.cpp:45:5:45:17 | ... = ... | |
|
||||
| smart_pointer.cpp:46:10:46:10 | ref arg p | smart_pointer.cpp:47:11:47:11 | p | |
|
||||
| smart_pointer.cpp:47:11:47:11 | p | smart_pointer.cpp:47:10:47:10 | call to operator* | TAINT |
|
||||
@@ -3147,6 +3268,7 @@
|
||||
| smart_pointer.cpp:65:28:65:46 | call to make_unique | smart_pointer.cpp:67:10:67:10 | p | |
|
||||
| smart_pointer.cpp:65:48:65:53 | call to source | smart_pointer.cpp:65:28:65:46 | call to make_unique | TAINT |
|
||||
| smart_pointer.cpp:65:58:65:58 | 0 | smart_pointer.cpp:65:28:65:46 | call to make_unique | TAINT |
|
||||
| smart_pointer.cpp:66:10:66:10 | ref arg p | smart_pointer.cpp:67:10:67:10 | p | |
|
||||
| standalone_iterators.cpp:39:45:39:51 | source1 | standalone_iterators.cpp:39:45:39:51 | source1 | |
|
||||
| standalone_iterators.cpp:39:45:39:51 | source1 | standalone_iterators.cpp:40:11:40:17 | source1 | |
|
||||
| standalone_iterators.cpp:39:45:39:51 | source1 | standalone_iterators.cpp:41:12:41:18 | source1 | |
|
||||
@@ -3197,6 +3319,56 @@
|
||||
| standalone_iterators.cpp:90:8:90:8 | call to operator-- | standalone_iterators.cpp:90:5:90:5 | call to operator* | TAINT |
|
||||
| standalone_iterators.cpp:90:8:90:8 | ref arg call to operator-- | standalone_iterators.cpp:90:6:90:7 | ref arg i2 | |
|
||||
| standalone_iterators.cpp:90:13:90:13 | 0 | standalone_iterators.cpp:90:5:90:5 | ref arg call to operator* | TAINT |
|
||||
| standalone_iterators.cpp:98:15:98:16 | call to container | standalone_iterators.cpp:101:6:101:7 | c1 | |
|
||||
| standalone_iterators.cpp:98:15:98:16 | call to container | standalone_iterators.cpp:102:6:102:7 | c1 | |
|
||||
| standalone_iterators.cpp:98:15:98:16 | call to container | standalone_iterators.cpp:106:6:106:7 | c1 | |
|
||||
| standalone_iterators.cpp:98:15:98:16 | call to container | standalone_iterators.cpp:109:7:109:8 | c1 | |
|
||||
| standalone_iterators.cpp:101:6:101:7 | c1 | standalone_iterators.cpp:101:9:101:13 | call to begin | TAINT |
|
||||
| standalone_iterators.cpp:101:6:101:7 | ref arg c1 | standalone_iterators.cpp:102:6:102:7 | c1 | |
|
||||
| standalone_iterators.cpp:101:6:101:7 | ref arg c1 | standalone_iterators.cpp:106:6:106:7 | c1 | |
|
||||
| standalone_iterators.cpp:101:6:101:7 | ref arg c1 | standalone_iterators.cpp:109:7:109:8 | c1 | |
|
||||
| standalone_iterators.cpp:101:9:101:13 | call to begin | standalone_iterators.cpp:101:2:101:15 | ... = ... | |
|
||||
| standalone_iterators.cpp:101:9:101:13 | call to begin | standalone_iterators.cpp:103:3:103:3 | a | |
|
||||
| standalone_iterators.cpp:101:9:101:13 | call to begin | standalone_iterators.cpp:104:7:104:7 | a | |
|
||||
| standalone_iterators.cpp:102:6:102:7 | c1 | standalone_iterators.cpp:102:9:102:13 | call to begin | TAINT |
|
||||
| standalone_iterators.cpp:102:6:102:7 | ref arg c1 | standalone_iterators.cpp:106:6:106:7 | c1 | |
|
||||
| standalone_iterators.cpp:102:6:102:7 | ref arg c1 | standalone_iterators.cpp:109:7:109:8 | c1 | |
|
||||
| standalone_iterators.cpp:102:9:102:13 | call to begin | standalone_iterators.cpp:102:2:102:15 | ... = ... | |
|
||||
| standalone_iterators.cpp:102:9:102:13 | call to begin | standalone_iterators.cpp:107:7:107:7 | b | |
|
||||
| standalone_iterators.cpp:103:2:103:2 | ref arg call to operator* | standalone_iterators.cpp:103:3:103:3 | ref arg a | TAINT |
|
||||
| standalone_iterators.cpp:103:2:103:2 | ref arg call to operator* | standalone_iterators.cpp:106:6:106:7 | c1 | |
|
||||
| standalone_iterators.cpp:103:2:103:2 | ref arg call to operator* | standalone_iterators.cpp:109:7:109:8 | c1 | |
|
||||
| standalone_iterators.cpp:103:3:103:3 | a | standalone_iterators.cpp:103:2:103:2 | call to operator* | TAINT |
|
||||
| standalone_iterators.cpp:103:3:103:3 | ref arg a | standalone_iterators.cpp:104:7:104:7 | a | |
|
||||
| standalone_iterators.cpp:103:7:103:12 | call to source | standalone_iterators.cpp:103:2:103:2 | ref arg call to operator* | TAINT |
|
||||
| standalone_iterators.cpp:104:7:104:7 | a [post update] | standalone_iterators.cpp:106:6:106:7 | c1 | |
|
||||
| standalone_iterators.cpp:104:7:104:7 | a [post update] | standalone_iterators.cpp:109:7:109:8 | c1 | |
|
||||
| standalone_iterators.cpp:106:6:106:7 | c1 | standalone_iterators.cpp:106:9:106:13 | call to begin | TAINT |
|
||||
| standalone_iterators.cpp:106:6:106:7 | ref arg c1 | standalone_iterators.cpp:109:7:109:8 | c1 | |
|
||||
| standalone_iterators.cpp:106:9:106:13 | call to begin | standalone_iterators.cpp:106:2:106:15 | ... = ... | |
|
||||
| standalone_iterators.cpp:106:9:106:13 | call to begin | standalone_iterators.cpp:108:7:108:7 | c | |
|
||||
| standalone_iterators.cpp:107:7:107:7 | b [post update] | standalone_iterators.cpp:109:7:109:8 | c1 | |
|
||||
| standalone_iterators.cpp:108:7:108:7 | c [post update] | standalone_iterators.cpp:109:7:109:8 | c1 | |
|
||||
| standalone_iterators.cpp:113:15:113:16 | call to container | standalone_iterators.cpp:116:7:116:8 | c1 | |
|
||||
| standalone_iterators.cpp:113:15:113:16 | call to container | standalone_iterators.cpp:122:7:122:8 | c1 | |
|
||||
| standalone_iterators.cpp:116:7:116:8 | c1 | standalone_iterators.cpp:116:10:116:14 | call to begin | TAINT |
|
||||
| standalone_iterators.cpp:116:7:116:8 | ref arg c1 | standalone_iterators.cpp:122:7:122:8 | c1 | |
|
||||
| standalone_iterators.cpp:116:10:116:14 | call to begin | standalone_iterators.cpp:116:2:116:16 | ... = ... | |
|
||||
| standalone_iterators.cpp:116:10:116:14 | call to begin | standalone_iterators.cpp:117:7:117:8 | it | |
|
||||
| standalone_iterators.cpp:116:10:116:14 | call to begin | standalone_iterators.cpp:118:2:118:3 | it | |
|
||||
| standalone_iterators.cpp:116:10:116:14 | call to begin | standalone_iterators.cpp:119:7:119:8 | it | |
|
||||
| standalone_iterators.cpp:116:10:116:14 | call to begin | standalone_iterators.cpp:120:2:120:3 | it | |
|
||||
| standalone_iterators.cpp:116:10:116:14 | call to begin | standalone_iterators.cpp:121:7:121:8 | it | |
|
||||
| standalone_iterators.cpp:117:7:117:8 | it [post update] | standalone_iterators.cpp:122:7:122:8 | c1 | |
|
||||
| standalone_iterators.cpp:118:2:118:3 | it | standalone_iterators.cpp:118:5:118:5 | call to operator+= | |
|
||||
| standalone_iterators.cpp:118:2:118:3 | ref arg it | standalone_iterators.cpp:119:7:119:8 | it | |
|
||||
| standalone_iterators.cpp:118:2:118:3 | ref arg it | standalone_iterators.cpp:120:2:120:3 | it | |
|
||||
| standalone_iterators.cpp:118:2:118:3 | ref arg it | standalone_iterators.cpp:121:7:121:8 | it | |
|
||||
| standalone_iterators.cpp:118:2:118:3 | ref arg it | standalone_iterators.cpp:122:7:122:8 | c1 | |
|
||||
| standalone_iterators.cpp:118:8:118:8 | 1 | standalone_iterators.cpp:118:2:118:3 | ref arg it | TAINT |
|
||||
| standalone_iterators.cpp:120:2:120:3 | it | standalone_iterators.cpp:120:5:120:5 | call to operator+= | |
|
||||
| standalone_iterators.cpp:120:2:120:3 | ref arg it | standalone_iterators.cpp:121:7:121:8 | it | |
|
||||
| standalone_iterators.cpp:120:8:120:13 | call to source | standalone_iterators.cpp:120:2:120:3 | ref arg it | TAINT |
|
||||
| stl.h:75:8:75:8 | Unknown literal | stl.h:75:8:75:8 | constructor init of field container | TAINT |
|
||||
| stl.h:75:8:75:8 | Unknown literal | stl.h:75:8:75:8 | constructor init of field container | TAINT |
|
||||
| stl.h:75:8:75:8 | this | stl.h:75:8:75:8 | constructor init of field container [pre-this] | |
|
||||
@@ -3408,6 +3580,9 @@
|
||||
| string.cpp:121:15:121:15 | ref arg (__begin) | string.cpp:121:15:121:15 | (__begin) | |
|
||||
| string.cpp:121:15:121:15 | ref arg (__begin) | string.cpp:121:15:121:15 | (__begin) | |
|
||||
| string.cpp:121:15:121:15 | ref arg (__begin) | string.cpp:121:15:121:15 | (__begin) | |
|
||||
| string.cpp:121:15:121:15 | ref arg (__begin) | string.cpp:121:15:121:15 | (__begin) | |
|
||||
| string.cpp:121:15:121:15 | ref arg (__begin) | string.cpp:121:15:121:15 | (__begin) | |
|
||||
| string.cpp:121:15:121:15 | ref arg (__begin) | string.cpp:121:15:121:15 | (__begin) | |
|
||||
| string.cpp:121:15:121:15 | ref arg (__range) | string.cpp:121:15:121:15 | (__range) | |
|
||||
| string.cpp:121:15:121:15 | s | string.cpp:121:15:121:15 | (__range) | |
|
||||
| string.cpp:121:15:121:15 | s | string.cpp:121:15:121:15 | (__range) | |
|
||||
@@ -3426,6 +3601,9 @@
|
||||
| string.cpp:125:61:125:62 | ref arg it | string.cpp:125:61:125:62 | it | |
|
||||
| string.cpp:125:61:125:62 | ref arg it | string.cpp:126:9:126:10 | it | |
|
||||
| string.cpp:126:9:126:10 | it | string.cpp:126:8:126:8 | call to operator* | TAINT |
|
||||
| string.cpp:126:9:126:10 | ref arg it | string.cpp:125:44:125:45 | it | |
|
||||
| string.cpp:126:9:126:10 | ref arg it | string.cpp:125:61:125:62 | it | |
|
||||
| string.cpp:126:9:126:10 | ref arg it | string.cpp:126:9:126:10 | it | |
|
||||
| string.cpp:129:16:129:16 | (__begin) | string.cpp:129:16:129:16 | call to operator* | TAINT |
|
||||
| string.cpp:129:16:129:16 | (__begin) | string.cpp:129:16:129:16 | call to operator++ | |
|
||||
| string.cpp:129:16:129:16 | (__end) | string.cpp:129:16:129:16 | call to iterator | |
|
||||
@@ -3439,6 +3617,9 @@
|
||||
| string.cpp:129:16:129:16 | ref arg (__begin) | string.cpp:129:16:129:16 | (__begin) | |
|
||||
| string.cpp:129:16:129:16 | ref arg (__begin) | string.cpp:129:16:129:16 | (__begin) | |
|
||||
| string.cpp:129:16:129:16 | ref arg (__begin) | string.cpp:129:16:129:16 | (__begin) | |
|
||||
| string.cpp:129:16:129:16 | ref arg (__begin) | string.cpp:129:16:129:16 | (__begin) | |
|
||||
| string.cpp:129:16:129:16 | ref arg (__begin) | string.cpp:129:16:129:16 | (__begin) | |
|
||||
| string.cpp:129:16:129:16 | ref arg (__begin) | string.cpp:129:16:129:16 | (__begin) | |
|
||||
| string.cpp:129:16:129:16 | ref arg (__range) | string.cpp:129:16:129:16 | (__range) | |
|
||||
| string.cpp:129:16:129:16 | s | string.cpp:129:16:129:16 | (__range) | |
|
||||
| string.cpp:129:16:129:16 | s | string.cpp:129:16:129:16 | (__range) | |
|
||||
@@ -3807,11 +3988,13 @@
|
||||
| string.cpp:376:31:376:35 | call to begin | string.cpp:378:9:378:13 | iter1 | |
|
||||
| string.cpp:376:31:376:35 | call to begin | string.cpp:379:8:379:12 | iter1 | |
|
||||
| string.cpp:378:9:378:13 | iter1 | string.cpp:378:8:378:8 | call to operator* | TAINT |
|
||||
| string.cpp:378:9:378:13 | ref arg iter1 | string.cpp:379:8:379:12 | iter1 | |
|
||||
| string.cpp:379:8:379:12 | iter1 | string.cpp:379:13:379:13 | call to operator[] | TAINT |
|
||||
| string.cpp:380:28:380:29 | s2 | string.cpp:380:31:380:35 | call to begin | TAINT |
|
||||
| string.cpp:380:31:380:35 | call to begin | string.cpp:382:9:382:13 | iter2 | |
|
||||
| string.cpp:380:31:380:35 | call to begin | string.cpp:383:8:383:12 | iter2 | |
|
||||
| string.cpp:382:9:382:13 | iter2 | string.cpp:382:8:382:8 | call to operator* | TAINT |
|
||||
| string.cpp:382:9:382:13 | ref arg iter2 | string.cpp:383:8:383:12 | iter2 | |
|
||||
| string.cpp:383:8:383:12 | iter2 | string.cpp:383:13:383:13 | call to operator[] | TAINT |
|
||||
| string.cpp:388:18:388:24 | hello | string.cpp:388:18:388:25 | call to basic_string | TAINT |
|
||||
| string.cpp:388:18:388:25 | call to basic_string | string.cpp:391:25:391:26 | s1 | |
|
||||
@@ -3855,10 +4038,12 @@
|
||||
| string.cpp:398:8:398:9 | i2 | string.cpp:398:3:398:9 | ... = ... | |
|
||||
| string.cpp:398:8:398:9 | i2 | string.cpp:399:12:399:13 | i3 | |
|
||||
| string.cpp:399:10:399:10 | call to operator++ | string.cpp:399:8:399:8 | call to operator* | TAINT |
|
||||
| string.cpp:399:10:399:10 | ref arg call to operator++ | string.cpp:399:12:399:13 | ref arg i3 | |
|
||||
| string.cpp:399:12:399:13 | i3 | string.cpp:399:10:399:10 | call to operator++ | |
|
||||
| string.cpp:400:8:400:9 | i2 | string.cpp:400:3:400:9 | ... = ... | |
|
||||
| string.cpp:400:8:400:9 | i2 | string.cpp:401:12:401:13 | i4 | |
|
||||
| string.cpp:401:10:401:10 | call to operator-- | string.cpp:401:8:401:8 | call to operator* | TAINT |
|
||||
| string.cpp:401:10:401:10 | ref arg call to operator-- | string.cpp:401:12:401:13 | ref arg i4 | |
|
||||
| string.cpp:401:12:401:13 | i4 | string.cpp:401:10:401:10 | call to operator-- | |
|
||||
| string.cpp:402:8:402:9 | i2 | string.cpp:402:3:402:9 | ... = ... | |
|
||||
| string.cpp:402:8:402:9 | i2 | string.cpp:403:3:403:4 | i5 | |
|
||||
@@ -3876,12 +4061,14 @@
|
||||
| string.cpp:408:8:408:9 | i2 | string.cpp:409:10:409:11 | i7 | |
|
||||
| string.cpp:409:10:409:11 | i7 | string.cpp:409:12:409:12 | call to operator+= | |
|
||||
| string.cpp:409:12:409:12 | call to operator+= | string.cpp:409:8:409:8 | call to operator* | TAINT |
|
||||
| string.cpp:409:14:409:14 | 1 | string.cpp:409:12:409:12 | call to operator+= | |
|
||||
| string.cpp:409:12:409:12 | ref arg call to operator+= | string.cpp:409:10:409:11 | ref arg i7 | TAINT |
|
||||
| string.cpp:409:14:409:14 | 1 | string.cpp:409:10:409:11 | ref arg i7 | TAINT |
|
||||
| string.cpp:410:8:410:9 | i2 | string.cpp:410:3:410:9 | ... = ... | |
|
||||
| string.cpp:410:8:410:9 | i2 | string.cpp:411:10:411:11 | i8 | |
|
||||
| string.cpp:411:10:411:11 | i8 | string.cpp:411:12:411:12 | call to operator-= | |
|
||||
| string.cpp:411:12:411:12 | call to operator-= | string.cpp:411:8:411:8 | call to operator* | TAINT |
|
||||
| string.cpp:411:14:411:14 | 1 | string.cpp:411:12:411:12 | call to operator-= | |
|
||||
| string.cpp:411:12:411:12 | ref arg call to operator-= | string.cpp:411:10:411:11 | ref arg i8 | TAINT |
|
||||
| string.cpp:411:14:411:14 | 1 | string.cpp:411:10:411:11 | ref arg i8 | TAINT |
|
||||
| string.cpp:413:8:413:9 | s2 | string.cpp:413:11:413:13 | call to end | TAINT |
|
||||
| string.cpp:413:11:413:13 | call to end | string.cpp:413:3:413:15 | ... = ... | |
|
||||
| string.cpp:413:11:413:13 | call to end | string.cpp:414:5:414:6 | i9 | |
|
||||
@@ -6042,6 +6229,22 @@
|
||||
| taint.cpp:631:6:631:14 | call to _strnextc | taint.cpp:631:2:631:18 | ... = ... | |
|
||||
| taint.cpp:631:6:631:14 | call to _strnextc | taint.cpp:632:7:632:7 | c | |
|
||||
| taint.cpp:631:16:631:17 | | taint.cpp:631:6:631:14 | call to _strnextc | TAINT |
|
||||
| taint.cpp:640:9:640:12 | this | taint.cpp:640:25:640:29 | this | |
|
||||
| taint.cpp:643:33:643:38 | source | taint.cpp:645:20:645:25 | source | |
|
||||
| taint.cpp:644:30:644:30 | c | taint.cpp:645:10:645:10 | c | |
|
||||
| taint.cpp:644:30:644:30 | c | taint.cpp:646:8:646:8 | c | |
|
||||
| taint.cpp:645:10:645:10 | ref arg c | taint.cpp:646:8:646:8 | c | |
|
||||
| taint.cpp:645:12:645:15 | call to data | taint.cpp:645:3:645:8 | call to memcpy | |
|
||||
| taint.cpp:645:20:645:25 | source | taint.cpp:645:3:645:8 | call to memcpy | TAINT |
|
||||
| taint.cpp:645:20:645:25 | source | taint.cpp:645:12:645:15 | ref arg call to data | TAINT |
|
||||
| taint.cpp:652:9:652:12 | this | taint.cpp:652:31:652:35 | this | |
|
||||
| taint.cpp:655:35:655:40 | source | taint.cpp:657:20:657:25 | source | |
|
||||
| taint.cpp:656:27:656:27 | c | taint.cpp:657:10:657:10 | c | |
|
||||
| taint.cpp:656:27:656:27 | c | taint.cpp:658:8:658:8 | c | |
|
||||
| taint.cpp:657:10:657:10 | ref arg c | taint.cpp:658:8:658:8 | c | |
|
||||
| taint.cpp:657:12:657:15 | call to data | taint.cpp:657:3:657:8 | call to memcpy | |
|
||||
| taint.cpp:657:20:657:25 | source | taint.cpp:657:3:657:8 | call to memcpy | TAINT |
|
||||
| taint.cpp:657:20:657:25 | source | taint.cpp:657:12:657:15 | ref arg call to data | TAINT |
|
||||
| vector.cpp:16:43:16:49 | source1 | vector.cpp:17:26:17:32 | source1 | |
|
||||
| vector.cpp:16:43:16:49 | source1 | vector.cpp:31:38:31:44 | source1 | |
|
||||
| vector.cpp:17:21:17:33 | call to vector | vector.cpp:19:14:19:14 | v | |
|
||||
@@ -6063,6 +6266,9 @@
|
||||
| vector.cpp:19:14:19:14 | ref arg (__begin) | vector.cpp:19:14:19:14 | (__begin) | |
|
||||
| vector.cpp:19:14:19:14 | ref arg (__begin) | vector.cpp:19:14:19:14 | (__begin) | |
|
||||
| vector.cpp:19:14:19:14 | ref arg (__begin) | vector.cpp:19:14:19:14 | (__begin) | |
|
||||
| vector.cpp:19:14:19:14 | ref arg (__begin) | vector.cpp:19:14:19:14 | (__begin) | |
|
||||
| vector.cpp:19:14:19:14 | ref arg (__begin) | vector.cpp:19:14:19:14 | (__begin) | |
|
||||
| vector.cpp:19:14:19:14 | ref arg (__begin) | vector.cpp:19:14:19:14 | (__begin) | |
|
||||
| vector.cpp:19:14:19:14 | ref arg (__range) | vector.cpp:19:14:19:14 | (__range) | |
|
||||
| vector.cpp:19:14:19:14 | v | vector.cpp:19:14:19:14 | (__range) | |
|
||||
| vector.cpp:19:14:19:14 | v | vector.cpp:19:14:19:14 | (__range) | |
|
||||
@@ -6083,6 +6289,9 @@
|
||||
| vector.cpp:23:66:23:67 | ref arg it | vector.cpp:23:66:23:67 | it | |
|
||||
| vector.cpp:23:66:23:67 | ref arg it | vector.cpp:24:9:24:10 | it | |
|
||||
| vector.cpp:24:9:24:10 | it | vector.cpp:24:8:24:8 | call to operator* | TAINT |
|
||||
| vector.cpp:24:9:24:10 | ref arg it | vector.cpp:23:49:23:50 | it | |
|
||||
| vector.cpp:24:9:24:10 | ref arg it | vector.cpp:23:66:23:67 | it | |
|
||||
| vector.cpp:24:9:24:10 | ref arg it | vector.cpp:24:9:24:10 | it | |
|
||||
| vector.cpp:27:15:27:15 | (__begin) | vector.cpp:27:15:27:15 | call to operator* | TAINT |
|
||||
| vector.cpp:27:15:27:15 | (__begin) | vector.cpp:27:15:27:15 | call to operator++ | |
|
||||
| vector.cpp:27:15:27:15 | (__end) | vector.cpp:27:15:27:15 | call to iterator | |
|
||||
@@ -6096,6 +6305,9 @@
|
||||
| vector.cpp:27:15:27:15 | ref arg (__begin) | vector.cpp:27:15:27:15 | (__begin) | |
|
||||
| vector.cpp:27:15:27:15 | ref arg (__begin) | vector.cpp:27:15:27:15 | (__begin) | |
|
||||
| vector.cpp:27:15:27:15 | ref arg (__begin) | vector.cpp:27:15:27:15 | (__begin) | |
|
||||
| vector.cpp:27:15:27:15 | ref arg (__begin) | vector.cpp:27:15:27:15 | (__begin) | |
|
||||
| vector.cpp:27:15:27:15 | ref arg (__begin) | vector.cpp:27:15:27:15 | (__begin) | |
|
||||
| vector.cpp:27:15:27:15 | ref arg (__begin) | vector.cpp:27:15:27:15 | (__begin) | |
|
||||
| vector.cpp:27:15:27:15 | ref arg (__range) | vector.cpp:27:15:27:15 | (__range) | |
|
||||
| vector.cpp:27:15:27:15 | v | vector.cpp:27:15:27:15 | (__range) | |
|
||||
| vector.cpp:27:15:27:15 | v | vector.cpp:27:15:27:15 | (__range) | |
|
||||
@@ -7019,16 +7231,20 @@
|
||||
| vector.cpp:329:62:329:65 | iter | vector.cpp:329:62:329:65 | iter | |
|
||||
| vector.cpp:329:62:329:65 | iter | vector.cpp:330:3:330:6 | iter | |
|
||||
| vector.cpp:330:2:330:2 | call to operator* [post update] | vector.cpp:329:62:329:65 | iter | |
|
||||
| vector.cpp:330:2:330:2 | call to operator* [post update] | vector.cpp:330:3:330:6 | ref arg iter | TAINT |
|
||||
| vector.cpp:330:2:330:17 | ... = ... | vector.cpp:330:2:330:2 | call to operator* [post update] | |
|
||||
| vector.cpp:330:3:330:6 | iter | vector.cpp:330:2:330:2 | call to operator* | TAINT |
|
||||
| vector.cpp:330:3:330:6 | ref arg iter | vector.cpp:329:62:329:65 | iter | |
|
||||
| vector.cpp:330:10:330:15 | call to source | vector.cpp:330:2:330:2 | call to operator* [post update] | TAINT |
|
||||
| vector.cpp:330:10:330:15 | call to source | vector.cpp:330:2:330:17 | ... = ... | |
|
||||
| vector.cpp:333:64:333:67 | iter | vector.cpp:333:64:333:67 | iter | |
|
||||
| vector.cpp:333:64:333:67 | iter | vector.cpp:334:3:334:6 | iter | |
|
||||
| vector.cpp:333:74:333:74 | i | vector.cpp:334:10:334:10 | i | |
|
||||
| vector.cpp:334:2:334:2 | call to operator* [post update] | vector.cpp:333:64:333:67 | iter | |
|
||||
| vector.cpp:334:2:334:2 | call to operator* [post update] | vector.cpp:334:3:334:6 | ref arg iter | TAINT |
|
||||
| vector.cpp:334:2:334:10 | ... = ... | vector.cpp:334:2:334:2 | call to operator* [post update] | |
|
||||
| vector.cpp:334:3:334:6 | iter | vector.cpp:334:2:334:2 | call to operator* | TAINT |
|
||||
| vector.cpp:334:3:334:6 | ref arg iter | vector.cpp:333:64:333:67 | iter | |
|
||||
| vector.cpp:334:10:334:10 | i | vector.cpp:334:2:334:2 | call to operator* [post update] | TAINT |
|
||||
| vector.cpp:334:10:334:10 | i | vector.cpp:334:2:334:10 | ... = ... | |
|
||||
| vector.cpp:337:38:337:38 | b | vector.cpp:372:5:372:5 | b | |
|
||||
@@ -7086,6 +7302,7 @@
|
||||
| vector.cpp:340:34:340:35 | ref arg v1 | vector.cpp:415:1:415:1 | v1 | |
|
||||
| vector.cpp:340:34:340:35 | v1 | vector.cpp:340:37:340:41 | call to begin | TAINT |
|
||||
| vector.cpp:340:37:340:41 | call to begin | vector.cpp:341:3:341:4 | i1 | |
|
||||
| vector.cpp:341:2:341:2 | call to operator* [post update] | vector.cpp:341:3:341:4 | ref arg i1 | TAINT |
|
||||
| vector.cpp:341:2:341:2 | call to operator* [post update] | vector.cpp:342:7:342:8 | v1 | |
|
||||
| vector.cpp:341:2:341:2 | call to operator* [post update] | vector.cpp:415:1:415:1 | v1 | |
|
||||
| vector.cpp:341:2:341:15 | ... = ... | vector.cpp:341:2:341:2 | call to operator* [post update] | |
|
||||
@@ -7109,10 +7326,14 @@
|
||||
| vector.cpp:344:68:344:69 | ref arg it | vector.cpp:344:68:344:69 | it | |
|
||||
| vector.cpp:344:68:344:69 | ref arg it | vector.cpp:345:4:345:5 | it | |
|
||||
| vector.cpp:345:3:345:3 | call to operator* [post update] | vector.cpp:344:56:344:57 | v2 | |
|
||||
| vector.cpp:345:3:345:3 | call to operator* [post update] | vector.cpp:345:4:345:5 | ref arg it | TAINT |
|
||||
| vector.cpp:345:3:345:3 | call to operator* [post update] | vector.cpp:347:7:347:8 | v2 | |
|
||||
| vector.cpp:345:3:345:3 | call to operator* [post update] | vector.cpp:415:1:415:1 | v2 | |
|
||||
| vector.cpp:345:3:345:16 | ... = ... | vector.cpp:345:3:345:3 | call to operator* [post update] | |
|
||||
| vector.cpp:345:4:345:5 | it | vector.cpp:345:3:345:3 | call to operator* | TAINT |
|
||||
| vector.cpp:345:4:345:5 | ref arg it | vector.cpp:344:50:344:51 | it | |
|
||||
| vector.cpp:345:4:345:5 | ref arg it | vector.cpp:344:68:344:69 | it | |
|
||||
| vector.cpp:345:4:345:5 | ref arg it | vector.cpp:345:4:345:5 | it | |
|
||||
| vector.cpp:345:9:345:14 | call to source | vector.cpp:345:3:345:3 | call to operator* [post update] | TAINT |
|
||||
| vector.cpp:345:9:345:14 | call to source | vector.cpp:345:3:345:16 | ... = ... | |
|
||||
| vector.cpp:347:7:347:8 | ref arg v2 | vector.cpp:415:1:415:1 | v2 | |
|
||||
@@ -7128,6 +7349,9 @@
|
||||
| vector.cpp:349:15:349:15 | ref arg (__begin) | vector.cpp:349:15:349:15 | (__begin) | |
|
||||
| vector.cpp:349:15:349:15 | ref arg (__begin) | vector.cpp:349:15:349:15 | (__begin) | |
|
||||
| vector.cpp:349:15:349:15 | ref arg (__begin) | vector.cpp:349:15:349:15 | (__begin) | |
|
||||
| vector.cpp:349:15:349:15 | ref arg (__begin) | vector.cpp:349:15:349:15 | (__begin) | |
|
||||
| vector.cpp:349:15:349:15 | ref arg (__begin) | vector.cpp:349:15:349:15 | (__begin) | |
|
||||
| vector.cpp:349:15:349:15 | ref arg (__begin) | vector.cpp:349:15:349:15 | (__begin) | |
|
||||
| vector.cpp:349:15:349:15 | ref arg (__range) | vector.cpp:349:15:349:15 | (__range) | |
|
||||
| vector.cpp:349:15:349:16 | v3 | vector.cpp:349:15:349:15 | (__range) | |
|
||||
| vector.cpp:349:15:349:16 | v3 | vector.cpp:349:15:349:15 | (__range) | |
|
||||
@@ -7164,15 +7388,18 @@
|
||||
| vector.cpp:359:34:359:35 | v5 | vector.cpp:359:37:359:41 | call to begin | TAINT |
|
||||
| vector.cpp:359:37:359:41 | call to begin | vector.cpp:360:3:360:4 | i5 | |
|
||||
| vector.cpp:359:37:359:41 | call to begin | vector.cpp:362:3:362:4 | i5 | |
|
||||
| vector.cpp:360:2:360:2 | call to operator* [post update] | vector.cpp:360:3:360:4 | ref arg i5 | TAINT |
|
||||
| vector.cpp:360:2:360:2 | call to operator* [post update] | vector.cpp:361:7:361:8 | v5 | |
|
||||
| vector.cpp:360:2:360:2 | call to operator* [post update] | vector.cpp:363:7:363:8 | v5 | |
|
||||
| vector.cpp:360:2:360:2 | call to operator* [post update] | vector.cpp:415:1:415:1 | v5 | |
|
||||
| vector.cpp:360:2:360:15 | ... = ... | vector.cpp:360:2:360:2 | call to operator* [post update] | |
|
||||
| vector.cpp:360:3:360:4 | i5 | vector.cpp:360:2:360:2 | call to operator* | TAINT |
|
||||
| vector.cpp:360:3:360:4 | ref arg i5 | vector.cpp:362:3:362:4 | i5 | |
|
||||
| vector.cpp:360:8:360:13 | call to source | vector.cpp:360:2:360:2 | call to operator* [post update] | TAINT |
|
||||
| vector.cpp:360:8:360:13 | call to source | vector.cpp:360:2:360:15 | ... = ... | |
|
||||
| vector.cpp:361:7:361:8 | ref arg v5 | vector.cpp:363:7:363:8 | v5 | |
|
||||
| vector.cpp:361:7:361:8 | ref arg v5 | vector.cpp:415:1:415:1 | v5 | |
|
||||
| vector.cpp:362:2:362:2 | call to operator* [post update] | vector.cpp:362:3:362:4 | ref arg i5 | TAINT |
|
||||
| vector.cpp:362:2:362:2 | call to operator* [post update] | vector.cpp:363:7:363:8 | v5 | |
|
||||
| vector.cpp:362:2:362:2 | call to operator* [post update] | vector.cpp:415:1:415:1 | v5 | |
|
||||
| vector.cpp:362:2:362:8 | ... = ... | vector.cpp:362:2:362:2 | call to operator* [post update] | |
|
||||
@@ -7186,6 +7413,7 @@
|
||||
| vector.cpp:365:34:365:35 | ref arg v6 | vector.cpp:415:1:415:1 | v6 | |
|
||||
| vector.cpp:365:34:365:35 | v6 | vector.cpp:365:37:365:41 | call to begin | TAINT |
|
||||
| vector.cpp:365:37:365:41 | call to begin | vector.cpp:366:3:366:4 | i6 | |
|
||||
| vector.cpp:366:2:366:2 | call to operator* [post update] | vector.cpp:366:3:366:4 | ref arg i6 | TAINT |
|
||||
| vector.cpp:366:2:366:2 | call to operator* [post update] | vector.cpp:367:7:367:8 | v6 | |
|
||||
| vector.cpp:366:2:366:2 | call to operator* [post update] | vector.cpp:368:2:368:3 | v6 | |
|
||||
| vector.cpp:366:2:366:2 | call to operator* [post update] | vector.cpp:369:7:369:8 | v6 | |
|
||||
@@ -7209,6 +7437,7 @@
|
||||
| vector.cpp:371:34:371:35 | v7 | vector.cpp:371:37:371:41 | call to begin | TAINT |
|
||||
| vector.cpp:371:37:371:41 | call to begin | vector.cpp:373:4:373:5 | i7 | |
|
||||
| vector.cpp:371:37:371:41 | call to begin | vector.cpp:376:4:376:5 | i7 | |
|
||||
| vector.cpp:373:3:373:3 | call to operator* [post update] | vector.cpp:373:4:373:5 | ref arg i7 | TAINT |
|
||||
| vector.cpp:373:3:373:3 | call to operator* [post update] | vector.cpp:374:8:374:9 | v7 | |
|
||||
| vector.cpp:373:3:373:3 | call to operator* [post update] | vector.cpp:379:7:379:8 | v7 | |
|
||||
| vector.cpp:373:3:373:3 | call to operator* [post update] | vector.cpp:415:1:415:1 | v7 | |
|
||||
@@ -7218,6 +7447,7 @@
|
||||
| vector.cpp:373:9:373:14 | call to source | vector.cpp:373:3:373:16 | ... = ... | |
|
||||
| vector.cpp:374:8:374:9 | ref arg v7 | vector.cpp:379:7:379:8 | v7 | |
|
||||
| vector.cpp:374:8:374:9 | ref arg v7 | vector.cpp:415:1:415:1 | v7 | |
|
||||
| vector.cpp:376:3:376:3 | call to operator* [post update] | vector.cpp:376:4:376:5 | ref arg i7 | TAINT |
|
||||
| vector.cpp:376:3:376:3 | call to operator* [post update] | vector.cpp:377:8:377:9 | v7 | |
|
||||
| vector.cpp:376:3:376:3 | call to operator* [post update] | vector.cpp:379:7:379:8 | v7 | |
|
||||
| vector.cpp:376:3:376:3 | call to operator* [post update] | vector.cpp:415:1:415:1 | v7 | |
|
||||
@@ -7234,15 +7464,18 @@
|
||||
| vector.cpp:381:34:381:35 | v8 | vector.cpp:381:37:381:41 | call to begin | TAINT |
|
||||
| vector.cpp:381:37:381:41 | call to begin | vector.cpp:382:3:382:4 | i8 | |
|
||||
| vector.cpp:381:37:381:41 | call to begin | vector.cpp:384:3:384:4 | i8 | |
|
||||
| vector.cpp:382:2:382:2 | call to operator* [post update] | vector.cpp:382:3:382:4 | ref arg i8 | TAINT |
|
||||
| vector.cpp:382:2:382:2 | call to operator* [post update] | vector.cpp:383:7:383:8 | v8 | |
|
||||
| vector.cpp:382:2:382:2 | call to operator* [post update] | vector.cpp:385:7:385:8 | v8 | |
|
||||
| vector.cpp:382:2:382:2 | call to operator* [post update] | vector.cpp:415:1:415:1 | v8 | |
|
||||
| vector.cpp:382:2:382:15 | ... = ... | vector.cpp:382:2:382:2 | call to operator* [post update] | |
|
||||
| vector.cpp:382:3:382:4 | i8 | vector.cpp:382:2:382:2 | call to operator* | TAINT |
|
||||
| vector.cpp:382:3:382:4 | ref arg i8 | vector.cpp:384:3:384:4 | i8 | |
|
||||
| vector.cpp:382:8:382:13 | call to source | vector.cpp:382:2:382:2 | call to operator* [post update] | TAINT |
|
||||
| vector.cpp:382:8:382:13 | call to source | vector.cpp:382:2:382:15 | ... = ... | |
|
||||
| vector.cpp:383:7:383:8 | ref arg v8 | vector.cpp:385:7:385:8 | v8 | |
|
||||
| vector.cpp:383:7:383:8 | ref arg v8 | vector.cpp:415:1:415:1 | v8 | |
|
||||
| vector.cpp:384:2:384:2 | call to operator* [post update] | vector.cpp:384:3:384:4 | ref arg i8 | TAINT |
|
||||
| vector.cpp:384:2:384:2 | call to operator* [post update] | vector.cpp:385:7:385:8 | v8 | |
|
||||
| vector.cpp:384:2:384:2 | call to operator* [post update] | vector.cpp:415:1:415:1 | v8 | |
|
||||
| vector.cpp:384:2:384:8 | ... = ... | vector.cpp:384:2:384:2 | call to operator* [post update] | |
|
||||
@@ -7255,10 +7488,12 @@
|
||||
| vector.cpp:387:34:387:35 | v9 | vector.cpp:387:37:387:41 | call to begin | TAINT |
|
||||
| vector.cpp:387:37:387:41 | call to begin | vector.cpp:389:3:389:4 | i9 | |
|
||||
| vector.cpp:387:37:387:41 | call to begin | vector.cpp:390:31:390:32 | i9 | |
|
||||
| vector.cpp:389:2:389:2 | call to operator* [post update] | vector.cpp:389:3:389:4 | ref arg i9 | TAINT |
|
||||
| vector.cpp:389:2:389:2 | call to operator* [post update] | vector.cpp:392:7:392:8 | v9 | |
|
||||
| vector.cpp:389:2:389:2 | call to operator* [post update] | vector.cpp:415:1:415:1 | v9 | |
|
||||
| vector.cpp:389:2:389:15 | ... = ... | vector.cpp:389:2:389:2 | call to operator* [post update] | |
|
||||
| vector.cpp:389:3:389:4 | i9 | vector.cpp:389:2:389:2 | call to operator* | TAINT |
|
||||
| vector.cpp:389:3:389:4 | ref arg i9 | vector.cpp:390:31:390:32 | i9 | |
|
||||
| vector.cpp:389:8:389:13 | call to source | vector.cpp:389:2:389:2 | call to operator* [post update] | TAINT |
|
||||
| vector.cpp:389:8:389:13 | call to source | vector.cpp:389:2:389:15 | ... = ... | |
|
||||
| vector.cpp:390:31:390:32 | call to iterator [post update] | vector.cpp:392:7:392:8 | v9 | |
|
||||
@@ -7300,6 +7535,7 @@
|
||||
| vector.cpp:403:6:403:6 | call to operator++ | vector.cpp:403:2:403:2 | call to operator* | TAINT |
|
||||
| vector.cpp:403:11:403:11 | 0 | vector.cpp:403:2:403:2 | call to operator* [post update] | TAINT |
|
||||
| vector.cpp:403:11:403:11 | 0 | vector.cpp:403:2:403:11 | ... = ... | |
|
||||
| vector.cpp:404:2:404:2 | call to operator* [post update] | vector.cpp:404:3:404:5 | ref arg i12 | TAINT |
|
||||
| vector.cpp:404:2:404:2 | call to operator* [post update] | vector.cpp:405:7:405:9 | v12 | |
|
||||
| vector.cpp:404:2:404:2 | call to operator* [post update] | vector.cpp:415:1:415:1 | v12 | |
|
||||
| vector.cpp:404:2:404:16 | ... = ... | vector.cpp:404:2:404:2 | call to operator* [post update] | |
|
||||
@@ -7481,3 +7717,70 @@
|
||||
| vector.cpp:496:25:496:30 | call to source | vector.cpp:496:2:496:3 | ref arg v2 | TAINT |
|
||||
| vector.cpp:496:25:496:30 | call to source | vector.cpp:496:5:496:11 | call to emplace | TAINT |
|
||||
| vector.cpp:497:7:497:8 | ref arg v2 | vector.cpp:498:1:498:1 | v2 | |
|
||||
| vector.cpp:503:18:503:21 | {...} | vector.cpp:506:8:506:9 | as | |
|
||||
| vector.cpp:503:18:503:21 | {...} | vector.cpp:507:8:507:9 | as | |
|
||||
| vector.cpp:503:18:503:21 | {...} | vector.cpp:509:9:509:10 | as | |
|
||||
| vector.cpp:503:18:503:21 | {...} | vector.cpp:515:8:515:9 | as | |
|
||||
| vector.cpp:503:20:503:20 | 0 | vector.cpp:503:18:503:21 | {...} | TAINT |
|
||||
| vector.cpp:506:8:506:9 | as | vector.cpp:506:8:506:12 | access to array | |
|
||||
| vector.cpp:506:11:506:11 | 1 | vector.cpp:506:8:506:12 | access to array | TAINT |
|
||||
| vector.cpp:507:8:507:9 | as | vector.cpp:507:8:507:19 | access to array | |
|
||||
| vector.cpp:507:11:507:16 | call to source | vector.cpp:507:8:507:19 | access to array | TAINT |
|
||||
| vector.cpp:509:9:509:10 | as | vector.cpp:509:3:509:10 | ... = ... | |
|
||||
| vector.cpp:509:9:509:10 | as | vector.cpp:510:9:510:11 | ptr | |
|
||||
| vector.cpp:509:9:509:10 | as | vector.cpp:511:3:511:5 | ptr | |
|
||||
| vector.cpp:510:9:510:11 | ptr | vector.cpp:510:8:510:11 | * ... | TAINT |
|
||||
| vector.cpp:511:3:511:5 | ptr | vector.cpp:511:3:511:10 | ... += ... | TAINT |
|
||||
| vector.cpp:511:3:511:10 | ... += ... | vector.cpp:512:9:512:11 | ptr | |
|
||||
| vector.cpp:511:3:511:10 | ... += ... | vector.cpp:513:3:513:5 | ptr | |
|
||||
| vector.cpp:511:10:511:10 | 1 | vector.cpp:511:3:511:10 | ... += ... | TAINT |
|
||||
| vector.cpp:512:9:512:11 | ptr | vector.cpp:512:8:512:11 | * ... | TAINT |
|
||||
| vector.cpp:513:3:513:5 | ptr | vector.cpp:513:3:513:17 | ... += ... | TAINT |
|
||||
| vector.cpp:513:3:513:17 | ... += ... | vector.cpp:514:9:514:11 | ptr | |
|
||||
| vector.cpp:513:10:513:15 | call to source | vector.cpp:513:3:513:17 | ... += ... | TAINT |
|
||||
| vector.cpp:514:9:514:11 | ptr | vector.cpp:514:8:514:11 | * ... | TAINT |
|
||||
| vector.cpp:515:8:515:9 | as | vector.cpp:515:8:515:12 | access to array | |
|
||||
| vector.cpp:515:11:515:11 | 1 | vector.cpp:515:8:515:12 | access to array | TAINT |
|
||||
| vector.cpp:520:25:520:31 | call to vector | vector.cpp:523:8:523:9 | vs | |
|
||||
| vector.cpp:520:25:520:31 | call to vector | vector.cpp:524:8:524:9 | vs | |
|
||||
| vector.cpp:520:25:520:31 | call to vector | vector.cpp:526:8:526:9 | vs | |
|
||||
| vector.cpp:520:25:520:31 | call to vector | vector.cpp:532:8:532:9 | vs | |
|
||||
| vector.cpp:520:25:520:31 | call to vector | vector.cpp:533:2:533:2 | vs | |
|
||||
| vector.cpp:520:30:520:30 | 0 | vector.cpp:520:25:520:31 | call to vector | TAINT |
|
||||
| vector.cpp:523:8:523:9 | ref arg vs | vector.cpp:524:8:524:9 | vs | |
|
||||
| vector.cpp:523:8:523:9 | ref arg vs | vector.cpp:526:8:526:9 | vs | |
|
||||
| vector.cpp:523:8:523:9 | ref arg vs | vector.cpp:532:8:532:9 | vs | |
|
||||
| vector.cpp:523:8:523:9 | ref arg vs | vector.cpp:533:2:533:2 | vs | |
|
||||
| vector.cpp:523:8:523:9 | vs | vector.cpp:523:10:523:10 | call to operator[] | TAINT |
|
||||
| vector.cpp:524:8:524:9 | ref arg vs | vector.cpp:526:8:526:9 | vs | |
|
||||
| vector.cpp:524:8:524:9 | ref arg vs | vector.cpp:532:8:532:9 | vs | |
|
||||
| vector.cpp:524:8:524:9 | ref arg vs | vector.cpp:533:2:533:2 | vs | |
|
||||
| vector.cpp:524:8:524:9 | vs | vector.cpp:524:10:524:10 | call to operator[] | TAINT |
|
||||
| vector.cpp:526:8:526:9 | ref arg vs | vector.cpp:532:8:532:9 | vs | |
|
||||
| vector.cpp:526:8:526:9 | ref arg vs | vector.cpp:533:2:533:2 | vs | |
|
||||
| vector.cpp:526:8:526:9 | vs | vector.cpp:526:11:526:15 | call to begin | TAINT |
|
||||
| vector.cpp:526:11:526:15 | call to begin | vector.cpp:526:3:526:17 | ... = ... | |
|
||||
| vector.cpp:526:11:526:15 | call to begin | vector.cpp:527:9:527:10 | it | |
|
||||
| vector.cpp:526:11:526:15 | call to begin | vector.cpp:528:3:528:4 | it | |
|
||||
| vector.cpp:526:11:526:15 | call to begin | vector.cpp:529:9:529:10 | it | |
|
||||
| vector.cpp:526:11:526:15 | call to begin | vector.cpp:530:3:530:4 | it | |
|
||||
| vector.cpp:526:11:526:15 | call to begin | vector.cpp:531:9:531:10 | it | |
|
||||
| vector.cpp:527:9:527:10 | it | vector.cpp:527:8:527:8 | call to operator* | TAINT |
|
||||
| vector.cpp:527:9:527:10 | ref arg it | vector.cpp:528:3:528:4 | it | |
|
||||
| vector.cpp:527:9:527:10 | ref arg it | vector.cpp:529:9:529:10 | it | |
|
||||
| vector.cpp:527:9:527:10 | ref arg it | vector.cpp:530:3:530:4 | it | |
|
||||
| vector.cpp:527:9:527:10 | ref arg it | vector.cpp:531:9:531:10 | it | |
|
||||
| vector.cpp:528:3:528:4 | it | vector.cpp:528:6:528:6 | call to operator+= | |
|
||||
| vector.cpp:528:3:528:4 | ref arg it | vector.cpp:529:9:529:10 | it | |
|
||||
| vector.cpp:528:3:528:4 | ref arg it | vector.cpp:530:3:530:4 | it | |
|
||||
| vector.cpp:528:3:528:4 | ref arg it | vector.cpp:531:9:531:10 | it | |
|
||||
| vector.cpp:528:9:528:9 | 1 | vector.cpp:528:3:528:4 | ref arg it | TAINT |
|
||||
| vector.cpp:529:9:529:10 | it | vector.cpp:529:8:529:8 | call to operator* | TAINT |
|
||||
| vector.cpp:529:9:529:10 | ref arg it | vector.cpp:530:3:530:4 | it | |
|
||||
| vector.cpp:529:9:529:10 | ref arg it | vector.cpp:531:9:531:10 | it | |
|
||||
| vector.cpp:530:3:530:4 | it | vector.cpp:530:6:530:6 | call to operator+= | |
|
||||
| vector.cpp:530:3:530:4 | ref arg it | vector.cpp:531:9:531:10 | it | |
|
||||
| vector.cpp:530:9:530:14 | call to source | vector.cpp:530:3:530:4 | ref arg it | TAINT |
|
||||
| vector.cpp:531:9:531:10 | it | vector.cpp:531:8:531:8 | call to operator* | TAINT |
|
||||
| vector.cpp:532:8:532:9 | ref arg vs | vector.cpp:533:2:533:2 | vs | |
|
||||
| vector.cpp:532:8:532:9 | vs | vector.cpp:532:10:532:10 | call to operator[] | TAINT |
|
||||
|
||||
@@ -90,3 +90,34 @@ void test_insert_iterator() {
|
||||
*i2-- = 0;
|
||||
sink(c2); // clean
|
||||
}
|
||||
|
||||
void sink(insert_iterator_by_trait);
|
||||
insert_iterator_by_trait &operator+=(insert_iterator_by_trait &it, int amount);
|
||||
|
||||
void test_assign_through_iterator() {
|
||||
container c1;
|
||||
insert_iterator_by_trait a, b, c;
|
||||
|
||||
a = c1.begin();
|
||||
b = c1.begin();
|
||||
*a = source();
|
||||
sink(a); // $ ast MISSING: ir
|
||||
|
||||
c = c1.begin();
|
||||
sink(b); // MISSING: ast,ir
|
||||
sink(c); // $ ast MISSING: ir
|
||||
sink(c1); // $ ast MISSING: ir
|
||||
}
|
||||
|
||||
void test_nonmember_iterator() {
|
||||
container c1;
|
||||
insert_iterator_by_trait it;
|
||||
|
||||
it = c1.begin();
|
||||
sink(it);
|
||||
it += 1;
|
||||
sink(it);
|
||||
it += source();
|
||||
sink(it); // $ ast,ir
|
||||
sink(c1);
|
||||
}
|
||||
|
||||
@@ -631,3 +631,29 @@ void test__strnextc(const char* source) {
|
||||
c = _strnextc("");
|
||||
sink(c);
|
||||
}
|
||||
|
||||
// --- taint through const specified function ---
|
||||
|
||||
class C_no_const_member_function {
|
||||
char* data_;
|
||||
public:
|
||||
char* data() { return data_; }
|
||||
};
|
||||
|
||||
void test_no_const_member(char* source) {
|
||||
C_no_const_member_function c;
|
||||
memcpy(c.data(), source, 16);
|
||||
sink(c.data()); // $ ast MISSING: ir
|
||||
}
|
||||
|
||||
class C_const_member_function {
|
||||
char* data_;
|
||||
public:
|
||||
char* data() const { return data_; }
|
||||
};
|
||||
|
||||
void test_with_const_member(char* source) {
|
||||
C_const_member_function c;
|
||||
memcpy(c.data(), source, 16);
|
||||
sink(c.data()); // $ ast MISSING: ir
|
||||
}
|
||||
@@ -496,3 +496,39 @@ void test_vector_emplace() {
|
||||
v2.emplace(v2.begin(), source());
|
||||
sink(v2); // $ ast,ir
|
||||
}
|
||||
|
||||
void test_vector_iterator() {
|
||||
{
|
||||
// array behaviour, for comparison
|
||||
short as[100] = {0};
|
||||
short *ptr;
|
||||
|
||||
sink(as[1]);
|
||||
sink(as[source()]); // $ ast,ir
|
||||
|
||||
ptr = as;
|
||||
sink(*ptr);
|
||||
ptr += 1;
|
||||
sink(*ptr);
|
||||
ptr += source();
|
||||
sink(*ptr); // $ ast,ir
|
||||
sink(as[1]);
|
||||
}
|
||||
|
||||
{
|
||||
// iterator behaviour
|
||||
std::vector<short> vs(100, 0);
|
||||
std::vector<short>::iterator it;
|
||||
|
||||
sink(vs[1]);
|
||||
sink(vs[source()]); // $ MISSING: ast,ir
|
||||
|
||||
it = vs.begin();
|
||||
sink(*it);
|
||||
it += 1;
|
||||
sink(*it);
|
||||
it += source();
|
||||
sink(*it); // $ ast,ir
|
||||
sink(vs[1]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,14 +8,14 @@ edges
|
||||
| search.c:22:24:22:28 | *query | search.c:23:39:23:43 | query |
|
||||
| search.c:22:24:22:28 | query | search.c:23:39:23:43 | query |
|
||||
| search.c:22:24:22:28 | query | search.c:23:39:23:43 | query |
|
||||
| search.c:41:21:41:26 | call to getenv | search.c:14:24:14:28 | *query |
|
||||
| search.c:41:21:41:26 | call to getenv | search.c:14:24:14:28 | *query |
|
||||
| search.c:41:21:41:26 | call to getenv | search.c:14:24:14:28 | query |
|
||||
| search.c:41:21:41:26 | call to getenv | search.c:14:24:14:28 | query |
|
||||
| search.c:41:21:41:26 | call to getenv | search.c:22:24:22:28 | *query |
|
||||
| search.c:41:21:41:26 | call to getenv | search.c:22:24:22:28 | *query |
|
||||
| search.c:41:21:41:26 | call to getenv | search.c:22:24:22:28 | query |
|
||||
| search.c:41:21:41:26 | call to getenv | search.c:22:24:22:28 | query |
|
||||
| search.c:51:21:51:26 | call to getenv | search.c:14:24:14:28 | *query |
|
||||
| search.c:51:21:51:26 | call to getenv | search.c:14:24:14:28 | *query |
|
||||
| search.c:51:21:51:26 | call to getenv | search.c:14:24:14:28 | query |
|
||||
| search.c:51:21:51:26 | call to getenv | search.c:14:24:14:28 | query |
|
||||
| search.c:51:21:51:26 | call to getenv | search.c:22:24:22:28 | *query |
|
||||
| search.c:51:21:51:26 | call to getenv | search.c:22:24:22:28 | *query |
|
||||
| search.c:51:21:51:26 | call to getenv | search.c:22:24:22:28 | query |
|
||||
| search.c:51:21:51:26 | call to getenv | search.c:22:24:22:28 | query |
|
||||
nodes
|
||||
| search.c:14:24:14:28 | *query | semmle.label | *query |
|
||||
| search.c:14:24:14:28 | query | semmle.label | query |
|
||||
@@ -29,12 +29,12 @@ nodes
|
||||
| search.c:23:39:23:43 | query | semmle.label | query |
|
||||
| search.c:23:39:23:43 | query | semmle.label | query |
|
||||
| search.c:23:39:23:43 | query | semmle.label | query |
|
||||
| search.c:41:21:41:26 | call to getenv | semmle.label | call to getenv |
|
||||
| search.c:41:21:41:26 | call to getenv | semmle.label | call to getenv |
|
||||
| search.c:45:5:45:15 | Argument 0 | semmle.label | Argument 0 |
|
||||
| search.c:45:17:45:25 | Argument 0 indirection | semmle.label | Argument 0 indirection |
|
||||
| search.c:47:5:47:15 | Argument 0 | semmle.label | Argument 0 |
|
||||
| search.c:47:17:47:25 | Argument 0 indirection | semmle.label | Argument 0 indirection |
|
||||
| search.c:51:21:51:26 | call to getenv | semmle.label | call to getenv |
|
||||
| search.c:51:21:51:26 | call to getenv | semmle.label | call to getenv |
|
||||
| search.c:55:5:55:15 | Argument 0 | semmle.label | Argument 0 |
|
||||
| search.c:55:17:55:25 | Argument 0 indirection | semmle.label | Argument 0 indirection |
|
||||
| search.c:57:5:57:15 | Argument 0 | semmle.label | Argument 0 |
|
||||
| search.c:57:17:57:25 | Argument 0 indirection | semmle.label | Argument 0 indirection |
|
||||
#select
|
||||
| search.c:17:8:17:12 | query | search.c:41:21:41:26 | call to getenv | search.c:17:8:17:12 | query | Cross-site scripting vulnerability due to $@. | search.c:41:21:41:26 | call to getenv | this query data |
|
||||
| search.c:23:39:23:43 | query | search.c:41:21:41:26 | call to getenv | search.c:23:39:23:43 | query | Cross-site scripting vulnerability due to $@. | search.c:41:21:41:26 | call to getenv | this query data |
|
||||
| search.c:17:8:17:12 | query | search.c:51:21:51:26 | call to getenv | search.c:17:8:17:12 | query | Cross-site scripting vulnerability due to $@. | search.c:51:21:51:26 | call to getenv | this query data |
|
||||
| search.c:23:39:23:43 | query | search.c:51:21:51:26 | call to getenv | search.c:23:39:23:43 | query | Cross-site scripting vulnerability due to $@. | search.c:51:21:51:26 | call to getenv | this query data |
|
||||
|
||||
@@ -26,7 +26,7 @@ void bad_server2(char* query) {
|
||||
puts(do_search(query));
|
||||
}
|
||||
|
||||
void good_server(char* query) {
|
||||
void good_server1(char* query) {
|
||||
puts("<p>Query results for ");
|
||||
// GOOD: Escape HTML characters before adding to a page
|
||||
char* query_escaped = escape_html(query);
|
||||
@@ -37,14 +37,25 @@ void good_server(char* query) {
|
||||
puts(do_search(query));
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
char* raw_query = getenv("QUERY_STRING");
|
||||
if (strcmp("good", argv[0]) == 0) {
|
||||
good_server(raw_query);
|
||||
} else if (strcmp("bad1", argv[0]) == 0) {
|
||||
bad_server1(raw_query);
|
||||
} else {
|
||||
bad_server2(raw_query);
|
||||
}
|
||||
int sscanf(const char *s, const char *format, ...);
|
||||
|
||||
void good_server2(char* query) {
|
||||
puts("<p>Query results for ");
|
||||
// GOOD: Only an integer is added to the page.
|
||||
int i = 0;
|
||||
sscanf(query, "value=%i", &i);
|
||||
printf("\n<p>%i</p>\n", i);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
char* raw_query = getenv("QUERY_STRING");
|
||||
if (strcmp("good1", argv[0]) == 0) {
|
||||
good_server1(raw_query);
|
||||
} else if (strcmp("bad1", argv[0]) == 0) {
|
||||
bad_server1(raw_query);
|
||||
} else if (strcmp("bad2", argv[0]) == 0) {
|
||||
bad_server2(raw_query);
|
||||
} else if (strcmp("good2", argv[0]) == 0) {
|
||||
good_server2(raw_query);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ namespace Semmle.Autobuild.Shared
|
||||
private readonly SolutionFile? solution;
|
||||
|
||||
private readonly IEnumerable<Project> includedProjects;
|
||||
|
||||
public override IEnumerable<IProjectOrSolution> IncludedProjects => includedProjects;
|
||||
|
||||
public IEnumerable<SolutionConfigurationInSolution> Configurations =>
|
||||
@@ -84,8 +85,12 @@ namespace Semmle.Autobuild.Shared
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
private IEnumerable<Version> ToolsVersions => includedProjects.Where(p => p.ValidToolsVersion).Select(p => p.ToolsVersion);
|
||||
private IEnumerable<Version> ToolsVersions => includedProjects
|
||||
.Where(p => p.ValidToolsVersion)
|
||||
.Select(p => p.ToolsVersion);
|
||||
|
||||
public Version ToolsVersion => ToolsVersions.Any() ? ToolsVersions.Max() : new Version();
|
||||
public Version ToolsVersion => ToolsVersions.Any()
|
||||
? ToolsVersions.Max()
|
||||
: new Version();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
lgtm,codescanning
|
||||
* The underlying methods of `foreach` statements are now explicitly extracted and
|
||||
they are made available on the `ForeachStmt` class.
|
||||
4
csharp/change-notes/2021-02-12-with-expression.md
Normal file
4
csharp/change-notes/2021-02-12-with-expression.md
Normal file
@@ -0,0 +1,4 @@
|
||||
lgtm,codescanning
|
||||
* C# 9 `with` expressions are now extracted. Data flow support has been added to
|
||||
handle flow through `with` expressions and also from `record` constructor arguments
|
||||
to its properties.
|
||||
@@ -163,7 +163,7 @@ namespace Semmle.Extraction.CIL.Driver
|
||||
}
|
||||
|
||||
private readonly HashSet<string> filesAnalyzed = new HashSet<string>();
|
||||
public HashSet<AssemblyName> MissingReferences {get;} = new HashSet<AssemblyName>();
|
||||
public HashSet<AssemblyName> MissingReferences { get; } = new HashSet<AssemblyName>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -95,11 +95,11 @@ namespace Semmle.Extraction.CIL
|
||||
/// <param name="h">The handle of the entity.</param>
|
||||
/// <param name="genericContext">The generic context.</param>
|
||||
/// <returns></returns>
|
||||
public IExtractedEntity CreateGeneric(GenericContext genericContext, Handle h) => genericHandleFactory[genericContext, h];
|
||||
public IExtractedEntity CreateGeneric(IGenericContext genericContext, Handle h) => genericHandleFactory[genericContext, h];
|
||||
|
||||
private readonly GenericContext defaultGenericContext;
|
||||
private readonly IGenericContext defaultGenericContext;
|
||||
|
||||
private IExtractedEntity CreateGenericHandle(GenericContext gc, Handle handle)
|
||||
private IExtractedEntity CreateGenericHandle(IGenericContext gc, Handle handle)
|
||||
{
|
||||
IExtractedEntity entity;
|
||||
switch (handle.Kind)
|
||||
@@ -136,7 +136,7 @@ namespace Semmle.Extraction.CIL
|
||||
return entity;
|
||||
}
|
||||
|
||||
private IExtractedEntity Create(GenericContext gc, MemberReferenceHandle handle)
|
||||
private IExtractedEntity Create(IGenericContext gc, MemberReferenceHandle handle)
|
||||
{
|
||||
var mr = MdReader.GetMemberReference(handle);
|
||||
switch (mr.GetKind())
|
||||
@@ -228,7 +228,7 @@ namespace Semmle.Extraction.CIL
|
||||
|
||||
#endregion
|
||||
|
||||
private readonly CachedFunction<GenericContext, Handle, IExtractedEntity> genericHandleFactory;
|
||||
private readonly CachedFunction<IGenericContext, Handle, IExtractedEntity> genericHandleFactory;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the short name of a member, without the preceding interface qualifier.
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace Semmle.Extraction.CIL
|
||||
|
||||
globalNamespace = new Lazy<Entities.Namespace>(() => Populate(new Entities.Namespace(this, "", null)));
|
||||
systemNamespace = new Lazy<Entities.Namespace>(() => Populate(new Entities.Namespace(this, "System")));
|
||||
genericHandleFactory = new CachedFunction<GenericContext, Handle, IExtractedEntity>(CreateGenericHandle);
|
||||
genericHandleFactory = new CachedFunction<IGenericContext, Handle, IExtractedEntity>(CreateGenericHandle);
|
||||
namespaceFactory = new CachedFunction<StringHandle, Entities.Namespace>(n => CreateNamespace(MdReader.GetString(n)));
|
||||
namespaceDefinitionFactory = new CachedFunction<NamespaceDefinitionHandle, Entities.Namespace>(CreateNamespace);
|
||||
sourceFiles = new CachedFunction<PDB.ISourceFile, Entities.PdbSourceFile>(path => new Entities.PdbSourceFile(this, path));
|
||||
|
||||
@@ -5,14 +5,18 @@ namespace Semmle.Extraction.CIL
|
||||
/// <summary>
|
||||
/// A generic context which does not contain any type parameters.
|
||||
/// </summary>
|
||||
public class EmptyContext : GenericContext
|
||||
public class EmptyContext : IGenericContext
|
||||
{
|
||||
public EmptyContext(Context cx) : base(cx)
|
||||
public EmptyContext(Context cx)
|
||||
{
|
||||
Cx = cx;
|
||||
}
|
||||
|
||||
public override IEnumerable<Entities.Type> TypeParameters { get { yield break; } }
|
||||
public Context Cx { get; }
|
||||
|
||||
public IEnumerable<Entities.Type> TypeParameters { get { yield break; } }
|
||||
|
||||
public IEnumerable<Entities.Type> MethodParameters { get { yield break; } }
|
||||
|
||||
public override IEnumerable<Entities.Type> MethodParameters { get { yield break; } }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
trapFile.Write(FullName);
|
||||
trapFile.Write("#file:///");
|
||||
trapFile.Write(Cx.AssemblyPath.Replace("\\", "/"));
|
||||
trapFile.Write(";assembly");
|
||||
}
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
@@ -49,8 +50,6 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
|
||||
public override int GetHashCode() => 7 * file.GetHashCode();
|
||||
|
||||
public override string IdSuffix => ";assembly";
|
||||
|
||||
private string FullName => assemblyName.GetPublicKey() is null ? assemblyName.FullName + ", PublicKeyToken=null" : assemblyName.FullName;
|
||||
|
||||
public override IEnumerable<IExtractionProduct> Contents
|
||||
@@ -136,7 +135,7 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
trapFile = trapWriter.TrapFile;
|
||||
if (nocache || !System.IO.File.Exists(trapFile))
|
||||
{
|
||||
var cx = extractor.CreateContext(null, trapWriter, null, false);
|
||||
var cx = new Extraction.Context(extractor, trapWriter);
|
||||
ExtractCIL(cx, assemblyPath, extractPdbs);
|
||||
extracted = true;
|
||||
}
|
||||
|
||||
@@ -12,9 +12,9 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
{
|
||||
private readonly CustomAttributeHandle handle;
|
||||
private readonly CustomAttribute attrib;
|
||||
private readonly IEntity @object;
|
||||
private readonly IExtractedEntity @object;
|
||||
|
||||
public Attribute(Context cx, IEntity @object, CustomAttributeHandle handle) : base(cx)
|
||||
public Attribute(Context cx, IExtractedEntity @object, CustomAttributeHandle handle) : base(cx)
|
||||
{
|
||||
attrib = cx.MdReader.GetCustomAttribute(handle);
|
||||
this.handle = handle;
|
||||
@@ -80,7 +80,7 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
return value?.ToString() ?? "null";
|
||||
}
|
||||
|
||||
public static IEnumerable<IExtractionProduct> Populate(Context cx, IEntity @object, CustomAttributeHandleCollection attributes)
|
||||
public static IEnumerable<IExtractionProduct> Populate(Context cx, IExtractedEntity @object, CustomAttributeHandleCollection attributes)
|
||||
{
|
||||
foreach (var attrib in attributes)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Semmle.Extraction.CIL
|
||||
{
|
||||
/// <summary>
|
||||
/// A CIL entity which has been extracted.
|
||||
/// </summary>
|
||||
public interface IExtractedEntity : IExtractionProduct, IEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// The contents of the entity.
|
||||
/// </summary>
|
||||
|
||||
IEnumerable<IExtractionProduct> Contents { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
namespace Semmle.Extraction.CIL
|
||||
{
|
||||
/// <summary>
|
||||
/// Something that is extracted from an entity.
|
||||
/// </summary>
|
||||
///
|
||||
/// <remarks>
|
||||
/// The extraction algorithm proceeds as follows:
|
||||
/// - Construct entity
|
||||
/// - Call Extract()
|
||||
/// - IExtractedEntity check if already extracted
|
||||
/// - Enumerate Contents to produce more extraction products
|
||||
/// - Extract these until there is nothing left to extract
|
||||
/// </remarks>
|
||||
public interface IExtractionProduct
|
||||
{
|
||||
/// <summary>
|
||||
/// Perform further extraction/population of this item as necessary.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="cx">The extraction context.</param>
|
||||
void Extract(Context cx);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Semmle.Extraction.CIL
|
||||
{
|
||||
/// <summary>
|
||||
/// When we decode a type/method signature, we need access to
|
||||
/// generic parameters.
|
||||
/// </summary>
|
||||
public interface IGenericContext
|
||||
{
|
||||
Context Cx { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The list of generic type parameters/arguments, including type parameters/arguments of
|
||||
/// containing types.
|
||||
/// </summary>
|
||||
IEnumerable<Entities.Type> TypeParameters { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The list of generic method parameters/arguments.
|
||||
/// </summary>
|
||||
IEnumerable<Entities.Type> MethodParameters { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace Semmle.Extraction.CIL
|
||||
{
|
||||
/// <summary>
|
||||
/// An entity that needs to be populated during extraction.
|
||||
/// This assigns a key and optionally extracts its contents.
|
||||
/// </summary>
|
||||
public abstract class LabelledEntity : Extraction.LabelledEntity, IExtractedEntity
|
||||
{
|
||||
// todo: with .NET 5 this can override the base context, and change the return type.
|
||||
public Context Cx { get; }
|
||||
|
||||
protected LabelledEntity(Context cx) : base(cx.Cx)
|
||||
{
|
||||
this.Cx = cx;
|
||||
}
|
||||
|
||||
public override Microsoft.CodeAnalysis.Location ReportingLocation => throw new NotImplementedException();
|
||||
|
||||
public void Extract(Context cx2)
|
||||
{
|
||||
cx2.Populate(this);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
using var writer = new StringWriter();
|
||||
WriteQuotedId(writer);
|
||||
return writer.ToString();
|
||||
}
|
||||
|
||||
public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.NoLabel;
|
||||
|
||||
public abstract IEnumerable<IExtractionProduct> Contents { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
namespace Semmle.Extraction.CIL
|
||||
{
|
||||
/// <summary>
|
||||
/// A tuple that is an extraction product.
|
||||
/// </summary>
|
||||
internal class Tuple : IExtractionProduct
|
||||
{
|
||||
private readonly Extraction.Tuple tuple;
|
||||
|
||||
public Tuple(string name, params object[] args)
|
||||
{
|
||||
tuple = new Extraction.Tuple(name, args);
|
||||
}
|
||||
|
||||
public void Extract(Context cx)
|
||||
{
|
||||
cx.Cx.Emit(tuple);
|
||||
}
|
||||
|
||||
public override string ToString() => tuple.ToString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Semmle.Extraction.CIL
|
||||
{
|
||||
/// <summary>
|
||||
/// An entity that has contents to extract. There is no need to populate
|
||||
/// a key as it's done in the contructor.
|
||||
/// </summary>
|
||||
public abstract class UnlabelledEntity : Extraction.UnlabelledEntity, IExtractedEntity
|
||||
{
|
||||
// todo: with .NET 5 this can override the base context, and change the return type.
|
||||
public Context Cx { get; }
|
||||
|
||||
protected UnlabelledEntity(Context cx) : base(cx.Cx)
|
||||
{
|
||||
Cx = cx;
|
||||
}
|
||||
|
||||
public override Microsoft.CodeAnalysis.Location ReportingLocation => throw new NotImplementedException();
|
||||
|
||||
public void Extract(Context cx2)
|
||||
{
|
||||
cx2.Extract(this);
|
||||
}
|
||||
|
||||
public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.NoLabel;
|
||||
|
||||
public abstract IEnumerable<IExtractionProduct> Contents { get; }
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
|
||||
public override IList<LocalVariable>? LocalVariables => locals;
|
||||
|
||||
public DefinitionMethod(GenericContext gc, MethodDefinitionHandle handle) : base(gc)
|
||||
public DefinitionMethod(IGenericContext gc, MethodDefinitionHandle handle) : base(gc)
|
||||
{
|
||||
md = Cx.MdReader.GetMethodDefinition(handle);
|
||||
this.gc = gc;
|
||||
|
||||
@@ -25,10 +25,9 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
parent.WriteId(trapFile);
|
||||
trapFile.Write('.');
|
||||
trapFile.Write(Cx.ShortName(ed.Name));
|
||||
trapFile.Write(";cil-event");
|
||||
}
|
||||
|
||||
public override string IdSuffix => ";cil-event";
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return obj is Event e && handle.Equals(e.handle);
|
||||
|
||||
@@ -7,13 +7,13 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
/// </summary>
|
||||
internal class ExceptionRegion : UnlabelledEntity
|
||||
{
|
||||
private readonly GenericContext gc;
|
||||
private readonly IGenericContext gc;
|
||||
private readonly MethodImplementation method;
|
||||
private readonly int index;
|
||||
private readonly System.Reflection.Metadata.ExceptionRegion r;
|
||||
private readonly Dictionary<int, Instruction> jump_table;
|
||||
|
||||
public ExceptionRegion(GenericContext gc, MethodImplementation method, int index, System.Reflection.Metadata.ExceptionRegion r, Dictionary<int, Instruction> jump_table) : base(gc.Cx)
|
||||
public ExceptionRegion(IGenericContext gc, MethodImplementation method, int index, System.Reflection.Metadata.ExceptionRegion r, Dictionary<int, Instruction> jump_table) : base(gc.Cx)
|
||||
{
|
||||
this.gc = gc;
|
||||
this.method = method;
|
||||
|
||||
@@ -8,40 +8,27 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
/// <summary>
|
||||
/// An entity representing a field.
|
||||
/// </summary>
|
||||
internal abstract class Field : GenericContext, IMember, ICustomModifierReceiver
|
||||
internal abstract class Field : LabelledEntity, IGenericContext, IMember, ICustomModifierReceiver
|
||||
{
|
||||
protected Field(Context cx) : base(cx)
|
||||
{
|
||||
}
|
||||
|
||||
public Label Label { get; set; }
|
||||
|
||||
public void WriteId(TextWriter trapFile)
|
||||
public override void WriteId(TextWriter trapFile)
|
||||
{
|
||||
trapFile.WriteSubId(DeclaringType);
|
||||
trapFile.Write('.');
|
||||
trapFile.Write(Name);
|
||||
trapFile.Write(";cil-field");
|
||||
}
|
||||
|
||||
public void WriteQuotedId(TextWriter trapFile)
|
||||
{
|
||||
trapFile.Write("@\"");
|
||||
WriteId(trapFile);
|
||||
trapFile.Write(idSuffix);
|
||||
trapFile.Write('\"');
|
||||
}
|
||||
|
||||
private const string idSuffix = ";cil-field";
|
||||
|
||||
public abstract string Name { get; }
|
||||
|
||||
public abstract Type DeclaringType { get; }
|
||||
|
||||
public Location ReportingLocation => throw new NotImplementedException();
|
||||
|
||||
public abstract Type Type { get; }
|
||||
|
||||
public virtual IEnumerable<IExtractionProduct> Contents
|
||||
public override IEnumerable<IExtractionProduct> Contents
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -55,11 +42,8 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
}
|
||||
}
|
||||
|
||||
public void Extract(Context cx2)
|
||||
{
|
||||
cx2.Populate(this);
|
||||
}
|
||||
public abstract IEnumerable<Type> TypeParameters { get; }
|
||||
|
||||
TrapStackBehaviour IEntity.TrapStackBehaviour => TrapStackBehaviour.NoLabel;
|
||||
public abstract IEnumerable<Type> MethodParameters { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
public override void WriteId(TextWriter trapFile)
|
||||
{
|
||||
trapFile.Write(TransformedPath.DatabaseId);
|
||||
trapFile.Write(";sourcefile");
|
||||
}
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
@@ -39,7 +40,5 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
yield return Tuples.files(this, TransformedPath.Value, TransformedPath.NameWithoutExtension, TransformedPath.Extension);
|
||||
}
|
||||
}
|
||||
|
||||
public override string IdSuffix => ";sourcefile";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,10 +15,9 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
public override void WriteId(TextWriter trapFile)
|
||||
{
|
||||
trapFile.Write(transformedPath.DatabaseId);
|
||||
trapFile.Write(";folder");
|
||||
}
|
||||
|
||||
public override string IdSuffix => ";folder";
|
||||
|
||||
public override IEnumerable<IExtractionProduct> Contents
|
||||
{
|
||||
get
|
||||
|
||||
@@ -4,6 +4,6 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
{
|
||||
internal interface ITypeSignature
|
||||
{
|
||||
void WriteId(TextWriter trapFile, GenericContext gc);
|
||||
void WriteId(TextWriter trapFile, IGenericContext gc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
/// <summary>
|
||||
/// A CIL instruction.
|
||||
/// </summary>
|
||||
internal class Instruction : UnlabelledEntity, IEntity
|
||||
internal class Instruction : UnlabelledEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// The additional data following the opcode, if any.
|
||||
@@ -289,11 +289,6 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
}
|
||||
}
|
||||
|
||||
Label IEntity.Label
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
private readonly byte[] data;
|
||||
|
||||
private int PayloadSize => payloadSizes[(int)PayloadType];
|
||||
|
||||
@@ -21,10 +21,9 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
trapFile.WriteSubId(method);
|
||||
trapFile.Write('_');
|
||||
trapFile.Write(index);
|
||||
trapFile.Write(";cil-local");
|
||||
}
|
||||
|
||||
public override string IdSuffix => ";cil-local";
|
||||
|
||||
public override IEnumerable<IExtractionProduct> Contents
|
||||
{
|
||||
get
|
||||
|
||||
@@ -8,10 +8,10 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
{
|
||||
private readonly MemberReferenceHandle handle;
|
||||
private readonly MemberReference mr;
|
||||
private readonly GenericContext gc;
|
||||
private readonly IGenericContext gc;
|
||||
private readonly Type declType;
|
||||
|
||||
public MemberReferenceField(GenericContext gc, MemberReferenceHandle handle) : base(gc.Cx)
|
||||
public MemberReferenceField(IGenericContext gc, MemberReferenceHandle handle) : base(gc.Cx)
|
||||
{
|
||||
this.handle = handle;
|
||||
this.gc = gc;
|
||||
|
||||
@@ -12,10 +12,10 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
private readonly MemberReferenceHandle handle;
|
||||
private readonly MemberReference mr;
|
||||
private readonly Type declaringType;
|
||||
private readonly GenericContext parent;
|
||||
private readonly IGenericContext parent;
|
||||
private readonly Method? sourceDeclaration;
|
||||
|
||||
public MemberReferenceMethod(GenericContext gc, MemberReferenceHandle handle) : base(gc)
|
||||
public MemberReferenceMethod(IGenericContext gc, MemberReferenceHandle handle) : base(gc)
|
||||
{
|
||||
this.handle = handle;
|
||||
this.gc = gc;
|
||||
@@ -23,7 +23,7 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
|
||||
signature = mr.DecodeMethodSignature(new SignatureDecoder(), gc);
|
||||
|
||||
parent = (GenericContext)Cx.CreateGeneric(gc, mr.Parent);
|
||||
parent = (IGenericContext)Cx.CreateGeneric(gc, mr.Parent);
|
||||
|
||||
var declType = parent is Method parentMethod
|
||||
? parentMethod.DeclaringType
|
||||
|
||||
@@ -12,10 +12,10 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
internal abstract class Method : TypeContainer, IMember, ICustomModifierReceiver, IParameterizable
|
||||
{
|
||||
protected MethodTypeParameter[]? genericParams;
|
||||
protected GenericContext gc;
|
||||
protected IGenericContext gc;
|
||||
protected MethodSignature<ITypeSignature> signature;
|
||||
|
||||
protected Method(GenericContext gc) : base(gc.Cx)
|
||||
protected Method(IGenericContext gc) : base(gc.Cx)
|
||||
{
|
||||
this.gc = gc;
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
private readonly Method unboundMethod;
|
||||
private readonly ImmutableArray<Type> typeParams;
|
||||
|
||||
public MethodSpecificationMethod(GenericContext gc, MethodSpecificationHandle handle) : base(gc)
|
||||
public MethodSpecificationMethod(IGenericContext gc, MethodSpecificationHandle handle) : base(gc)
|
||||
{
|
||||
this.handle = handle;
|
||||
ms = Cx.MdReader.GetMethodSpecification(handle);
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
|
||||
public override string Name => "!" + index;
|
||||
|
||||
public MethodTypeParameter(GenericContext gc, Method m, int index) : base(gc)
|
||||
public MethodTypeParameter(IGenericContext gc, Method m, int index) : base(gc)
|
||||
{
|
||||
method = m;
|
||||
this.index = index;
|
||||
|
||||
@@ -14,9 +14,6 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
|
||||
public bool IsGlobalNamespace => ParentNamespace is null;
|
||||
|
||||
public override string IdSuffix => ";namespace";
|
||||
|
||||
|
||||
public override void WriteId(TextWriter trapFile)
|
||||
{
|
||||
if (ParentNamespace != null && !ParentNamespace.IsGlobalNamespace)
|
||||
@@ -27,6 +24,8 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
trapFile.Write(Name);
|
||||
}
|
||||
|
||||
public override string IdSuffix => ";namespacee";
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
if (obj is Namespace ns && Name == ns.Name)
|
||||
|
||||
@@ -8,41 +8,40 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
/// </summary>
|
||||
internal sealed class Parameter : LabelledEntity
|
||||
{
|
||||
private readonly IParameterizable method;
|
||||
private readonly IParameterizable parameterizable;
|
||||
private readonly int index;
|
||||
private readonly Type type;
|
||||
|
||||
public Parameter(Context cx, IParameterizable m, int i, Type t) : base(cx)
|
||||
public Parameter(Context cx, IParameterizable p, int i, Type t) : base(cx)
|
||||
{
|
||||
method = m;
|
||||
parameterizable = p;
|
||||
index = i;
|
||||
type = t;
|
||||
}
|
||||
|
||||
public override void WriteId(TextWriter trapFile)
|
||||
{
|
||||
trapFile.WriteSubId(method);
|
||||
trapFile.WriteSubId(parameterizable);
|
||||
trapFile.Write('_');
|
||||
trapFile.Write(index);
|
||||
trapFile.Write(";cil-parameter");
|
||||
}
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return obj is Parameter param && method.Equals(param.method) && index == param.index;
|
||||
return obj is Parameter param && parameterizable.Equals(param.parameterizable) && index == param.index;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return 23 * method.GetHashCode() + index;
|
||||
return 23 * parameterizable.GetHashCode() + index;
|
||||
}
|
||||
|
||||
public override string IdSuffix => ";cil-parameter";
|
||||
|
||||
public override IEnumerable<IExtractionProduct> Contents
|
||||
{
|
||||
get
|
||||
{
|
||||
yield return Tuples.cil_parameter(this, method, index, type);
|
||||
yield return Tuples.cil_parameter(this, parameterizable, index, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,10 +13,9 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
private readonly Handle handle;
|
||||
private readonly Type type;
|
||||
private readonly PropertyDefinition pd;
|
||||
public override string IdSuffix => ";cil-property";
|
||||
private readonly GenericContext gc;
|
||||
private readonly IGenericContext gc;
|
||||
|
||||
public Property(GenericContext gc, Type type, PropertyDefinitionHandle handle) : base(gc.Cx)
|
||||
public Property(IGenericContext gc, Type type, PropertyDefinitionHandle handle) : base(gc.Cx)
|
||||
{
|
||||
this.gc = gc;
|
||||
this.handle = handle;
|
||||
@@ -38,6 +37,7 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
param.WriteId(trapFile, gc);
|
||||
}
|
||||
trapFile.Write(")");
|
||||
trapFile.Write(";cil-property");
|
||||
}
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
this.shape = shape;
|
||||
}
|
||||
|
||||
public void WriteId(TextWriter trapFile, GenericContext gc)
|
||||
public void WriteId(TextWriter trapFile, IGenericContext gc)
|
||||
{
|
||||
elementType.WriteId(trapFile, gc);
|
||||
trapFile.Write('[');
|
||||
@@ -38,7 +38,7 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
this.elementType = elementType;
|
||||
}
|
||||
|
||||
public void WriteId(TextWriter trapFile, GenericContext gc)
|
||||
public void WriteId(TextWriter trapFile, IGenericContext gc)
|
||||
{
|
||||
elementType.WriteId(trapFile, gc);
|
||||
trapFile.Write('&');
|
||||
@@ -54,7 +54,7 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
this.signature = signature;
|
||||
}
|
||||
|
||||
public void WriteId(TextWriter trapFile, GenericContext gc)
|
||||
public void WriteId(TextWriter trapFile, IGenericContext gc)
|
||||
{
|
||||
FunctionPointerType.WriteName(
|
||||
trapFile.Write,
|
||||
@@ -84,7 +84,7 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
this.typeArguments = typeArguments;
|
||||
}
|
||||
|
||||
public void WriteId(TextWriter trapFile, GenericContext gc)
|
||||
public void WriteId(TextWriter trapFile, IGenericContext gc)
|
||||
{
|
||||
genericType.WriteId(trapFile, gc);
|
||||
trapFile.Write('<');
|
||||
@@ -112,7 +112,7 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public void WriteId(TextWriter trapFile, GenericContext outerGc)
|
||||
public void WriteId(TextWriter trapFile, IGenericContext outerGc)
|
||||
{
|
||||
if (!ReferenceEquals(innerGc, outerGc) && innerGc is Method method)
|
||||
{
|
||||
@@ -132,7 +132,7 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public void WriteId(TextWriter trapFile, GenericContext gc)
|
||||
public void WriteId(TextWriter trapFile, IGenericContext gc)
|
||||
{
|
||||
trapFile.Write("T!");
|
||||
trapFile.Write(index);
|
||||
@@ -158,7 +158,7 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
this.isRequired = isRequired;
|
||||
}
|
||||
|
||||
public void WriteId(TextWriter trapFile, GenericContext gc)
|
||||
public void WriteId(TextWriter trapFile, IGenericContext gc)
|
||||
{
|
||||
unmodifiedType.WriteId(trapFile, gc);
|
||||
trapFile.Write(isRequired ? " modreq(" : " modopt(");
|
||||
@@ -186,7 +186,7 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
this.elementType = elementType;
|
||||
}
|
||||
|
||||
public void WriteId(TextWriter trapFile, GenericContext gc)
|
||||
public void WriteId(TextWriter trapFile, IGenericContext gc)
|
||||
{
|
||||
elementType.WriteId(trapFile, gc);
|
||||
trapFile.Write('*');
|
||||
@@ -207,7 +207,7 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
this.typeCode = typeCode;
|
||||
}
|
||||
|
||||
public void WriteId(TextWriter trapFile, GenericContext gc)
|
||||
public void WriteId(TextWriter trapFile, IGenericContext gc)
|
||||
{
|
||||
trapFile.Write(typeCode.Id());
|
||||
}
|
||||
@@ -227,7 +227,7 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
this.elementType = elementType;
|
||||
}
|
||||
|
||||
public void WriteId(TextWriter trapFile, GenericContext gc)
|
||||
public void WriteId(TextWriter trapFile, IGenericContext gc)
|
||||
{
|
||||
elementType.WriteId(trapFile, gc);
|
||||
trapFile.Write("[]");
|
||||
@@ -248,7 +248,7 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
this.handle = handle;
|
||||
}
|
||||
|
||||
public void WriteId(TextWriter trapFile, GenericContext gc)
|
||||
public void WriteId(TextWriter trapFile, IGenericContext gc)
|
||||
{
|
||||
var type = (Type)gc.Cx.Create(handle);
|
||||
type.WriteId(trapFile);
|
||||
@@ -269,7 +269,7 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
this.handle = handle;
|
||||
}
|
||||
|
||||
public void WriteId(TextWriter trapFile, GenericContext gc)
|
||||
public void WriteId(TextWriter trapFile, IGenericContext gc)
|
||||
{
|
||||
var type = (Type)gc.Cx.Create(handle);
|
||||
type.WriteId(trapFile);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user