Merge branch 'main' of github.com:github/codeql into python-port-stacktrace-exosure

This commit is contained in:
Rasmus Lerchedahl Petersen
2021-02-25 07:24:41 +01:00
667 changed files with 32683 additions and 11632 deletions

21
.github/workflows/check-change-note.yml vendored Normal file
View 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

View File

@@ -5,10 +5,14 @@ on:
branches: branches:
- main - main
- 'rc/*' - 'rc/*'
paths:
- 'csharp/**'
pull_request: pull_request:
branches: branches:
- main - main
- 'rc/*' - 'rc/*'
paths:
- 'csharp/**'
schedule: schedule:
- cron: '0 9 * * 1' - cron: '0 9 * * 1'

View File

@@ -50,7 +50,7 @@ jobs:
uses: ammaraskar/sphinx-action@8b4f60114d7fd1faeba1a712269168508d4750d2 # v0.4 uses: ammaraskar/sphinx-action@8b4f60114d7fd1faeba1a712269168508d4750d2 # v0.4
with: with:
docs-folder: "query-help/" 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" build-command: "sphinx-build -b dirhtml . _build"
- name: Upload HTML artifacts - name: Upload HTML artifacts
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v2

View File

@@ -3,18 +3,3 @@
/java/ @github/codeql-java /java/ @github/codeql-java
/javascript/ @github/codeql-javascript /javascript/ @github/codeql-javascript
/python/ @github/codeql-python /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

View File

@@ -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. - 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). 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).

View File

@@ -356,6 +356,7 @@
], ],
"Inline Test Expectations": [ "Inline Test Expectations": [
"cpp/ql/test/TestUtilities/InlineExpectationsTest.qll", "cpp/ql/test/TestUtilities/InlineExpectationsTest.qll",
"java/ql/test/TestUtilities/InlineExpectationsTest.qll",
"python/ql/test/TestUtilities/InlineExpectationsTest.qll" "python/ql/test/TestUtilities/InlineExpectationsTest.qll"
], ],
"C++ ExternalAPIs": [ "C++ ExternalAPIs": [

View File

@@ -46,7 +46,7 @@ class UntrustedDataToExternalAPIConfig extends TaintTracking::Configuration {
UntrustedDataToExternalAPIConfig() { this = "UntrustedDataToExternalAPIConfig" } UntrustedDataToExternalAPIConfig() { this = "UntrustedDataToExternalAPIConfig" }
override predicate isSource(DataFlow::Node source) { override predicate isSource(DataFlow::Node source) {
exists(RemoteFlowFunction remoteFlow | exists(RemoteFlowSourceFunction remoteFlow |
remoteFlow = source.asExpr().(Call).getTarget() and remoteFlow = source.asExpr().(Call).getTarget() and
remoteFlow.hasRemoteFlowSource(_, _) remoteFlow.hasRemoteFlowSource(_, _)
) )

View File

@@ -34,6 +34,10 @@ class Configuration extends TaintTrackingConfiguration {
override predicate isSink(Element tainted) { override predicate isSink(Element tainted) {
exists(PrintStdoutCall call | call.getAnArgument() = 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 from QueryString query, Element printedArg, PathNode sourceNode, PathNode sinkNode

View File

@@ -8,6 +8,7 @@
* @tags reliability * @tags reliability
* security * security
* external/cwe/cwe-242 * external/cwe/cwe-242
* external/cwe/cwe-676
*/ */
import cpp import cpp

View File

@@ -139,6 +139,19 @@ class Declaration extends Locatable, @declaration {
this.hasQualifiedName("std", "", name) 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. */ /** Gets a specifier of this declaration. */
Specifier getASpecifier() { none() } // overridden in subclasses Specifier getASpecifier() { none() } // overridden in subclasses

View File

@@ -467,7 +467,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
// ... and likewise for destructors. // ... and likewise for destructors.
this.(Destructor).getADestruction().mayBeGloballyImpure() this.(Destructor).getADestruction().mayBeGloballyImpure()
else 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. // have side-effects.
not this.hasGlobalOrStdName([ not this.hasGlobalOrStdName([
"strcmp", "wcscmp", "_mbscmp", "strlen", "wcslen", "_mbslen", "_mbslen_l", "_mbstrlen", "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 * 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: * `TopLevelFunction` but `MyMemberFunction` is not:
* ``` * ```
* void MyFunction() { * void MyFunction() {

View File

@@ -34,10 +34,10 @@ class Scanf extends ScanfFunction {
Scanf() { Scanf() {
this instanceof TopLevelFunction and this instanceof TopLevelFunction and
( (
hasName("scanf") or // scanf(format, args...) hasGlobalOrStdOrBslName("scanf") or // scanf(format, args...)
hasName("wscanf") or // wscanf(format, args...) hasGlobalOrStdOrBslName("wscanf") or // wscanf(format, args...)
hasName("_scanf_l") or // _scanf_l(format, locale, args...) hasGlobalName("_scanf_l") or // _scanf_l(format, locale, args...)
hasName("_wscanf_l") // _wscanf_l(format, locale, args...) hasGlobalName("_wscanf_l") // _wscanf_l(format, locale, args...)
) )
} }
@@ -53,10 +53,10 @@ class Fscanf extends ScanfFunction {
Fscanf() { Fscanf() {
this instanceof TopLevelFunction and this instanceof TopLevelFunction and
( (
hasName("fscanf") or // fscanf(src_stream, format, args...) hasGlobalOrStdOrBslName("fscanf") or // fscanf(src_stream, format, args...)
hasName("fwscanf") or // fwscanf(src_stream, format, args...) hasGlobalOrStdOrBslName("fwscanf") or // fwscanf(src_stream, format, args...)
hasName("_fscanf_l") or // _fscanf_l(src_stream, format, locale, args...) hasGlobalName("_fscanf_l") or // _fscanf_l(src_stream, format, locale, args...)
hasName("_fwscanf_l") // _fwscanf_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() { Sscanf() {
this instanceof TopLevelFunction and this instanceof TopLevelFunction and
( (
hasName("sscanf") or // sscanf(src_stream, format, args...) hasGlobalOrStdOrBslName("sscanf") or // sscanf(src_stream, format, args...)
hasName("swscanf") or // swscanf(src, format, args...) hasGlobalOrStdOrBslName("swscanf") or // swscanf(src, format, args...)
hasName("_sscanf_l") or // _sscanf_l(src, format, locale, args...) hasGlobalName("_sscanf_l") or // _sscanf_l(src, format, locale, args...)
hasName("_swscanf_l") // _swscanf_l(src, format, locale, args...) hasGlobalName("_swscanf_l") // _swscanf_l(src, format, locale, args...)
) )
} }
@@ -91,10 +91,10 @@ class Snscanf extends ScanfFunction {
Snscanf() { Snscanf() {
this instanceof TopLevelFunction and this instanceof TopLevelFunction and
( (
hasName("_snscanf") or // _snscanf(src, max_amount, format, args...) hasGlobalName("_snscanf") or // _snscanf(src, max_amount, format, args...)
hasName("_snwscanf") or // _snwscanf(src, max_amount, format, args...) hasGlobalName("_snwscanf") or // _snwscanf(src, max_amount, format, args...)
hasName("_snscanf_l") or // _snscanf_l(src, max_amount, format, locale, args...) hasGlobalName("_snscanf_l") or // _snscanf_l(src, max_amount, format, locale, args...)
hasName("_snwscanf_l") // _snwscanf_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 // 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. // limit used with non null-terminated strings.
) )

View File

@@ -131,7 +131,22 @@ private predicate lvalueToUpdate(Expr lvalue, Expr outer, ControlFlowNode node)
exists(Call call | node = call | exists(Call call | node = call |
outer = call.getQualifier().getFullyConverted() and outer = call.getQualifier().getFullyConverted() and
outer.getUnspecifiedType() instanceof Class 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 or
assignmentTo(outer, node) assignmentTo(outer, node)
@@ -170,7 +185,11 @@ private predicate pointerToUpdate(Expr pointer, Expr outer, ControlFlowNode node
or or
outer = call.getQualifier().getFullyConverted() and outer = call.getQualifier().getFullyConverted() and
outer.getUnspecifiedType() instanceof PointerType 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 or
exists(PointerFieldAccess fa | exists(PointerFieldAccess fa |

View File

@@ -3598,6 +3598,7 @@ private module FlowExploration {
or or
exists(PartialPathNodeRev mid | exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and revPartialPathStep(mid, node, sc1, sc2, ap, config) and
not clearsContent(node, ap.getHead()) and
not fullBarrier(node, config) and not fullBarrier(node, config) and
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
) )
@@ -3611,6 +3612,7 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid | exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and not fullBarrier(node, config) and
not clearsContent(node, ap.getHead().getContent()) and
if node instanceof CastingNode if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType()) then compatibleTypes(getNodeType(node), ap.getType())
else any() else any()

View File

@@ -3598,6 +3598,7 @@ private module FlowExploration {
or or
exists(PartialPathNodeRev mid | exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and revPartialPathStep(mid, node, sc1, sc2, ap, config) and
not clearsContent(node, ap.getHead()) and
not fullBarrier(node, config) and not fullBarrier(node, config) and
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
) )
@@ -3611,6 +3612,7 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid | exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and not fullBarrier(node, config) and
not clearsContent(node, ap.getHead().getContent()) and
if node instanceof CastingNode if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType()) then compatibleTypes(getNodeType(node), ap.getType())
else any() else any()

View File

@@ -3598,6 +3598,7 @@ private module FlowExploration {
or or
exists(PartialPathNodeRev mid | exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and revPartialPathStep(mid, node, sc1, sc2, ap, config) and
not clearsContent(node, ap.getHead()) and
not fullBarrier(node, config) and not fullBarrier(node, config) and
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
) )
@@ -3611,6 +3612,7 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid | exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and not fullBarrier(node, config) and
not clearsContent(node, ap.getHead().getContent()) and
if node instanceof CastingNode if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType()) then compatibleTypes(getNodeType(node), ap.getType())
else any() else any()

View File

@@ -3598,6 +3598,7 @@ private module FlowExploration {
or or
exists(PartialPathNodeRev mid | exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and revPartialPathStep(mid, node, sc1, sc2, ap, config) and
not clearsContent(node, ap.getHead()) and
not fullBarrier(node, config) and not fullBarrier(node, config) and
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
) )
@@ -3611,6 +3612,7 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid | exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and not fullBarrier(node, config) and
not clearsContent(node, ap.getHead().getContent()) and
if node instanceof CastingNode if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType()) then compatibleTypes(getNodeType(node), ap.getType())
else any() else any()

View File

@@ -3598,6 +3598,7 @@ private module FlowExploration {
or or
exists(PartialPathNodeRev mid | exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and revPartialPathStep(mid, node, sc1, sc2, ap, config) and
not clearsContent(node, ap.getHead()) and
not fullBarrier(node, config) and not fullBarrier(node, config) and
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
) )
@@ -3611,6 +3612,7 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid | exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and not fullBarrier(node, config) and
not clearsContent(node, ap.getHead().getContent()) and
if node instanceof CastingNode if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType()) then compatibleTypes(getNodeType(node), ap.getType())
else any() else any()

View File

@@ -3598,6 +3598,7 @@ private module FlowExploration {
or or
exists(PartialPathNodeRev mid | exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and revPartialPathStep(mid, node, sc1, sc2, ap, config) and
not clearsContent(node, ap.getHead()) and
not fullBarrier(node, config) and not fullBarrier(node, config) and
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
) )
@@ -3611,6 +3612,7 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid | exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and not fullBarrier(node, config) and
not clearsContent(node, ap.getHead().getContent()) and
if node instanceof CastingNode if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType()) then compatibleTypes(getNodeType(node), ap.getType())
else any() else any()

View File

@@ -3598,6 +3598,7 @@ private module FlowExploration {
or or
exists(PartialPathNodeRev mid | exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and revPartialPathStep(mid, node, sc1, sc2, ap, config) and
not clearsContent(node, ap.getHead()) and
not fullBarrier(node, config) and not fullBarrier(node, config) and
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
) )
@@ -3611,6 +3612,7 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid | exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and not fullBarrier(node, config) and
not clearsContent(node, ap.getHead().getContent()) and
if node instanceof CastingNode if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType()) then compatibleTypes(getNodeType(node), ap.getType())
else any() else any()

View File

@@ -3598,6 +3598,7 @@ private module FlowExploration {
or or
exists(PartialPathNodeRev mid | exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and revPartialPathStep(mid, node, sc1, sc2, ap, config) and
not clearsContent(node, ap.getHead()) and
not fullBarrier(node, config) and not fullBarrier(node, config) and
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
) )
@@ -3611,6 +3612,7 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid | exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and not fullBarrier(node, config) and
not clearsContent(node, ap.getHead().getContent()) and
if node instanceof CastingNode if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType()) then compatibleTypes(getNodeType(node), ap.getType())
else any() else any()

View File

@@ -3598,6 +3598,7 @@ private module FlowExploration {
or or
exists(PartialPathNodeRev mid | exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and revPartialPathStep(mid, node, sc1, sc2, ap, config) and
not clearsContent(node, ap.getHead()) and
not fullBarrier(node, config) and not fullBarrier(node, config) and
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
) )
@@ -3611,6 +3612,7 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid | exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and not fullBarrier(node, config) and
not clearsContent(node, ap.getHead().getContent()) and
if node instanceof CastingNode if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType()) then compatibleTypes(getNodeType(node), ap.getType())
else any() else any()

View File

@@ -28,3 +28,8 @@ private import implementations.Swap
private import implementations.GetDelim private import implementations.GetDelim
private import implementations.SmartPointer private import implementations.SmartPointer
private import implementations.Sscanf private import implementations.Sscanf
private import implementations.Send
private import implementations.Recv
private import implementations.Accept
private import implementations.Poll
private import implementations.Select

View 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() }
}

View File

@@ -15,7 +15,7 @@ private class MallocAllocationFunction extends AllocationFunction {
MallocAllocationFunction() { MallocAllocationFunction() {
// --- C library allocation // --- C library allocation
hasGlobalOrStdName("malloc") and // malloc(size) hasGlobalOrStdOrBslName("malloc") and // malloc(size)
sizeArg = 0 sizeArg = 0
or or
hasGlobalName([ hasGlobalName([
@@ -104,7 +104,7 @@ private class CallocAllocationFunction extends AllocationFunction {
CallocAllocationFunction() { CallocAllocationFunction() {
// --- C library allocation // --- C library allocation
hasGlobalOrStdName("calloc") and // calloc(num, size) hasGlobalOrStdOrBslName("calloc") and // calloc(num, size)
sizeArg = 1 and sizeArg = 1 and
multArg = 0 multArg = 0
} }
@@ -124,7 +124,7 @@ private class ReallocAllocationFunction extends AllocationFunction {
ReallocAllocationFunction() { ReallocAllocationFunction() {
// --- C library allocation // --- C library allocation
hasGlobalOrStdName("realloc") and // realloc(ptr, size) hasGlobalOrStdOrBslName("realloc") and // realloc(ptr, size)
sizeArg = 1 and sizeArg = 1 and
reallocArg = 0 reallocArg = 0
or or

View File

@@ -13,9 +13,13 @@ private class StandardDeallocationFunction extends DeallocationFunction {
int freedArg; int freedArg;
StandardDeallocationFunction() { StandardDeallocationFunction() {
hasGlobalName([ hasGlobalOrStdOrBslName([
// --- C library allocation // --- C library allocation
"free", "realloc", "free", "realloc"
]) and
freedArg = 0
or
hasGlobalName([
// --- OpenSSL memory allocation // --- OpenSSL memory allocation
"CRYPTO_free", "CRYPTO_secure_free" "CRYPTO_free", "CRYPTO_secure_free"
]) and ]) and

View File

@@ -1,8 +1,8 @@
import semmle.code.cpp.models.interfaces.Alias import semmle.code.cpp.models.interfaces.Alias
import semmle.code.cpp.models.interfaces.FlowSource import semmle.code.cpp.models.interfaces.FlowSource
private class Fread extends AliasFunction, RemoteFlowFunction { private class Fread extends AliasFunction, RemoteFlowSourceFunction {
Fread() { this.hasGlobalName("fread") } Fread() { this.hasGlobalOrStdOrBslName("fread") }
override predicate parameterNeverEscapes(int n) { override predicate parameterNeverEscapes(int n) {
n = 0 or n = 0 or

View File

@@ -7,7 +7,7 @@ import semmle.code.cpp.models.interfaces.FlowSource
* The standard functions `getdelim`, `getwdelim` and the glibc variant `__getdelim`. * The standard functions `getdelim`, `getwdelim` and the glibc variant `__getdelim`.
*/ */
private class GetDelimFunction extends TaintFunction, AliasFunction, SideEffectFunction, private class GetDelimFunction extends TaintFunction, AliasFunction, SideEffectFunction,
RemoteFlowFunction { RemoteFlowSourceFunction {
GetDelimFunction() { hasGlobalName(["getdelim", "getwdelim", "__getdelim"]) } GetDelimFunction() { hasGlobalName(["getdelim", "getwdelim", "__getdelim"]) }
override predicate hasTaintFlow(FunctionInput i, FunctionOutput o) { override predicate hasTaintFlow(FunctionInput i, FunctionOutput o) {

View File

@@ -8,8 +8,8 @@ import semmle.code.cpp.models.interfaces.FlowSource
/** /**
* The POSIX function `getenv`. * The POSIX function `getenv`.
*/ */
class Getenv extends LocalFlowFunction { class Getenv extends LocalFlowSourceFunction {
Getenv() { this.hasGlobalName("getenv") } Getenv() { this.hasGlobalOrStdOrBslName("getenv") }
override predicate hasLocalFlowSource(FunctionOutput output, string description) { override predicate hasLocalFlowSource(FunctionOutput output, string description) {
( (

View File

@@ -14,12 +14,12 @@ import semmle.code.cpp.models.interfaces.FlowSource
* The standard functions `gets` and `fgets`. * The standard functions `gets` and `fgets`.
*/ */
private class GetsFunction extends DataFlowFunction, TaintFunction, ArrayFunction, AliasFunction, private class GetsFunction extends DataFlowFunction, TaintFunction, ArrayFunction, AliasFunction,
SideEffectFunction, RemoteFlowFunction { SideEffectFunction, RemoteFlowSourceFunction {
GetsFunction() { GetsFunction() {
// gets(str) // gets(str)
// fgets(str, num, stream) // fgets(str, num, stream)
// fgetws(wstr, num, stream) // fgetws(wstr, num, stream)
hasGlobalOrStdName(["gets", "fgets", "fgetws"]) hasGlobalOrStdOrBslName(["gets", "fgets", "fgetws"])
} }
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { 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) { override predicate hasArrayWithVariableSize(int bufParam, int countParam) {
not hasGlobalOrStdName("gets") and not hasName("gets") and
bufParam = 0 and bufParam = 0 and
countParam = 1 countParam = 1
} }
override predicate hasArrayWithUnknownSize(int bufParam) { override predicate hasArrayWithUnknownSize(int bufParam) {
hasGlobalOrStdName("gets") and hasName("gets") and
bufParam = 0 bufParam = 0
} }

View File

@@ -6,12 +6,9 @@ import semmle.code.cpp.models.interfaces.SideEffect
/** /**
* The standard function templates `std::move` and `std::forward`. * The standard function templates `std::move` and `std::forward`.
*/ */
private class IdentityFunction extends DataFlowFunction, SideEffectFunction, AliasFunction { private class IdentityFunction extends DataFlowFunction, SideEffectFunction, AliasFunction,
IdentityFunction() { FunctionTemplateInstantiation {
this.getNamespace().getParentNamespace() instanceof GlobalNamespace and IdentityFunction() { this.hasQualifiedName("std", ["move", "forward"]) }
this.getNamespace().getName() = "std" and
this.getName() = ["move", "forward"]
}
override predicate hasOnlySpecificReadSideEffects() { any() } override predicate hasOnlySpecificReadSideEffects() { any() }

View File

@@ -15,7 +15,7 @@ import semmle.code.cpp.models.interfaces.Iterator
*/ */
private class IteratorTraits extends Class { private class IteratorTraits extends Class {
IteratorTraits() { IteratorTraits() {
this.hasQualifiedName("std", "iterator_traits") and this.hasQualifiedName(["std", "bsl"], "iterator_traits") and
not this instanceof TemplateClass and not this instanceof TemplateClass and
exists(TypedefType t | exists(TypedefType t |
this.getAMember() = t and this.getAMember() = t and
@@ -26,6 +26,14 @@ private class IteratorTraits extends Class {
Type getIteratorType() { result = this.getTemplateArgument(0) } 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. * 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("pointer") and
this.getAMember().(TypedefType).hasName("reference") and this.getAMember().(TypedefType).hasName("reference") and
this.getAMember().(TypedefType).hasName("iterator_category") 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. * The `std::iterator` class.
*/ */
private class StdIterator extends 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 * Gets the `FunctionInput` corresponding to an iterator parameter to
* `std::iterator_traits` instantiation for it. * 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) { private FunctionInput getIteratorArgumentInput(Operator op, int index) {
exists(Type t | exists(Type t |
t = t =
@@ -155,17 +159,21 @@ private class IteratorSubOperator extends Operator, TaintFunction {
private class IteratorAssignArithmeticOperator extends Operator, DataFlowFunction, TaintFunction { private class IteratorAssignArithmeticOperator extends Operator, DataFlowFunction, TaintFunction {
IteratorAssignArithmeticOperator() { IteratorAssignArithmeticOperator() {
this.hasName(["operator+=", "operator-="]) and this.hasName(["operator+=", "operator-="]) and
this.getDeclaringType() instanceof Iterator exists(getIteratorArgumentInput(this, 0))
} }
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
input.isParameter(0) and input.isParameter(0) and
output.isReturnValue() output.isReturnValue()
or
input.isParameterDeref(0) and output.isReturnValueDeref()
} }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { 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 input.isParameterDeref(1) and
output.isParameterDeref(0) output.isParameterDeref(0)
} }
@@ -177,8 +185,7 @@ private class IteratorAssignArithmeticOperator extends Operator, DataFlowFunctio
class IteratorPointerDereferenceMemberOperator extends MemberFunction, TaintFunction, class IteratorPointerDereferenceMemberOperator extends MemberFunction, TaintFunction,
IteratorReferenceFunction { IteratorReferenceFunction {
IteratorPointerDereferenceMemberOperator() { IteratorPointerDereferenceMemberOperator() {
this.hasName("operator*") and this.getClassAndName("operator*") instanceof Iterator
this.getDeclaringType() instanceof Iterator
} }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
@@ -195,8 +202,7 @@ class IteratorPointerDereferenceMemberOperator extends MemberFunction, TaintFunc
*/ */
private class IteratorCrementMemberOperator extends MemberFunction, DataFlowFunction, TaintFunction { private class IteratorCrementMemberOperator extends MemberFunction, DataFlowFunction, TaintFunction {
IteratorCrementMemberOperator() { IteratorCrementMemberOperator() {
this.hasName(["operator++", "operator--"]) and this.getClassAndName(["operator++", "operator--"]) instanceof Iterator
this.getDeclaringType() instanceof Iterator
} }
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { 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. * A member `operator->` function for an iterator type.
*/ */
private class IteratorFieldMemberOperator extends Operator, TaintFunction { private class IteratorFieldMemberOperator extends Operator, TaintFunction {
IteratorFieldMemberOperator() { IteratorFieldMemberOperator() { this.getClassAndName("operator->") instanceof Iterator }
this.hasName("operator->") and
this.getDeclaringType() instanceof Iterator
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isQualifierObject() and input.isQualifierObject() and
@@ -236,8 +239,7 @@ private class IteratorFieldMemberOperator extends Operator, TaintFunction {
*/ */
private class IteratorBinaryArithmeticMemberOperator extends MemberFunction, TaintFunction { private class IteratorBinaryArithmeticMemberOperator extends MemberFunction, TaintFunction {
IteratorBinaryArithmeticMemberOperator() { IteratorBinaryArithmeticMemberOperator() {
this.hasName(["operator+", "operator-"]) and this.getClassAndName(["operator+", "operator-"]) instanceof Iterator
this.getDeclaringType() instanceof Iterator
} }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
@@ -252,21 +254,24 @@ private class IteratorBinaryArithmeticMemberOperator extends MemberFunction, Tai
private class IteratorAssignArithmeticMemberOperator extends MemberFunction, DataFlowFunction, private class IteratorAssignArithmeticMemberOperator extends MemberFunction, DataFlowFunction,
TaintFunction { TaintFunction {
IteratorAssignArithmeticMemberOperator() { IteratorAssignArithmeticMemberOperator() {
this.hasName(["operator+=", "operator-="]) and this.getClassAndName(["operator+=", "operator-="]) instanceof Iterator
this.getDeclaringType() instanceof Iterator
} }
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
input.isQualifierAddress() and input.isQualifierAddress() and
output.isReturnValue() output.isReturnValue()
or
input.isReturnValueDeref() and
output.isQualifierObject()
} }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isQualifierObject() and input.isQualifierObject() and
output.isReturnValueDeref() 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, private class IteratorArrayMemberOperator extends MemberFunction, TaintFunction,
IteratorReferenceFunction { IteratorReferenceFunction {
IteratorArrayMemberOperator() { IteratorArrayMemberOperator() { this.getClassAndName("operator[]") instanceof Iterator }
this.hasName("operator[]") and
this.getDeclaringType() instanceof Iterator
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isQualifierObject() and input.isQualifierObject() and
@@ -295,8 +297,7 @@ private class IteratorArrayMemberOperator extends MemberFunction, TaintFunction,
*/ */
private class IteratorAssignmentMemberOperator extends MemberFunction, TaintFunction { private class IteratorAssignmentMemberOperator extends MemberFunction, TaintFunction {
IteratorAssignmentMemberOperator() { IteratorAssignmentMemberOperator() {
this.hasName("operator=") and this.getClassAndName("operator=") instanceof Iterator and
this.getDeclaringType() instanceof Iterator and
not this instanceof CopyAssignmentOperator and not this instanceof CopyAssignmentOperator and
not this instanceof MoveAssignmentOperator not this instanceof MoveAssignmentOperator
} }
@@ -337,7 +338,7 @@ private class BeginOrEndFunction extends MemberFunction, TaintFunction, GetItera
*/ */
private class InserterIteratorFunction extends GetIteratorFunction { private class InserterIteratorFunction extends GetIteratorFunction {
InserterIteratorFunction() { 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) { override predicate getsIterator(FunctionInput input, FunctionOutput output) {

View File

@@ -20,7 +20,7 @@ private class MemcpyFunction extends ArrayFunction, DataFlowFunction, SideEffect
// memcpy(dest, src, num) // memcpy(dest, src, num)
// memmove(dest, src, num) // memmove(dest, src, num)
// memmove(dest, src, num, remaining) // memmove(dest, src, num, remaining)
this.hasGlobalOrStdName(["memcpy", "memmove"]) this.hasGlobalOrStdOrBslName(["memcpy", "memmove"])
or or
// bcopy(src, dest, num) // bcopy(src, dest, num)
// mempcpy(dest, src, num) // mempcpy(dest, src, num)

View File

@@ -15,7 +15,9 @@ import semmle.code.cpp.models.interfaces.SideEffect
private class MemsetFunction extends ArrayFunction, DataFlowFunction, AliasFunction, private class MemsetFunction extends ArrayFunction, DataFlowFunction, AliasFunction,
SideEffectFunction { SideEffectFunction {
MemsetFunction() { MemsetFunction() {
this.hasGlobalOrStdName(["memset", "wmemset"]) this.hasGlobalOrStdOrBslName("memset")
or
this.hasGlobalOrStdName("wmemset")
or or
this.hasGlobalName([bzero(), "__builtin_memset", "__builtin_memset_chk"]) this.hasGlobalName([bzero(), "__builtin_memset", "__builtin_memset_chk"])
} }

View 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() }
}

View File

@@ -15,7 +15,7 @@ private class Printf extends FormattingFunction, AliasFunction {
Printf() { Printf() {
this instanceof TopLevelFunction and this instanceof TopLevelFunction and
( (
hasGlobalOrStdName(["printf", "wprintf"]) or hasGlobalOrStdOrBslName(["printf", "wprintf"]) or
hasGlobalName(["printf_s", "wprintf_s", "g_printf"]) hasGlobalName(["printf_s", "wprintf_s", "g_printf"])
) and ) and
not exists(getDefinition().getFile().getRelativePath()) not exists(getDefinition().getFile().getRelativePath())
@@ -23,10 +23,7 @@ private class Printf extends FormattingFunction, AliasFunction {
override int getFormatParameterIndex() { result = 0 } override int getFormatParameterIndex() { result = 0 }
deprecated override predicate isWideCharDefault() { deprecated override predicate isWideCharDefault() { hasName(["wprintf", "wprintf_s"]) }
hasGlobalOrStdName("wprintf") or
hasGlobalName("wprintf_s")
}
override predicate isOutputGlobal() { any() } override predicate isOutputGlobal() { any() }
@@ -44,7 +41,7 @@ private class Fprintf extends FormattingFunction {
Fprintf() { Fprintf() {
this instanceof TopLevelFunction and this instanceof TopLevelFunction and
( (
hasGlobalOrStdName(["fprintf", "fwprintf"]) or hasGlobalOrStdOrBslName(["fprintf", "fwprintf"]) or
hasGlobalName("g_fprintf") hasGlobalName("g_fprintf")
) and ) and
not exists(getDefinition().getFile().getRelativePath()) not exists(getDefinition().getFile().getRelativePath())
@@ -52,7 +49,7 @@ private class Fprintf extends FormattingFunction {
override int getFormatParameterIndex() { result = 1 } 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 } override int getOutputParameterIndex(boolean isStream) { result = 0 and isStream = true }
} }
@@ -64,7 +61,7 @@ private class Sprintf extends FormattingFunction {
Sprintf() { Sprintf() {
this instanceof TopLevelFunction and this instanceof TopLevelFunction and
( (
hasGlobalOrStdName([ hasGlobalOrStdOrBslName([
"sprintf", // sprintf(dst, format, args...) "sprintf", // sprintf(dst, format, args...)
"wsprintf" // wsprintf(dst, format, args...) "wsprintf" // wsprintf(dst, format, args...)
]) ])
@@ -90,22 +87,20 @@ private class Sprintf extends FormattingFunction {
} }
override int getFormatParameterIndex() { override int getFormatParameterIndex() {
hasGlobalName("g_strdup_printf") and result = 0 hasName("g_strdup_printf") and result = 0
or or
hasGlobalName("__builtin___sprintf_chk") and result = 3 hasName("__builtin___sprintf_chk") and result = 3
or or
not getName() = ["g_strdup_printf", "__builtin___sprintf_chk"] and not getName() = ["g_strdup_printf", "__builtin___sprintf_chk"] and
result = 1 result = 1
} }
override int getOutputParameterIndex(boolean isStream) { 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() { override int getFirstFormatArgumentIndex() {
if hasGlobalName("__builtin___sprintf_chk") if hasName("__builtin___sprintf_chk") then result = 4 else result = getNumberOfParameters()
then result = 4
else result = getNumberOfParameters()
} }
} }
@@ -116,7 +111,7 @@ private class SnprintfImpl extends Snprintf {
SnprintfImpl() { SnprintfImpl() {
this instanceof TopLevelFunction and this instanceof TopLevelFunction and
( (
hasGlobalOrStdName([ hasGlobalOrStdOrBslName([
"snprintf", // C99 defines snprintf "snprintf", // C99 defines snprintf
"swprintf" // The s version of wide-char printf is also always the n version "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() { override predicate returnsFullFormatLength() {
( hasName(["snprintf", "g_snprintf", "__builtin___snprintf_chk", "snprintf_s"]) and
hasGlobalOrStdName("snprintf") or
hasGlobalName(["g_snprintf", "__builtin___snprintf_chk", "snprintf_s"])
) and
not exists(getDefinition().getFile().getRelativePath()) not exists(getDefinition().getFile().getRelativePath())
} }

View File

@@ -3,11 +3,14 @@ import semmle.code.cpp.models.interfaces.Taint
import semmle.code.cpp.models.interfaces.Alias import semmle.code.cpp.models.interfaces.Alias
import semmle.code.cpp.models.interfaces.SideEffect 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, private class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunction,
SideEffectFunction { SideEffectFunction {
PureStrFunction() { PureStrFunction() {
hasGlobalOrStdName([ hasGlobalOrStdOrBslName([
atoi(), "strcasestr", "strchnul", "strchr", "strchrnul", "strstr", "strpbrk", "strrchr", atoi(), "strcasestr", "strchnul", "strchr", "strchrnul", "strstr", "strpbrk", "strrchr",
"strspn", strtol(), strrev(), strcmp(), strlwr(), strupr() "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 { private class StrLenFunction extends AliasFunction, ArrayFunction, SideEffectFunction {
StrLenFunction() { StrLenFunction() {
hasGlobalOrStdName(["strlen", "strnlen", "wcslen"]) hasGlobalOrStdOrBslName(["strlen", "strnlen", "wcslen"])
or or
hasGlobalName(["_mbslen", "_mbslen_l", "_mbstrlen", "_mbstrlen_l"]) 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 { private class PureFunction extends TaintFunction, SideEffectFunction {
PureFunction() { hasGlobalOrStdName(["abs", "labs"]) } PureFunction() { hasGlobalOrStdOrBslName(["abs", "labs"]) }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
exists(ParameterIndex i | exists(ParameterIndex i |
@@ -140,11 +148,14 @@ private class PureFunction extends TaintFunction, SideEffectFunction {
override predicate hasOnlySpecificWriteSideEffects() { any() } 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, private class PureMemFunction extends AliasFunction, ArrayFunction, TaintFunction,
SideEffectFunction { SideEffectFunction {
PureMemFunction() { PureMemFunction() {
hasGlobalOrStdName([ hasGlobalOrStdOrBslName([
"memchr", "__builtin_memchr", "memrchr", "rawmemchr", "memcmp", "__builtin_memcmp", "memmem" "memchr", "__builtin_memchr", "memrchr", "rawmemchr", "memcmp", "__builtin_memcmp", "memmem"
]) or ]) or
this.hasGlobalName("memfrob") this.hasGlobalName("memfrob")

View 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()
}
}

View 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() }
}

View 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()
}
}

View File

@@ -4,14 +4,14 @@ import semmle.code.cpp.models.interfaces.Taint
* The `std::shared_ptr` and `std::unique_ptr` template classes. * The `std::shared_ptr` and `std::unique_ptr` template classes.
*/ */
private class UniqueOrSharedPtr extends Class { 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. * The `std::make_shared` and `std::make_unique` template functions.
*/ */
private class MakeUniqueOrShared extends TaintFunction { 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) { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// Exclude the specializations of `std::make_shared` and `std::make_unique` that allocate arrays // Exclude the specializations of `std::make_shared` and `std::make_unique` that allocate arrays

View File

@@ -5,6 +5,41 @@
import semmle.code.cpp.models.interfaces.Taint import semmle.code.cpp.models.interfaces.Taint
import semmle.code.cpp.models.interfaces.Iterator 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 * Additional model for standard container constructors that reference the
* value type of the container (that is, the `T` in `std::vector<T>`). For * 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 { private class StdSequenceContainerConstructor extends Constructor, TaintFunction {
StdSequenceContainerConstructor() { 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`. * The standard container function `data`.
*/ */
private class StdSequenceContainerData extends TaintFunction { 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) { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from container itself (qualifier) to return value // flow from container itself (qualifier) to return value
@@ -69,8 +110,10 @@ private class StdSequenceContainerData extends TaintFunction {
*/ */
private class StdSequenceContainerPush extends TaintFunction { private class StdSequenceContainerPush extends TaintFunction {
StdSequenceContainerPush() { StdSequenceContainerPush() {
this.hasQualifiedName("std", ["vector", "deque", "list"], "push_back") or this.getClassAndName("push_back") instanceof Vector or
this.hasQualifiedName("std", ["deque", "list", "forward_list"], "push_front") 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) { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
@@ -85,8 +128,11 @@ private class StdSequenceContainerPush extends TaintFunction {
*/ */
private class StdSequenceContainerFrontBack extends TaintFunction { private class StdSequenceContainerFrontBack extends TaintFunction {
StdSequenceContainerFrontBack() { StdSequenceContainerFrontBack() {
this.hasQualifiedName("std", ["array", "vector", "deque", "list", "forward_list"], "front") or this.getClassAndName(["front", "back"]) instanceof Array or
this.hasQualifiedName("std", ["array", "vector", "deque", "list"], "back") 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) { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
@@ -101,8 +147,10 @@ private class StdSequenceContainerFrontBack extends TaintFunction {
*/ */
private class StdSequenceContainerInsert extends TaintFunction { private class StdSequenceContainerInsert extends TaintFunction {
StdSequenceContainerInsert() { StdSequenceContainerInsert() {
this.hasQualifiedName("std", ["vector", "deque", "list"], "insert") or this.getClassAndName("insert") instanceof Deque or
this.hasQualifiedName("std", "forward_list", "insert_after") 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 { private class StdSequenceContainerAssign extends TaintFunction {
StdSequenceContainerAssign() { 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 { private class StdSequenceContainerAt extends TaintFunction {
StdSequenceContainerAt() { 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) { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
@@ -188,7 +241,7 @@ private class StdSequenceContainerAt extends TaintFunction {
* The standard vector `emplace` function. * The standard vector `emplace` function.
*/ */
class StdVectorEmplace extends TaintFunction { class StdVectorEmplace extends TaintFunction {
StdVectorEmplace() { this.hasQualifiedName("std", "vector", "emplace") } StdVectorEmplace() { this.getClassAndName("emplace") instanceof Vector }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from any parameter except the position iterator to qualifier and return value // 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. * The standard vector `emplace_back` function.
*/ */
class StdVectorEmplaceBack extends TaintFunction { 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) { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from any parameter to qualifier // flow from any parameter to qualifier

View File

@@ -5,14 +5,18 @@
import semmle.code.cpp.models.interfaces.Taint import semmle.code.cpp.models.interfaces.Taint
import semmle.code.cpp.models.interfaces.Iterator 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. * Additional model for map constructors using iterator inputs.
*/ */
private class StdMapConstructor extends Constructor, TaintFunction { private class StdMapConstructor extends Constructor, TaintFunction {
StdMapConstructor() { StdMapConstructor() { this.getDeclaringType() instanceof MapOrUnorderedMap }
this.hasQualifiedName("std", "map", "map") or
this.hasQualifiedName("std", "unordered_map", "unordered_map")
}
/** /**
* Gets the index of a parameter to this function that is an iterator. * 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 { private class StdMapInsert extends TaintFunction {
StdMapInsert() { 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) { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
@@ -55,9 +59,7 @@ private class StdMapInsert extends TaintFunction {
* The standard map `emplace` and `emplace_hint` functions. * The standard map `emplace` and `emplace_hint` functions.
*/ */
private class StdMapEmplace extends TaintFunction { private class StdMapEmplace extends TaintFunction {
StdMapEmplace() { StdMapEmplace() { this.getClassAndName(["emplace", "emplace_hint"]) instanceof MapOrUnorderedMap }
this.hasQualifiedName("std", ["map", "unordered_map"], ["emplace", "emplace_hint"])
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from the last parameter (which may be the value part used to // 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. * The standard map `try_emplace` function.
*/ */
private class StdMapTryEmplace extends TaintFunction { 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) { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from any parameter apart from the key to qualifier and return value // 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. * The standard map `merge` function.
*/ */
private class StdMapMerge extends TaintFunction { 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) { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// container1.merge(container2) // container1.merge(container2)
@@ -119,7 +121,7 @@ private class StdMapMerge extends TaintFunction {
* The standard map functions `at` and `operator[]`. * The standard map functions `at` and `operator[]`.
*/ */
private class StdMapAt extends TaintFunction { 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) { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from qualifier to referenced return value // flow from qualifier to referenced return value
@@ -136,7 +138,7 @@ private class StdMapAt extends TaintFunction {
* The standard map `find` function. * The standard map `find` function.
*/ */
private class StdMapFind extends TaintFunction { 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) { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isQualifierObject() and input.isQualifierObject() and
@@ -148,7 +150,7 @@ private class StdMapFind extends TaintFunction {
* The standard map `erase` function. * The standard map `erase` function.
*/ */
private class StdMapErase extends TaintFunction { 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) { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from qualifier to iterator return value // flow from qualifier to iterator return value
@@ -163,8 +165,7 @@ private class StdMapErase extends TaintFunction {
*/ */
private class StdMapEqualRange extends TaintFunction { private class StdMapEqualRange extends TaintFunction {
StdMapEqualRange() { StdMapEqualRange() {
this.hasQualifiedName("std", ["map", "unordered_map"], this.getClassAndName(["lower_bound", "upper_bound", "equal_range"]) instanceof MapOrUnorderedMap
["lower_bound", "upper_bound", "equal_range"])
} }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {

View File

@@ -7,10 +7,16 @@ import semmle.code.cpp.models.interfaces.Taint
/** /**
* An instantiation of `std::pair<T1, T2>`. * An instantiation of `std::pair<T1, T2>`.
*/ */
class StdPairClass extends ClassTemplateInstantiation { private class StdPair extends ClassTemplateInstantiation {
StdPairClass() { getTemplate().hasQualifiedName("std", "pair") } 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 * 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 * 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 { class StdPairCopyishConstructor extends Constructor, TaintFunction {
StdPairCopyishConstructor() { StdPairCopyishConstructor() {
this.getDeclaringType() instanceof StdPairClass and this.getDeclaringType() instanceof StdPair and
this.getNumberOfParameters() = 1 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) { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
@@ -38,7 +44,7 @@ class StdPairCopyishConstructor extends Constructor, TaintFunction {
* Additional model for `std::pair` constructors. * Additional model for `std::pair` constructors.
*/ */
private class StdPairConstructor extends Constructor, TaintFunction { 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 * Gets the index of a parameter to this function that is a reference to

View File

@@ -5,14 +5,18 @@
import semmle.code.cpp.models.interfaces.Taint import semmle.code.cpp.models.interfaces.Taint
import semmle.code.cpp.models.interfaces.Iterator 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. * Additional model for set constructors using iterator inputs.
*/ */
private class StdSetConstructor extends Constructor, TaintFunction { private class StdSetConstructor extends Constructor, TaintFunction {
StdSetConstructor() { StdSetConstructor() { this.getDeclaringType() instanceof StdSet }
this.hasQualifiedName("std", "set", "set") or
this.hasQualifiedName("std", "unordered_set", "unordered_set")
}
/** /**
* Gets the index of a parameter to this function that is an iterator. * 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. * The standard set `insert` and `insert_or_assign` functions.
*/ */
private class StdSetInsert extends TaintFunction { 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) { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from last parameter to qualifier and return value // 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. * The standard set `emplace` and `emplace_hint` functions.
*/ */
private class StdSetEmplace extends TaintFunction { private class StdSetEmplace extends TaintFunction {
StdSetEmplace() { StdSetEmplace() { this.getClassAndName(["emplace", "emplace_hint"]) instanceof StdSet }
this.hasQualifiedName("std", ["set", "unordered_set"], ["emplace", "emplace_hint"])
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from any parameter to qualifier and return value // flow from any parameter to qualifier and return value
@@ -76,7 +78,7 @@ private class StdSetEmplace extends TaintFunction {
* The standard set `merge` function. * The standard set `merge` function.
*/ */
private class StdSetMerge extends TaintFunction { 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) { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// container1.merge(container2) // container1.merge(container2)
@@ -89,7 +91,7 @@ private class StdSetMerge extends TaintFunction {
* The standard set `find` function. * The standard set `find` function.
*/ */
private class StdSetFind extends TaintFunction { 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) { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isQualifierObject() and input.isQualifierObject() and
@@ -101,7 +103,7 @@ private class StdSetFind extends TaintFunction {
* The standard set `erase` function. * The standard set `erase` function.
*/ */
private class StdSetErase extends TaintFunction { 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) { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from qualifier to iterator return value // flow from qualifier to iterator return value
@@ -116,8 +118,7 @@ private class StdSetErase extends TaintFunction {
*/ */
private class StdSetEqualRange extends TaintFunction { private class StdSetEqualRange extends TaintFunction {
StdSetEqualRange() { StdSetEqualRange() {
this.hasQualifiedName("std", ["set", "unordered_set"], this.getClassAndName(["lower_bound", "upper_bound", "equal_range"]) instanceof StdSet
["lower_bound", "upper_bound", "equal_range"])
} }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {

View File

@@ -12,7 +12,7 @@ import semmle.code.cpp.models.interfaces.DataFlow
* The `std::basic_string` template class instantiations. * The `std::basic_string` template class instantiations.
*/ */
private class StdBasicString extends ClassTemplateInstantiation { 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 { private class StdStringPlus extends TaintFunction {
StdStringPlus() { StdStringPlus() {
this.hasQualifiedName("std", "operator+") and this.hasQualifiedName(["std", "bsl"], "operator+") and
this.getUnspecifiedType() instanceof StdBasicString 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[]`. * The `std::string` functions `at` and `operator[]`.
*/ */
@@ -280,7 +273,7 @@ private class StdStringAt extends TaintFunction {
* The `std::basic_istream` template class instantiations. * The `std::basic_istream` template class instantiations.
*/ */
private class StdBasicIStream extends ClassTemplateInstantiation { 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 { private class StdIStreamInNonMember extends DataFlowFunction, TaintFunction {
StdIStreamInNonMember() { StdIStreamInNonMember() {
this.hasQualifiedName("std", "operator>>") and this.hasQualifiedName(["std", "bsl"], "operator>>") and
this.getUnspecifiedType().(ReferenceType).getBaseType() instanceof StdBasicIStream this.getUnspecifiedType().(ReferenceType).getBaseType() instanceof StdBasicIStream
} }
@@ -462,7 +455,7 @@ private class StdIStreamGetLine extends DataFlowFunction, TaintFunction {
* The (non-member) function `std::getline`. * The (non-member) function `std::getline`.
*/ */
private class StdGetLine extends DataFlowFunction, TaintFunction { private class StdGetLine extends DataFlowFunction, TaintFunction {
StdGetLine() { this.hasQualifiedName("std", "getline") } StdGetLine() { this.hasQualifiedName(["std", "bsl"], "getline") }
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
// flow from first parameter to return value // flow from first parameter to return value
@@ -488,7 +481,7 @@ private class StdGetLine extends DataFlowFunction, TaintFunction {
* The `std::basic_ostream` template class instantiations. * The `std::basic_ostream` template class instantiations.
*/ */
private class StdBasicOStream extends ClassTemplateInstantiation { 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 { private class StdOStreamOutNonMember extends DataFlowFunction, TaintFunction {
StdOStreamOutNonMember() { StdOStreamOutNonMember() {
this.hasQualifiedName("std", "operator<<") and this.hasQualifiedName(["std", "bsl"], "operator<<") and
this.getUnspecifiedType().(ReferenceType).getBaseType() instanceof StdBasicOStream 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 * Additional model for `std::stringstream` constructors that take a string
* input parameter. * input parameter.
@@ -609,7 +609,7 @@ private class StdStringStreamStr extends TaintFunction {
* The `std::basic_ios` template class instantiations. * The `std::basic_ios` template class instantiations.
*/ */
private class StdBasicIOS extends ClassTemplateInstantiation { private class StdBasicIOS extends ClassTemplateInstantiation {
StdBasicIOS() { this.hasQualifiedName("std", "basic_ios") } StdBasicIOS() { this.hasQualifiedName(["std", "bsl"], "basic_ios") }
} }
/** /**

View File

@@ -13,7 +13,7 @@ import semmle.code.cpp.models.interfaces.SideEffect
*/ */
class StrcatFunction extends TaintFunction, DataFlowFunction, ArrayFunction, SideEffectFunction { class StrcatFunction extends TaintFunction, DataFlowFunction, ArrayFunction, SideEffectFunction {
StrcatFunction() { StrcatFunction() {
this.hasGlobalOrStdName([ this.hasGlobalOrStdOrBslName([
"strcat", // strcat(dst, src) "strcat", // strcat(dst, src)
"strncat", // strncat(dst, src, max_amount) "strncat", // strncat(dst, src, max_amount)
"wcscat", // wcscat(dst, src) "wcscat", // wcscat(dst, src)

View File

@@ -13,7 +13,7 @@ import semmle.code.cpp.models.interfaces.SideEffect
*/ */
class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction, SideEffectFunction { class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction, SideEffectFunction {
StrcpyFunction() { StrcpyFunction() {
this.hasGlobalOrStdName([ this.hasGlobalOrStdOrBslName([
"strcpy", // strcpy(dst, src) "strcpy", // strcpy(dst, src)
"wcscpy", // wcscpy(dst, src) "wcscpy", // wcscpy(dst, src)
"strncpy", // strncpy(dst, src, max_amount) "strncpy", // strncpy(dst, src, max_amount)

View File

@@ -15,7 +15,7 @@ import semmle.code.cpp.models.interfaces.Taint
*/ */
private class Strtok extends ArrayFunction, AliasFunction, TaintFunction, SideEffectFunction { private class Strtok extends ArrayFunction, AliasFunction, TaintFunction, SideEffectFunction {
Strtok() { Strtok() {
this.hasGlobalOrStdName("strtok") or this.hasGlobalOrStdOrBslName("strtok") or
this.hasGlobalName(["strtok_r", "_strtok_l", "wcstok", "_wcstok_l", "_mbstok", "_mbstok_l"]) this.hasGlobalName(["strtok_r", "_strtok_l", "wcstok", "_wcstok_l", "_mbstok", "_mbstok_l"])
} }

View File

@@ -9,7 +9,7 @@ import semmle.code.cpp.models.interfaces.Alias
* ``` * ```
*/ */
private class Swap extends DataFlowFunction { private class Swap extends DataFlowFunction {
Swap() { this.hasQualifiedName("std", "swap") } Swap() { this.hasQualifiedName(["std", "bsl"], "swap") }
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
input.isParameterDeref(0) and input.isParameterDeref(0) and

View File

@@ -1,9 +1,9 @@
/** /**
* Provides a class for modeling functions that return data from potentially untrusted sources. To use * Provides classes for modeling functions that return data from (or send data to) potentially untrusted
* this QL library, create a QL class extending `DataFlowFunction` with a * 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 * characteristic predicate that selects the function or set of functions you
* are modeling. Within that class, override the predicates provided by * 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 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. * 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. * Holds if remote data described by `description` flows from `output` of a call to this function.
*/ */
abstract predicate hasRemoteFlowSource(FunctionOutput output, string description); 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. * 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. * Holds if data described by `description` flows from `output` of a call to this function.
*/ */
abstract predicate hasLocalFlowSource(FunctionOutput output, string description); 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);
}

View File

@@ -23,7 +23,7 @@ private class RemoteReturnSource extends RemoteFlowSource {
string sourceType; string sourceType;
RemoteReturnSource() { RemoteReturnSource() {
exists(RemoteFlowFunction func, CallInstruction instr, FunctionOutput output | exists(RemoteFlowSourceFunction func, CallInstruction instr, FunctionOutput output |
asInstruction() = instr and asInstruction() = instr and
instr.getStaticCallTarget() = func and instr.getStaticCallTarget() = func and
func.hasRemoteFlowSource(output, sourceType) and func.hasRemoteFlowSource(output, sourceType) and
@@ -42,7 +42,7 @@ private class RemoteParameterSource extends RemoteFlowSource {
string sourceType; string sourceType;
RemoteParameterSource() { RemoteParameterSource() {
exists(RemoteFlowFunction func, WriteSideEffectInstruction instr, FunctionOutput output | exists(RemoteFlowSourceFunction func, WriteSideEffectInstruction instr, FunctionOutput output |
asInstruction() = instr and asInstruction() = instr and
instr.getPrimaryInstruction().(CallInstruction).getStaticCallTarget() = func and instr.getPrimaryInstruction().(CallInstruction).getStaticCallTarget() = func and
func.hasRemoteFlowSource(output, sourceType) and func.hasRemoteFlowSource(output, sourceType) and
@@ -57,7 +57,7 @@ private class LocalReturnSource extends LocalFlowSource {
string sourceType; string sourceType;
LocalReturnSource() { LocalReturnSource() {
exists(LocalFlowFunction func, CallInstruction instr, FunctionOutput output | exists(LocalFlowSourceFunction func, CallInstruction instr, FunctionOutput output |
asInstruction() = instr and asInstruction() = instr and
instr.getStaticCallTarget() = func and instr.getStaticCallTarget() = func and
func.hasLocalFlowSource(output, sourceType) and func.hasLocalFlowSource(output, sourceType) and
@@ -76,7 +76,7 @@ private class LocalParameterSource extends LocalFlowSource {
string sourceType; string sourceType;
LocalParameterSource() { LocalParameterSource() {
exists(LocalFlowFunction func, WriteSideEffectInstruction instr, FunctionOutput output | exists(LocalFlowSourceFunction func, WriteSideEffectInstruction instr, FunctionOutput output |
asInstruction() = instr and asInstruction() = instr and
instr.getPrimaryInstruction().(CallInstruction).getStaticCallTarget() = func and instr.getPrimaryInstruction().(CallInstruction).getStaticCallTarget() = func and
func.hasLocalFlowSource(output, sourceType) and func.hasLocalFlowSource(output, sourceType) and
@@ -98,3 +98,31 @@ private class ArgvSource extends LocalFlowSource {
override string getSourceType() { result = "a command-line argument" } 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 }
}

View File

@@ -6,6 +6,7 @@
import semmle.code.cpp.exprs.Expr import semmle.code.cpp.exprs.Expr
import semmle.code.cpp.commons.Environment import semmle.code.cpp.commons.Environment
import semmle.code.cpp.security.SecurityOptions import semmle.code.cpp.security.SecurityOptions
import semmle.code.cpp.models.interfaces.FlowSource
/** /**
* Extend this class to customize the security queries for * Extend this class to customize the security queries for
@@ -59,14 +60,14 @@ class SecurityOptions extends string {
or or
functionCall.getTarget().hasGlobalName(fname) and functionCall.getTarget().hasGlobalName(fname) and
exists(functionCall.getArgument(arg)) and exists(functionCall.getArgument(arg)) and
( fname = "getaddrinfo" and
fname = ["read", "recv", "recvmsg"] and arg = 1 arg = 3
or
fname = "getaddrinfo" and arg = 3
or
fname = "recvfrom" and
(arg = 1 or arg = 4 or arg = 5)
) )
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) userInputReturn(fname)
) )
) )
or
exists(RemoteFlowSourceFunction remote, FunctionOutput output |
functionCall.getTarget() = remote and
(output.isReturnValue() or output.isReturnValueDeref()) and
remote.hasRemoteFlowSource(output, _)
)
} }
/** /**

View File

@@ -1,6 +1,6 @@
# C/C++ CodeQL tests # 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. The tests can be run through Visual Studio Code. Advanced users may also use the `codeql test run` command.

View File

@@ -216,3 +216,46 @@ void test_pointers2()
sink(ptr4); // clean sink(ptr4); // clean
sink(*ptr4); // $ MISSING: ast,ir 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
}

View File

@@ -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()
)
}
}

View File

@@ -36,9 +36,6 @@ argHasPostUpdate
| arrays.cpp:10:8:10:15 | * ... | ArgumentNode is missing PostUpdateNode. | | 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:16:8:16:13 | access to array | ArgumentNode is missing PostUpdateNode. |
| arrays.cpp:17:8:17: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 postWithInFlow
| A.cpp:25:13:25:13 | c [post update] | PostUpdateNode should not be the target of local flow. | | 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. | | A.cpp:27:28:27:28 | c [post update] | PostUpdateNode should not be the target of local flow. |

View File

@@ -227,14 +227,18 @@
| by_reference.cpp:20:23:20:27 | value | AST only | | by_reference.cpp:20:23:20:27 | value | AST only |
| by_reference.cpp:24:19:24:22 | this | 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: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:3:50:3 | s | AST only |
| by_reference.cpp:50:17:50:26 | call to user_input | 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:51:10:51:20 | call to getDirectly | AST only |
| by_reference.cpp:56:3:56:3 | s | 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: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:57:10:57:22 | call to getIndirectly | AST only |
| by_reference.cpp:62:3:62:3 | s | 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: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:63:10:63:28 | call to getThroughNonMember | AST only |
| by_reference.cpp:68:17:68:18 | & ... | AST only | | by_reference.cpp:68:17:68:18 | & ... | AST only |
| by_reference.cpp:68:21:68:30 | call to user_input | AST only | | by_reference.cpp:68:21:68:30 | call to user_input | AST only |

View File

@@ -266,14 +266,18 @@
| by_reference.cpp:20:23:20:27 | value | | by_reference.cpp:20:23:20:27 | value |
| by_reference.cpp:24:19:24:22 | this | | by_reference.cpp:24:19:24:22 | this |
| by_reference.cpp:24:25:24:29 | value | | 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:3:50:3 | s |
| by_reference.cpp:50:17:50:26 | call to user_input | | 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:51:10:51:20 | call to getDirectly |
| by_reference.cpp:56:3:56:3 | s | | by_reference.cpp:56:3:56:3 | s |
| by_reference.cpp:56:19:56:28 | call to user_input | | 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:57:10:57:22 | call to getIndirectly |
| by_reference.cpp:62:3:62:3 | s | | by_reference.cpp:62:3:62:3 | s |
| by_reference.cpp:62:25:62:34 | call to user_input | | 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:63:10:63:28 | call to getThroughNonMember |
| by_reference.cpp:68:17:68:18 | & ... | | by_reference.cpp:68:17:68:18 | & ... |
| by_reference.cpp:68:21:68:30 | call to user_input | | by_reference.cpp:68:21:68:30 | call to user_input |

View 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
}

View File

@@ -135,6 +135,17 @@
| arrayassignment.cpp:145:12:145:12 | 5 | arrayassignment.cpp:145:7:145:13 | access to array | TAINT | | 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: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 | | 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: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: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 | | 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: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: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 | 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 | 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 | 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 | 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:152:30:152:31 | m2 | |
| map.cpp:152:12:152:13 | ref arg m2 | map.cpp:182:7:182:8 | 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: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: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 | 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 | 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 | 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 | 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:158:30:158:31 | m3 | |
| map.cpp:158:12:158:13 | ref arg m3 | map.cpp:252:1:252:1 | 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: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: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 | 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 | 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 | 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: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:171:7:171:9 | m10 | |
| map.cpp:166:27:166:29 | call to map | map.cpp:252:1:252:1 | 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: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: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 | 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 | 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 | 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 | 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:304:30:304:31 | m2 | |
| map.cpp:304:12:304:13 | ref arg m2 | map.cpp:334:7:334:8 | 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: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: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 | 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 | 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 | 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 | 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:310:30:310:31 | m3 | |
| map.cpp:310:12:310:13 | ref arg m3 | map.cpp:438:1:438:1 | 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: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: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 | 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 | 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 | 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: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:323:7:323:9 | m10 | |
| map.cpp:318:37:318:39 | call to unordered_map | map.cpp:438:1:438:1 | 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:55:40:55:41 | i1 | |
| set.cpp:55:40:55:41 | ref arg i1 | set.cpp:57:9:57:10 | 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 | 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: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 | 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 | | 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:59:40:59:41 | i2 | |
| set.cpp:59:40:59:41 | ref arg i2 | set.cpp:61:9:61:10 | 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 | 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: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:67:2:67:4 | s11 | |
| set.cpp:65:19:65:21 | call to set | set.cpp:68:2:68: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:169:40:169:41 | i1 | |
| set.cpp:169:40:169:41 | ref arg i1 | set.cpp:171:9:171:10 | 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 | 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: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 | 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 | | 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:173:40:173:41 | i2 | |
| set.cpp:173:40:173:41 | ref arg i2 | set.cpp:175:9:175:10 | 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 | 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: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:181:2:181:4 | s11 | |
| set.cpp:179:29:179:31 | call to unordered_set | set.cpp:182:2:182: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: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: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 | 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: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: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 | 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: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: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: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 | 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: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: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 | 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: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: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: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: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 | 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: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: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 | | 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: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: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 | 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: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: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 | | 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: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: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: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: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:40:11:40:17 | source1 | |
| standalone_iterators.cpp:39:45:39:51 | source1 | standalone_iterators.cpp:41:12:41:18 | 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 | 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: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: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 | 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] | | | 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 (__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 | 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) | |
| 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:125:61:125:62 | it | |
| string.cpp:125:61:125:62 | ref arg it | string.cpp:126:9:126:10 | 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 | 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* | TAINT |
| string.cpp:129:16:129:16 | (__begin) | string.cpp:129:16:129:16 | call to operator++ | | | 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 | | | 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 (__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 | 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) | |
| 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:378:9:378:13 | iter1 | |
| string.cpp:376:31:376:35 | call to begin | string.cpp:379:8:379:12 | 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 | 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: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: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:382:9:382:13 | iter2 | |
| string.cpp:380:31:380:35 | call to begin | string.cpp:383:8:383:12 | 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 | 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: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: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 | | | 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:398:3:398:9 | ... = ... | |
| string.cpp:398:8:398:9 | i2 | string.cpp:399:12:399:13 | i3 | | | 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 | 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: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:400:3:400:9 | ... = ... | |
| string.cpp:400:8:400:9 | i2 | string.cpp:401:12:401:13 | i4 | | | 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 | 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: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:402:3:402:9 | ... = ... | |
| string.cpp:402:8:402:9 | i2 | string.cpp:403:3:403:4 | i5 | | | 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: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: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: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:410:3:410:9 | ... = ... | |
| string.cpp:410:8:410:9 | i2 | string.cpp:411:10:411:11 | i8 | | | 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: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: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: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:413:3:413:15 | ... = ... | |
| string.cpp:413:11:413:13 | call to end | string.cpp:414:5:414:6 | i9 | | | 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:631:2:631:18 | ... = ... | |
| taint.cpp:631:6:631:14 | call to _strnextc | taint.cpp:632:7:632:7 | c | | | 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: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:17:26:17:32 | source1 | |
| vector.cpp:16:43:16:49 | source1 | vector.cpp:31:38:31:44 | 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 | | | 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 (__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 | 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) | |
| 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:23:66:23:67 | it | |
| vector.cpp:23:66:23:67 | ref arg it | vector.cpp:24:9:24:10 | 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 | 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* | TAINT |
| vector.cpp:27:15:27:15 | (__begin) | vector.cpp:27:15:27:15 | call to operator++ | | | 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 | | | 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 (__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 | 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) | |
| 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:329:62:329:65 | iter | |
| vector.cpp:329:62:329:65 | iter | vector.cpp:330:3:330:6 | 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: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: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 | 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:2 | call to operator* [post update] | TAINT |
| vector.cpp:330:10:330:15 | call to source | vector.cpp:330:2:330:17 | ... = ... | | | 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:333:64:333:67 | iter | |
| vector.cpp:333:64:333:67 | iter | vector.cpp:334:3:334:6 | 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: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: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: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 | 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:2 | call to operator* [post update] | TAINT |
| vector.cpp:334:10:334:10 | i | vector.cpp:334:2:334:10 | ... = ... | | | 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 | | | 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 | 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: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: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: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: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] | | | 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:344:68:344:69 | it | |
| vector.cpp:344:68:344:69 | ref arg it | vector.cpp:345:4:345:5 | 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: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: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: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: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 | 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:3 | call to operator* [post update] | TAINT |
| vector.cpp:345:9:345:14 | call to source | vector.cpp:345:3:345:16 | ... = ... | | | 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 | | | 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 (__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: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) | |
| 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: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:360:3:360:4 | i5 | |
| vector.cpp:359:37:359:41 | call to begin | vector.cpp:362:3:362: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: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: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: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: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 | 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:2 | call to operator* [post update] | TAINT |
| vector.cpp:360:8:360:13 | call to source | vector.cpp:360:2:360:15 | ... = ... | | | 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:363:7:363:8 | v5 | |
| vector.cpp:361:7:361:8 | ref arg v5 | vector.cpp:415:1:415:1 | 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: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: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] | | | 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 | 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: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: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: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:368:2:368:3 | v6 | |
| vector.cpp:366:2:366:2 | call to operator* [post update] | vector.cpp:369:7:369:8 | 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: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:373:4:373:5 | i7 | |
| vector.cpp:371:37:371:41 | call to begin | vector.cpp:376:4:376: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: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:379:7:379:8 | v7 | |
| vector.cpp:373:3:373:3 | call to operator* [post update] | vector.cpp:415:1:415:1 | 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: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:379:7:379:8 | v7 | |
| vector.cpp:374:8:374:9 | ref arg v7 | vector.cpp:415:1:415:1 | 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: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:379:7:379:8 | v7 | |
| vector.cpp:376:3:376:3 | call to operator* [post update] | vector.cpp:415:1:415:1 | 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: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:382:3:382:4 | i8 | |
| vector.cpp:381:37:381:41 | call to begin | vector.cpp:384:3:384: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: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: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: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: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 | 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:2 | call to operator* [post update] | TAINT |
| vector.cpp:382:8:382:13 | call to source | vector.cpp:382:2:382:15 | ... = ... | | | 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:385:7:385:8 | v8 | |
| vector.cpp:383:7:383:8 | ref arg v8 | vector.cpp:415:1:415:1 | 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: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: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] | | | 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: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:389:3:389:4 | i9 | |
| vector.cpp:387:37:387:41 | call to begin | vector.cpp:390:31:390:32 | 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: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: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: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 | 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:2 | call to operator* [post update] | TAINT |
| vector.cpp:389:8:389:13 | call to source | vector.cpp:389:2:389:15 | ... = ... | | | 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 | | | 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: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:2 | call to operator* [post update] | TAINT |
| vector.cpp:403:11:403:11 | 0 | vector.cpp:403:2:403:11 | ... = ... | | | 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: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: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] | | | 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: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: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: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 |

View File

@@ -90,3 +90,34 @@ void test_insert_iterator() {
*i2-- = 0; *i2-- = 0;
sink(c2); // clean 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);
}

View File

@@ -631,3 +631,29 @@ void test__strnextc(const char* source) {
c = _strnextc(""); c = _strnextc("");
sink(c); 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
}

View File

@@ -496,3 +496,39 @@ void test_vector_emplace() {
v2.emplace(v2.begin(), source()); v2.emplace(v2.begin(), source());
sink(v2); // $ ast,ir 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]);
}
}

View File

@@ -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: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:51:21:51: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:51:21:51: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:51:21:51: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:51:21:51: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:51:21:51: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: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: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:22:24:22:28 | query |
nodes nodes
| search.c:14:24:14:28 | *query | semmle.label | *query | | search.c:14:24:14:28 | *query | semmle.label | *query |
| 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: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:51:21:51: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:51:21:51:26 | call to getenv | semmle.label | call to getenv |
| search.c:45:5:45:15 | Argument 0 | semmle.label | Argument 0 | | search.c:55:5:55:15 | Argument 0 | semmle.label | Argument 0 |
| search.c:45:17:45:25 | Argument 0 indirection | semmle.label | Argument 0 indirection | | search.c:55:17:55:25 | Argument 0 indirection | semmle.label | Argument 0 indirection |
| search.c:47:5:47:15 | Argument 0 | semmle.label | Argument 0 | | search.c:57:5:57:15 | Argument 0 | semmle.label | Argument 0 |
| search.c:47:17:47:25 | Argument 0 indirection | semmle.label | Argument 0 indirection | | search.c:57:17:57:25 | Argument 0 indirection | semmle.label | Argument 0 indirection |
#select #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: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: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: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 |

View File

@@ -26,7 +26,7 @@ void bad_server2(char* query) {
puts(do_search(query)); puts(do_search(query));
} }
void good_server(char* query) { void good_server1(char* query) {
puts("<p>Query results for "); puts("<p>Query results for ");
// GOOD: Escape HTML characters before adding to a page // GOOD: Escape HTML characters before adding to a page
char* query_escaped = escape_html(query); char* query_escaped = escape_html(query);
@@ -37,14 +37,25 @@ void good_server(char* query) {
puts(do_search(query)); puts(do_search(query));
} }
int main(int argc, char** argv) { int sscanf(const char *s, const char *format, ...);
char* raw_query = getenv("QUERY_STRING");
if (strcmp("good", argv[0]) == 0) { void good_server2(char* query) {
good_server(raw_query); puts("<p>Query results for ");
} else if (strcmp("bad1", argv[0]) == 0) { // GOOD: Only an integer is added to the page.
bad_server1(raw_query); int i = 0;
} else { sscanf(query, "value=%i", &i);
bad_server2(raw_query); 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);
}
}

View File

@@ -45,6 +45,7 @@ namespace Semmle.Autobuild.Shared
private readonly SolutionFile? solution; private readonly SolutionFile? solution;
private readonly IEnumerable<Project> includedProjects; private readonly IEnumerable<Project> includedProjects;
public override IEnumerable<IProjectOrSolution> IncludedProjects => includedProjects; public override IEnumerable<IProjectOrSolution> IncludedProjects => includedProjects;
public IEnumerable<SolutionConfigurationInSolution> Configurations => public IEnumerable<SolutionConfigurationInSolution> Configurations =>
@@ -84,8 +85,12 @@ namespace Semmle.Autobuild.Shared
.ToArray(); .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();
} }
} }

View File

@@ -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.

View 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.

View File

@@ -163,7 +163,7 @@ namespace Semmle.Extraction.CIL.Driver
} }
private readonly HashSet<string> filesAnalyzed = new HashSet<string>(); 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> /// <summary>

View File

@@ -95,11 +95,11 @@ namespace Semmle.Extraction.CIL
/// <param name="h">The handle of the entity.</param> /// <param name="h">The handle of the entity.</param>
/// <param name="genericContext">The generic context.</param> /// <param name="genericContext">The generic context.</param>
/// <returns></returns> /// <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; IExtractedEntity entity;
switch (handle.Kind) switch (handle.Kind)
@@ -136,7 +136,7 @@ namespace Semmle.Extraction.CIL
return entity; return entity;
} }
private IExtractedEntity Create(GenericContext gc, MemberReferenceHandle handle) private IExtractedEntity Create(IGenericContext gc, MemberReferenceHandle handle)
{ {
var mr = MdReader.GetMemberReference(handle); var mr = MdReader.GetMemberReference(handle);
switch (mr.GetKind()) switch (mr.GetKind())
@@ -228,7 +228,7 @@ namespace Semmle.Extraction.CIL
#endregion #endregion
private readonly CachedFunction<GenericContext, Handle, IExtractedEntity> genericHandleFactory; private readonly CachedFunction<IGenericContext, Handle, IExtractedEntity> genericHandleFactory;
/// <summary> /// <summary>
/// Gets the short name of a member, without the preceding interface qualifier. /// Gets the short name of a member, without the preceding interface qualifier.

View File

@@ -37,7 +37,7 @@ namespace Semmle.Extraction.CIL
globalNamespace = new Lazy<Entities.Namespace>(() => Populate(new Entities.Namespace(this, "", null))); globalNamespace = new Lazy<Entities.Namespace>(() => Populate(new Entities.Namespace(this, "", null)));
systemNamespace = new Lazy<Entities.Namespace>(() => Populate(new Entities.Namespace(this, "System"))); 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))); namespaceFactory = new CachedFunction<StringHandle, Entities.Namespace>(n => CreateNamespace(MdReader.GetString(n)));
namespaceDefinitionFactory = new CachedFunction<NamespaceDefinitionHandle, Entities.Namespace>(CreateNamespace); namespaceDefinitionFactory = new CachedFunction<NamespaceDefinitionHandle, Entities.Namespace>(CreateNamespace);
sourceFiles = new CachedFunction<PDB.ISourceFile, Entities.PdbSourceFile>(path => new Entities.PdbSourceFile(this, path)); sourceFiles = new CachedFunction<PDB.ISourceFile, Entities.PdbSourceFile>(path => new Entities.PdbSourceFile(this, path));

View File

@@ -5,14 +5,18 @@ namespace Semmle.Extraction.CIL
/// <summary> /// <summary>
/// A generic context which does not contain any type parameters. /// A generic context which does not contain any type parameters.
/// </summary> /// </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; } }
} }
} }

View File

@@ -40,6 +40,7 @@ namespace Semmle.Extraction.CIL.Entities
trapFile.Write(FullName); trapFile.Write(FullName);
trapFile.Write("#file:///"); trapFile.Write("#file:///");
trapFile.Write(Cx.AssemblyPath.Replace("\\", "/")); trapFile.Write(Cx.AssemblyPath.Replace("\\", "/"));
trapFile.Write(";assembly");
} }
public override bool Equals(object? obj) public override bool Equals(object? obj)
@@ -49,8 +50,6 @@ namespace Semmle.Extraction.CIL.Entities
public override int GetHashCode() => 7 * file.GetHashCode(); 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; private string FullName => assemblyName.GetPublicKey() is null ? assemblyName.FullName + ", PublicKeyToken=null" : assemblyName.FullName;
public override IEnumerable<IExtractionProduct> Contents public override IEnumerable<IExtractionProduct> Contents
@@ -136,7 +135,7 @@ namespace Semmle.Extraction.CIL.Entities
trapFile = trapWriter.TrapFile; trapFile = trapWriter.TrapFile;
if (nocache || !System.IO.File.Exists(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); ExtractCIL(cx, assemblyPath, extractPdbs);
extracted = true; extracted = true;
} }

View File

@@ -12,9 +12,9 @@ namespace Semmle.Extraction.CIL.Entities
{ {
private readonly CustomAttributeHandle handle; private readonly CustomAttributeHandle handle;
private readonly CustomAttribute attrib; 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); attrib = cx.MdReader.GetCustomAttribute(handle);
this.handle = handle; this.handle = handle;
@@ -80,7 +80,7 @@ namespace Semmle.Extraction.CIL.Entities
return value?.ToString() ?? "null"; 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) foreach (var attrib in attributes)
{ {

View File

@@ -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; }
}
}

View File

@@ -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);
}
}

View File

@@ -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; }
}
}

View File

@@ -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; }
}
}

View File

@@ -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();
}
}

View File

@@ -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; }
}
}

View File

@@ -23,7 +23,7 @@ namespace Semmle.Extraction.CIL.Entities
public override IList<LocalVariable>? LocalVariables => locals; 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); md = Cx.MdReader.GetMethodDefinition(handle);
this.gc = gc; this.gc = gc;

View File

@@ -25,10 +25,9 @@ namespace Semmle.Extraction.CIL.Entities
parent.WriteId(trapFile); parent.WriteId(trapFile);
trapFile.Write('.'); trapFile.Write('.');
trapFile.Write(Cx.ShortName(ed.Name)); trapFile.Write(Cx.ShortName(ed.Name));
trapFile.Write(";cil-event");
} }
public override string IdSuffix => ";cil-event";
public override bool Equals(object? obj) public override bool Equals(object? obj)
{ {
return obj is Event e && handle.Equals(e.handle); return obj is Event e && handle.Equals(e.handle);

View File

@@ -7,13 +7,13 @@ namespace Semmle.Extraction.CIL.Entities
/// </summary> /// </summary>
internal class ExceptionRegion : UnlabelledEntity internal class ExceptionRegion : UnlabelledEntity
{ {
private readonly GenericContext gc; private readonly IGenericContext gc;
private readonly MethodImplementation method; private readonly MethodImplementation method;
private readonly int index; private readonly int index;
private readonly System.Reflection.Metadata.ExceptionRegion r; private readonly System.Reflection.Metadata.ExceptionRegion r;
private readonly Dictionary<int, Instruction> jump_table; 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.gc = gc;
this.method = method; this.method = method;

View File

@@ -8,40 +8,27 @@ namespace Semmle.Extraction.CIL.Entities
/// <summary> /// <summary>
/// An entity representing a field. /// An entity representing a field.
/// </summary> /// </summary>
internal abstract class Field : GenericContext, IMember, ICustomModifierReceiver internal abstract class Field : LabelledEntity, IGenericContext, IMember, ICustomModifierReceiver
{ {
protected Field(Context cx) : base(cx) protected Field(Context cx) : base(cx)
{ {
} }
public Label Label { get; set; } public override void WriteId(TextWriter trapFile)
public void WriteId(TextWriter trapFile)
{ {
trapFile.WriteSubId(DeclaringType); trapFile.WriteSubId(DeclaringType);
trapFile.Write('.'); trapFile.Write('.');
trapFile.Write(Name); 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 string Name { get; }
public abstract Type DeclaringType { get; } public abstract Type DeclaringType { get; }
public Location ReportingLocation => throw new NotImplementedException();
public abstract Type Type { get; } public abstract Type Type { get; }
public virtual IEnumerable<IExtractionProduct> Contents public override IEnumerable<IExtractionProduct> Contents
{ {
get get
{ {
@@ -55,11 +42,8 @@ namespace Semmle.Extraction.CIL.Entities
} }
} }
public void Extract(Context cx2) public abstract IEnumerable<Type> TypeParameters { get; }
{
cx2.Populate(this);
}
TrapStackBehaviour IEntity.TrapStackBehaviour => TrapStackBehaviour.NoLabel; public abstract IEnumerable<Type> MethodParameters { get; }
} }
} }

View File

@@ -17,6 +17,7 @@ namespace Semmle.Extraction.CIL.Entities
public override void WriteId(TextWriter trapFile) public override void WriteId(TextWriter trapFile)
{ {
trapFile.Write(TransformedPath.DatabaseId); trapFile.Write(TransformedPath.DatabaseId);
trapFile.Write(";sourcefile");
} }
public override bool Equals(object? obj) 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); yield return Tuples.files(this, TransformedPath.Value, TransformedPath.NameWithoutExtension, TransformedPath.Extension);
} }
} }
public override string IdSuffix => ";sourcefile";
} }
} }

View File

@@ -15,10 +15,9 @@ namespace Semmle.Extraction.CIL.Entities
public override void WriteId(TextWriter trapFile) public override void WriteId(TextWriter trapFile)
{ {
trapFile.Write(transformedPath.DatabaseId); trapFile.Write(transformedPath.DatabaseId);
trapFile.Write(";folder");
} }
public override string IdSuffix => ";folder";
public override IEnumerable<IExtractionProduct> Contents public override IEnumerable<IExtractionProduct> Contents
{ {
get get

View File

@@ -4,6 +4,6 @@ namespace Semmle.Extraction.CIL.Entities
{ {
internal interface ITypeSignature internal interface ITypeSignature
{ {
void WriteId(TextWriter trapFile, GenericContext gc); void WriteId(TextWriter trapFile, IGenericContext gc);
} }
} }

View File

@@ -8,7 +8,7 @@ namespace Semmle.Extraction.CIL.Entities
/// <summary> /// <summary>
/// A CIL instruction. /// A CIL instruction.
/// </summary> /// </summary>
internal class Instruction : UnlabelledEntity, IEntity internal class Instruction : UnlabelledEntity
{ {
/// <summary> /// <summary>
/// The additional data following the opcode, if any. /// 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 readonly byte[] data;
private int PayloadSize => payloadSizes[(int)PayloadType]; private int PayloadSize => payloadSizes[(int)PayloadType];

View File

@@ -21,10 +21,9 @@ namespace Semmle.Extraction.CIL.Entities
trapFile.WriteSubId(method); trapFile.WriteSubId(method);
trapFile.Write('_'); trapFile.Write('_');
trapFile.Write(index); trapFile.Write(index);
trapFile.Write(";cil-local");
} }
public override string IdSuffix => ";cil-local";
public override IEnumerable<IExtractionProduct> Contents public override IEnumerable<IExtractionProduct> Contents
{ {
get get

View File

@@ -8,10 +8,10 @@ namespace Semmle.Extraction.CIL.Entities
{ {
private readonly MemberReferenceHandle handle; private readonly MemberReferenceHandle handle;
private readonly MemberReference mr; private readonly MemberReference mr;
private readonly GenericContext gc; private readonly IGenericContext gc;
private readonly Type declType; 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.handle = handle;
this.gc = gc; this.gc = gc;

View File

@@ -12,10 +12,10 @@ namespace Semmle.Extraction.CIL.Entities
private readonly MemberReferenceHandle handle; private readonly MemberReferenceHandle handle;
private readonly MemberReference mr; private readonly MemberReference mr;
private readonly Type declaringType; private readonly Type declaringType;
private readonly GenericContext parent; private readonly IGenericContext parent;
private readonly Method? sourceDeclaration; private readonly Method? sourceDeclaration;
public MemberReferenceMethod(GenericContext gc, MemberReferenceHandle handle) : base(gc) public MemberReferenceMethod(IGenericContext gc, MemberReferenceHandle handle) : base(gc)
{ {
this.handle = handle; this.handle = handle;
this.gc = gc; this.gc = gc;
@@ -23,7 +23,7 @@ namespace Semmle.Extraction.CIL.Entities
signature = mr.DecodeMethodSignature(new SignatureDecoder(), gc); 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 var declType = parent is Method parentMethod
? parentMethod.DeclaringType ? parentMethod.DeclaringType

View File

@@ -12,10 +12,10 @@ namespace Semmle.Extraction.CIL.Entities
internal abstract class Method : TypeContainer, IMember, ICustomModifierReceiver, IParameterizable internal abstract class Method : TypeContainer, IMember, ICustomModifierReceiver, IParameterizable
{ {
protected MethodTypeParameter[]? genericParams; protected MethodTypeParameter[]? genericParams;
protected GenericContext gc; protected IGenericContext gc;
protected MethodSignature<ITypeSignature> signature; protected MethodSignature<ITypeSignature> signature;
protected Method(GenericContext gc) : base(gc.Cx) protected Method(IGenericContext gc) : base(gc.Cx)
{ {
this.gc = gc; this.gc = gc;
} }

View File

@@ -18,7 +18,7 @@ namespace Semmle.Extraction.CIL.Entities
private readonly Method unboundMethod; private readonly Method unboundMethod;
private readonly ImmutableArray<Type> typeParams; private readonly ImmutableArray<Type> typeParams;
public MethodSpecificationMethod(GenericContext gc, MethodSpecificationHandle handle) : base(gc) public MethodSpecificationMethod(IGenericContext gc, MethodSpecificationHandle handle) : base(gc)
{ {
this.handle = handle; this.handle = handle;
ms = Cx.MdReader.GetMethodSpecification(handle); ms = Cx.MdReader.GetMethodSpecification(handle);

View File

@@ -21,7 +21,7 @@ namespace Semmle.Extraction.CIL.Entities
public override string Name => "!" + index; 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; method = m;
this.index = index; this.index = index;

View File

@@ -14,9 +14,6 @@ namespace Semmle.Extraction.CIL.Entities
public bool IsGlobalNamespace => ParentNamespace is null; public bool IsGlobalNamespace => ParentNamespace is null;
public override string IdSuffix => ";namespace";
public override void WriteId(TextWriter trapFile) public override void WriteId(TextWriter trapFile)
{ {
if (ParentNamespace != null && !ParentNamespace.IsGlobalNamespace) if (ParentNamespace != null && !ParentNamespace.IsGlobalNamespace)
@@ -27,6 +24,8 @@ namespace Semmle.Extraction.CIL.Entities
trapFile.Write(Name); trapFile.Write(Name);
} }
public override string IdSuffix => ";namespacee";
public override bool Equals(object? obj) public override bool Equals(object? obj)
{ {
if (obj is Namespace ns && Name == ns.Name) if (obj is Namespace ns && Name == ns.Name)

View File

@@ -8,41 +8,40 @@ namespace Semmle.Extraction.CIL.Entities
/// </summary> /// </summary>
internal sealed class Parameter : LabelledEntity internal sealed class Parameter : LabelledEntity
{ {
private readonly IParameterizable method; private readonly IParameterizable parameterizable;
private readonly int index; private readonly int index;
private readonly Type type; 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; index = i;
type = t; type = t;
} }
public override void WriteId(TextWriter trapFile) public override void WriteId(TextWriter trapFile)
{ {
trapFile.WriteSubId(method); trapFile.WriteSubId(parameterizable);
trapFile.Write('_'); trapFile.Write('_');
trapFile.Write(index); trapFile.Write(index);
trapFile.Write(";cil-parameter");
} }
public override bool Equals(object? obj) 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() 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 public override IEnumerable<IExtractionProduct> Contents
{ {
get get
{ {
yield return Tuples.cil_parameter(this, method, index, type); yield return Tuples.cil_parameter(this, parameterizable, index, type);
} }
} }
} }

View File

@@ -13,10 +13,9 @@ namespace Semmle.Extraction.CIL.Entities
private readonly Handle handle; private readonly Handle handle;
private readonly Type type; private readonly Type type;
private readonly PropertyDefinition pd; private readonly PropertyDefinition pd;
public override string IdSuffix => ";cil-property"; private readonly IGenericContext gc;
private readonly GenericContext 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.gc = gc;
this.handle = handle; this.handle = handle;
@@ -38,6 +37,7 @@ namespace Semmle.Extraction.CIL.Entities
param.WriteId(trapFile, gc); param.WriteId(trapFile, gc);
} }
trapFile.Write(")"); trapFile.Write(")");
trapFile.Write(";cil-property");
} }
public override bool Equals(object? obj) public override bool Equals(object? obj)

View File

@@ -17,7 +17,7 @@ namespace Semmle.Extraction.CIL.Entities
this.shape = shape; this.shape = shape;
} }
public void WriteId(TextWriter trapFile, GenericContext gc) public void WriteId(TextWriter trapFile, IGenericContext gc)
{ {
elementType.WriteId(trapFile, gc); elementType.WriteId(trapFile, gc);
trapFile.Write('['); trapFile.Write('[');
@@ -38,7 +38,7 @@ namespace Semmle.Extraction.CIL.Entities
this.elementType = elementType; this.elementType = elementType;
} }
public void WriteId(TextWriter trapFile, GenericContext gc) public void WriteId(TextWriter trapFile, IGenericContext gc)
{ {
elementType.WriteId(trapFile, gc); elementType.WriteId(trapFile, gc);
trapFile.Write('&'); trapFile.Write('&');
@@ -54,7 +54,7 @@ namespace Semmle.Extraction.CIL.Entities
this.signature = signature; this.signature = signature;
} }
public void WriteId(TextWriter trapFile, GenericContext gc) public void WriteId(TextWriter trapFile, IGenericContext gc)
{ {
FunctionPointerType.WriteName( FunctionPointerType.WriteName(
trapFile.Write, trapFile.Write,
@@ -84,7 +84,7 @@ namespace Semmle.Extraction.CIL.Entities
this.typeArguments = typeArguments; this.typeArguments = typeArguments;
} }
public void WriteId(TextWriter trapFile, GenericContext gc) public void WriteId(TextWriter trapFile, IGenericContext gc)
{ {
genericType.WriteId(trapFile, gc); genericType.WriteId(trapFile, gc);
trapFile.Write('<'); trapFile.Write('<');
@@ -112,7 +112,7 @@ namespace Semmle.Extraction.CIL.Entities
this.index = index; 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) if (!ReferenceEquals(innerGc, outerGc) && innerGc is Method method)
{ {
@@ -132,7 +132,7 @@ namespace Semmle.Extraction.CIL.Entities
this.index = index; this.index = index;
} }
public void WriteId(TextWriter trapFile, GenericContext gc) public void WriteId(TextWriter trapFile, IGenericContext gc)
{ {
trapFile.Write("T!"); trapFile.Write("T!");
trapFile.Write(index); trapFile.Write(index);
@@ -158,7 +158,7 @@ namespace Semmle.Extraction.CIL.Entities
this.isRequired = isRequired; this.isRequired = isRequired;
} }
public void WriteId(TextWriter trapFile, GenericContext gc) public void WriteId(TextWriter trapFile, IGenericContext gc)
{ {
unmodifiedType.WriteId(trapFile, gc); unmodifiedType.WriteId(trapFile, gc);
trapFile.Write(isRequired ? " modreq(" : " modopt("); trapFile.Write(isRequired ? " modreq(" : " modopt(");
@@ -186,7 +186,7 @@ namespace Semmle.Extraction.CIL.Entities
this.elementType = elementType; this.elementType = elementType;
} }
public void WriteId(TextWriter trapFile, GenericContext gc) public void WriteId(TextWriter trapFile, IGenericContext gc)
{ {
elementType.WriteId(trapFile, gc); elementType.WriteId(trapFile, gc);
trapFile.Write('*'); trapFile.Write('*');
@@ -207,7 +207,7 @@ namespace Semmle.Extraction.CIL.Entities
this.typeCode = typeCode; this.typeCode = typeCode;
} }
public void WriteId(TextWriter trapFile, GenericContext gc) public void WriteId(TextWriter trapFile, IGenericContext gc)
{ {
trapFile.Write(typeCode.Id()); trapFile.Write(typeCode.Id());
} }
@@ -227,7 +227,7 @@ namespace Semmle.Extraction.CIL.Entities
this.elementType = elementType; this.elementType = elementType;
} }
public void WriteId(TextWriter trapFile, GenericContext gc) public void WriteId(TextWriter trapFile, IGenericContext gc)
{ {
elementType.WriteId(trapFile, gc); elementType.WriteId(trapFile, gc);
trapFile.Write("[]"); trapFile.Write("[]");
@@ -248,7 +248,7 @@ namespace Semmle.Extraction.CIL.Entities
this.handle = handle; this.handle = handle;
} }
public void WriteId(TextWriter trapFile, GenericContext gc) public void WriteId(TextWriter trapFile, IGenericContext gc)
{ {
var type = (Type)gc.Cx.Create(handle); var type = (Type)gc.Cx.Create(handle);
type.WriteId(trapFile); type.WriteId(trapFile);
@@ -269,7 +269,7 @@ namespace Semmle.Extraction.CIL.Entities
this.handle = handle; this.handle = handle;
} }
public void WriteId(TextWriter trapFile, GenericContext gc) public void WriteId(TextWriter trapFile, IGenericContext gc)
{ {
var type = (Type)gc.Cx.Create(handle); var type = (Type)gc.Cx.Create(handle);
type.WriteId(trapFile); type.WriteId(trapFile);

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