Merge branch 'main' into rdmarsh2/cpp/ir-synthetic-destructors

This commit is contained in:
Robert Marsh
2024-02-22 18:10:13 +00:00
119 changed files with 1678 additions and 590 deletions

View File

@@ -1,4 +1,12 @@
common --enable_platform_specific_config
common --enable_bzlmod
# because we use --override_module with `%workspace%`, the lock file is not stable
common --lockfile_mode=off
# when building from this repository in isolation, the internal repository will not be found at ..
# where `MODULE.bazel` looks for it. The following will get us past the module loading phase, so
# that we can build things that do not rely on that
common --override_module=semmle_code=%workspace%/misc/bazel/semmle_code_stub
build --repo_env=CC=clang --repo_env=CXX=clang++

View File

@@ -1 +1 @@
6.3.1
6.5.0

View File

@@ -25,6 +25,7 @@
# Bazel (excluding BUILD.bazel files)
WORKSPACE.bazel @github/codeql-ci-reviewers
MODULE.bazel @github/codeql-ci-reviewers
.bazelversion @github/codeql-ci-reviewers
.bazelrc @github/codeql-ci-reviewers
**/*.bzl @github/codeql-ci-reviewers

53
MODULE.bazel Normal file
View File

@@ -0,0 +1,53 @@
module(
name = "codeql",
version = "0.0",
)
# this points to our internal repository when `codeql` is checked out as a submodule thereof
# when building things from `codeql` independently this is stubbed out in `.bazelrc`
bazel_dep(name = "semmle_code", version = "0.0")
local_path_override(
module_name = "semmle_code",
path = "..",
)
# see https://registry.bazel.build/ for a list of available packages
bazel_dep(name = "platforms", version = "0.0.8")
bazel_dep(name = "rules_pkg", version = "0.9.1")
bazel_dep(name = "rules_nodejs", version = "6.0.3")
bazel_dep(name = "rules_python", version = "0.31.0")
bazel_dep(name = "bazel_skylib", version = "1.5.0")
bazel_dep(name = "abseil-cpp", version = "20240116.0", repo_name = "absl")
bazel_dep(name = "nlohmann_json", version = "3.11.3", repo_name = "json")
bazel_dep(name = "fmt", version = "10.0.0")
pip = use_extension("@rules_python//python/extensions:pip.bzl", "pip")
pip.parse(
hub_name = "codegen_deps",
python_version = "3.11",
requirements_lock = "//misc/codegen:requirements_lock.txt",
)
use_repo(pip, "codegen_deps")
swift_deps = use_extension("//swift/third_party:load.bzl", "swift_deps")
use_repo(
swift_deps,
"binlog",
"picosha2",
"swift_prebuilt_darwin_x86_64",
"swift_prebuilt_linux",
"swift_toolchain_linux",
"swift_toolchain_macos",
)
node = use_extension("@rules_nodejs//nodejs:extensions.bzl", "node")
node.toolchain(
name = "nodejs",
node_version = "18.15.0",
)
use_repo(node, "nodejs", "nodejs_toolchains")
register_toolchains(
"@nodejs_toolchains//:all",
)

View File

@@ -1,12 +1,2 @@
# Please notice that any bazel targets and definitions in this repository are currently experimental
# and for internal use only.
workspace(name = "codeql")
load("//misc/bazel:workspace.bzl", "codeql_workspace")
codeql_workspace()
load("//misc/bazel:workspace_deps.bzl", "codeql_workspace_deps")
codeql_workspace_deps()
# please use MODULE.bazel to add dependencies
# this empty file is required by internal repositories, don't remove it

View File

@@ -55,29 +55,12 @@ private newtype TIRDataFlowNode =
TFinalParameterNode(Parameter p, int indirectionIndex) {
exists(Ssa::FinalParameterUse use |
use.getParameter() = p and
use.getIndirectionIndex() = indirectionIndex and
parameterIsRedefined(p)
use.getIndirectionIndex() = indirectionIndex
)
} or
TFinalGlobalValue(Ssa::GlobalUse globalUse) or
TInitialGlobalValue(Ssa::GlobalDef globalUse)
/**
* Holds if the value of `*p` (or `**p`, `***p`, etc.) is redefined somewhere in the body
* of the enclosing function of `p`.
*
* Only parameters satisfying this predicate will generate a `FinalParameterNode` transferring
* flow out of the function.
*/
private predicate parameterIsRedefined(Parameter p) {
exists(Ssa::Def def |
def.getSourceVariable().getBaseVariable().(Ssa::BaseIRVariable).getIRVariable().getAst() = p and
def.getIndirectionIndex() = 0 and
def.getIndirection() > 1 and
not def.getValue().asInstruction() instanceof InitializeParameterInstruction
)
}
/**
* An operand that is defined by a `FieldAddressInstruction`.
*/

View File

@@ -4,7 +4,11 @@ private import DataFlowUtil
private import DataFlowImplCommon as DataFlowImplCommon
private import semmle.code.cpp.models.interfaces.Allocation as Alloc
private import semmle.code.cpp.models.interfaces.DataFlow as DataFlow
private import semmle.code.cpp.models.interfaces.Taint as Taint
private import semmle.code.cpp.models.interfaces.PartialFlow as PartialFlow
private import semmle.code.cpp.models.interfaces.FunctionInputsAndOutputs as FIO
private import semmle.code.cpp.ir.internal.IRCppLanguage
private import semmle.code.cpp.ir.dataflow.internal.ModelUtil
private import DataFlowPrivate
private import ssa0.SsaInternals as SsaInternals0
import SsaInternalsCommon
@@ -138,12 +142,11 @@ private newtype TDefOrUseImpl =
isIteratorUse(container, iteratorAddress, _, indirectionIndex)
} or
TFinalParameterUse(Parameter p, int indirectionIndex) {
// Avoid creating parameter nodes if there is no definitions of the variable other than the initializaion.
exists(SsaInternals0::Def def |
def.getSourceVariable().getBaseVariable().(BaseIRVariable).getIRVariable().getAst() = p and
not def.getValue().asInstruction() instanceof InitializeParameterInstruction and
underlyingTypeIsModifiableAt(p.getUnderlyingType(), indirectionIndex)
)
underlyingTypeIsModifiableAt(p.getUnderlyingType(), indirectionIndex) and
// Only create an SSA read for the final use of a parameter if there's
// actually a body of the enclosing function. If there's no function body
// then we'll never need to flow out of the function anyway.
p.getFunction().hasDefinition()
}
private predicate isGlobalUse(
@@ -796,10 +799,58 @@ private Node getAPriorDefinition(SsaDefOrUse defOrUse) {
)
}
private predicate inOut(FIO::FunctionInput input, FIO::FunctionOutput output) {
exists(int indirectionIndex |
input.isQualifierObject(indirectionIndex) and
output.isQualifierObject(indirectionIndex)
or
exists(int i |
input.isParameterDeref(i, indirectionIndex) and
output.isParameterDeref(i, indirectionIndex)
)
)
}
/**
* Holds if there should not be use-use flow out of `n`. That is, `n` is
* an out-barrier to use-use flow. This includes:
*
* - an input to a call that would be assumed to have use-use flow to the same
* argument as an output, but this flow should be blocked because the
* function is modeled with another flow to that output (for example the
* first argument of `strcpy`).
* - a conversion that flows to such an input.
*/
private predicate modeledFlowBarrier(Node n) {
exists(
FIO::FunctionInput input, FIO::FunctionOutput output, CallInstruction call,
PartialFlow::PartialFlowFunction partialFlowFunc
|
n = callInput(call, input) and
inOut(input, output) and
exists(callOutput(call, output)) and
partialFlowFunc = call.getStaticCallTarget() and
not partialFlowFunc.isPartialWrite(output)
|
call.getStaticCallTarget().(DataFlow::DataFlowFunction).hasDataFlow(_, output)
or
call.getStaticCallTarget().(Taint::TaintFunction).hasTaintFlow(_, output)
)
or
exists(Operand operand, Instruction instr, Node n0, int indirectionIndex |
modeledFlowBarrier(n0) and
nodeHasInstruction(n0, instr, indirectionIndex) and
conversionFlow(operand, instr, false, _) and
nodeHasOperand(n, operand, indirectionIndex)
)
}
/** Holds if there is def-use or use-use flow from `nodeFrom` to `nodeTo`. */
predicate ssaFlow(Node nodeFrom, Node nodeTo) {
exists(Node nFrom, boolean uncertain, SsaDefOrUse defOrUse |
ssaFlowImpl(defOrUse, nFrom, nodeTo, uncertain) and nodeFrom != nodeTo
ssaFlowImpl(defOrUse, nFrom, nodeTo, uncertain) and
not modeledFlowBarrier(nFrom) and
nodeFrom != nodeTo
|
if uncertain = true then nodeFrom = [nFrom, getAPriorDefinition(defOrUse)] else nodeFrom = nFrom
)

View File

@@ -15,6 +15,8 @@ private class GetDelimFunction extends TaintFunction, AliasFunction, SideEffectF
i.isParameter(3) and o.isParameterDeref(0)
}
override predicate isPartialWrite(FunctionOutput o) { o.isParameterDeref(3) }
override predicate parameterNeverEscapes(int index) { index = [0, 1, 3] }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }

View File

@@ -27,6 +27,8 @@ private class FgetsFunction extends DataFlowFunction, TaintFunction, ArrayFuncti
output.isReturnValue()
}
override predicate isPartialWrite(FunctionOutput output) { output.isParameterDeref(2) }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isParameter(2) and
output.isParameterDeref(0)

View File

@@ -20,6 +20,8 @@ private class InetAton extends TaintFunction, ArrayFunction {
output.isParameterDeref(1)
}
override predicate isPartialWrite(FunctionOutput output) { output.isParameterDeref(1) }
override predicate hasArrayInput(int bufParam) { bufParam = 0 }
override predicate hasArrayOutput(int bufParam) { bufParam = 1 }

View File

@@ -118,6 +118,8 @@ private class StdSequenceContainerData extends TaintFunction {
input.isReturnValueDeref() and
output.isQualifierObject()
}
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
}
/**
@@ -147,6 +149,8 @@ private class StdSequenceContainerPushModel extends StdSequenceContainerPush, Ta
input.isParameterDeref(0) and
output.isQualifierObject()
}
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
}
/**
@@ -207,6 +211,8 @@ private class StdSequenceContainerInsertModel extends StdSequenceContainerInsert
output.isReturnValue()
)
}
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
}
/**
@@ -263,6 +269,8 @@ private class StdSequenceContainerAt extends TaintFunction {
input.isReturnValueDeref() and
output.isQualifierObject()
}
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
}
/**
@@ -297,6 +305,8 @@ private class StdSequenceEmplaceModel extends StdSequenceEmplace, TaintFunction
output.isReturnValue()
)
}
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
}
/**
@@ -335,6 +345,8 @@ private class StdSequenceEmplaceBackModel extends StdSequenceEmplaceBack, TaintF
input.isParameterDeref([0 .. this.getNumberOfParameters() - 1]) and
output.isQualifierObject()
}
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
}
/**

View File

@@ -3,6 +3,7 @@
*/
import semmle.code.cpp.models.interfaces.Taint
import semmle.code.cpp.models.interfaces.DataFlow
import semmle.code.cpp.models.interfaces.Iterator
/**
@@ -53,6 +54,8 @@ private class StdMapInsert extends TaintFunction {
output.isReturnValue()
)
}
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
}
/**
@@ -75,6 +78,8 @@ private class StdMapEmplace extends TaintFunction {
input.isQualifierObject() and
output.isReturnValue()
}
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
}
/**
@@ -102,6 +107,8 @@ private class StdMapTryEmplace extends TaintFunction {
input.isQualifierObject() and
output.isReturnValue()
}
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
}
/**
@@ -115,6 +122,8 @@ private class StdMapMerge extends TaintFunction {
input.isParameterDeref(0) and
output.isQualifierObject()
}
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
}
/**
@@ -132,6 +141,8 @@ private class StdMapAt extends TaintFunction {
input.isReturnValueDeref() and
output.isQualifierObject()
}
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
}
/**

View File

@@ -61,6 +61,8 @@ private class StdSetInsert extends TaintFunction {
output.isReturnValue()
)
}
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
}
/**
@@ -82,6 +84,8 @@ private class StdSetEmplace extends TaintFunction {
input.isQualifierObject() and
output.isReturnValue()
}
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
}
/**
@@ -95,6 +99,8 @@ private class StdSetMerge extends TaintFunction {
input.isParameterDeref(0) and
output.isQualifierObject()
}
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
}
/**

View File

@@ -129,6 +129,8 @@ private class StdStringDataModel extends StdStringData, StdStringTaintFunction {
input.isReturnValueDeref() and
output.isQualifierObject()
}
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
}
/**
@@ -142,6 +144,8 @@ private class StdStringPush extends StdStringTaintFunction {
input.isParameter(0) and
output.isQualifierObject()
}
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
}
/**
@@ -204,6 +208,8 @@ private class StdStringAppend extends StdStringTaintFunction {
input.isReturnValueDeref() and
output.isQualifierObject()
}
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
}
/**
@@ -237,6 +243,8 @@ private class StdStringInsert extends StdStringTaintFunction {
input.isReturnValueDeref() and
output.isQualifierObject()
}
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
}
/**
@@ -305,6 +313,8 @@ private class StdStringAt extends StdStringTaintFunction {
input.isReturnValueDeref() and
output.isQualifierObject()
}
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
}
/**
@@ -338,6 +348,8 @@ private class StdIStreamIn extends DataFlowFunction, TaintFunction {
input.isReturnValueDeref() and
output.isQualifierObject()
}
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
}
/**
@@ -358,6 +370,8 @@ private class StdIStreamInNonMember extends DataFlowFunction, TaintFunction {
output.isReturnValueDeref()
}
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from first parameter to second parameter
input.isParameterDeref(0) and
@@ -403,6 +417,8 @@ private class StdIStreamRead extends DataFlowFunction, TaintFunction {
output.isReturnValueDeref()
}
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from qualifier to first parameter
input.isQualifierObject() and
@@ -442,6 +458,8 @@ private class StdIStreamPutBack extends DataFlowFunction, TaintFunction {
output.isReturnValueDeref()
}
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from first parameter (value or pointer) to qualifier
input.isParameter(0) and
@@ -478,6 +496,8 @@ private class StdIStreamGetLine extends DataFlowFunction, TaintFunction {
output.isReturnValueDeref()
}
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from qualifier to first parameter
input.isQualifierObject() and
@@ -540,6 +560,8 @@ private class StdOStreamOut extends DataFlowFunction, TaintFunction {
output.isReturnValueDeref()
}
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from first parameter (value or pointer) to qualifier
input.isParameter(0) and
@@ -579,6 +601,8 @@ private class StdOStreamOutNonMember extends DataFlowFunction, TaintFunction {
output.isReturnValueDeref()
}
override predicate isPartialWrite(FunctionOutput output) { output.isParameterDeref(0) }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from second parameter to first parameter
input.isParameterDeref(1) and
@@ -672,6 +696,8 @@ private class StdStreamFunction extends DataFlowFunction, TaintFunction {
output.isReturnValueDeref()
}
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// reverse flow from returned reference to the qualifier
input.isReturnValueDeref() and

View File

@@ -36,6 +36,8 @@ private class Strcrement extends ArrayFunction, TaintFunction, SideEffectFunctio
input.isParameter(index) and output.isReturnValue()
or
input.isParameterDeref(index) and output.isReturnValueDeref()
or
input.isParameterDeref(index) and output.isParameterDeref(index)
)
}

View File

@@ -10,6 +10,7 @@
import semmle.code.cpp.Function
import FunctionInputsAndOutputs
import semmle.code.cpp.models.Models
import PartialFlow
/**
* A library function for which a value is or may be copied from a parameter
@@ -18,7 +19,7 @@ import semmle.code.cpp.models.Models
* Note that this does not include partial copying of values or partial writes
* to destinations; that is covered by `TaintModel.qll`.
*/
abstract class DataFlowFunction extends Function {
abstract class DataFlowFunction extends PartialFlowFunction {
/**
* Holds if data can be copied from the argument, qualifier, or buffer
* represented by `input` to the return value or buffer represented by

View File

@@ -0,0 +1,31 @@
/**
* Provides an abstract class to override the implicit assumption that a
* dataflow/taint-tracking model always fully override the parameters they are
* are modeled as writing to. To use this QL library, create a QL class
* extending `PartialFlowFunction` with a characteristic predicate that selects
* the function or set of functions you are modeling and override the
* `isPartialWrite` predicate.
*
* Note: Since both `DataFlowFunction` and `TaintFunction` extend this class
* you don't need to explicitly add this as a base class if your QL class
* already extends either `DataFlowFunction` or `TaintFunction`.
*/
import semmle.code.cpp.Function
import FunctionInputsAndOutputs
import semmle.code.cpp.models.Models
/**
* A function that may update part of a `FunctionOutput`.
*
* For example, the destination argument of `strcat` only updates part of the
* argument.
*/
abstract class PartialFlowFunction extends Function {
/**
* Holds if the write to output does not overwrite the entire value that was
* there before, or does not do so reliably. For example the destination
* argument of `strcat` is modified but not overwritten.
*/
predicate isPartialWrite(FunctionOutput output) { none() }
}

View File

@@ -10,6 +10,7 @@
import semmle.code.cpp.Function
import FunctionInputsAndOutputs
import semmle.code.cpp.models.Models
import PartialFlow
/**
* A library function for which a taint-tracking library should propagate taint
@@ -23,7 +24,7 @@ import semmle.code.cpp.models.Models
* altered (for example copying a string with `strncpy`), this is also considered
* data flow.
*/
abstract class TaintFunction extends Function {
abstract class TaintFunction extends PartialFlowFunction {
/**
* Holds if data passed into the argument, qualifier, or buffer represented by
* `input` influences the return value or buffer represented by `output`

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The new C/C++ dataflow and taint-tracking libraries (`semmle.code.cpp.dataflow.new.DataFlow` and `semmle.code.cpp.dataflow.new.TaintTracking`) now implicitly assume that dataflow and taint modelled via `DataFlowFunction` and `TaintFunction` always fully overwrite their buffers and thus act as flow barriers. As a result, many dataflow and taint-tracking queries now produce fewer false positives. To remove this assumption and go back to the previous behavior for a given model, one can override the new `isPartialWrite` predicate.

View File

@@ -33,11 +33,14 @@ edges
| test.cpp:76:20:76:29 | *call to mk_array_p [p] | test.cpp:83:9:83:11 | *arr [p] | provenance | |
| test.cpp:79:9:79:11 | *arr [p] | test.cpp:79:14:79:14 | p | provenance | |
| test.cpp:83:9:83:11 | *arr [p] | test.cpp:83:14:83:14 | p | provenance | |
| test.cpp:87:28:87:30 | *arr [p] | test.cpp:87:28:87:30 | *arr [p] | provenance | |
| test.cpp:87:28:87:30 | *arr [p] | test.cpp:89:9:89:11 | *arr [p] | provenance | |
| test.cpp:87:28:87:30 | *arr [p] | test.cpp:93:9:93:11 | *arr [p] | provenance | |
| test.cpp:89:9:89:11 | *arr [p] | test.cpp:89:14:89:14 | p | provenance | |
| test.cpp:93:9:93:11 | *arr [p] | test.cpp:93:14:93:14 | p | provenance | |
| test.cpp:98:18:98:27 | *call to mk_array_p [p] | test.cpp:87:28:87:30 | *arr [p] | provenance | |
| test.cpp:98:18:98:27 | *call to mk_array_p [p] | test.cpp:98:18:98:27 | test6_callee output argument [p] | provenance | |
| test.cpp:98:18:98:27 | test6_callee output argument [p] | test.cpp:98:18:98:27 | *call to mk_array_p [p] | provenance | |
nodes
| test.cpp:4:17:4:22 | call to malloc | semmle.label | call to malloc |
| test.cpp:6:9:6:11 | arr | semmle.label | arr |
@@ -77,12 +80,15 @@ nodes
| test.cpp:83:9:83:11 | *arr [p] | semmle.label | *arr [p] |
| test.cpp:83:14:83:14 | p | semmle.label | p |
| test.cpp:87:28:87:30 | *arr [p] | semmle.label | *arr [p] |
| test.cpp:87:28:87:30 | *arr [p] | semmle.label | *arr [p] |
| test.cpp:89:9:89:11 | *arr [p] | semmle.label | *arr [p] |
| test.cpp:89:14:89:14 | p | semmle.label | p |
| test.cpp:93:9:93:11 | *arr [p] | semmle.label | *arr [p] |
| test.cpp:93:14:93:14 | p | semmle.label | p |
| test.cpp:98:18:98:27 | *call to mk_array_p [p] | semmle.label | *call to mk_array_p [p] |
| test.cpp:98:18:98:27 | test6_callee output argument [p] | semmle.label | test6_callee output argument [p] |
subpaths
| test.cpp:98:18:98:27 | *call to mk_array_p [p] | test.cpp:87:28:87:30 | *arr [p] | test.cpp:87:28:87:30 | *arr [p] | test.cpp:98:18:98:27 | test6_callee output argument [p] |
#select
| test.cpp:10:9:10:11 | arr | test.cpp:4:17:4:22 | call to malloc | test.cpp:10:9:10:11 | arr | Off-by one error allocated at $@ bounded by $@. | test.cpp:4:17:4:22 | call to malloc | call to malloc | test.cpp:4:24:4:27 | size | size |
| test.cpp:10:9:10:11 | arr | test.cpp:4:17:4:22 | call to malloc | test.cpp:10:9:10:11 | arr | Off-by one error allocated at $@ bounded by $@. | test.cpp:4:17:4:22 | call to malloc | call to malloc | test.cpp:4:24:4:27 | size | size |

View File

@@ -65,7 +65,7 @@ namespace std {
};
template<class Container>
constexpr back_insert_iterator<Container> back_inserter(Container& x) {
constexpr back_insert_iterator<Container> back_inserter(Container& x) { // $ ir-def=*x
return back_insert_iterator<Container>(x);
}
@@ -89,7 +89,7 @@ namespace std {
constexpr front_insert_iterator operator++(int);
};
template<class Container>
constexpr front_insert_iterator<Container> front_inserter(Container& x) {
constexpr front_insert_iterator<Container> front_inserter(Container& x) { // $ ir-def=*x
return front_insert_iterator<Container>(x);
}
}

View File

@@ -56,7 +56,7 @@ void bg_stackstruct(XY s1, XY s2) {
}
}
void bg_structptr(XY *p1, XY *p2) { // $ ast-def=p1 ast-def=p2
void bg_structptr(XY *p1, XY *p2) { // $ ast-def=p1 ast-def=p2 ir-def=*p1 ir-def=*p2
p1->x = source();
if (guarded(p1->x)) {
sink(p1->x); // $ SPURIOUS: ast

View File

@@ -8,7 +8,7 @@ struct twoIntFields {
int getFirst() { return m1; }
};
void following_pointers( // $ ast-def=sourceStruct1_ptr
void following_pointers( // $ ast-def=sourceStruct1_ptr ir-def=*cleanArray1 ir-def=*sourceArray1 ir-def=*sourceStruct1_ptr
int sourceArray1[],
int cleanArray1[],
twoIntFields sourceStruct1,

View File

@@ -25,7 +25,7 @@ struct Bottom : Middle {
void notSink(int x) override { }
};
void VirtualDispatch(Bottom *bottomPtr, Bottom &bottomRef) { // $ ast-def=bottomPtr ast-def=bottomRef
void VirtualDispatch(Bottom *bottomPtr, Bottom &bottomRef) { // $ ast-def=bottomPtr ast-def=bottomRef ir-def=*bottomPtr ir-def=*bottomRef
Top *topPtr = bottomPtr, &topRef = bottomRef;
sink(topPtr->isSource1()); // $ ir MISSING: ast
@@ -65,11 +65,11 @@ Top *allocateBottom() {
return new Bottom();
}
void callSinkByPointer(Top *top) { // $ ast-def=top
void callSinkByPointer(Top *top) { // $ ast-def=top ir-def=*top
top->isSink(source()); // leads to MISSING from ast
}
void callSinkByReference(Top &top) { // $ ast-def=top
void callSinkByReference(Top &top) { // $ ast-def=top ir-def=*top
top.isSink(source()); // leads to MISSING from ast
}
@@ -81,11 +81,11 @@ void globalVirtualDispatch() {
x->isSink(source()); // $ MISSING: ast,ir
}
Top *identity(Top *top) { // $ ast-def=top
Top *identity(Top *top) { // $ ast-def=top ir-def=*top
return top;
}
void callIdentityFunctions(Top *top, Bottom *bottom) { // $ ast-def=bottom ast-def=top
void callIdentityFunctions(Top *top, Bottom *bottom) { // $ ast-def=bottom ast-def=top ir-def=*bottom ir-def=*top
identity(bottom)->isSink(source()); // $ MISSING: ast,ir
identity(top)->isSink(source()); // no flow
}
@@ -120,7 +120,7 @@ namespace virtual_inheritance {
struct Bottom : Middle {
};
void VirtualDispatch(Bottom *bottomPtr, Bottom &bottomRef) { // $ ast-def=bottomPtr ast-def=bottomRef
void VirtualDispatch(Bottom *bottomPtr, Bottom &bottomRef) { // $ ast-def=bottomPtr ast-def=bottomRef ir-def=*bottomPtr ir-def=*bottomRef
// Because the inheritance from `Top` is virtual, the following casts go
// directly from `Bottom` to `Top`, skipping `Middle`. That means we don't
// get flow from a `Middle` value to the call qualifier.

View File

@@ -12,7 +12,7 @@ typedef struct
char isTrue;
} MyBool;
void myTest_with_local_flow(MyBool *b, int pos) // $ ast-def=b
void myTest_with_local_flow(MyBool *b, int pos) // $ ast-def=b ir-def=*b
{
MyCoords coords = {0};

View File

@@ -7,7 +7,7 @@ void source_ref(int *toTaint) { // $ ir-def=*toTaint ast-def=toTaint
void source_ref(char *toTaint) { // $ ir-def=*toTaint ast-def=toTaint
*toTaint = source();
}
void modify_copy(int* ptr) { // $ ast-def=ptr
void modify_copy(int* ptr) { // $ ast-def=ptr ir-def=*ptr
int deref = *ptr;
int* other = &deref;
source_ref(other);
@@ -19,7 +19,7 @@ void test_output_copy() {
sink(x); // clean
}
void modify(int* ptr) { // $ ast-def=ptr
void modify(int* ptr) { // $ ast-def=ptr ir-def=*ptr
int* deref = ptr;
int* other = &*deref;
source_ref(other);
@@ -31,7 +31,7 @@ void test_output() {
sink(x); // $ ir MISSING: ast
}
void modify_copy_of_pointer(int* p, unsigned len) { // $ ast-def=p
void modify_copy_of_pointer(int* p, unsigned len) { // $ ast-def=p ir-def=*p
int* p2 = new int[len];
for(unsigned i = 0; i < len; ++i) {
p2[i] = p[i];
@@ -46,7 +46,7 @@ void test_modify_copy_of_pointer() {
sink(x[0]); // $ SPURIOUS: ast // clean
}
void modify_pointer(int* p, unsigned len) { // $ ast-def=p
void modify_pointer(int* p, unsigned len) { // $ ast-def=p ir-def=*p
int** p2 = &p;
for(unsigned i = 0; i < len; ++i) {
*p2[i] = p[i];
@@ -63,17 +63,17 @@ void test_modify_of_pointer() {
char* strdup(const char* p);
void modify_copy_via_strdup(char* p) { // $ ast-def=p
void modify_copy_via_strdup(char* p) { // $ ast-def=p ir-def=*p
char* p2 = strdup(p);
source_ref(p2);
}
void test_modify_copy_via_strdup(char* p) { // $ ast-def=p
void test_modify_copy_via_strdup(char* p) { // $ ast-def=p ir-def=*p
modify_copy_via_strdup(p);
sink(*p); // clean
}
int* deref(int** p) { // $ ast-def=p
int* deref(int** p) { // $ ast-def=p ir-def=*p ir-def=**p
int* q = *p;
return q;
}
@@ -90,7 +90,7 @@ void addtaint1(int* q) { // $ ast-def=q ir-def=*q
*q = source();
}
void addtaint2(int** p) { // $ ast-def=p
void addtaint2(int** p) { // $ ast-def=p ir-def=*p ir-def=**p
int* q = *p;
addtaint1(q);
}
@@ -106,13 +106,13 @@ using size_t = decltype(sizeof(int));
void* memcpy(void* dest, const void* src, size_t);
void modify_copy_via_memcpy(char* p) { // $ ast-def=p
void modify_copy_via_memcpy(char* p) { // $ ast-def=p ir-def=*p
char* dest;
char* p2 = (char*)memcpy(dest, p, 10);
source_ref(p2);
}
void test_modify_copy_via_memcpy(char* p) { // $ ast-def=p
void test_modify_copy_via_memcpy(char* p) { // $ ast-def=p ir-def=*p
modify_copy_via_memcpy(p);
sink(*p); // clean
}
@@ -134,14 +134,14 @@ void source_ref_ref(char** toTaint) { // $ ast-def=toTaint ir-def=*toTaint ir-de
// This function copies the value of **p into a new location **p2 and then
// taints **p. Thus, **p does not contain tainted data after returning from
// this function.
void modify_copy_via_strdup_ptr_001(char** p) { // $ ast-def=p
void modify_copy_via_strdup_ptr_001(char** p) { // $ ast-def=p ir-def=*p ir-def=**p
// **p -> **p2
char** p2 = strdup_ptr_001(p);
// source -> **p2
source_ref_ref(p2);
}
void test_modify_copy_via_strdup_001(char** p) { // $ ast-def=p
void test_modify_copy_via_strdup_001(char** p) { // $ ast-def=p ir-def=*p ir-def=**p
modify_copy_via_strdup_ptr_001(p);
sink(**p); // clean
}
@@ -149,14 +149,14 @@ void test_modify_copy_via_strdup_001(char** p) { // $ ast-def=p
// This function copies the value of *p into a new location *p2 and then
// taints **p2. Thus, **p contains tainted data after returning from this
// function.
void modify_copy_via_strdup_ptr_011(char** p) { // $ ast-def=p
void modify_copy_via_strdup_ptr_011(char** p) { // $ ast-def=p ir-def=*p ir-def=**p
// **p -> **p2 and *p -> *p2
char** p2 = strdup_ptr_011(p);
// source -> **p2
source_ref_ref(p2);
}
void test_modify_copy_via_strdup_011(char** p) { // $ ast-def=p
void test_modify_copy_via_strdup_011(char** p) { // $ ast-def=p ir-def=*p ir-def=**p
modify_copy_via_strdup_ptr_011(p);
sink(**p); // $ ir MISSING: ast
}
@@ -171,7 +171,7 @@ void source_ref_2(char** toTaint) { // $ ast-def=toTaint ir-def=*toTaint ir-def=
// This function copies the value of p into a new location p2 and then
// taints *p2. Thus, *p contains tainted data after returning from this
// function.
void modify_copy_via_strdup_ptr_111_taint_ind(char** p) { // $ ast-def=p
void modify_copy_via_strdup_ptr_111_taint_ind(char** p) { // $ ast-def=p ir-def=*p ir-def=**p
// **p -> **p2, *p -> *p2, and p -> p2
char** p2 = strdup_ptr_111(p);
// source -> *p2
@@ -180,7 +180,7 @@ void modify_copy_via_strdup_ptr_111_taint_ind(char** p) { // $ ast-def=p
void sink(char*);
void test_modify_copy_via_strdup_111_taint_ind(char** p) { // $ ast-def=p
void test_modify_copy_via_strdup_111_taint_ind(char** p) { // $ ast-def=p ir-def=*p ir-def=**p
modify_copy_via_strdup_ptr_111_taint_ind(p);
sink(*p); // $ ir MISSING: ast
}
@@ -188,7 +188,7 @@ void test_modify_copy_via_strdup_111_taint_ind(char** p) { // $ ast-def=p
// This function copies the value of p into a new location p2 and then
// taints **p2. Thus, **p contains tainted data after returning from this
// function.
void modify_copy_via_strdup_ptr_111_taint_ind_ind(char** p) { // $ ast-def=p
void modify_copy_via_strdup_ptr_111_taint_ind_ind(char** p) { // $ ast-def=p ir-def=*p ir-def=**p
// **p -> **p2, *p -> *p2, and p -> p2
char** p2 = strdup_ptr_111(p);
// source -> **p2
@@ -197,7 +197,7 @@ void modify_copy_via_strdup_ptr_111_taint_ind_ind(char** p) { // $ ast-def=p
void sink(char*);
void test_modify_copy_via_strdup_111_taint_ind_ind(char** p) { // $ ast-def=p
void test_modify_copy_via_strdup_111_taint_ind_ind(char** p) { // $ ast-def=p ir-def=*p ir-def=**p
modify_copy_via_strdup_ptr_111_taint_ind_ind(p);
sink(**p); // $ ir MISSING: ast
}

View File

@@ -37,7 +37,7 @@ void test_lambdas()
};
d(t, u);
auto e = [](int &a, int &b, int &c) { // $ ast-def=a ast-def=b ast-def=c ir-def=*c
auto e = [](int &a, int &b, int &c) { // $ ast-def=a ast-def=b ast-def=c ir-def=*c ir-def=*a ir-def=*b
sink(a); // $ ast,ir
sink(b);
c = source();

View File

@@ -12,7 +12,7 @@ namespace withoutFields {
}
template<typename T>
void assignWrapper(T &lhs, T rhs) { // $ ast-def=lhs ast-def=lhs
void assignWrapper(T &lhs, T rhs) { // $ ast-def=lhs ast-def=lhs ir-def=*lhs
assign(lhs, rhs);
}
@@ -71,15 +71,15 @@ namespace withFields {
int val;
};
void assign(Int &lhs, int rhs) { // $ ast-def=lhs
void assign(Int &lhs, int rhs) { // $ ast-def=lhs ir-def=*lhs
lhs.val = rhs;
}
void assignWrapper(Int &lhs, int rhs) { // $ ast-def=lhs
void assignWrapper(Int &lhs, int rhs) { // $ ast-def=lhs ir-def=*lhs
assign(lhs, rhs);
}
void notAssign(Int &lhs, int rhs) { // $ ast-def=lhs
void notAssign(Int &lhs, int rhs) { // $ ast-def=lhs ir-def=*lhs
lhs.val = rhs;
// Field flow ignores that the field is subsequently overwritten, leading
// to false flow here.
@@ -90,14 +90,14 @@ namespace withFields {
}
}
void sourceToParam(Int &out) { // $ ast-def=out
void sourceToParam(Int &out) { // $ ast-def=out ir-def=*out
out.val = source();
if (arbitrary) {
out.val = 1;
}
}
void sourceToParamWrapper(Int &out) { // $ ast-def=out
void sourceToParamWrapper(Int &out) { // $ ast-def=out ir-def=*out
if (arbitrary) {
sourceToParam(out);
} else {
@@ -105,7 +105,7 @@ namespace withFields {
}
}
void notSource(Int &out) { // $ ast-def=out
void notSource(Int &out) { // $ ast-def=out ir-def=*out
out.val = source();
// Field flow ignores that the field is subsequently overwritten, leading
// to false flow here.

View File

@@ -3,12 +3,12 @@ void incr(unsigned char **ps) // $ ast-def=ps ir-def=*ps ir-def=**ps
*ps += 1;
}
void callincr(unsigned char *s) // $ ast-def=s
void callincr(unsigned char *s) // $ ast-def=s ir-def=*s
{
incr(&s);
}
void test(unsigned char *s) // $ ast-def=s
void test(unsigned char *s) // $ ast-def=s ir-def=*s
{
callincr(s); // $ flow
}

View File

@@ -238,8 +238,6 @@ irFlow
| test.cpp:382:48:382:54 | source1 | test.cpp:385:8:385:10 | tmp |
| test.cpp:388:53:388:59 | source1 | test.cpp:392:8:392:10 | tmp |
| test.cpp:388:53:388:59 | source1 | test.cpp:394:10:394:12 | tmp |
| test.cpp:399:7:399:9 | definition of tmp | test.cpp:401:8:401:10 | tmp |
| test.cpp:405:7:405:9 | definition of tmp | test.cpp:408:8:408:10 | tmp |
| test.cpp:416:7:416:11 | definition of local | test.cpp:418:8:418:12 | local |
| test.cpp:417:16:417:20 | intRefSource output argument | test.cpp:418:8:418:12 | local |
| test.cpp:422:7:422:11 | definition of local | test.cpp:424:8:424:12 | local |
@@ -266,6 +264,7 @@ irFlow
| test.cpp:576:17:576:31 | *call to indirect_source | test.cpp:568:10:568:19 | * ... |
| test.cpp:576:17:576:31 | *call to indirect_source | test.cpp:572:10:572:19 | * ... |
| test.cpp:576:17:576:31 | *call to indirect_source | test.cpp:578:10:578:19 | * ... |
| test.cpp:583:11:583:16 | call to source | test.cpp:590:8:590:8 | x |
| test.cpp:594:12:594:26 | *call to indirect_source | test.cpp:597:8:597:13 | * ... |
| test.cpp:601:20:601:20 | intPointerSource output argument | test.cpp:603:8:603:9 | * ... |
| test.cpp:607:20:607:20 | intPointerSource output argument | test.cpp:609:8:609:9 | * ... |

View File

@@ -63,7 +63,7 @@ namespace std {
template<class T> T&& move(T& t) noexcept; // simplified signature
}
void identityOperations(int* source1) { // $ ast-def=source1
void identityOperations(int* source1) { // $ ast-def=source1 ir-def=*source1
const int *x1 = std::move(source1);
int* x2 = const_cast<int*>(x1);
int* x3 = (x2);
@@ -398,14 +398,14 @@ void flowThroughMemcpy_blockvar_with_local_flow(int source1, int b) {
void cleanedByMemcpy_ssa(int clean1) { // currently modeled with BlockVar, not SSA
int tmp;
memcpy(&tmp, &clean1, sizeof tmp);
sink(tmp); // $ SPURIOUS: ast,ir
sink(tmp); // $ SPURIOUS: ast
}
void cleanedByMemcpy_blockvar(int clean1) {
int tmp;
int *capture = &tmp;
memcpy(&tmp, &clean1, sizeof tmp);
sink(tmp); // $ SPURIOUS: ast,ir
sink(tmp); // $ SPURIOUS: ast
}
void intRefSource(int &ref_source);
@@ -484,7 +484,7 @@ struct MyStruct {
int* content;
};
void local_field_flow_def_by_ref_steps_with_local_flow(MyStruct * s) { // $ ast-def=s
void local_field_flow_def_by_ref_steps_with_local_flow(MyStruct * s) { // $ ast-def=s ir-def=*s
writes_to_content(s->content);
int* p_content = s->content;
sink(*p_content);
@@ -521,12 +521,12 @@ void uncertain_definition() {
sink(stackArray[0]); // $ ast=519:19 ir SPURIOUS: ast=517:7
}
void set_through_const_pointer(int x, const int **e) // $ ast-def=e ir-def=**e ir-def=*e
void set_through_const_pointer(int x, const int **e) // $ ast-def=e ir-def=*e ir-def=**e
{
*e = &x;
}
void test_set_through_const_pointer(int *e) // $ ast-def=e
void test_set_through_const_pointer(int *e) // $ ast-def=e ir-def=*e
{
set_through_const_pointer(source(), &e);
sink(*e); // $ ir MISSING: ast
@@ -579,7 +579,7 @@ namespace IndirectFlowThroughGlobals {
}
}
void write_to_param(int* x) { // $ ast-def=x
void write_to_param(int* x) { // $ ast-def=x ir-def=*x
int s = source();
x = &s;
}
@@ -587,7 +587,7 @@ void write_to_param(int* x) { // $ ast-def=x
void test_write_to_param() {
int x = 0;
write_to_param(&x);
sink(x); // $ SPURIOUS: ast
sink(x); // $ SPURIOUS: ast,ir
}
void test_indirect_flow_to_array() {
@@ -609,7 +609,7 @@ void test_def_by_ref_followed_by_uncertain_write_pointer(int* p) { // $ ast-def=
sink(*p); // $ ir MISSING: ast
}
void test_flow_through_void_double_pointer(int *p) // $ ast-def=p
void test_flow_through_void_double_pointer(int *p) // $ ast-def=p ir-def=*p
{
intPointerSource(p);
void* q = (void*)&p;
@@ -695,11 +695,11 @@ void increment_buf(int** buf) { // $ ast-def=buf ir-def=*buf ir-def=**buf
sink(buf); // $ SPURIOUS: ast
}
void call_increment_buf(int** buf) { // $ ast-def=buf
void call_increment_buf(int** buf) { // $ ast-def=buf ir-def=*buf ir-def=**buf
increment_buf(buf);
}
void test_conflation_regression(int* source) { // $ ast-def=source
void test_conflation_regression(int* source) { // $ ast-def=source ir-def=*source
int* buf = source;
call_increment_buf(&buf);
}
@@ -709,13 +709,13 @@ void write_to_star_star_p(unsigned char **p) // $ ast-def=p ir-def=**p ir-def=*p
**p = 0;
}
void write_to_star_buf(unsigned char *buf) // $ ast-def=buf
void write_to_star_buf(unsigned char *buf) // $ ast-def=buf ir-def=*buf
{
unsigned char *c = buf;
write_to_star_star_p(&c);
}
void test_write_to_star_buf(unsigned char *source) // $ ast-def=source
void test_write_to_star_buf(unsigned char *source) // $ ast-def=source ir-def=*source
{
write_to_star_buf(source);
sink(*source); // clean
@@ -1041,7 +1041,7 @@ namespace test_gettext {
void* memset(void*, int, size_t);
void memset_test(char* buf) { // $ ast-def=buf
void memset_test(char* buf) { // $ ast-def=buf ir-def=*buf
memset(buf, source(), 10);
sink(*buf); // $ ir MISSING: ast
}

View File

@@ -52,13 +52,17 @@ edges
| A.cpp:103:14:103:14 | *c [a] | A.cpp:120:12:120:13 | *c1 [a] | provenance | |
| A.cpp:107:12:107:13 | *c1 [a] | A.cpp:107:12:107:16 | a | provenance | |
| A.cpp:120:12:120:13 | *c1 [a] | A.cpp:120:12:120:16 | a | provenance | |
| A.cpp:124:14:124:14 | *b [c] | A.cpp:131:8:131:8 | f7 output argument [c] | provenance | |
| A.cpp:126:5:126:5 | set output argument [c] | A.cpp:124:14:124:14 | *b [c] | provenance | |
| A.cpp:126:5:126:5 | set output argument [c] | A.cpp:131:8:131:8 | f7 output argument [c] | provenance | |
| A.cpp:126:12:126:18 | new | A.cpp:27:17:27:17 | c | provenance | |
| A.cpp:126:12:126:18 | new | A.cpp:126:5:126:5 | set output argument [c] | provenance | |
| A.cpp:126:12:126:18 | new | A.cpp:126:12:126:18 | new | provenance | |
| A.cpp:131:8:131:8 | f7 output argument [c] | A.cpp:132:10:132:10 | *b [c] | provenance | |
| A.cpp:132:10:132:10 | *b [c] | A.cpp:132:10:132:13 | c | provenance | |
| A.cpp:140:13:140:13 | *b [c] | A.cpp:151:18:151:18 | D output argument [c] | provenance | |
| A.cpp:140:13:140:13 | b | A.cpp:143:7:143:31 | ... = ... | provenance | |
| A.cpp:142:7:142:7 | *b [post update] [c] | A.cpp:140:13:140:13 | *b [c] | provenance | |
| A.cpp:142:7:142:7 | *b [post update] [c] | A.cpp:143:7:143:31 | *... = ... [c] | provenance | |
| A.cpp:142:7:142:7 | *b [post update] [c] | A.cpp:151:18:151:18 | D output argument [c] | provenance | |
| A.cpp:142:7:142:20 | ... = ... | A.cpp:142:7:142:7 | *b [post update] [c] | provenance | |
@@ -70,12 +74,20 @@ edges
| A.cpp:143:7:143:31 | ... = ... | A.cpp:143:7:143:10 | *this [post update] [b] | provenance | |
| A.cpp:143:25:143:31 | new | A.cpp:143:7:143:31 | ... = ... | provenance | |
| A.cpp:150:12:150:18 | new | A.cpp:151:18:151:18 | b | provenance | |
| A.cpp:151:12:151:24 | call to D [*b, c] | A.cpp:152:10:152:10 | *d [*b, c] | provenance | |
| A.cpp:151:12:151:24 | call to D [*b, c] | A.cpp:153:10:153:10 | *d [*b, c] | provenance | |
| A.cpp:151:12:151:24 | call to D [b] | A.cpp:152:10:152:10 | *d [b] | provenance | |
| A.cpp:151:18:151:18 | D output argument [c] | A.cpp:154:10:154:10 | *b [c] | provenance | |
| A.cpp:151:18:151:18 | b | A.cpp:140:13:140:13 | b | provenance | |
| A.cpp:151:18:151:18 | b | A.cpp:151:12:151:24 | call to D [b] | provenance | |
| A.cpp:152:10:152:10 | *d [*b, c] | A.cpp:152:10:152:13 | *b [c] | provenance | |
| A.cpp:152:10:152:10 | *d [*b, c] | A.cpp:152:13:152:13 | *b [c] | provenance | |
| A.cpp:152:10:152:10 | *d [b] | A.cpp:152:10:152:13 | b | provenance | |
| A.cpp:152:10:152:10 | *d [post update] [*b, c] | A.cpp:153:10:153:10 | *d [*b, c] | provenance | |
| A.cpp:152:10:152:13 | *b [c] | A.cpp:152:10:152:13 | sink output argument [c] | provenance | |
| A.cpp:152:10:152:13 | *b [c] | A.cpp:173:26:173:26 | *o [c] | provenance | |
| A.cpp:152:10:152:13 | sink output argument [c] | A.cpp:152:10:152:10 | *d [post update] [*b, c] | provenance | |
| A.cpp:152:13:152:13 | *b [c] | A.cpp:152:10:152:13 | *b [c] | provenance | |
| A.cpp:153:10:153:10 | *d [*b, c] | A.cpp:153:13:153:13 | *b [c] | provenance | |
| A.cpp:153:13:153:13 | *b [c] | A.cpp:153:10:153:16 | c | provenance | |
| A.cpp:154:10:154:10 | *b [c] | A.cpp:154:10:154:13 | c | provenance | |
@@ -98,6 +110,7 @@ edges
| A.cpp:167:47:167:50 | *next [*next, head] | A.cpp:167:44:167:44 | *l [*next, head] | provenance | |
| A.cpp:167:47:167:50 | *next [head] | A.cpp:169:12:169:12 | *l [head] | provenance | |
| A.cpp:169:12:169:12 | *l [head] | A.cpp:169:12:169:18 | head | provenance | |
| A.cpp:173:26:173:26 | *o [c] | A.cpp:173:26:173:26 | *o [c] | provenance | |
| A.cpp:181:15:181:21 | newHead | A.cpp:183:7:183:20 | ... = ... | provenance | |
| A.cpp:181:32:181:35 | *next [*next, head] | A.cpp:184:7:184:23 | *... = ... [*next, head] | provenance | |
| A.cpp:181:32:181:35 | *next [head] | A.cpp:184:7:184:23 | *... = ... [head] | provenance | |
@@ -200,9 +213,13 @@ edges
| E.cpp:30:23:30:26 | *data [post update] [*buffer] | E.cpp:30:21:30:21 | *p [post update] [data, *buffer] | provenance | |
| E.cpp:32:10:32:10 | *b [*buffer] | E.cpp:32:13:32:18 | *buffer | provenance | |
| E.cpp:33:18:33:19 | *& ... [data, *buffer] | E.cpp:19:27:19:27 | *p [data, *buffer] | provenance | |
| aliasing.cpp:8:23:8:23 | *s [m1] | aliasing.cpp:25:17:25:19 | pointerSetter output argument [m1] | provenance | |
| aliasing.cpp:9:3:9:3 | *s [post update] [m1] | aliasing.cpp:8:23:8:23 | *s [m1] | provenance | |
| aliasing.cpp:9:3:9:3 | *s [post update] [m1] | aliasing.cpp:25:17:25:19 | pointerSetter output argument [m1] | provenance | |
| aliasing.cpp:9:3:9:22 | ... = ... | aliasing.cpp:9:3:9:3 | *s [post update] [m1] | provenance | |
| aliasing.cpp:9:11:9:20 | call to user_input | aliasing.cpp:9:3:9:22 | ... = ... | provenance | |
| aliasing.cpp:12:25:12:25 | *s [m1] | aliasing.cpp:26:19:26:20 | referenceSetter output argument [m1] | provenance | |
| aliasing.cpp:13:3:13:3 | *s [post update] [m1] | aliasing.cpp:12:25:12:25 | *s [m1] | provenance | |
| aliasing.cpp:13:3:13:3 | *s [post update] [m1] | aliasing.cpp:26:19:26:20 | referenceSetter output argument [m1] | provenance | |
| aliasing.cpp:13:3:13:21 | ... = ... | aliasing.cpp:13:3:13:3 | *s [post update] [m1] | provenance | |
| aliasing.cpp:13:10:13:19 | call to user_input | aliasing.cpp:13:3:13:21 | ... = ... | provenance | |
@@ -313,6 +330,7 @@ edges
| arrays.cpp:50:10:50:17 | *indirect [*ptr, data] | arrays.cpp:50:20:50:22 | *ptr [data] | provenance | |
| arrays.cpp:50:20:50:22 | *ptr [data] | arrays.cpp:50:8:50:25 | *access to array [data] | provenance | |
| by_reference.cpp:11:48:11:52 | value | by_reference.cpp:12:5:12:16 | ... = ... | provenance | |
| by_reference.cpp:12:5:12:5 | *s [post update] [a] | by_reference.cpp:11:39:11:39 | *s [a] | provenance | |
| by_reference.cpp:12:5:12:16 | ... = ... | by_reference.cpp:12:5:12:5 | *s [post update] [a] | provenance | |
| by_reference.cpp:15:26:15:30 | value | by_reference.cpp:16:5:16:19 | ... = ... | provenance | |
| by_reference.cpp:16:5:16:19 | ... = ... | by_reference.cpp:16:5:16:8 | *this [post update] [a] | provenance | |
@@ -356,12 +374,22 @@ edges
| by_reference.cpp:68:21:68:30 | call to user_input | by_reference.cpp:68:17:68:18 | nonMemberSetA output argument [a] | provenance | |
| by_reference.cpp:69:22:69:23 | *& ... [a] | by_reference.cpp:31:46:31:46 | *s [a] | provenance | |
| by_reference.cpp:69:22:69:23 | *& ... [a] | by_reference.cpp:69:8:69:20 | call to nonMemberGetA | provenance | |
| by_reference.cpp:83:31:83:35 | *inner [a] | by_reference.cpp:102:21:102:39 | taint_inner_a_ptr output argument [a] | provenance | |
| by_reference.cpp:83:31:83:35 | *inner [a] | by_reference.cpp:103:27:103:35 | taint_inner_a_ptr output argument [a] | provenance | |
| by_reference.cpp:83:31:83:35 | *inner [a] | by_reference.cpp:106:21:106:41 | taint_inner_a_ptr output argument [a] | provenance | |
| by_reference.cpp:83:31:83:35 | *inner [a] | by_reference.cpp:107:29:107:37 | taint_inner_a_ptr output argument [a] | provenance | |
| by_reference.cpp:84:3:84:7 | *inner [post update] [a] | by_reference.cpp:83:31:83:35 | *inner [a] | provenance | |
| by_reference.cpp:84:3:84:7 | *inner [post update] [a] | by_reference.cpp:102:21:102:39 | taint_inner_a_ptr output argument [a] | provenance | |
| by_reference.cpp:84:3:84:7 | *inner [post update] [a] | by_reference.cpp:103:27:103:35 | taint_inner_a_ptr output argument [a] | provenance | |
| by_reference.cpp:84:3:84:7 | *inner [post update] [a] | by_reference.cpp:106:21:106:41 | taint_inner_a_ptr output argument [a] | provenance | |
| by_reference.cpp:84:3:84:7 | *inner [post update] [a] | by_reference.cpp:107:29:107:37 | taint_inner_a_ptr output argument [a] | provenance | |
| by_reference.cpp:84:3:84:25 | ... = ... | by_reference.cpp:84:3:84:7 | *inner [post update] [a] | provenance | |
| by_reference.cpp:84:14:84:23 | call to user_input | by_reference.cpp:84:3:84:25 | ... = ... | provenance | |
| by_reference.cpp:87:31:87:35 | *inner [a] | by_reference.cpp:122:21:122:38 | taint_inner_a_ref output argument [a] | provenance | |
| by_reference.cpp:87:31:87:35 | *inner [a] | by_reference.cpp:123:21:123:36 | taint_inner_a_ref output argument [a] | provenance | |
| by_reference.cpp:87:31:87:35 | *inner [a] | by_reference.cpp:126:21:126:40 | taint_inner_a_ref output argument [a] | provenance | |
| by_reference.cpp:87:31:87:35 | *inner [a] | by_reference.cpp:127:21:127:38 | taint_inner_a_ref output argument [a] | provenance | |
| by_reference.cpp:88:3:88:7 | *inner [post update] [a] | by_reference.cpp:87:31:87:35 | *inner [a] | provenance | |
| by_reference.cpp:88:3:88:7 | *inner [post update] [a] | by_reference.cpp:122:21:122:38 | taint_inner_a_ref output argument [a] | provenance | |
| by_reference.cpp:88:3:88:7 | *inner [post update] [a] | by_reference.cpp:123:21:123:36 | taint_inner_a_ref output argument [a] | provenance | |
| by_reference.cpp:88:3:88:7 | *inner [post update] [a] | by_reference.cpp:126:21:126:40 | taint_inner_a_ref output argument [a] | provenance | |
@@ -614,8 +642,10 @@ edges
| qualifiers.cpp:9:21:9:25 | value | qualifiers.cpp:9:30:9:44 | ... = ... | provenance | |
| qualifiers.cpp:9:30:9:44 | ... = ... | qualifiers.cpp:9:30:9:33 | *this [post update] [a] | provenance | |
| qualifiers.cpp:12:40:12:44 | value | qualifiers.cpp:12:49:12:64 | ... = ... | provenance | |
| qualifiers.cpp:12:49:12:53 | *inner [post update] [a] | qualifiers.cpp:12:27:12:31 | *inner [a] | provenance | |
| qualifiers.cpp:12:49:12:64 | ... = ... | qualifiers.cpp:12:49:12:53 | *inner [post update] [a] | provenance | |
| qualifiers.cpp:13:42:13:46 | value | qualifiers.cpp:13:51:13:65 | ... = ... | provenance | |
| qualifiers.cpp:13:51:13:55 | *inner [post update] [a] | qualifiers.cpp:13:29:13:33 | *inner [a] | provenance | |
| qualifiers.cpp:13:51:13:65 | ... = ... | qualifiers.cpp:13:51:13:55 | *inner [post update] [a] | provenance | |
| qualifiers.cpp:22:5:22:9 | getInner output argument [*inner, a] | qualifiers.cpp:23:10:23:14 | *outer [*inner, a] | provenance | |
| qualifiers.cpp:22:5:22:38 | ... = ... | qualifiers.cpp:22:11:22:18 | *call to getInner [post update] [a] | provenance | |
@@ -716,6 +746,7 @@ edges
| simple.cpp:103:24:103:24 | x | simple.cpp:104:14:104:14 | x | provenance | |
| simple.cpp:108:17:108:26 | call to user_input | simple.cpp:109:43:109:43 | x | provenance | |
| simple.cpp:109:43:109:43 | x | simple.cpp:103:24:103:24 | x | provenance | |
| struct_init.c:14:24:14:25 | *ab [a] | struct_init.c:14:24:14:25 | *ab [a] | provenance | |
| struct_init.c:14:24:14:25 | *ab [a] | struct_init.c:15:8:15:9 | *ab [a] | provenance | |
| struct_init.c:15:8:15:9 | *ab [a] | struct_init.c:15:12:15:12 | a | provenance | |
| struct_init.c:20:13:20:14 | *definition of ab [a] | struct_init.c:22:8:22:9 | *ab [a] | provenance | |
@@ -726,6 +757,8 @@ edges
| struct_init.c:20:20:20:29 | call to user_input | struct_init.c:20:20:20:29 | call to user_input | provenance | |
| struct_init.c:22:8:22:9 | *ab [a] | struct_init.c:22:11:22:11 | a | provenance | |
| struct_init.c:24:10:24:12 | *& ... [a] | struct_init.c:14:24:14:25 | *ab [a] | provenance | |
| struct_init.c:24:10:24:12 | *& ... [a] | struct_init.c:24:10:24:12 | absink output argument [a] | provenance | |
| struct_init.c:24:10:24:12 | absink output argument [a] | struct_init.c:28:5:28:7 | *& ... [a] | provenance | |
| struct_init.c:26:16:26:20 | *definition of outer [nestedAB, a] | struct_init.c:31:8:31:12 | *outer [nestedAB, a] | provenance | |
| struct_init.c:26:16:26:20 | *definition of outer [nestedAB, a] | struct_init.c:36:11:36:15 | *outer [nestedAB, a] | provenance | |
| struct_init.c:26:16:26:20 | *definition of outer [post update] [*pointerAB, a] | struct_init.c:33:8:33:12 | *outer [*pointerAB, a] | provenance | |
@@ -805,12 +838,14 @@ nodes
| A.cpp:107:12:107:16 | a | semmle.label | a |
| A.cpp:120:12:120:13 | *c1 [a] | semmle.label | *c1 [a] |
| A.cpp:120:12:120:16 | a | semmle.label | a |
| A.cpp:124:14:124:14 | *b [c] | semmle.label | *b [c] |
| A.cpp:126:5:126:5 | set output argument [c] | semmle.label | set output argument [c] |
| A.cpp:126:12:126:18 | new | semmle.label | new |
| A.cpp:126:12:126:18 | new | semmle.label | new |
| A.cpp:131:8:131:8 | f7 output argument [c] | semmle.label | f7 output argument [c] |
| A.cpp:132:10:132:10 | *b [c] | semmle.label | *b [c] |
| A.cpp:132:10:132:13 | c | semmle.label | c |
| A.cpp:140:13:140:13 | *b [c] | semmle.label | *b [c] |
| A.cpp:140:13:140:13 | b | semmle.label | b |
| A.cpp:142:7:142:7 | *b [post update] [c] | semmle.label | *b [post update] [c] |
| A.cpp:142:7:142:20 | ... = ... | semmle.label | ... = ... |
@@ -827,8 +862,13 @@ nodes
| A.cpp:151:12:151:24 | call to D [b] | semmle.label | call to D [b] |
| A.cpp:151:18:151:18 | D output argument [c] | semmle.label | D output argument [c] |
| A.cpp:151:18:151:18 | b | semmle.label | b |
| A.cpp:152:10:152:10 | *d [*b, c] | semmle.label | *d [*b, c] |
| A.cpp:152:10:152:10 | *d [b] | semmle.label | *d [b] |
| A.cpp:152:10:152:10 | *d [post update] [*b, c] | semmle.label | *d [post update] [*b, c] |
| A.cpp:152:10:152:13 | *b [c] | semmle.label | *b [c] |
| A.cpp:152:10:152:13 | b | semmle.label | b |
| A.cpp:152:10:152:13 | sink output argument [c] | semmle.label | sink output argument [c] |
| A.cpp:152:13:152:13 | *b [c] | semmle.label | *b [c] |
| A.cpp:153:10:153:10 | *d [*b, c] | semmle.label | *d [*b, c] |
| A.cpp:153:10:153:16 | c | semmle.label | c |
| A.cpp:153:13:153:13 | *b [c] | semmle.label | *b [c] |
@@ -851,6 +891,8 @@ nodes
| A.cpp:167:47:167:50 | *next [head] | semmle.label | *next [head] |
| A.cpp:169:12:169:12 | *l [head] | semmle.label | *l [head] |
| A.cpp:169:12:169:18 | head | semmle.label | head |
| A.cpp:173:26:173:26 | *o [c] | semmle.label | *o [c] |
| A.cpp:173:26:173:26 | *o [c] | semmle.label | *o [c] |
| A.cpp:181:15:181:21 | newHead | semmle.label | newHead |
| A.cpp:181:32:181:35 | *next [*next, head] | semmle.label | *next [*next, head] |
| A.cpp:181:32:181:35 | *next [head] | semmle.label | *next [head] |
@@ -964,9 +1006,11 @@ nodes
| E.cpp:32:10:32:10 | *b [*buffer] | semmle.label | *b [*buffer] |
| E.cpp:32:13:32:18 | *buffer | semmle.label | *buffer |
| E.cpp:33:18:33:19 | *& ... [data, *buffer] | semmle.label | *& ... [data, *buffer] |
| aliasing.cpp:8:23:8:23 | *s [m1] | semmle.label | *s [m1] |
| aliasing.cpp:9:3:9:3 | *s [post update] [m1] | semmle.label | *s [post update] [m1] |
| aliasing.cpp:9:3:9:22 | ... = ... | semmle.label | ... = ... |
| aliasing.cpp:9:11:9:20 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:12:25:12:25 | *s [m1] | semmle.label | *s [m1] |
| aliasing.cpp:13:3:13:3 | *s [post update] [m1] | semmle.label | *s [post update] [m1] |
| aliasing.cpp:13:3:13:21 | ... = ... | semmle.label | ... = ... |
| aliasing.cpp:13:10:13:19 | call to user_input | semmle.label | call to user_input |
@@ -1084,6 +1128,7 @@ nodes
| arrays.cpp:50:10:50:17 | *indirect [*ptr, data] | semmle.label | *indirect [*ptr, data] |
| arrays.cpp:50:20:50:22 | *ptr [data] | semmle.label | *ptr [data] |
| arrays.cpp:50:27:50:30 | data | semmle.label | data |
| by_reference.cpp:11:39:11:39 | *s [a] | semmle.label | *s [a] |
| by_reference.cpp:11:48:11:52 | value | semmle.label | value |
| by_reference.cpp:12:5:12:5 | *s [post update] [a] | semmle.label | *s [post update] [a] |
| by_reference.cpp:12:5:12:16 | ... = ... | semmle.label | ... = ... |
@@ -1128,9 +1173,11 @@ nodes
| by_reference.cpp:68:21:68:30 | call to user_input | semmle.label | call to user_input |
| by_reference.cpp:69:8:69:20 | call to nonMemberGetA | semmle.label | call to nonMemberGetA |
| by_reference.cpp:69:22:69:23 | *& ... [a] | semmle.label | *& ... [a] |
| by_reference.cpp:83:31:83:35 | *inner [a] | semmle.label | *inner [a] |
| by_reference.cpp:84:3:84:7 | *inner [post update] [a] | semmle.label | *inner [post update] [a] |
| by_reference.cpp:84:3:84:25 | ... = ... | semmle.label | ... = ... |
| by_reference.cpp:84:14:84:23 | call to user_input | semmle.label | call to user_input |
| by_reference.cpp:87:31:87:35 | *inner [a] | semmle.label | *inner [a] |
| by_reference.cpp:88:3:88:7 | *inner [post update] [a] | semmle.label | *inner [post update] [a] |
| by_reference.cpp:88:3:88:24 | ... = ... | semmle.label | ... = ... |
| by_reference.cpp:88:13:88:22 | call to user_input | semmle.label | call to user_input |
@@ -1393,9 +1440,11 @@ nodes
| qualifiers.cpp:9:21:9:25 | value | semmle.label | value |
| qualifiers.cpp:9:30:9:33 | *this [post update] [a] | semmle.label | *this [post update] [a] |
| qualifiers.cpp:9:30:9:44 | ... = ... | semmle.label | ... = ... |
| qualifiers.cpp:12:27:12:31 | *inner [a] | semmle.label | *inner [a] |
| qualifiers.cpp:12:40:12:44 | value | semmle.label | value |
| qualifiers.cpp:12:49:12:53 | *inner [post update] [a] | semmle.label | *inner [post update] [a] |
| qualifiers.cpp:12:49:12:64 | ... = ... | semmle.label | ... = ... |
| qualifiers.cpp:13:29:13:33 | *inner [a] | semmle.label | *inner [a] |
| qualifiers.cpp:13:42:13:46 | value | semmle.label | value |
| qualifiers.cpp:13:51:13:55 | *inner [post update] [a] | semmle.label | *inner [post update] [a] |
| qualifiers.cpp:13:51:13:65 | ... = ... | semmle.label | ... = ... |
@@ -1507,6 +1556,7 @@ nodes
| simple.cpp:108:17:108:26 | call to user_input | semmle.label | call to user_input |
| simple.cpp:109:43:109:43 | x | semmle.label | x |
| struct_init.c:14:24:14:25 | *ab [a] | semmle.label | *ab [a] |
| struct_init.c:14:24:14:25 | *ab [a] | semmle.label | *ab [a] |
| struct_init.c:15:8:15:9 | *ab [a] | semmle.label | *ab [a] |
| struct_init.c:15:12:15:12 | a | semmle.label | a |
| struct_init.c:20:13:20:14 | *definition of ab [a] | semmle.label | *definition of ab [a] |
@@ -1516,6 +1566,7 @@ nodes
| struct_init.c:22:8:22:9 | *ab [a] | semmle.label | *ab [a] |
| struct_init.c:22:11:22:11 | a | semmle.label | a |
| struct_init.c:24:10:24:12 | *& ... [a] | semmle.label | *& ... [a] |
| struct_init.c:24:10:24:12 | absink output argument [a] | semmle.label | absink output argument [a] |
| struct_init.c:26:16:26:20 | *definition of outer [nestedAB, a] | semmle.label | *definition of outer [nestedAB, a] |
| struct_init.c:26:16:26:20 | *definition of outer [post update] [*pointerAB, a] | semmle.label | *definition of outer [post update] [*pointerAB, a] |
| struct_init.c:26:16:26:20 | *definition of outer [post update] [nestedAB, a] | semmle.label | *definition of outer [post update] [nestedAB, a] |
@@ -1552,6 +1603,7 @@ subpaths
| A.cpp:90:15:90:15 | c | A.cpp:27:17:27:17 | c | A.cpp:27:22:27:25 | *this [post update] [c] | A.cpp:90:7:90:8 | set output argument [c] |
| A.cpp:126:12:126:18 | new | A.cpp:27:17:27:17 | c | A.cpp:27:22:27:25 | *this [post update] [c] | A.cpp:126:5:126:5 | set output argument [c] |
| A.cpp:151:18:151:18 | b | A.cpp:140:13:140:13 | b | A.cpp:143:7:143:10 | *this [post update] [b] | A.cpp:151:12:151:24 | call to D [b] |
| A.cpp:152:10:152:13 | *b [c] | A.cpp:173:26:173:26 | *o [c] | A.cpp:173:26:173:26 | *o [c] | A.cpp:152:10:152:13 | sink output argument [c] |
| A.cpp:160:29:160:29 | b | A.cpp:181:15:181:21 | newHead | A.cpp:183:7:183:10 | *this [post update] [head] | A.cpp:160:18:160:60 | call to MyList [head] |
| A.cpp:161:38:161:39 | *l1 [head] | A.cpp:181:32:181:35 | *next [head] | A.cpp:184:7:184:10 | *this [post update] [*next, head] | A.cpp:161:18:161:40 | call to MyList [*next, head] |
| A.cpp:162:38:162:39 | *l2 [*next, head] | A.cpp:181:32:181:35 | *next [*next, head] | A.cpp:184:7:184:10 | *this [post update] [*next, *next, head] | A.cpp:162:18:162:40 | call to MyList [*next, *next, head] |
@@ -1564,6 +1616,7 @@ subpaths
| D.cpp:37:21:37:21 | e | D.cpp:11:24:11:24 | e | D.cpp:11:29:11:32 | *this [post update] [elem] | D.cpp:37:8:37:10 | setElem output argument [elem] |
| D.cpp:51:27:51:27 | e | D.cpp:11:24:11:24 | e | D.cpp:11:29:11:32 | *this [post update] [elem] | D.cpp:51:8:51:14 | setElem output argument [elem] |
| by_reference.cpp:20:23:20:27 | value | by_reference.cpp:15:26:15:30 | value | by_reference.cpp:16:5:16:8 | *this [post update] [a] | by_reference.cpp:20:5:20:8 | setDirectly output argument [a] |
| by_reference.cpp:24:25:24:29 | value | by_reference.cpp:11:48:11:52 | value | by_reference.cpp:11:39:11:39 | *s [a] | by_reference.cpp:24:19:24:22 | nonMemberSetA output argument [a] |
| by_reference.cpp:24:25:24:29 | value | by_reference.cpp:11:48:11:52 | value | by_reference.cpp:12:5:12:5 | *s [post update] [a] | by_reference.cpp:24:19:24:22 | nonMemberSetA output argument [a] |
| by_reference.cpp:40:12:40:15 | *this [a] | by_reference.cpp:35:9:35:19 | *this [a] | by_reference.cpp:35:9:35:19 | *getDirectly | by_reference.cpp:40:18:40:28 | call to getDirectly |
| by_reference.cpp:44:26:44:29 | *this [a] | by_reference.cpp:31:46:31:46 | *s [a] | by_reference.cpp:31:16:31:28 | *nonMemberGetA | by_reference.cpp:44:12:44:24 | call to nonMemberGetA |
@@ -1573,6 +1626,7 @@ subpaths
| by_reference.cpp:57:8:57:8 | *s [a] | by_reference.cpp:39:9:39:21 | *this [a] | by_reference.cpp:39:9:39:21 | *getIndirectly | by_reference.cpp:57:10:57:22 | call to getIndirectly |
| by_reference.cpp:62:25:62:34 | call to user_input | by_reference.cpp:23:34:23:38 | value | by_reference.cpp:24:19:24:22 | nonMemberSetA output argument [a] | by_reference.cpp:62:3:62:3 | setThroughNonMember output argument [a] |
| by_reference.cpp:63:8:63:8 | *s [a] | by_reference.cpp:43:9:43:27 | *this [a] | by_reference.cpp:43:9:43:27 | *getThroughNonMember | by_reference.cpp:63:10:63:28 | call to getThroughNonMember |
| by_reference.cpp:68:21:68:30 | call to user_input | by_reference.cpp:11:48:11:52 | value | by_reference.cpp:11:39:11:39 | *s [a] | by_reference.cpp:68:17:68:18 | nonMemberSetA output argument [a] |
| by_reference.cpp:68:21:68:30 | call to user_input | by_reference.cpp:11:48:11:52 | value | by_reference.cpp:12:5:12:5 | *s [post update] [a] | by_reference.cpp:68:17:68:18 | nonMemberSetA output argument [a] |
| by_reference.cpp:69:22:69:23 | *& ... [a] | by_reference.cpp:31:46:31:46 | *s [a] | by_reference.cpp:31:16:31:28 | *nonMemberGetA | by_reference.cpp:69:8:69:20 | call to nonMemberGetA |
| complex.cpp:42:16:42:16 | *f [a_] | complex.cpp:9:7:9:7 | *this [a_] | complex.cpp:9:7:9:7 | *a | complex.cpp:42:18:42:18 | call to a |
@@ -1588,7 +1642,9 @@ subpaths
| constructors.cpp:36:11:36:20 | call to user_input | constructors.cpp:23:13:23:13 | a | constructors.cpp:23:5:23:7 | *this [post update] [a_] | constructors.cpp:36:9:36:9 | call to Foo [a_] |
| constructors.cpp:36:25:36:34 | call to user_input | constructors.cpp:23:20:23:20 | b | constructors.cpp:23:5:23:7 | *this [post update] [b_] | constructors.cpp:36:9:36:9 | call to Foo [b_] |
| qualifiers.cpp:27:28:27:37 | call to user_input | qualifiers.cpp:9:21:9:25 | value | qualifiers.cpp:9:30:9:33 | *this [post update] [a] | qualifiers.cpp:27:11:27:18 | setA output argument [a] |
| qualifiers.cpp:32:35:32:44 | call to user_input | qualifiers.cpp:12:40:12:44 | value | qualifiers.cpp:12:27:12:31 | *inner [a] | qualifiers.cpp:32:23:32:30 | pointerSetA output argument [a] |
| qualifiers.cpp:32:35:32:44 | call to user_input | qualifiers.cpp:12:40:12:44 | value | qualifiers.cpp:12:49:12:53 | *inner [post update] [a] | qualifiers.cpp:32:23:32:30 | pointerSetA output argument [a] |
| qualifiers.cpp:37:38:37:47 | call to user_input | qualifiers.cpp:13:42:13:46 | value | qualifiers.cpp:13:29:13:33 | *inner [a] | qualifiers.cpp:37:19:37:35 | referenceSetA output argument [a] |
| qualifiers.cpp:37:38:37:47 | call to user_input | qualifiers.cpp:13:42:13:46 | value | qualifiers.cpp:13:51:13:55 | *inner [post update] [a] | qualifiers.cpp:37:19:37:35 | referenceSetA output argument [a] |
| simple.cpp:28:10:28:10 | *f [a_] | simple.cpp:18:9:18:9 | *this [a_] | simple.cpp:18:9:18:9 | *a | simple.cpp:28:12:28:12 | call to a |
| simple.cpp:29:10:29:10 | *f [b_] | simple.cpp:19:9:19:9 | *this [b_] | simple.cpp:19:9:19:9 | *b | simple.cpp:29:12:29:12 | call to b |
@@ -1597,6 +1653,7 @@ subpaths
| simple.cpp:41:12:41:21 | call to user_input | simple.cpp:20:19:20:19 | a | simple.cpp:20:24:20:25 | *this [post update] [a_] | simple.cpp:41:5:41:5 | setA output argument [a_] |
| simple.cpp:42:12:42:21 | call to user_input | simple.cpp:21:19:21:19 | b | simple.cpp:21:24:21:25 | *this [post update] [b_] | simple.cpp:42:5:42:5 | setB output argument [b_] |
| simple.cpp:84:14:84:20 | *this [f2, f1] | simple.cpp:78:9:78:15 | *this [f2, f1] | simple.cpp:78:9:78:15 | *getf2f1 | simple.cpp:84:14:84:20 | call to getf2f1 |
| struct_init.c:24:10:24:12 | *& ... [a] | struct_init.c:14:24:14:25 | *ab [a] | struct_init.c:14:24:14:25 | *ab [a] | struct_init.c:24:10:24:12 | absink output argument [a] |
#select
| A.cpp:43:10:43:12 | *& ... | A.cpp:41:15:41:21 | new | A.cpp:43:10:43:12 | *& ... | *& ... flows from $@ | A.cpp:41:15:41:21 | new | new |
| A.cpp:49:10:49:13 | c | A.cpp:47:12:47:18 | new | A.cpp:49:10:49:13 | c | c flows from $@ | A.cpp:47:12:47:18 | new | new |

View File

@@ -6490,6 +6490,7 @@ WARNING: Module TaintTracking has been deprecated and may be removed in future (
| taint.cpp:607:10:607:16 | call to _strinc | taint.cpp:609:8:609:12 | dest1 | |
| taint.cpp:607:18:607:23 | source | taint.cpp:607:10:607:16 | call to _strinc | TAINT |
| taint.cpp:607:26:607:31 | locale | taint.cpp:607:10:607:16 | call to _strinc | TAINT |
| taint.cpp:607:26:607:31 | locale | taint.cpp:607:26:607:31 | ref arg locale | TAINT |
| taint.cpp:607:26:607:31 | ref arg locale | taint.cpp:606:82:606:87 | locale | |
| taint.cpp:607:26:607:31 | ref arg locale | taint.cpp:611:25:611:30 | locale | |
| taint.cpp:608:7:608:11 | ref arg dest1 | taint.cpp:606:52:606:56 | dest1 | |
@@ -6501,6 +6502,7 @@ WARNING: Module TaintTracking has been deprecated and may be removed in future (
| taint.cpp:611:10:611:16 | call to _strinc | taint.cpp:613:8:613:12 | dest2 | |
| taint.cpp:611:18:611:22 | clean | taint.cpp:611:10:611:16 | call to _strinc | TAINT |
| taint.cpp:611:25:611:30 | locale | taint.cpp:611:10:611:16 | call to _strinc | TAINT |
| taint.cpp:611:25:611:30 | locale | taint.cpp:611:25:611:30 | ref arg locale | TAINT |
| taint.cpp:611:25:611:30 | ref arg locale | taint.cpp:606:82:606:87 | locale | |
| taint.cpp:612:7:612:11 | ref arg dest2 | taint.cpp:606:65:606:69 | dest2 | |
| taint.cpp:612:7:612:11 | ref arg dest2 | taint.cpp:613:8:613:12 | dest2 | |
@@ -6657,6 +6659,23 @@ WARNING: Module TaintTracking has been deprecated and may be removed in future (
| taint.cpp:745:27:745:32 | buffer | taint.cpp:745:19:745:25 | call to realloc | TAINT |
| taint.cpp:746:9:746:15 | * ... | taint.cpp:746:8:746:15 | * ... | TAINT |
| taint.cpp:746:10:746:15 | buffer | taint.cpp:746:9:746:15 | * ... | TAINT |
| taint.cpp:751:31:751:34 | path | taint.cpp:751:31:751:34 | path | |
| taint.cpp:751:31:751:34 | path | taint.cpp:752:10:752:13 | path | |
| taint.cpp:751:31:751:34 | path | taint.cpp:753:10:753:13 | path | |
| taint.cpp:751:43:751:46 | data | taint.cpp:751:43:751:46 | data | |
| taint.cpp:751:43:751:46 | data | taint.cpp:753:22:753:25 | data | |
| taint.cpp:752:10:752:13 | ref arg path | taint.cpp:751:31:751:34 | path | |
| taint.cpp:752:10:752:13 | ref arg path | taint.cpp:753:10:753:13 | path | |
| taint.cpp:752:16:752:19 | %s | taint.cpp:752:10:752:13 | ref arg path | TAINT |
| taint.cpp:752:22:752:26 | abc | taint.cpp:752:10:752:13 | ref arg path | TAINT |
| taint.cpp:753:10:753:13 | ref arg path | taint.cpp:751:31:751:34 | path | |
| taint.cpp:753:16:753:19 | %s | taint.cpp:753:10:753:13 | ref arg path | TAINT |
| taint.cpp:753:22:753:25 | data | taint.cpp:753:10:753:13 | ref arg path | TAINT |
| taint.cpp:753:22:753:25 | ref arg data | taint.cpp:751:43:751:46 | data | |
| taint.cpp:757:7:757:10 | path | taint.cpp:758:21:758:24 | path | |
| taint.cpp:757:7:757:10 | path | taint.cpp:759:8:759:11 | path | |
| taint.cpp:758:21:758:24 | ref arg path | taint.cpp:759:8:759:11 | path | |
| taint.cpp:759:8:759:11 | path | taint.cpp:759:7:759:11 | * ... | |
| vector.cpp:16:43:16:49 | source1 | vector.cpp:17:26:17:32 | source1 | |
| vector.cpp:16:43:16:49 | source1 | vector.cpp:31:38:31:44 | source1 | |
| vector.cpp:17:21:17:33 | call to vector | vector.cpp:19:14:19:14 | v | |

View File

@@ -71,11 +71,11 @@ void test_pair()
sink(i.second); // $ MISSING: ast,ir
sink(i); // $ ast,ir
sink(j.first);
sink(j.second); // $ SPURIOUS: ast,ir
sink(j); // $ SPURIOUS: ast,ir
sink(j.second); // $ SPURIOUS: ast
sink(j); // $ SPURIOUS: ast
sink(k.first);
sink(k.second); // $ SPURIOUS: ast,ir
sink(k); // $ SPURIOUS: ast,ir
sink(k.second); // $ SPURIOUS: ast
sink(k); // $ SPURIOUS: ast
sink(l.first);
sink(l.second); // $ MISSING: ast,ir
sink(l); // $ ast,ir
@@ -196,10 +196,10 @@ void test_map()
sink(m18); // $ ast,ir
m15.swap(m16);
m17.swap(m18);
sink(m15); // $ SPURIOUS: ast,ir
sink(m15); // $ SPURIOUS: ast
sink(m16); // $ ast,ir
sink(m17); // $ ast,ir
sink(m18); // $ SPURIOUS: ast,ir
sink(m18); // $ SPURIOUS: ast
// merge
std::map<char *, char *> m19, m20, m21, m22;
@@ -345,10 +345,10 @@ void test_unordered_map()
sink(m18); // $ ast,ir
m15.swap(m16);
m17.swap(m18);
sink(m15); // $ SPURIOUS: ast,ir
sink(m15); // $ SPURIOUS: ast
sink(m16); // $ ast,ir
sink(m17); // $ ast,ir
sink(m18); // $ SPURIOUS: ast,ir
sink(m18); // $ SPURIOUS: ast
// merge
std::unordered_map<char *, char *> m19, m20, m21, m22;

View File

@@ -81,10 +81,10 @@ void test_set()
sink(s15); // $ ast,ir
s12.swap(s13);
s14.swap(s15);
sink(s12); // $ SPURIOUS: ast,ir
sink(s12); // $ SPURIOUS: ast
sink(s13); // $ ast,ir
sink(s14); // $ ast,ir
sink(s15); // $ SPURIOUS: ast,ir
sink(s15); // $ SPURIOUS: ast
// merge
std::set<char *> s16, s17, s18, s19;
@@ -193,10 +193,10 @@ void test_unordered_set()
sink(s15); // $ ast,ir
s12.swap(s13);
s14.swap(s15);
sink(s12); // $ SPURIOUS: ast,ir
sink(s12); // $ SPURIOUS: ast
sink(s13); // $ ast,ir
sink(s14); // $ ast,ir
sink(s15); // $ SPURIOUS: ast,ir
sink(s15); // $ SPURIOUS: ast
// merge
std::unordered_set<char *> s16, s17, s18, s19;

View File

@@ -203,7 +203,7 @@ void test_string_assign() {
sink(s5); // $ ast,ir
sink(s6.assign(s1));
sink(s6); // $ SPURIOUS: ast,ir
sink(s6); // $ SPURIOUS: ast
}
void test_string_insert() {
@@ -280,9 +280,9 @@ void test_string_swap() {
s4.swap(s3);
sink(s1); // $ ast,ir
sink(s2); // $ SPURIOUS: ast,ir
sink(s2); // $ SPURIOUS: ast
sink(s3); // $ ast,ir
sink(s4); // $ SPURIOUS: ast,ir
sink(s4); // $ SPURIOUS: ast
}
void test_string_clear() {
@@ -495,7 +495,7 @@ void test_string_iterator_methods()
sink(h); // $ ast,ir
sink(s6.assign(s5.cbegin(), s5.cend()));
sink(s6); // $ SPURIOUS: ast,ir
sink(s6); // $ SPURIOUS: ast
}
}

View File

@@ -50,7 +50,7 @@ void test_stringstream_string(int amount)
ss7.str(source());
ss7.str("abc"); // (overwrites)
sink(ss6); // $ ast,ir
sink(ss7); // $ SPURIOUS: ast,ir
sink(ss7); // $ SPURIOUS: ast
sink(ss8.put('a'));
sink(ss9.put(ns_char::source())); // $ ast,ir
@@ -118,9 +118,9 @@ void test_stringstream_swap()
ss4.swap(ss3);
sink(ss1); // $ ast,ir
sink(ss2); // $ SPURIOUS: ast,ir
sink(ss2); // $ SPURIOUS: ast
sink(ss3); // $ ast,ir
sink(ss4); // $ SPURIOUS: ast,ir
sink(ss4); // $ SPURIOUS: ast
}
void test_stringstream_in()
@@ -217,7 +217,7 @@ void test_getline()
sink(ss1.getline(b3, 1000));
sink(b1);
sink(b2); // $ ast,ir
sink(b3); // $ SPURIOUS: ast,ir
sink(b3); // $ SPURIOUS: ast
sink(ss1.getline(b4, 1000, ' '));
sink(ss2.getline(b5, 1000, ' ')); // $ ast,ir
@@ -225,7 +225,7 @@ void test_getline()
sink(ss1.getline(b6, 1000, ' '));
sink(b4);
sink(b5); // $ ast,ir
sink(b6); // $ SPURIOUS: ast,ir
sink(b6); // $ SPURIOUS: ast
sink(ss2.getline(b7, 1000).getline(b8, 1000)); // $ ast,ir
sink(b7); // $ ast,ir
@@ -237,7 +237,7 @@ void test_getline()
sink(getline(ss1, s3));
sink(s1);
sink(s2); // $ ast,ir
sink(s3); // $ SPURIOUS: ast,ir
sink(s3); // $ SPURIOUS: ast
sink(getline(ss1, s4, ' '));
sink(getline(ss2, s5, ' ')); // $ ast,ir
@@ -245,7 +245,7 @@ void test_getline()
sink(getline(ss1, s6, ' '));
sink(s4);
sink(s5); // $ ast,ir
sink(s6); // $ SPURIOUS: ast,ir
sink(s6); // $ SPURIOUS: ast
sink(getline(getline(ss2, s7), s8)); // $ ast,ir
sink(s7); // $ ast,ir

View File

@@ -212,7 +212,7 @@ void test_swap() {
std::swap(x, y);
sink(x); // $ SPURIOUS: ast,ir
sink(x); // $ SPURIOUS: ast
sink(y); // $ ast,ir
}
@@ -744,4 +744,17 @@ void test_realloc_2_indirections(int **buffer) {
**buffer = source();
buffer = (int**)realloc(buffer, 16);
sink(**buffer); // $ ir MISSING: ast
}
int sprintf(char *, const char *, ...);
void call_sprintf_twice(char* path, char* data) {
sprintf(path, "%s", "abc");
sprintf(path, "%s", data);
}
void test_call_sprintf() {
char path[10];
call_sprintf_twice(path, indirect_source());
sink(*path); // $ ast,ir
}

View File

@@ -114,10 +114,10 @@ void test_vector_swap() {
v1.swap(v2);
v3.swap(v4);
sink(v1); // $ SPURIOUS: ast,ir
sink(v1); // $ SPURIOUS: ast
sink(v2); // $ ast,ir
sink(v3); // $ ast,ir
sink(v4); // $ SPURIOUS: ast,ir
sink(v4); // $ SPURIOUS: ast
}
void test_vector_clear() {
@@ -138,7 +138,7 @@ void test_vector_clear() {
sink(v1); // $ SPURIOUS: ast,ir
sink(v2); // $ ast,ir
sink(v3); // $ ast,ir
sink(v3); // $ SPURIOUS: ast
sink(v4);
}

View File

@@ -46,6 +46,8 @@ edges
| test.cpp:187:11:187:15 | strncat output argument | test.cpp:188:20:188:24 | *flags | provenance | |
| test.cpp:187:18:187:25 | *filename | test.cpp:187:11:187:15 | strncat output argument | provenance | |
| test.cpp:187:18:187:25 | *filename | test.cpp:187:11:187:15 | strncat output argument | provenance | |
| test.cpp:188:11:188:17 | strncat output argument | test.cpp:186:19:186:25 | *command | provenance | |
| test.cpp:188:11:188:17 | strncat output argument | test.cpp:186:19:186:25 | *command | provenance | |
| test.cpp:188:20:188:24 | *flags | test.cpp:188:11:188:17 | strncat output argument | provenance | |
| test.cpp:188:20:188:24 | *flags | test.cpp:188:11:188:17 | strncat output argument | provenance | |
| test.cpp:194:9:194:16 | fread output argument | test.cpp:196:26:196:33 | *filename | provenance | |
@@ -57,9 +59,6 @@ edges
| test.cpp:218:9:218:16 | fread output argument | test.cpp:220:19:220:26 | *filename | provenance | |
| test.cpp:220:10:220:16 | strncat output argument | test.cpp:220:10:220:16 | strncat output argument | provenance | |
| test.cpp:220:10:220:16 | strncat output argument | test.cpp:220:10:220:16 | strncat output argument | provenance | |
| test.cpp:220:10:220:16 | strncat output argument | test.cpp:220:10:220:16 | strncat output argument | provenance | |
| test.cpp:220:10:220:16 | strncat output argument | test.cpp:222:32:222:38 | *command | provenance | |
| test.cpp:220:10:220:16 | strncat output argument | test.cpp:222:32:222:38 | *command | provenance | |
| test.cpp:220:10:220:16 | strncat output argument | test.cpp:222:32:222:38 | *command | provenance | |
| test.cpp:220:10:220:16 | strncat output argument | test.cpp:222:32:222:38 | *command | provenance | |
| test.cpp:220:19:220:26 | *filename | test.cpp:220:10:220:16 | strncat output argument | provenance | |
@@ -118,6 +117,8 @@ nodes
| test.cpp:183:32:183:38 | *command | semmle.label | *command |
| test.cpp:183:32:183:38 | *command | semmle.label | *command |
| test.cpp:183:32:183:38 | *command | semmle.label | *command |
| test.cpp:186:19:186:25 | *command | semmle.label | *command |
| test.cpp:186:19:186:25 | *command | semmle.label | *command |
| test.cpp:186:47:186:54 | *filename | semmle.label | *filename |
| test.cpp:187:11:187:15 | strncat output argument | semmle.label | strncat output argument |
| test.cpp:187:11:187:15 | strncat output argument | semmle.label | strncat output argument |
@@ -142,6 +143,8 @@ nodes
| test.cpp:222:32:222:38 | *command | semmle.label | *command |
| test.cpp:222:32:222:38 | *command | semmle.label | *command |
subpaths
| test.cpp:196:26:196:33 | *filename | test.cpp:186:47:186:54 | *filename | test.cpp:186:19:186:25 | *command | test.cpp:196:10:196:16 | concat output argument |
| test.cpp:196:26:196:33 | *filename | test.cpp:186:47:186:54 | *filename | test.cpp:186:19:186:25 | *command | test.cpp:196:10:196:16 | concat output argument |
| test.cpp:196:26:196:33 | *filename | test.cpp:186:47:186:54 | *filename | test.cpp:188:11:188:17 | strncat output argument | test.cpp:196:10:196:16 | concat output argument |
| test.cpp:196:26:196:33 | *filename | test.cpp:186:47:186:54 | *filename | test.cpp:188:11:188:17 | strncat output argument | test.cpp:196:10:196:16 | concat output argument |
#select

View File

@@ -47,6 +47,7 @@ edges
| test.cpp:222:15:222:20 | buffer | test.cpp:214:24:214:24 | p | provenance | |
| test.cpp:228:27:228:54 | call to malloc | test.cpp:232:10:232:15 | buffer | provenance | |
| test.cpp:235:40:235:45 | buffer | test.cpp:236:5:236:26 | ... = ... | provenance | |
| test.cpp:236:5:236:9 | *p_str [post update] [string] | test.cpp:235:27:235:31 | *p_str [string] | provenance | |
| test.cpp:236:5:236:26 | ... = ... | test.cpp:236:5:236:9 | *p_str [post update] [string] | provenance | |
| test.cpp:241:20:241:38 | call to malloc | test.cpp:242:22:242:27 | buffer | provenance | |
| test.cpp:242:16:242:19 | set_string output argument [string] | test.cpp:243:12:243:14 | *str [string] | provenance | |
@@ -110,6 +111,7 @@ nodes
| test.cpp:222:15:222:20 | buffer | semmle.label | buffer |
| test.cpp:228:27:228:54 | call to malloc | semmle.label | call to malloc |
| test.cpp:232:10:232:15 | buffer | semmle.label | buffer |
| test.cpp:235:27:235:31 | *p_str [string] | semmle.label | *p_str [string] |
| test.cpp:235:40:235:45 | buffer | semmle.label | buffer |
| test.cpp:236:5:236:9 | *p_str [post update] [string] | semmle.label | *p_str [post update] [string] |
| test.cpp:236:5:236:26 | ... = ... | semmle.label | ... = ... |
@@ -126,6 +128,7 @@ nodes
| test.cpp:264:13:264:30 | call to malloc | semmle.label | call to malloc |
| test.cpp:266:12:266:12 | p | semmle.label | p |
subpaths
| test.cpp:242:22:242:27 | buffer | test.cpp:235:40:235:45 | buffer | test.cpp:235:27:235:31 | *p_str [string] | test.cpp:242:16:242:19 | set_string output argument [string] |
| test.cpp:242:22:242:27 | buffer | test.cpp:235:40:235:45 | buffer | test.cpp:236:5:236:9 | *p_str [post update] [string] | test.cpp:242:16:242:19 | set_string output argument [string] |
#select
| test.cpp:42:5:42:11 | call to strncpy | test.cpp:18:19:18:24 | call to malloc | test.cpp:42:18:42:23 | string | This write may overflow $@ by 1 element. | test.cpp:42:18:42:23 | string | string |

View File

@@ -3,11 +3,14 @@ edges
| main.cpp:7:33:7:36 | **argv | overflowdestination.cpp:23:45:23:48 | **argv | provenance | |
| overflowdestination.cpp:23:45:23:48 | **argv | overflowdestination.cpp:30:17:30:20 | *arg1 | provenance | |
| overflowdestination.cpp:43:8:43:10 | fgets output argument | overflowdestination.cpp:46:15:46:17 | *src | provenance | |
| overflowdestination.cpp:50:52:50:54 | *src | overflowdestination.cpp:50:52:50:54 | *src | provenance | |
| overflowdestination.cpp:50:52:50:54 | *src | overflowdestination.cpp:53:15:53:17 | *src | provenance | |
| overflowdestination.cpp:57:52:57:54 | *src | overflowdestination.cpp:64:16:64:19 | *src2 | provenance | |
| overflowdestination.cpp:73:8:73:10 | fgets output argument | overflowdestination.cpp:75:30:75:32 | *src | provenance | |
| overflowdestination.cpp:73:8:73:10 | fgets output argument | overflowdestination.cpp:76:30:76:32 | *src | provenance | |
| overflowdestination.cpp:75:30:75:32 | *src | overflowdestination.cpp:50:52:50:54 | *src | provenance | |
| overflowdestination.cpp:75:30:75:32 | *src | overflowdestination.cpp:75:30:75:32 | overflowdest_test2 output argument | provenance | |
| overflowdestination.cpp:75:30:75:32 | overflowdest_test2 output argument | overflowdestination.cpp:76:30:76:32 | *src | provenance | |
| overflowdestination.cpp:76:30:76:32 | *src | overflowdestination.cpp:57:52:57:54 | *src | provenance | |
nodes
| main.cpp:6:27:6:30 | **argv | semmle.label | **argv |
@@ -17,13 +20,16 @@ nodes
| overflowdestination.cpp:43:8:43:10 | fgets output argument | semmle.label | fgets output argument |
| overflowdestination.cpp:46:15:46:17 | *src | semmle.label | *src |
| overflowdestination.cpp:50:52:50:54 | *src | semmle.label | *src |
| overflowdestination.cpp:50:52:50:54 | *src | semmle.label | *src |
| overflowdestination.cpp:53:15:53:17 | *src | semmle.label | *src |
| overflowdestination.cpp:57:52:57:54 | *src | semmle.label | *src |
| overflowdestination.cpp:64:16:64:19 | *src2 | semmle.label | *src2 |
| overflowdestination.cpp:73:8:73:10 | fgets output argument | semmle.label | fgets output argument |
| overflowdestination.cpp:75:30:75:32 | *src | semmle.label | *src |
| overflowdestination.cpp:75:30:75:32 | overflowdest_test2 output argument | semmle.label | overflowdest_test2 output argument |
| overflowdestination.cpp:76:30:76:32 | *src | semmle.label | *src |
subpaths
| overflowdestination.cpp:75:30:75:32 | *src | overflowdestination.cpp:50:52:50:54 | *src | overflowdestination.cpp:50:52:50:54 | *src | overflowdestination.cpp:75:30:75:32 | overflowdest_test2 output argument |
#select
| overflowdestination.cpp:30:2:30:8 | call to strncpy | main.cpp:6:27:6:30 | **argv | overflowdestination.cpp:30:17:30:20 | *arg1 | To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size. |
| overflowdestination.cpp:46:2:46:7 | call to memcpy | overflowdestination.cpp:43:8:43:10 | fgets output argument | overflowdestination.cpp:46:15:46:17 | *src | To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size. |

View File

@@ -1,6 +1,44 @@
edges
| main.cpp:6:27:6:30 | **argv | main.cpp:7:33:7:36 | **argv | provenance | |
| main.cpp:6:27:6:30 | **argv | main.cpp:8:34:8:37 | **argv | provenance | |
| main.cpp:6:27:6:30 | **argv | main.cpp:9:29:9:32 | **argv | provenance | |
| main.cpp:6:27:6:30 | **argv | main.cpp:10:20:10:23 | **argv | provenance | |
| main.cpp:7:33:7:36 | **argv | main.cpp:7:33:7:36 | overflowdesination_main output argument | provenance | |
| main.cpp:7:33:7:36 | **argv | main.cpp:7:33:7:36 | overflowdesination_main output argument | provenance | |
| main.cpp:7:33:7:36 | **argv | overflowdestination.cpp:23:45:23:48 | **argv | provenance | |
| main.cpp:7:33:7:36 | overflowdesination_main output argument | main.cpp:8:34:8:37 | **argv | provenance | |
| main.cpp:7:33:7:36 | overflowdesination_main output argument | main.cpp:8:34:8:37 | *argv | provenance | |
| main.cpp:7:33:7:36 | overflowdesination_main output argument | main.cpp:9:29:9:32 | **argv | provenance | |
| main.cpp:7:33:7:36 | overflowdesination_main output argument | main.cpp:9:29:9:32 | *argv | provenance | |
| main.cpp:7:33:7:36 | overflowdesination_main output argument | main.cpp:10:20:10:23 | **argv | provenance | |
| main.cpp:7:33:7:36 | overflowdesination_main output argument | main.cpp:10:20:10:23 | *argv | provenance | |
| main.cpp:8:34:8:37 | **argv | main.cpp:8:34:8:37 | test_buffer_overrun_main output argument | provenance | |
| main.cpp:8:34:8:37 | **argv | main.cpp:8:34:8:37 | test_buffer_overrun_main output argument | provenance | |
| main.cpp:8:34:8:37 | **argv | test_buffer_overrun.cpp:32:46:32:49 | **argv | provenance | |
| main.cpp:8:34:8:37 | *argv | main.cpp:8:34:8:37 | test_buffer_overrun_main output argument | provenance | |
| main.cpp:8:34:8:37 | *argv | main.cpp:8:34:8:37 | test_buffer_overrun_main output argument | provenance | |
| main.cpp:8:34:8:37 | *argv | test_buffer_overrun.cpp:32:46:32:49 | **argv | provenance | |
| main.cpp:8:34:8:37 | *argv | test_buffer_overrun.cpp:32:46:32:49 | *argv | provenance | |
| main.cpp:8:34:8:37 | test_buffer_overrun_main output argument | main.cpp:9:29:9:32 | **argv | provenance | |
| main.cpp:8:34:8:37 | test_buffer_overrun_main output argument | main.cpp:9:29:9:32 | *argv | provenance | |
| main.cpp:8:34:8:37 | test_buffer_overrun_main output argument | main.cpp:10:20:10:23 | **argv | provenance | |
| main.cpp:8:34:8:37 | test_buffer_overrun_main output argument | main.cpp:10:20:10:23 | *argv | provenance | |
| main.cpp:9:29:9:32 | **argv | main.cpp:9:29:9:32 | tests_restrict_main output argument | provenance | |
| main.cpp:9:29:9:32 | **argv | tests_restrict.c:15:41:15:44 | **argv | provenance | |
| main.cpp:9:29:9:32 | *argv | main.cpp:9:29:9:32 | tests_restrict_main output argument | provenance | |
| main.cpp:9:29:9:32 | *argv | main.cpp:9:29:9:32 | tests_restrict_main output argument | provenance | |
| main.cpp:9:29:9:32 | *argv | tests_restrict.c:15:41:15:44 | **argv | provenance | |
| main.cpp:9:29:9:32 | *argv | tests_restrict.c:15:41:15:44 | *argv | provenance | |
| main.cpp:9:29:9:32 | tests_restrict_main output argument | main.cpp:10:20:10:23 | **argv | provenance | |
| main.cpp:9:29:9:32 | tests_restrict_main output argument | main.cpp:10:20:10:23 | *argv | provenance | |
| main.cpp:10:20:10:23 | **argv | tests.cpp:657:32:657:35 | **argv | provenance | |
| main.cpp:10:20:10:23 | *argv | tests.cpp:657:32:657:35 | **argv | provenance | |
| main.cpp:10:20:10:23 | *argv | tests.cpp:657:32:657:35 | *argv | provenance | |
| overflowdestination.cpp:23:45:23:48 | **argv | overflowdestination.cpp:23:45:23:48 | **argv | provenance | |
| overflowdestination.cpp:23:45:23:48 | **argv | overflowdestination.cpp:23:45:23:48 | *argv | provenance | |
| test_buffer_overrun.cpp:32:46:32:49 | **argv | test_buffer_overrun.cpp:32:46:32:49 | **argv | provenance | |
| test_buffer_overrun.cpp:32:46:32:49 | **argv | test_buffer_overrun.cpp:32:46:32:49 | *argv | provenance | |
| test_buffer_overrun.cpp:32:46:32:49 | *argv | test_buffer_overrun.cpp:32:46:32:49 | *argv | provenance | |
| tests.cpp:613:19:613:24 | *source | tests.cpp:615:17:615:22 | *source | provenance | |
| tests.cpp:622:19:622:24 | *source | tests.cpp:625:2:625:16 | *... = ... | provenance | |
| tests.cpp:625:2:625:2 | *s [post update] [*home] | tests.cpp:628:14:628:14 | *s [*home] | provenance | |
@@ -10,11 +48,35 @@ edges
| tests.cpp:628:16:628:19 | *home | tests.cpp:628:14:628:19 | *home | provenance | |
| tests.cpp:657:32:657:35 | **argv | tests.cpp:682:9:682:15 | *access to array | provenance | |
| tests.cpp:657:32:657:35 | **argv | tests.cpp:683:9:683:15 | *access to array | provenance | |
| tests.cpp:657:32:657:35 | *argv | tests.cpp:682:9:682:15 | *access to array | provenance | |
| tests.cpp:657:32:657:35 | *argv | tests.cpp:683:9:683:15 | *access to array | provenance | |
| tests.cpp:682:9:682:15 | *access to array | tests.cpp:613:19:613:24 | *source | provenance | |
| tests.cpp:683:9:683:15 | *access to array | tests.cpp:622:19:622:24 | *source | provenance | |
| tests_restrict.c:15:41:15:44 | **argv | tests_restrict.c:15:41:15:44 | **argv | provenance | |
| tests_restrict.c:15:41:15:44 | *argv | tests_restrict.c:15:41:15:44 | *argv | provenance | |
nodes
| main.cpp:6:27:6:30 | **argv | semmle.label | **argv |
| main.cpp:7:33:7:36 | **argv | semmle.label | **argv |
| main.cpp:7:33:7:36 | overflowdesination_main output argument | semmle.label | overflowdesination_main output argument |
| main.cpp:7:33:7:36 | overflowdesination_main output argument | semmle.label | overflowdesination_main output argument |
| main.cpp:8:34:8:37 | **argv | semmle.label | **argv |
| main.cpp:8:34:8:37 | *argv | semmle.label | *argv |
| main.cpp:8:34:8:37 | test_buffer_overrun_main output argument | semmle.label | test_buffer_overrun_main output argument |
| main.cpp:8:34:8:37 | test_buffer_overrun_main output argument | semmle.label | test_buffer_overrun_main output argument |
| main.cpp:9:29:9:32 | **argv | semmle.label | **argv |
| main.cpp:9:29:9:32 | *argv | semmle.label | *argv |
| main.cpp:9:29:9:32 | tests_restrict_main output argument | semmle.label | tests_restrict_main output argument |
| main.cpp:9:29:9:32 | tests_restrict_main output argument | semmle.label | tests_restrict_main output argument |
| main.cpp:10:20:10:23 | **argv | semmle.label | **argv |
| main.cpp:10:20:10:23 | *argv | semmle.label | *argv |
| overflowdestination.cpp:23:45:23:48 | **argv | semmle.label | **argv |
| overflowdestination.cpp:23:45:23:48 | **argv | semmle.label | **argv |
| overflowdestination.cpp:23:45:23:48 | *argv | semmle.label | *argv |
| test_buffer_overrun.cpp:32:46:32:49 | **argv | semmle.label | **argv |
| test_buffer_overrun.cpp:32:46:32:49 | **argv | semmle.label | **argv |
| test_buffer_overrun.cpp:32:46:32:49 | *argv | semmle.label | *argv |
| test_buffer_overrun.cpp:32:46:32:49 | *argv | semmle.label | *argv |
| test_buffer_overrun.cpp:32:46:32:49 | *argv | semmle.label | *argv |
| tests.cpp:613:19:613:24 | *source | semmle.label | *source |
| tests.cpp:615:17:615:22 | *source | semmle.label | *source |
| tests.cpp:622:19:622:24 | *source | semmle.label | *source |
@@ -24,9 +86,24 @@ nodes
| tests.cpp:628:14:628:19 | *home | semmle.label | *home |
| tests.cpp:628:16:628:19 | *home | semmle.label | *home |
| tests.cpp:657:32:657:35 | **argv | semmle.label | **argv |
| tests.cpp:657:32:657:35 | *argv | semmle.label | *argv |
| tests.cpp:682:9:682:15 | *access to array | semmle.label | *access to array |
| tests.cpp:683:9:683:15 | *access to array | semmle.label | *access to array |
| tests_restrict.c:15:41:15:44 | **argv | semmle.label | **argv |
| tests_restrict.c:15:41:15:44 | **argv | semmle.label | **argv |
| tests_restrict.c:15:41:15:44 | *argv | semmle.label | *argv |
| tests_restrict.c:15:41:15:44 | *argv | semmle.label | *argv |
subpaths
| main.cpp:7:33:7:36 | **argv | overflowdestination.cpp:23:45:23:48 | **argv | overflowdestination.cpp:23:45:23:48 | **argv | main.cpp:7:33:7:36 | overflowdesination_main output argument |
| main.cpp:7:33:7:36 | **argv | overflowdestination.cpp:23:45:23:48 | **argv | overflowdestination.cpp:23:45:23:48 | *argv | main.cpp:7:33:7:36 | overflowdesination_main output argument |
| main.cpp:8:34:8:37 | **argv | test_buffer_overrun.cpp:32:46:32:49 | **argv | test_buffer_overrun.cpp:32:46:32:49 | **argv | main.cpp:8:34:8:37 | test_buffer_overrun_main output argument |
| main.cpp:8:34:8:37 | **argv | test_buffer_overrun.cpp:32:46:32:49 | **argv | test_buffer_overrun.cpp:32:46:32:49 | *argv | main.cpp:8:34:8:37 | test_buffer_overrun_main output argument |
| main.cpp:8:34:8:37 | *argv | test_buffer_overrun.cpp:32:46:32:49 | **argv | test_buffer_overrun.cpp:32:46:32:49 | **argv | main.cpp:8:34:8:37 | test_buffer_overrun_main output argument |
| main.cpp:8:34:8:37 | *argv | test_buffer_overrun.cpp:32:46:32:49 | **argv | test_buffer_overrun.cpp:32:46:32:49 | *argv | main.cpp:8:34:8:37 | test_buffer_overrun_main output argument |
| main.cpp:8:34:8:37 | *argv | test_buffer_overrun.cpp:32:46:32:49 | *argv | test_buffer_overrun.cpp:32:46:32:49 | *argv | main.cpp:8:34:8:37 | test_buffer_overrun_main output argument |
| main.cpp:9:29:9:32 | **argv | tests_restrict.c:15:41:15:44 | **argv | tests_restrict.c:15:41:15:44 | **argv | main.cpp:9:29:9:32 | tests_restrict_main output argument |
| main.cpp:9:29:9:32 | *argv | tests_restrict.c:15:41:15:44 | **argv | tests_restrict.c:15:41:15:44 | **argv | main.cpp:9:29:9:32 | tests_restrict_main output argument |
| main.cpp:9:29:9:32 | *argv | tests_restrict.c:15:41:15:44 | *argv | tests_restrict.c:15:41:15:44 | *argv | main.cpp:9:29:9:32 | tests_restrict_main output argument |
#select
| tests.cpp:615:2:615:7 | call to strcpy | main.cpp:6:27:6:30 | **argv | tests.cpp:615:17:615:22 | *source | This 'call to strcpy' with input from $@ may overflow the destination. | main.cpp:6:27:6:30 | **argv | a command-line argument |
| tests.cpp:628:2:628:7 | call to strcpy | main.cpp:6:27:6:30 | **argv | tests.cpp:628:14:628:19 | *home | This 'call to strcpy' with input from $@ may overflow the destination. | main.cpp:6:27:6:30 | **argv | a command-line argument |

View File

@@ -1,20 +1,28 @@
edges
| argvLocal.c:9:25:9:31 | *correct | argvLocal.c:9:25:9:31 | *correct | provenance | |
| argvLocal.c:13:27:13:30 | **argv | argvLocal.c:95:9:95:15 | *access to array | provenance | |
| argvLocal.c:13:27:13:30 | **argv | argvLocal.c:96:15:96:21 | *access to array | provenance | |
| argvLocal.c:13:27:13:30 | **argv | argvLocal.c:96:15:96:21 | *access to array | provenance | |
| argvLocal.c:13:27:13:30 | **argv | argvLocal.c:101:9:101:10 | *i1 | provenance | |
| argvLocal.c:13:27:13:30 | **argv | argvLocal.c:102:15:102:16 | *i1 | provenance | |
| argvLocal.c:13:27:13:30 | **argv | argvLocal.c:102:15:102:16 | *i1 | provenance | |
| argvLocal.c:13:27:13:30 | **argv | argvLocal.c:106:9:106:13 | *access to array | provenance | |
| argvLocal.c:13:27:13:30 | **argv | argvLocal.c:107:15:107:19 | *access to array | provenance | |
| argvLocal.c:13:27:13:30 | **argv | argvLocal.c:107:15:107:19 | *access to array | provenance | |
| argvLocal.c:13:27:13:30 | **argv | argvLocal.c:110:9:110:11 | ** ... | provenance | |
| argvLocal.c:13:27:13:30 | **argv | argvLocal.c:111:15:111:17 | ** ... | provenance | |
| argvLocal.c:13:27:13:30 | **argv | argvLocal.c:116:9:116:10 | *i3 | provenance | |
| argvLocal.c:13:27:13:30 | **argv | argvLocal.c:117:15:117:16 | *i3 | provenance | |
| argvLocal.c:13:27:13:30 | **argv | argvLocal.c:117:15:117:16 | *i3 | provenance | |
| argvLocal.c:13:27:13:30 | **argv | argvLocal.c:121:9:121:10 | *i4 | provenance | |
| argvLocal.c:13:27:13:30 | **argv | argvLocal.c:122:15:122:16 | *i4 | provenance | |
| argvLocal.c:13:27:13:30 | **argv | argvLocal.c:122:15:122:16 | *i4 | provenance | |
| argvLocal.c:13:27:13:30 | **argv | argvLocal.c:127:9:127:10 | *i5 | provenance | |
| argvLocal.c:13:27:13:30 | **argv | argvLocal.c:128:15:128:16 | *i5 | provenance | |
| argvLocal.c:13:27:13:30 | **argv | argvLocal.c:128:15:128:16 | *i5 | provenance | |
| argvLocal.c:13:27:13:30 | **argv | argvLocal.c:131:9:131:14 | *... + ... | provenance | |
| argvLocal.c:13:27:13:30 | **argv | argvLocal.c:132:15:132:20 | *... + ... | provenance | |
| argvLocal.c:13:27:13:30 | **argv | argvLocal.c:132:15:132:20 | *... + ... | provenance | |
| argvLocal.c:13:27:13:30 | **argv | argvLocal.c:135:9:135:12 | *... ++ | provenance | |
| argvLocal.c:13:27:13:30 | **argv | argvLocal.c:136:15:136:18 | *-- ... | provenance | |
| argvLocal.c:13:27:13:30 | **argv | argvLocal.c:139:9:139:26 | *... ? ... : ... | provenance | |
@@ -23,24 +31,100 @@ edges
| argvLocal.c:13:27:13:30 | **argv | argvLocal.c:145:15:145:16 | *i7 | provenance | |
| argvLocal.c:13:27:13:30 | **argv | argvLocal.c:150:9:150:10 | *i8 | provenance | |
| argvLocal.c:13:27:13:30 | **argv | argvLocal.c:151:15:151:16 | *i8 | provenance | |
| argvLocal.c:96:15:96:21 | *access to array | argvLocal.c:9:25:9:31 | *correct | provenance | |
| argvLocal.c:96:15:96:21 | *access to array | argvLocal.c:96:15:96:21 | printWrapper output argument | provenance | |
| argvLocal.c:96:15:96:21 | printWrapper output argument | argvLocal.c:101:9:101:10 | *i1 | provenance | |
| argvLocal.c:96:15:96:21 | printWrapper output argument | argvLocal.c:102:15:102:16 | *i1 | provenance | |
| argvLocal.c:96:15:96:21 | printWrapper output argument | argvLocal.c:102:15:102:16 | *i1 | provenance | |
| argvLocal.c:96:15:96:21 | printWrapper output argument | argvLocal.c:106:9:106:13 | *access to array | provenance | |
| argvLocal.c:96:15:96:21 | printWrapper output argument | argvLocal.c:107:15:107:19 | *access to array | provenance | |
| argvLocal.c:96:15:96:21 | printWrapper output argument | argvLocal.c:107:15:107:19 | *access to array | provenance | |
| argvLocal.c:96:15:96:21 | printWrapper output argument | argvLocal.c:110:9:110:11 | ** ... | provenance | |
| argvLocal.c:96:15:96:21 | printWrapper output argument | argvLocal.c:111:15:111:17 | ** ... | provenance | |
| argvLocal.c:96:15:96:21 | printWrapper output argument | argvLocal.c:116:9:116:10 | *i3 | provenance | |
| argvLocal.c:96:15:96:21 | printWrapper output argument | argvLocal.c:117:15:117:16 | *i3 | provenance | |
| argvLocal.c:96:15:96:21 | printWrapper output argument | argvLocal.c:117:15:117:16 | *i3 | provenance | |
| argvLocal.c:96:15:96:21 | printWrapper output argument | argvLocal.c:121:9:121:10 | *i4 | provenance | |
| argvLocal.c:96:15:96:21 | printWrapper output argument | argvLocal.c:122:15:122:16 | *i4 | provenance | |
| argvLocal.c:96:15:96:21 | printWrapper output argument | argvLocal.c:122:15:122:16 | *i4 | provenance | |
| argvLocal.c:96:15:96:21 | printWrapper output argument | argvLocal.c:127:9:127:10 | *i5 | provenance | |
| argvLocal.c:96:15:96:21 | printWrapper output argument | argvLocal.c:128:15:128:16 | *i5 | provenance | |
| argvLocal.c:96:15:96:21 | printWrapper output argument | argvLocal.c:128:15:128:16 | *i5 | provenance | |
| argvLocal.c:96:15:96:21 | printWrapper output argument | argvLocal.c:131:9:131:14 | *... + ... | provenance | |
| argvLocal.c:96:15:96:21 | printWrapper output argument | argvLocal.c:132:15:132:20 | *... + ... | provenance | |
| argvLocal.c:96:15:96:21 | printWrapper output argument | argvLocal.c:132:15:132:20 | *... + ... | provenance | |
| argvLocal.c:96:15:96:21 | printWrapper output argument | argvLocal.c:135:9:135:12 | *... ++ | provenance | |
| argvLocal.c:96:15:96:21 | printWrapper output argument | argvLocal.c:136:15:136:18 | *-- ... | provenance | |
| argvLocal.c:96:15:96:21 | printWrapper output argument | argvLocal.c:139:9:139:26 | *... ? ... : ... | provenance | |
| argvLocal.c:96:15:96:21 | printWrapper output argument | argvLocal.c:140:15:140:32 | *... ? ... : ... | provenance | |
| argvLocal.c:96:15:96:21 | printWrapper output argument | argvLocal.c:144:9:144:10 | *i7 | provenance | |
| argvLocal.c:96:15:96:21 | printWrapper output argument | argvLocal.c:145:15:145:16 | *i7 | provenance | |
| argvLocal.c:96:15:96:21 | printWrapper output argument | argvLocal.c:150:9:150:10 | *i8 | provenance | |
| argvLocal.c:96:15:96:21 | printWrapper output argument | argvLocal.c:151:15:151:16 | *i8 | provenance | |
| argvLocal.c:102:15:102:16 | *i1 | argvLocal.c:9:25:9:31 | *correct | provenance | |
| argvLocal.c:102:15:102:16 | *i1 | argvLocal.c:102:15:102:16 | printWrapper output argument | provenance | |
| argvLocal.c:102:15:102:16 | printWrapper output argument | argvLocal.c:144:9:144:10 | *i7 | provenance | |
| argvLocal.c:102:15:102:16 | printWrapper output argument | argvLocal.c:145:15:145:16 | *i7 | provenance | |
| argvLocal.c:107:15:107:19 | *access to array | argvLocal.c:9:25:9:31 | *correct | provenance | |
| argvLocal.c:107:15:107:19 | *access to array | argvLocal.c:107:15:107:19 | printWrapper output argument | provenance | |
| argvLocal.c:107:15:107:19 | printWrapper output argument | argvLocal.c:110:9:110:11 | ** ... | provenance | |
| argvLocal.c:107:15:107:19 | printWrapper output argument | argvLocal.c:111:15:111:17 | ** ... | provenance | |
| argvLocal.c:117:15:117:16 | *i3 | argvLocal.c:9:25:9:31 | *correct | provenance | |
| argvLocal.c:117:15:117:16 | *i3 | argvLocal.c:117:15:117:16 | printWrapper output argument | provenance | |
| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:121:9:121:10 | *i4 | provenance | |
| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:122:15:122:16 | *i4 | provenance | |
| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:122:15:122:16 | *i4 | provenance | |
| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:135:9:135:12 | *... ++ | provenance | |
| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:136:15:136:18 | *-- ... | provenance | |
| argvLocal.c:122:15:122:16 | *i4 | argvLocal.c:9:25:9:31 | *correct | provenance | |
| argvLocal.c:122:15:122:16 | *i4 | argvLocal.c:122:15:122:16 | printWrapper output argument | provenance | |
| argvLocal.c:122:15:122:16 | printWrapper output argument | argvLocal.c:135:9:135:12 | *... ++ | provenance | |
| argvLocal.c:122:15:122:16 | printWrapper output argument | argvLocal.c:136:15:136:18 | *-- ... | provenance | |
| argvLocal.c:128:15:128:16 | *i5 | argvLocal.c:9:25:9:31 | *correct | provenance | |
| argvLocal.c:128:15:128:16 | *i5 | argvLocal.c:128:15:128:16 | printWrapper output argument | provenance | |
| argvLocal.c:128:15:128:16 | printWrapper output argument | argvLocal.c:131:9:131:14 | *... + ... | provenance | |
| argvLocal.c:128:15:128:16 | printWrapper output argument | argvLocal.c:132:15:132:20 | *... + ... | provenance | |
| argvLocal.c:128:15:128:16 | printWrapper output argument | argvLocal.c:132:15:132:20 | *... + ... | provenance | |
| argvLocal.c:128:15:128:16 | printWrapper output argument | argvLocal.c:139:9:139:26 | *... ? ... : ... | provenance | |
| argvLocal.c:128:15:128:16 | printWrapper output argument | argvLocal.c:140:15:140:32 | *... ? ... : ... | provenance | |
| argvLocal.c:132:15:132:20 | *... + ... | argvLocal.c:9:25:9:31 | *correct | provenance | |
| argvLocal.c:132:15:132:20 | *... + ... | argvLocal.c:132:15:132:20 | printWrapper output argument | provenance | |
| argvLocal.c:132:15:132:20 | printWrapper output argument | argvLocal.c:139:9:139:26 | *... ? ... : ... | provenance | |
| argvLocal.c:132:15:132:20 | printWrapper output argument | argvLocal.c:140:15:140:32 | *... ? ... : ... | provenance | |
nodes
| argvLocal.c:9:25:9:31 | *correct | semmle.label | *correct |
| argvLocal.c:9:25:9:31 | *correct | semmle.label | *correct |
| argvLocal.c:13:27:13:30 | **argv | semmle.label | **argv |
| argvLocal.c:95:9:95:15 | *access to array | semmle.label | *access to array |
| argvLocal.c:96:15:96:21 | *access to array | semmle.label | *access to array |
| argvLocal.c:96:15:96:21 | *access to array | semmle.label | *access to array |
| argvLocal.c:96:15:96:21 | printWrapper output argument | semmle.label | printWrapper output argument |
| argvLocal.c:101:9:101:10 | *i1 | semmle.label | *i1 |
| argvLocal.c:102:15:102:16 | *i1 | semmle.label | *i1 |
| argvLocal.c:102:15:102:16 | *i1 | semmle.label | *i1 |
| argvLocal.c:102:15:102:16 | printWrapper output argument | semmle.label | printWrapper output argument |
| argvLocal.c:106:9:106:13 | *access to array | semmle.label | *access to array |
| argvLocal.c:107:15:107:19 | *access to array | semmle.label | *access to array |
| argvLocal.c:107:15:107:19 | *access to array | semmle.label | *access to array |
| argvLocal.c:107:15:107:19 | printWrapper output argument | semmle.label | printWrapper output argument |
| argvLocal.c:110:9:110:11 | ** ... | semmle.label | ** ... |
| argvLocal.c:111:15:111:17 | ** ... | semmle.label | ** ... |
| argvLocal.c:116:9:116:10 | *i3 | semmle.label | *i3 |
| argvLocal.c:117:15:117:16 | *i3 | semmle.label | *i3 |
| argvLocal.c:117:15:117:16 | *i3 | semmle.label | *i3 |
| argvLocal.c:117:15:117:16 | printWrapper output argument | semmle.label | printWrapper output argument |
| argvLocal.c:121:9:121:10 | *i4 | semmle.label | *i4 |
| argvLocal.c:122:15:122:16 | *i4 | semmle.label | *i4 |
| argvLocal.c:122:15:122:16 | *i4 | semmle.label | *i4 |
| argvLocal.c:122:15:122:16 | printWrapper output argument | semmle.label | printWrapper output argument |
| argvLocal.c:127:9:127:10 | *i5 | semmle.label | *i5 |
| argvLocal.c:128:15:128:16 | *i5 | semmle.label | *i5 |
| argvLocal.c:128:15:128:16 | *i5 | semmle.label | *i5 |
| argvLocal.c:128:15:128:16 | printWrapper output argument | semmle.label | printWrapper output argument |
| argvLocal.c:131:9:131:14 | *... + ... | semmle.label | *... + ... |
| argvLocal.c:132:15:132:20 | *... + ... | semmle.label | *... + ... |
| argvLocal.c:132:15:132:20 | *... + ... | semmle.label | *... + ... |
| argvLocal.c:132:15:132:20 | printWrapper output argument | semmle.label | printWrapper output argument |
| argvLocal.c:135:9:135:12 | *... ++ | semmle.label | *... ++ |
| argvLocal.c:136:15:136:18 | *-- ... | semmle.label | *-- ... |
| argvLocal.c:139:9:139:26 | *... ? ... : ... | semmle.label | *... ? ... : ... |
@@ -50,6 +134,13 @@ nodes
| argvLocal.c:150:9:150:10 | *i8 | semmle.label | *i8 |
| argvLocal.c:151:15:151:16 | *i8 | semmle.label | *i8 |
subpaths
| argvLocal.c:96:15:96:21 | *access to array | argvLocal.c:9:25:9:31 | *correct | argvLocal.c:9:25:9:31 | *correct | argvLocal.c:96:15:96:21 | printWrapper output argument |
| argvLocal.c:102:15:102:16 | *i1 | argvLocal.c:9:25:9:31 | *correct | argvLocal.c:9:25:9:31 | *correct | argvLocal.c:102:15:102:16 | printWrapper output argument |
| argvLocal.c:107:15:107:19 | *access to array | argvLocal.c:9:25:9:31 | *correct | argvLocal.c:9:25:9:31 | *correct | argvLocal.c:107:15:107:19 | printWrapper output argument |
| argvLocal.c:117:15:117:16 | *i3 | argvLocal.c:9:25:9:31 | *correct | argvLocal.c:9:25:9:31 | *correct | argvLocal.c:117:15:117:16 | printWrapper output argument |
| argvLocal.c:122:15:122:16 | *i4 | argvLocal.c:9:25:9:31 | *correct | argvLocal.c:9:25:9:31 | *correct | argvLocal.c:122:15:122:16 | printWrapper output argument |
| argvLocal.c:128:15:128:16 | *i5 | argvLocal.c:9:25:9:31 | *correct | argvLocal.c:9:25:9:31 | *correct | argvLocal.c:128:15:128:16 | printWrapper output argument |
| argvLocal.c:132:15:132:20 | *... + ... | argvLocal.c:9:25:9:31 | *correct | argvLocal.c:9:25:9:31 | *correct | argvLocal.c:132:15:132:20 | printWrapper output argument |
#select
| argvLocal.c:95:9:95:15 | *access to array | argvLocal.c:13:27:13:30 | **argv | argvLocal.c:95:9:95:15 | *access to array | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | argvLocal.c:13:27:13:30 | **argv | a command-line argument |
| argvLocal.c:96:15:96:21 | *access to array | argvLocal.c:13:27:13:30 | **argv | argvLocal.c:96:15:96:21 | *access to array | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:13:27:13:30 | **argv | a command-line argument |

View File

@@ -1,29 +1,46 @@
edges
| globalVars.c:8:7:8:10 | **copy | globalVars.c:27:9:27:12 | *copy | provenance | |
| globalVars.c:8:7:8:10 | **copy | globalVars.c:30:15:30:18 | *copy | provenance | |
| globalVars.c:8:7:8:10 | **copy | globalVars.c:30:15:30:18 | *copy | provenance | |
| globalVars.c:8:7:8:10 | **copy | globalVars.c:35:11:35:14 | *copy | provenance | |
| globalVars.c:9:7:9:11 | **copy2 | globalVars.c:38:9:38:13 | *copy2 | provenance | |
| globalVars.c:9:7:9:11 | **copy2 | globalVars.c:41:15:41:19 | *copy2 | provenance | |
| globalVars.c:9:7:9:11 | **copy2 | globalVars.c:41:15:41:19 | *copy2 | provenance | |
| globalVars.c:9:7:9:11 | **copy2 | globalVars.c:50:9:50:13 | *copy2 | provenance | |
| globalVars.c:11:22:11:25 | **argv | globalVars.c:8:7:8:10 | **copy | provenance | |
| globalVars.c:15:21:15:23 | *val | globalVars.c:9:7:9:11 | **copy2 | provenance | |
| globalVars.c:19:25:19:27 | *str | globalVars.c:19:25:19:27 | *str | provenance | |
| globalVars.c:23:27:23:30 | **argv | globalVars.c:24:11:24:14 | **argv | provenance | |
| globalVars.c:24:11:24:14 | **argv | globalVars.c:11:22:11:25 | **argv | provenance | |
| globalVars.c:30:15:30:18 | *copy | globalVars.c:19:25:19:27 | *str | provenance | |
| globalVars.c:30:15:30:18 | *copy | globalVars.c:30:15:30:18 | printWrapper output argument | provenance | |
| globalVars.c:30:15:30:18 | printWrapper output argument | globalVars.c:35:11:35:14 | *copy | provenance | |
| globalVars.c:35:11:35:14 | *copy | globalVars.c:15:21:15:23 | *val | provenance | |
| globalVars.c:41:15:41:19 | *copy2 | globalVars.c:19:25:19:27 | *str | provenance | |
| globalVars.c:41:15:41:19 | *copy2 | globalVars.c:41:15:41:19 | printWrapper output argument | provenance | |
| globalVars.c:41:15:41:19 | printWrapper output argument | globalVars.c:50:9:50:13 | *copy2 | provenance | |
nodes
| globalVars.c:8:7:8:10 | **copy | semmle.label | **copy |
| globalVars.c:9:7:9:11 | **copy2 | semmle.label | **copy2 |
| globalVars.c:11:22:11:25 | **argv | semmle.label | **argv |
| globalVars.c:15:21:15:23 | *val | semmle.label | *val |
| globalVars.c:19:25:19:27 | *str | semmle.label | *str |
| globalVars.c:19:25:19:27 | *str | semmle.label | *str |
| globalVars.c:23:27:23:30 | **argv | semmle.label | **argv |
| globalVars.c:24:11:24:14 | **argv | semmle.label | **argv |
| globalVars.c:27:9:27:12 | *copy | semmle.label | *copy |
| globalVars.c:30:15:30:18 | *copy | semmle.label | *copy |
| globalVars.c:30:15:30:18 | *copy | semmle.label | *copy |
| globalVars.c:30:15:30:18 | printWrapper output argument | semmle.label | printWrapper output argument |
| globalVars.c:35:11:35:14 | *copy | semmle.label | *copy |
| globalVars.c:38:9:38:13 | *copy2 | semmle.label | *copy2 |
| globalVars.c:41:15:41:19 | *copy2 | semmle.label | *copy2 |
| globalVars.c:41:15:41:19 | *copy2 | semmle.label | *copy2 |
| globalVars.c:41:15:41:19 | printWrapper output argument | semmle.label | printWrapper output argument |
| globalVars.c:50:9:50:13 | *copy2 | semmle.label | *copy2 |
subpaths
| globalVars.c:30:15:30:18 | *copy | globalVars.c:19:25:19:27 | *str | globalVars.c:19:25:19:27 | *str | globalVars.c:30:15:30:18 | printWrapper output argument |
| globalVars.c:41:15:41:19 | *copy2 | globalVars.c:19:25:19:27 | *str | globalVars.c:19:25:19:27 | *str | globalVars.c:41:15:41:19 | printWrapper output argument |
#select
| globalVars.c:27:9:27:12 | *copy | globalVars.c:23:27:23:30 | **argv | globalVars.c:27:9:27:12 | *copy | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | globalVars.c:23:27:23:30 | **argv | a command-line argument |
| globalVars.c:30:15:30:18 | *copy | globalVars.c:23:27:23:30 | **argv | globalVars.c:30:15:30:18 | *copy | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(str), which calls printf(format). | globalVars.c:23:27:23:30 | **argv | a command-line argument |

View File

@@ -1,7 +1,6 @@
edges
| test2.cpp:62:18:62:25 | password | test2.cpp:65:31:65:34 | cpy1 | provenance | |
| test2.cpp:72:15:72:24 | password | test2.cpp:73:30:73:32 | *buf | provenance | |
| test2.cpp:72:15:72:24 | password | test2.cpp:76:30:76:32 | *buf | provenance | |
| test2.cpp:98:45:98:52 | password | test2.cpp:99:27:99:32 | *buffer | provenance | |
| test.cpp:70:38:70:48 | thePassword | test.cpp:73:43:73:53 | thePassword | provenance | |
| test.cpp:73:63:73:73 | thePassword | test.cpp:73:43:73:53 | thePassword | provenance | |
@@ -17,7 +16,6 @@ nodes
| test2.cpp:65:31:65:34 | cpy1 | semmle.label | cpy1 |
| test2.cpp:72:15:72:24 | password | semmle.label | password |
| test2.cpp:73:30:73:32 | *buf | semmle.label | *buf |
| test2.cpp:76:30:76:32 | *buf | semmle.label | *buf |
| test2.cpp:98:45:98:52 | password | semmle.label | password |
| test2.cpp:99:27:99:32 | *buffer | semmle.label | *buffer |
| test.cpp:45:9:45:19 | thePassword | semmle.label | thePassword |
@@ -36,7 +34,6 @@ subpaths
| test2.cpp:57:2:57:8 | call to fprintf | test2.cpp:57:39:57:49 | call to getPassword | test2.cpp:57:39:57:49 | call to getPassword | This write into file 'log' may contain unencrypted data from $@. | test2.cpp:57:39:57:49 | call to getPassword | this source. |
| test2.cpp:65:3:65:9 | call to fprintf | test2.cpp:62:18:62:25 | password | test2.cpp:65:31:65:34 | cpy1 | This write into file 'log' may contain unencrypted data from $@. | test2.cpp:62:18:62:25 | password | this source. |
| test2.cpp:73:3:73:9 | call to fprintf | test2.cpp:72:15:72:24 | password | test2.cpp:73:30:73:32 | *buf | This write into file 'log' may contain unencrypted data from $@. | test2.cpp:72:17:72:24 | password | this source. |
| test2.cpp:76:3:76:9 | call to fprintf | test2.cpp:72:15:72:24 | password | test2.cpp:76:30:76:32 | *buf | This write into file 'log' may contain unencrypted data from $@. | test2.cpp:72:17:72:24 | password | this source. |
| test2.cpp:99:3:99:9 | call to fprintf | test2.cpp:98:45:98:52 | password | test2.cpp:99:27:99:32 | *buffer | This write into file 'log' may contain unencrypted data from $@. | test2.cpp:98:45:98:52 | password | this source. |
| test.cpp:45:3:45:7 | call to fputs | test.cpp:45:9:45:19 | thePassword | test.cpp:45:9:45:19 | thePassword | This write into file 'file' may contain unencrypted data from $@. | test.cpp:45:9:45:19 | thePassword | this source. |
| test.cpp:70:35:70:35 | call to operator<< | test.cpp:70:38:70:48 | thePassword | test.cpp:70:38:70:48 | thePassword | This write into file 'mystream' may contain unencrypted data from $@. | test.cpp:70:38:70:48 | thePassword | this source. |

View File

@@ -73,7 +73,7 @@ void tests(FILE *log, myStruct &s)
fprintf(log, "buf = %s\n", buf); // BAD
strcpy(buf, s.password_hash);
fprintf(log, "buf = %s\n", buf); // GOOD [FALSE POSITIVE]
fprintf(log, "buf = %s\n", buf); // GOOD
}
{

View File

@@ -41,11 +41,14 @@ edges
| tests.cpp:73:23:73:43 | call to XercesDOMParser | tests.cpp:80:2:80:2 | *p | provenance | |
| tests.cpp:85:24:85:44 | call to XercesDOMParser | tests.cpp:88:3:88:3 | *q | provenance | |
| tests.cpp:100:24:100:44 | call to XercesDOMParser | tests.cpp:104:3:104:3 | *q | provenance | |
| tests.cpp:112:39:112:39 | *p | tests.cpp:112:39:112:39 | *p | provenance | |
| tests.cpp:112:39:112:39 | *p | tests.cpp:113:2:113:2 | *p | provenance | |
| tests.cpp:116:39:116:39 | *p | tests.cpp:117:2:117:2 | *p | provenance | |
| tests.cpp:122:23:122:43 | call to XercesDOMParser | tests.cpp:126:18:126:18 | *q | provenance | |
| tests.cpp:122:23:122:43 | call to XercesDOMParser | tests.cpp:128:18:128:18 | *q | provenance | |
| tests.cpp:126:18:126:18 | *q | tests.cpp:112:39:112:39 | *p | provenance | |
| tests.cpp:126:18:126:18 | *q | tests.cpp:126:18:126:18 | test10_doParseB output argument | provenance | |
| tests.cpp:126:18:126:18 | test10_doParseB output argument | tests.cpp:128:18:128:18 | *q | provenance | |
| tests.cpp:128:18:128:18 | *q | tests.cpp:116:39:116:39 | *p | provenance | |
nodes
| tests2.cpp:20:17:20:31 | call to SAXParser | semmle.label | call to SAXParser |
@@ -117,13 +120,16 @@ nodes
| tests.cpp:100:24:100:44 | call to XercesDOMParser | semmle.label | call to XercesDOMParser |
| tests.cpp:104:3:104:3 | *q | semmle.label | *q |
| tests.cpp:112:39:112:39 | *p | semmle.label | *p |
| tests.cpp:112:39:112:39 | *p | semmle.label | *p |
| tests.cpp:113:2:113:2 | *p | semmle.label | *p |
| tests.cpp:116:39:116:39 | *p | semmle.label | *p |
| tests.cpp:117:2:117:2 | *p | semmle.label | *p |
| tests.cpp:122:23:122:43 | call to XercesDOMParser | semmle.label | call to XercesDOMParser |
| tests.cpp:126:18:126:18 | *q | semmle.label | *q |
| tests.cpp:126:18:126:18 | test10_doParseB output argument | semmle.label | test10_doParseB output argument |
| tests.cpp:128:18:128:18 | *q | semmle.label | *q |
subpaths
| tests.cpp:126:18:126:18 | *q | tests.cpp:112:39:112:39 | *p | tests.cpp:112:39:112:39 | *p | tests.cpp:126:18:126:18 | test10_doParseB output argument |
#select
| tests2.cpp:22:2:22:2 | *p | tests2.cpp:20:17:20:31 | call to SAXParser | tests2.cpp:22:2:22:2 | *p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests2.cpp:20:17:20:31 | call to SAXParser | XML parser |
| tests2.cpp:37:2:37:2 | *p | tests2.cpp:33:17:33:31 | call to SAXParser | tests2.cpp:37:2:37:2 | *p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests2.cpp:33:17:33:31 | call to SAXParser | XML parser |

View File

@@ -882,14 +882,14 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
var alreadyDownloadedPackages = GetRestoredPackageDirectoryNames(packageDirectory.DirInfo);
var alreadyDownloadedLegacyPackages = GetRestoredLegacyPackageNames();
var notYetDownloadedPackages = new HashSet<string>(fileContent.AllPackages);
var notYetDownloadedPackages = new HashSet<PackageReference>(fileContent.AllPackages);
foreach (var alreadyDownloadedPackage in alreadyDownloadedPackages)
{
notYetDownloadedPackages.Remove(alreadyDownloadedPackage);
notYetDownloadedPackages.Remove(new(alreadyDownloadedPackage, PackageReferenceSource.SdkCsProj));
}
foreach (var alreadyDownloadedLegacyPackage in alreadyDownloadedLegacyPackages)
{
notYetDownloadedPackages.Remove(alreadyDownloadedLegacyPackage);
notYetDownloadedPackages.Remove(new(alreadyDownloadedLegacyPackage, PackageReferenceSource.PackagesConfig));
}
if (notYetDownloadedPackages.Count == 0)
@@ -930,7 +930,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
Parallel.ForEach(notYetDownloadedPackages, new ParallelOptions { MaxDegreeOfParallelism = options.Threads }, package =>
{
var success = TryRestorePackageManually(package, nugetConfig);
var success = TryRestorePackageManually(package.Name, nugetConfig, package.PackageReferenceSource);
if (!success)
{
return;
@@ -947,7 +947,10 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
dllPaths.Add(missingPackageDirectory.DirInfo.FullName);
}
private bool TryRestorePackageManually(string package, string? nugetConfig)
[GeneratedRegex(@"<TargetFramework>.*</TargetFramework>", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline)]
private static partial Regex TargetFramework();
private bool TryRestorePackageManually(string package, string? nugetConfig, PackageReferenceSource packageReferenceSource = PackageReferenceSource.SdkCsProj)
{
logger.LogInfo($"Restoring package {package}...");
using var tempDir = new TemporaryDirectory(ComputeTempDirectory(package, "missingpackages_workingdir"));
@@ -957,6 +960,11 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
return false;
}
if (packageReferenceSource == PackageReferenceSource.PackagesConfig)
{
TryChangeTargetFrameworkMoniker(tempDir.DirInfo);
}
success = dotnet.AddPackage(tempDir.DirInfo.FullName, package);
if (!success)
{
@@ -972,7 +980,9 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
res = dotnet.Restore(new(tempDir.DirInfo.FullName, missingPackageDirectory.DirInfo.FullName, ForceDotnetRefAssemblyFetching: false, PathToNugetConfig: null, ForceReevaluation: true));
}
// TODO: the restore might fail, we could retry with a prerelease (*-* instead of *) version of the package.
// TODO: the restore might fail, we could retry with
// - a prerelease (*-* instead of *) version of the package,
// - a different target framework moniker.
if (!res.Success)
{
@@ -984,6 +994,38 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
return true;
}
private void TryChangeTargetFrameworkMoniker(DirectoryInfo tempDir)
{
try
{
logger.LogInfo($"Changing the target framework moniker in {tempDir.FullName}...");
var csprojs = tempDir.GetFiles("*.csproj", new EnumerationOptions { RecurseSubdirectories = false, MatchCasing = MatchCasing.CaseInsensitive });
if (csprojs.Length != 1)
{
logger.LogError($"Could not find the .csproj file in {tempDir.FullName}, count = {csprojs.Length}");
return;
}
var csproj = csprojs[0];
var content = File.ReadAllText(csproj.FullName);
var matches = TargetFramework().Matches(content);
if (matches.Count == 0)
{
logger.LogError($"Could not find target framework in {csproj.FullName}");
}
else
{
content = TargetFramework().Replace(content, $"<TargetFramework>{FrameworkPackageNames.LatestNetFrameworkMoniker}</TargetFramework>", 1);
File.WriteAllText(csproj.FullName, content);
}
}
catch (Exception exc)
{
logger.LogError($"Failed to update target framework in {tempDir.FullName}: {exc}");
}
}
public void Dispose(TemporaryDirectory? dir, string name)
{
try

View File

@@ -19,11 +19,11 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
private readonly ILogger logger;
private readonly IUnsafeFileReader unsafeFileReader;
private readonly IEnumerable<string> files;
private readonly HashSet<string> allPackages = new HashSet<string>();
private readonly HashSet<PackageReference> allPackages = new HashSet<PackageReference>();
private readonly HashSet<string> implicitUsingNamespaces = new HashSet<string>();
private readonly Initializer initialize;
public HashSet<string> AllPackages
public HashSet<PackageReference> AllPackages
{
get
{
@@ -157,7 +157,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
return false;
}
private void AddPackageReference(ReadOnlySpan<char> line, string groupName, Func<Regex> regex)
private void AddPackageReference(ReadOnlySpan<char> line, string groupName, Func<Regex> regex, PackageReferenceSource source)
{
foreach (var valueMatch in regex().EnumerateMatches(line))
{
@@ -165,7 +165,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
var packageName = GetGroup(line, valueMatch, groupName).ToLowerInvariant();
if (!string.IsNullOrEmpty(packageName))
{
allPackages.Add(packageName);
allPackages.Add(new PackageReference(packageName, source));
}
}
}
@@ -181,11 +181,13 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
foreach (ReadOnlySpan<char> line in unsafeFileReader.ReadLines(file))
{
// Find all the packages.
AddPackageReference(line, "Include", PackageReference);
if (isPackagesConfig)
{
AddPackageReference(line, "id", LegacyPackageReference);
AddPackageReference(line, "id", LegacyPackageReference, PackageReferenceSource.PackagesConfig);
}
else
{
AddPackageReference(line, "Include", PackageReference, PackageReferenceSource.SdkCsProj);
}
// Determine if ASP.NET is used.
@@ -268,4 +270,12 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
}
}
}
public enum PackageReferenceSource
{
SdkCsProj,
PackagesConfig
}
public record PackageReference(string Name, PackageReferenceSource PackageReferenceSource);
}

View File

@@ -4,7 +4,9 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
{
internal static class FrameworkPackageNames
{
public static string LatestNetFrameworkReferenceAssemblies { get; } = "microsoft.netframework.referenceassemblies.net481";
public const string LatestNetFrameworkMoniker = "net481";
public static string LatestNetFrameworkReferenceAssemblies { get; } = $"microsoft.netframework.referenceassemblies.{LatestNetFrameworkMoniker}";
public static string AspNetCoreFramework { get; } = "microsoft.aspnetcore.app.ref";

View File

@@ -55,9 +55,9 @@ namespace Semmle.Extraction.Tests
// Verify
Assert.False(useAspNetDlls);
Assert.Equal(3, allPackages.Count);
Assert.Contains("DotNetAnalyzers.DocumentationAnalyzers".ToLowerInvariant(), allPackages);
Assert.Contains("Microsoft.CodeAnalysis.NetAnalyzers".ToLowerInvariant(), allPackages);
Assert.Contains("StyleCop.Analyzers".ToLowerInvariant(), allPackages);
Assert.Contains(new PackageReference("DotNetAnalyzers.DocumentationAnalyzers".ToLowerInvariant(), PackageReferenceSource.SdkCsProj), allPackages);
Assert.Contains(new PackageReference("Microsoft.CodeAnalysis.NetAnalyzers".ToLowerInvariant(), PackageReferenceSource.SdkCsProj), allPackages);
Assert.Contains(new PackageReference("StyleCop.Analyzers".ToLowerInvariant(), PackageReferenceSource.SdkCsProj), allPackages);
}
[Fact]
@@ -80,8 +80,8 @@ namespace Semmle.Extraction.Tests
// Verify
Assert.True(useAspNetDlls);
Assert.Equal(2, allPackages.Count);
Assert.Contains("Microsoft.CodeAnalysis.NetAnalyzers".ToLowerInvariant(), allPackages);
Assert.Contains("StyleCop.Analyzers".ToLowerInvariant(), allPackages);
Assert.Contains(new PackageReference("Microsoft.CodeAnalysis.NetAnalyzers".ToLowerInvariant(), PackageReferenceSource.SdkCsProj), allPackages);
Assert.Contains(new PackageReference("StyleCop.Analyzers".ToLowerInvariant(), PackageReferenceSource.SdkCsProj), allPackages);
}
private static void CsProjSettingsTest(string line, bool expected, Func<FileContent, bool> func)

View File

@@ -2074,7 +2074,9 @@ predicate storeStep(Node node1, ContentSet c, Node node2) {
exists(Parameter p |
node1 = TExplicitParameterNode(p) and
node2 = TPrimaryConstructorThisAccessNode(p, true) and
c.(PrimaryConstructorParameterContent).getParameter() = p
if p.getCallable().getDeclaringType() instanceof RecordType
then c.(PropertyContent).getProperty().getName() = p.getName()
else c.(PrimaryConstructorParameterContent).getParameter() = p
)
or
FlowSummaryImpl::Private::Steps::summaryStoreStep(node1.(FlowSummaryNode).getSummaryNode(), c,

View File

@@ -358,63 +358,6 @@ private module BidirectionalImports {
private import semmle.code.csharp.frameworks.EntityFramework
}
private predicate recordConstructorFlow(Constructor c, int i, Property p) {
c = any(RecordType r).getAMember() and
exists(string name |
c.getParameter(i).getName() = name and
c.getDeclaringType().getAMember(name) = p
)
}
private class RecordConstructorFlow extends Impl::Private::SummarizedCallableImpl {
RecordConstructorFlow() { recordConstructorFlow(this, _, _) }
predicate propagatesFlowImpl(
Impl::Private::SummaryComponentStack input, Impl::Private::SummaryComponentStack output,
boolean preservesValue
) {
exists(int i, Property p |
recordConstructorFlow(this, i, p) and
input = Private::SummaryComponentStack::argument(i) and
output =
Private::SummaryComponentStack::propertyOf(p, Private::SummaryComponentStack::return()) and
preservesValue = true
)
}
override predicate propagatesFlow(
Impl::Private::SummaryComponentStack input, Impl::Private::SummaryComponentStack output,
boolean preservesValue
) {
this.propagatesFlowImpl(input, output, preservesValue)
}
override predicate hasProvenance(Public::Provenance provenance) { provenance = "manual" }
}
// see `SummarizedCallableImpl` qldoc
private class RecordConstructorFlowAdapter extends Impl::Public::SummarizedCallable instanceof RecordConstructorFlow
{
override predicate propagatesFlow(string input, string output, boolean preservesValue) { none() }
override predicate hasProvenance(Public::Provenance provenance) {
RecordConstructorFlow.super.hasProvenance(provenance)
}
}
private class RecordConstructorFlowRequiredSummaryComponentStack extends Impl::Private::RequiredSummaryComponentStack
{
override predicate required(
Impl::Private::SummaryComponent head, Impl::Private::SummaryComponentStack tail
) {
exists(Property p |
recordConstructorFlow(_, _, p) and
head = Private::SummaryComponent::property(p) and
tail = Private::SummaryComponentStack::return()
)
}
}
private import semmle.code.csharp.frameworks.system.linq.Expressions
private predicate mayInvokeCallback(Callable c, int n) {

View File

@@ -78,6 +78,16 @@ edges
| Constructors.cs:132:29:132:30 | access to local variable o2 : Object | Constructors.cs:132:18:132:31 | object creation of type C4 : C4 [property Obj2] : Object | provenance | |
| Constructors.cs:133:14:133:15 | access to local variable c4 : C4 [property Obj1] : Object | Constructors.cs:133:14:133:20 | access to property Obj1 | provenance | |
| Constructors.cs:134:14:134:15 | access to local variable c4 : C4 [property Obj2] : Object | Constructors.cs:134:14:134:20 | access to property Obj2 | provenance | |
| Constructors.cs:141:18:141:34 | call to method Source<Object> : Object | Constructors.cs:143:25:143:26 | access to local variable o1 : Object | provenance | |
| Constructors.cs:142:18:142:35 | call to method Source<Object> : Object | Constructors.cs:143:29:143:30 | access to local variable o2 : Object | provenance | |
| Constructors.cs:143:18:143:31 | object creation of type R1 : R1 [property Obj1] : Object | Constructors.cs:144:14:144:15 | access to local variable r1 : R1 [property Obj1] : Object | provenance | |
| Constructors.cs:143:18:143:31 | object creation of type R1 : R1 [property Obj2] : Object | Constructors.cs:145:14:145:15 | access to local variable r1 : R1 [property Obj2] : Object | provenance | |
| Constructors.cs:143:25:143:26 | access to local variable o1 : Object | Constructors.cs:137:29:137:32 | Obj1 : Object | provenance | |
| Constructors.cs:143:25:143:26 | access to local variable o1 : Object | Constructors.cs:143:18:143:31 | object creation of type R1 : R1 [property Obj1] : Object | provenance | |
| Constructors.cs:143:29:143:30 | access to local variable o2 : Object | Constructors.cs:137:42:137:45 | Obj2 : Object | provenance | |
| Constructors.cs:143:29:143:30 | access to local variable o2 : Object | Constructors.cs:143:18:143:31 | object creation of type R1 : R1 [property Obj2] : Object | provenance | |
| Constructors.cs:144:14:144:15 | access to local variable r1 : R1 [property Obj1] : Object | Constructors.cs:144:14:144:20 | access to property Obj1 | provenance | |
| Constructors.cs:145:14:145:15 | access to local variable r1 : R1 [property Obj2] : Object | Constructors.cs:145:14:145:20 | access to property Obj2 | provenance | |
nodes
| Constructors.cs:5:24:5:25 | [post] this access : C_no_ctor [field s1] : Object | semmle.label | [post] this access : C_no_ctor [field s1] : Object |
| Constructors.cs:5:29:5:45 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object |
@@ -164,6 +174,18 @@ nodes
| Constructors.cs:133:14:133:20 | access to property Obj1 | semmle.label | access to property Obj1 |
| Constructors.cs:134:14:134:15 | access to local variable c4 : C4 [property Obj2] : Object | semmle.label | access to local variable c4 : C4 [property Obj2] : Object |
| Constructors.cs:134:14:134:20 | access to property Obj2 | semmle.label | access to property Obj2 |
| Constructors.cs:137:29:137:32 | Obj1 : Object | semmle.label | Obj1 : Object |
| Constructors.cs:137:42:137:45 | Obj2 : Object | semmle.label | Obj2 : Object |
| Constructors.cs:141:18:141:34 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object |
| Constructors.cs:142:18:142:35 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object |
| Constructors.cs:143:18:143:31 | object creation of type R1 : R1 [property Obj1] : Object | semmle.label | object creation of type R1 : R1 [property Obj1] : Object |
| Constructors.cs:143:18:143:31 | object creation of type R1 : R1 [property Obj2] : Object | semmle.label | object creation of type R1 : R1 [property Obj2] : Object |
| Constructors.cs:143:25:143:26 | access to local variable o1 : Object | semmle.label | access to local variable o1 : Object |
| Constructors.cs:143:29:143:30 | access to local variable o2 : Object | semmle.label | access to local variable o2 : Object |
| Constructors.cs:144:14:144:15 | access to local variable r1 : R1 [property Obj1] : Object | semmle.label | access to local variable r1 : R1 [property Obj1] : Object |
| Constructors.cs:144:14:144:20 | access to property Obj1 | semmle.label | access to property Obj1 |
| Constructors.cs:145:14:145:15 | access to local variable r1 : R1 [property Obj2] : Object | semmle.label | access to local variable r1 : R1 [property Obj2] : Object |
| Constructors.cs:145:14:145:20 | access to property Obj2 | semmle.label | access to property Obj2 |
subpaths
| Constructors.cs:64:37:64:37 | access to parameter o : Object | Constructors.cs:57:54:57:55 | o2 : Object | Constructors.cs:59:13:59:19 | SSA def(o1) : Object | Constructors.cs:64:27:64:34 | SSA def(o22param) : Object |
| Constructors.cs:71:25:71:25 | access to local variable o : Object | Constructors.cs:41:26:41:26 | o : Object | Constructors.cs:41:32:41:34 | [post] this access : C1 [field Obj] : Object | Constructors.cs:71:18:71:26 | object creation of type C1 : C1 [field Obj] : Object |
@@ -179,6 +201,8 @@ subpaths
| Constructors.cs:113:14:113:15 | access to local variable c3 : C3 [parameter o31param] : Object | Constructors.cs:106:32:106:39 | this : C3 [parameter o31param] : Object | Constructors.cs:106:32:106:39 | access to parameter o31param : Object | Constructors.cs:113:14:113:21 | access to property Obj31 |
| Constructors.cs:132:25:132:26 | access to local variable o1 : Object | Constructors.cs:121:26:121:28 | oc1 : Object | Constructors.cs:123:13:123:16 | [post] this access : C4 [property Obj1] : Object | Constructors.cs:132:18:132:31 | object creation of type C4 : C4 [property Obj1] : Object |
| Constructors.cs:132:29:132:30 | access to local variable o2 : Object | Constructors.cs:121:38:121:40 | oc2 : Object | Constructors.cs:124:13:124:16 | [post] this access : C4 [property Obj2] : Object | Constructors.cs:132:18:132:31 | object creation of type C4 : C4 [property Obj2] : Object |
| Constructors.cs:143:25:143:26 | access to local variable o1 : Object | Constructors.cs:137:29:137:32 | Obj1 : Object | Constructors.cs:137:29:137:32 | Obj1 : Object | Constructors.cs:143:18:143:31 | object creation of type R1 : R1 [property Obj1] : Object |
| Constructors.cs:143:29:143:30 | access to local variable o2 : Object | Constructors.cs:137:42:137:45 | Obj2 : Object | Constructors.cs:137:42:137:45 | Obj2 : Object | Constructors.cs:143:18:143:31 | object creation of type R1 : R1 [property Obj2] : Object |
#select
| Constructors.cs:15:18:15:19 | access to field s1 | Constructors.cs:5:29:5:45 | call to method Source<Object> : Object | Constructors.cs:15:18:15:19 | access to field s1 | $@ | Constructors.cs:5:29:5:45 | call to method Source<Object> : Object | call to method Source<Object> : Object |
| Constructors.cs:33:18:33:19 | access to field s1 | Constructors.cs:21:29:21:45 | call to method Source<Object> : Object | Constructors.cs:33:18:33:19 | access to field s1 | $@ | Constructors.cs:21:29:21:45 | call to method Source<Object> : Object | call to method Source<Object> : Object |
@@ -191,3 +215,5 @@ subpaths
| Constructors.cs:113:14:113:21 | access to property Obj31 | Constructors.cs:111:19:111:35 | call to method Source<Object> : Object | Constructors.cs:113:14:113:21 | access to property Obj31 | $@ | Constructors.cs:111:19:111:35 | call to method Source<Object> : Object | call to method Source<Object> : Object |
| Constructors.cs:133:14:133:20 | access to property Obj1 | Constructors.cs:130:18:130:34 | call to method Source<Object> : Object | Constructors.cs:133:14:133:20 | access to property Obj1 | $@ | Constructors.cs:130:18:130:34 | call to method Source<Object> : Object | call to method Source<Object> : Object |
| Constructors.cs:134:14:134:20 | access to property Obj2 | Constructors.cs:131:18:131:34 | call to method Source<Object> : Object | Constructors.cs:134:14:134:20 | access to property Obj2 | $@ | Constructors.cs:131:18:131:34 | call to method Source<Object> : Object | call to method Source<Object> : Object |
| Constructors.cs:144:14:144:20 | access to property Obj1 | Constructors.cs:141:18:141:34 | call to method Source<Object> : Object | Constructors.cs:144:14:144:20 | access to property Obj1 | $@ | Constructors.cs:141:18:141:34 | call to method Source<Object> : Object | call to method Source<Object> : Object |
| Constructors.cs:145:14:145:20 | access to property Obj2 | Constructors.cs:142:18:142:35 | call to method Source<Object> : Object | Constructors.cs:145:14:145:20 | access to property Obj2 | $@ | Constructors.cs:142:18:142:35 | call to method Source<Object> : Object | call to method Source<Object> : Object |

View File

@@ -134,6 +134,17 @@ public class Constructors
Sink(c4.Obj2); // $ hasValueFlow=8
}
public record R1(object Obj1, object Obj2);
public void M7()
{
var o1 = Source<object>(9);
var o2 = Source<object>(10);
var r1 = new R1(o1, o2);
Sink(r1.Obj1); // $ hasValueFlow=9
Sink(r1.Obj2); // $ hasValueFlow=10
}
public static void Sink(object o) { }
public static T Source<T>(object source) => throw null;

View File

@@ -814,6 +814,8 @@ edges
| J.cs:22:18:22:41 | object creation of type RecordClass : RecordClass [property Prop1] : Object | J.cs:27:14:27:15 | access to local variable r2 : RecordClass [property Prop1] : Object | provenance | |
| J.cs:22:18:22:41 | object creation of type RecordClass : RecordClass [property Prop1] : Object | J.cs:31:14:31:15 | access to local variable r3 : RecordClass [property Prop1] : Object | provenance | |
| J.cs:22:18:22:41 | object creation of type RecordClass : RecordClass [property Prop1] : Object | J.cs:31:14:31:15 | access to local variable r3 : RecordClass [property Prop1] : Object | provenance | |
| J.cs:22:34:22:34 | access to local variable o : Object | J.cs:6:40:6:44 | Prop1 : Object | provenance | |
| J.cs:22:34:22:34 | access to local variable o : Object | J.cs:6:40:6:44 | Prop1 : Object | provenance | |
| J.cs:22:34:22:34 | access to local variable o : Object | J.cs:22:18:22:41 | object creation of type RecordClass : RecordClass [property Prop1] : Object | provenance | |
| J.cs:22:34:22:34 | access to local variable o : Object | J.cs:22:18:22:41 | object creation of type RecordClass : RecordClass [property Prop1] : Object | provenance | |
| J.cs:23:14:23:15 | access to local variable r1 : RecordClass [property Prop1] : Object | J.cs:23:14:23:21 | access to property Prop1 | provenance | |
@@ -836,6 +838,8 @@ edges
| J.cs:42:18:42:42 | object creation of type RecordStruct : RecordStruct [property Prop1] : Object | J.cs:47:14:47:15 | access to local variable r2 : RecordStruct [property Prop1] : Object | provenance | |
| J.cs:42:18:42:42 | object creation of type RecordStruct : RecordStruct [property Prop1] : Object | J.cs:51:14:51:15 | access to local variable r3 : RecordStruct [property Prop1] : Object | provenance | |
| J.cs:42:18:42:42 | object creation of type RecordStruct : RecordStruct [property Prop1] : Object | J.cs:51:14:51:15 | access to local variable r3 : RecordStruct [property Prop1] : Object | provenance | |
| J.cs:42:35:42:35 | access to local variable o : Object | J.cs:8:42:8:46 | Prop1 : Object | provenance | |
| J.cs:42:35:42:35 | access to local variable o : Object | J.cs:8:42:8:46 | Prop1 : Object | provenance | |
| J.cs:42:35:42:35 | access to local variable o : Object | J.cs:42:18:42:42 | object creation of type RecordStruct : RecordStruct [property Prop1] : Object | provenance | |
| J.cs:42:35:42:35 | access to local variable o : Object | J.cs:42:18:42:42 | object creation of type RecordStruct : RecordStruct [property Prop1] : Object | provenance | |
| J.cs:43:14:43:15 | access to local variable r1 : RecordStruct [property Prop1] : Object | J.cs:43:14:43:21 | access to property Prop1 | provenance | |
@@ -1781,6 +1785,10 @@ nodes
| I.cs:40:14:40:14 | access to parameter i : I [field Field1] : Object | semmle.label | access to parameter i : I [field Field1] : Object |
| I.cs:40:14:40:21 | access to field Field1 | semmle.label | access to field Field1 |
| I.cs:40:14:40:21 | access to field Field1 | semmle.label | access to field Field1 |
| J.cs:6:40:6:44 | Prop1 : Object | semmle.label | Prop1 : Object |
| J.cs:6:40:6:44 | Prop1 : Object | semmle.label | Prop1 : Object |
| J.cs:8:42:8:46 | Prop1 : Object | semmle.label | Prop1 : Object |
| J.cs:8:42:8:46 | Prop1 : Object | semmle.label | Prop1 : Object |
| J.cs:14:26:14:30 | field : Object | semmle.label | field : Object |
| J.cs:14:26:14:30 | field : Object | semmle.label | field : Object |
| J.cs:14:40:14:43 | prop : Object | semmle.label | prop : Object |
@@ -2022,6 +2030,10 @@ subpaths
| H.cs:147:25:147:38 | call to method Source<A> : A | H.cs:138:27:138:27 | o : A | H.cs:142:16:142:34 | access to field FieldB : A | H.cs:147:17:147:39 | call to method Through : A |
| H.cs:164:22:164:22 | access to local variable o : Object | H.cs:153:32:153:32 | o : Object | H.cs:157:9:157:9 | [post] access to parameter a : A [field FieldA, field FieldB] : Object | H.cs:164:19:164:19 | [post] access to local variable a : A [field FieldA, field FieldB] : Object |
| H.cs:164:22:164:22 | access to local variable o : Object | H.cs:153:32:153:32 | o : Object | H.cs:157:9:157:9 | [post] access to parameter a : A [field FieldA, field FieldB] : Object | H.cs:164:19:164:19 | [post] access to local variable a : A [field FieldA, field FieldB] : Object |
| J.cs:22:34:22:34 | access to local variable o : Object | J.cs:6:40:6:44 | Prop1 : Object | J.cs:6:40:6:44 | Prop1 : Object | J.cs:22:18:22:41 | object creation of type RecordClass : RecordClass [property Prop1] : Object |
| J.cs:22:34:22:34 | access to local variable o : Object | J.cs:6:40:6:44 | Prop1 : Object | J.cs:6:40:6:44 | Prop1 : Object | J.cs:22:18:22:41 | object creation of type RecordClass : RecordClass [property Prop1] : Object |
| J.cs:42:35:42:35 | access to local variable o : Object | J.cs:8:42:8:46 | Prop1 : Object | J.cs:8:42:8:46 | Prop1 : Object | J.cs:42:18:42:42 | object creation of type RecordStruct : RecordStruct [property Prop1] : Object |
| J.cs:42:35:42:35 | access to local variable o : Object | J.cs:8:42:8:46 | Prop1 : Object | J.cs:8:42:8:46 | Prop1 : Object | J.cs:42:18:42:42 | object creation of type RecordStruct : RecordStruct [property Prop1] : Object |
| J.cs:62:29:62:29 | access to local variable o : Object | J.cs:14:26:14:30 | field : Object | J.cs:14:50:14:54 | [post] this access : Struct [field Field] : Object | J.cs:62:18:62:36 | object creation of type Struct : Struct [field Field] : Object |
| J.cs:62:29:62:29 | access to local variable o : Object | J.cs:14:26:14:30 | field : Object | J.cs:14:50:14:54 | [post] this access : Struct [field Field] : Object | J.cs:62:18:62:36 | object creation of type Struct : Struct [field Field] : Object |
| J.cs:80:35:80:35 | access to local variable o : Object | J.cs:14:40:14:43 | prop : Object | J.cs:14:57:14:60 | [post] this access : Struct [property Prop] : Object | J.cs:80:18:80:36 | object creation of type Struct : Struct [property Prop] : Object |

View File

@@ -148,6 +148,8 @@ edges
| Tuples.cs:99:17:99:33 | call to method Source<String> : String | Tuples.cs:100:24:100:24 | access to local variable o : String | provenance | |
| Tuples.cs:100:17:100:28 | object creation of type R1 : R1 [property i] : String | Tuples.cs:101:14:101:14 | access to local variable r : R1 [property i] : String | provenance | |
| Tuples.cs:100:17:100:28 | object creation of type R1 : R1 [property i] : String | Tuples.cs:101:14:101:14 | access to local variable r : R1 [property i] : String | provenance | |
| Tuples.cs:100:24:100:24 | access to local variable o : String | Tuples.cs:95:22:95:22 | i : String | provenance | |
| Tuples.cs:100:24:100:24 | access to local variable o : String | Tuples.cs:95:22:95:22 | i : String | provenance | |
| Tuples.cs:100:24:100:24 | access to local variable o : String | Tuples.cs:100:17:100:28 | object creation of type R1 : R1 [property i] : String | provenance | |
| Tuples.cs:100:24:100:24 | access to local variable o : String | Tuples.cs:100:17:100:28 | object creation of type R1 : R1 [property i] : String | provenance | |
| Tuples.cs:101:14:101:14 | access to local variable r : R1 [property i] : String | Tuples.cs:101:14:101:16 | access to property i | provenance | |
@@ -359,6 +361,8 @@ nodes
| Tuples.cs:89:18:89:18 | access to local variable p | semmle.label | access to local variable p |
| Tuples.cs:90:18:90:18 | access to local variable r | semmle.label | access to local variable r |
| Tuples.cs:90:18:90:18 | access to local variable r | semmle.label | access to local variable r |
| Tuples.cs:95:22:95:22 | i : String | semmle.label | i : String |
| Tuples.cs:95:22:95:22 | i : String | semmle.label | i : String |
| Tuples.cs:99:17:99:33 | call to method Source<String> : String | semmle.label | call to method Source<String> : String |
| Tuples.cs:99:17:99:33 | call to method Source<String> : String | semmle.label | call to method Source<String> : String |
| Tuples.cs:100:17:100:28 | object creation of type R1 : R1 [property i] : String | semmle.label | object creation of type R1 : R1 [property i] : String |
@@ -412,6 +416,8 @@ nodes
| Tuples.cs:134:14:134:15 | access to local variable y4 | semmle.label | access to local variable y4 |
| Tuples.cs:134:14:134:15 | access to local variable y4 | semmle.label | access to local variable y4 |
subpaths
| Tuples.cs:100:24:100:24 | access to local variable o : String | Tuples.cs:95:22:95:22 | i : String | Tuples.cs:95:22:95:22 | i : String | Tuples.cs:100:17:100:28 | object creation of type R1 : R1 [property i] : String |
| Tuples.cs:100:24:100:24 | access to local variable o : String | Tuples.cs:95:22:95:22 | i : String | Tuples.cs:95:22:95:22 | i : String | Tuples.cs:100:17:100:28 | object creation of type R1 : R1 [property i] : String |
#select
| Tuples.cs:12:14:12:14 | access to local variable a | Tuples.cs:7:18:7:34 | call to method Source<Object> : Object | Tuples.cs:12:14:12:14 | access to local variable a | $@ | Tuples.cs:7:18:7:34 | call to method Source<Object> : Object | call to method Source<Object> : Object |
| Tuples.cs:12:14:12:14 | access to local variable a | Tuples.cs:7:18:7:34 | call to method Source<Object> : Object | Tuples.cs:12:14:12:14 | access to local variable a | $@ | Tuples.cs:7:18:7:34 | call to method Source<Object> : Object | call to method Source<Object> : Object |

View File

@@ -46,7 +46,7 @@ def version_string_to_version(version):
# Version number used by CI.
ci_version = '1.9.0'
many_versions = [ '1.5.0', '1.5.10', '1.5.20', '1.5.30', '1.6.0', '1.6.20', '1.7.0', '1.7.20', '1.8.0', '1.9.0-Beta', '1.9.20-Beta', '2.0.0-Beta3', '2.0.255-SNAPSHOT' ]
many_versions = [ '1.5.0', '1.5.10', '1.5.20', '1.5.30', '1.6.0', '1.6.20', '1.7.0', '1.7.20', '1.8.0', '1.9.0-Beta', '1.9.20-Beta', '2.0.0-Beta4', '2.0.255-SNAPSHOT' ]
many_versions_versions = [version_string_to_version(v) for v in many_versions]
many_versions_versions_asc = sorted(many_versions_versions, key = lambda v: v.toTupleWithTag())

View File

@@ -1,6 +1,7 @@
/** Definitions for the insecure local authentication query. */
import java
private import semmle.code.java.dataflow.DataFlow
/** A base class that is used as a callback for biometric authentication. */
private class AuthenticationCallbackClass extends Class {
@@ -40,3 +41,24 @@ class AuthenticationSuccessCallback extends Method {
not result = this.getASuperResultUse()
}
}
/** A call that sets a parameter for key generation that is insecure for use with biometric authentication. */
class InsecureBiometricKeyParamCall extends MethodCall {
InsecureBiometricKeyParamCall() {
exists(string name, CompileTimeConstantExpr val |
this.getMethod()
.hasQualifiedName("android.security.keystore", "KeyGenParameterSpec$Builder", name) and
DataFlow::localExprFlow(val, this.getArgument(0)) and
(
name = ["setUserAuthenticationRequired", "setInvalidatedByBiometricEnrollment"] and
val.getBooleanValue() = false
or
name = "setUserAuthenticationValidityDurationSeconds" and
val.getIntValue() != -1
)
)
}
}
/** Holds if the application contains an instance of a key being used for local biometric authentication. */
predicate usesLocalAuth() { exists(AuthenticationSuccessCallback cb | exists(cb.getAResultUse())) }

View File

@@ -1,5 +1,5 @@
/**
* @name Exposure of sensitive information to UI text views.
* @name Exposure of sensitive information to UI text views
* @id java/android/sensitive-text
* @kind path-problem
* @description Sensitive information displayed in UI text views should be properly masked.

View File

@@ -0,0 +1,43 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
Biometric authentication, such as fingerprint recognition, can be used alongside cryptographic keys stored in the Android <code>KeyStore</code> to protect sensitive parts of the application. However,
when a key generated for this purpose has certain parameters set insecurely, an attacker with physical access can bypass the
authentication check using application hooking tools such as Frida.
</p>
</overview>
<recommendation>
<p>
When generating a key for use with biometric authentication, ensure that the following parameters of <code>KeyGenParameterSpec.Builder</code> are set:
</p>
<ul>
<li><code>setUserAuthenticationRequired</code> should be set to <code>true</code>; otherwise, the key can be used without user authentication.</li>
<li><code>setInvalidatedByBiometricEnrollment</code> should be set to <code>true</code> (the default); otherwise, an attacker can use the key by enrolling additional biometrics on the device.</li>
<li><code>setUserAuthenticationValidityDurationSeconds</code>, if used, should be set to <code>-1</code>; otherwise, non-biometric (less secure) credentials can be used to access the key. We recommend using <code>setUserAuthenticationParameters</code> instead to explicitly set both the timeout and the types of credentials that may be used.</li>
</ul>
</recommendation>
<example>
<p>The following example demonstrates a key that is configured with secure paramaters:</p>
<sample src="AndroidInsecureKeysGood.java"/>
<p>In each of the following cases, a parameter is set insecurely:</p>
<sample src="AndroidInsecureKeysBad.java"/>
</example>
<references>
<li>
WithSecure: <a href="https://labs.withsecure.com/publications/how-secure-is-your-android-keystore-authentication">How Secure is your Android Keystore Authentication?</a>.
</li>
<li>
Android Developers: <a href="https://developer.android.com/reference/android/security/keystore/KeyGenParameterSpec.Builder">KeyGenParameterSpec.Builder</a>.
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,18 @@
/**
* @name Insecurely generated keys for local authentication
* @description Generation of keys with insecure parameters for local biometric authentication can allow attackers with physical access to bypass authentication checks.
* @kind problem
* @problem.severity warning
* @security-severity 4.4
* @precision medium
* @id java/android/insecure-local-key-gen
* @tags security
* external/cwe/cwe-287
*/
import java
import semmle.code.java.security.AndroidLocalAuthQuery
from InsecureBiometricKeyParamCall call
where usesLocalAuth()
select call, "This key is not secure for biometric authentication."

View File

@@ -0,0 +1,47 @@
private void generateSecretKey() {
KeyGenParameterSpec keyGenParameterSpec = new KeyGenParameterSpec.Builder(
"MySecretKey",
KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_CBC)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
// BAD: User authentication is not required to use this key.
.setUserAuthenticationRequired(false)
.build();
KeyGenerator keyGenerator = KeyGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
keyGenerator.init(keyGenParameterSpec);
keyGenerator.generateKey();
}
private void generateSecretKey() {
KeyGenParameterSpec keyGenParameterSpec = new KeyGenParameterSpec.Builder(
"MySecretKey",
KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_CBC)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
.setUserAuthenticationRequired(true)
// BAD: An attacker can access this key by enrolling additional biometrics.
.setInvalidatedByBiometricEnrollment(false)
.build();
KeyGenerator keyGenerator = KeyGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
keyGenerator.init(keyGenParameterSpec);
keyGenerator.generateKey();
}
private void generateSecretKey() {
KeyGenParameterSpec keyGenParameterSpec = new KeyGenParameterSpec.Builder(
"MySecretKey",
KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_CBC)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
.setUserAuthenticationRequired(true)
.setInvalidatedByBiometricEnrollment(true)
// BAD: This key can be accessed using non-biometric credentials.
.setUserAuthenticationValidityDurationSeconds(30)
.build();
KeyGenerator keyGenerator = KeyGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
keyGenerator.init(keyGenParameterSpec);
keyGenerator.generateKey();
}

View File

@@ -0,0 +1,16 @@
private void generateSecretKey() {
KeyGenParameterSpec keyGenParameterSpec = new KeyGenParameterSpec.Builder(
"MySecretKey",
KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_CBC)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
// GOOD: Secure parameters are used to generate a key for biometric authentication.
.setUserAuthenticationRequired(true)
.setInvalidatedByBiometricEnrollment(true)
.setUserAuthenticationParameters(0, KeyProperties.AUTH_BIOMETRIC_STRONG)
.build();
KeyGenerator keyGenerator = KeyGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
keyGenerator.init(keyGenParameterSpec);
keyGenerator.generateKey();
}

View File

@@ -0,0 +1,4 @@
---
category: newQuery
---
* Added a new query `java/android/insecure-local-key-gen` for finding instances of keys generated for biometric authentication in an insecure way.

View File

@@ -1521,27 +1521,27 @@
| exprs.kt:179:5:179:18 | Color | exprs.kt:0:0:0:0 | <clinit> | TypeAccess |
| exprs.kt:179:5:179:18 | Color | file://:0:0:0:0 | <none> | TypeAccess |
| exprs.kt:179:5:179:18 | Color.RED | exprs.kt:0:0:0:0 | <clinit> | VarAccess |
| exprs.kt:179:5:179:18 | new Color(...) | exprs.kt:0:0:0:0 | <clinit> | ClassInstanceExpr |
| exprs.kt:179:8:179:17 | new Color(...) | exprs.kt:0:0:0:0 | <clinit> | ClassInstanceExpr |
| exprs.kt:179:9:179:16 | 16711680 | exprs.kt:0:0:0:0 | <clinit> | IntegerLiteral |
| exprs.kt:180:5:180:20 | ...=... | exprs.kt:0:0:0:0 | <clinit> | KtInitializerAssignExpr |
| exprs.kt:180:5:180:20 | Color | exprs.kt:0:0:0:0 | <clinit> | TypeAccess |
| exprs.kt:180:5:180:20 | Color | exprs.kt:0:0:0:0 | <clinit> | TypeAccess |
| exprs.kt:180:5:180:20 | Color | file://:0:0:0:0 | <none> | TypeAccess |
| exprs.kt:180:5:180:20 | Color.GREEN | exprs.kt:0:0:0:0 | <clinit> | VarAccess |
| exprs.kt:180:5:180:20 | new Color(...) | exprs.kt:0:0:0:0 | <clinit> | ClassInstanceExpr |
| exprs.kt:180:10:180:19 | new Color(...) | exprs.kt:0:0:0:0 | <clinit> | ClassInstanceExpr |
| exprs.kt:180:11:180:18 | 65280 | exprs.kt:0:0:0:0 | <clinit> | IntegerLiteral |
| exprs.kt:181:5:181:18 | ...=... | exprs.kt:0:0:0:0 | <clinit> | KtInitializerAssignExpr |
| exprs.kt:181:5:181:18 | Color | exprs.kt:0:0:0:0 | <clinit> | TypeAccess |
| exprs.kt:181:5:181:18 | Color | exprs.kt:0:0:0:0 | <clinit> | TypeAccess |
| exprs.kt:181:5:181:18 | Color | file://:0:0:0:0 | <none> | TypeAccess |
| exprs.kt:181:5:181:18 | Color.BLUE | exprs.kt:0:0:0:0 | <clinit> | VarAccess |
| exprs.kt:181:5:181:18 | new Color(...) | exprs.kt:0:0:0:0 | <clinit> | ClassInstanceExpr |
| exprs.kt:181:9:181:18 | new Color(...) | exprs.kt:0:0:0:0 | <clinit> | ClassInstanceExpr |
| exprs.kt:181:10:181:17 | 255 | exprs.kt:0:0:0:0 | <clinit> | IntegerLiteral |
| exprs.kt:184:1:187:1 | Unit | file://:0:0:0:0 | <none> | TypeAccess |
| exprs.kt:185:9:185:13 | south | exprs.kt:184:1:187:1 | enums | LocalVariableDeclExpr |
| exprs.kt:185:5:185:31 | south | exprs.kt:184:1:187:1 | enums | LocalVariableDeclExpr |
| exprs.kt:185:27:185:31 | Direction | exprs.kt:184:1:187:1 | enums | TypeAccess |
| exprs.kt:185:27:185:31 | Direction.SOUTH | exprs.kt:184:1:187:1 | enums | VarAccess |
| exprs.kt:186:9:186:13 | green | exprs.kt:184:1:187:1 | enums | LocalVariableDeclExpr |
| exprs.kt:186:5:186:27 | green | exprs.kt:184:1:187:1 | enums | LocalVariableDeclExpr |
| exprs.kt:186:23:186:27 | Color | exprs.kt:184:1:187:1 | enums | TypeAccess |
| exprs.kt:186:23:186:27 | Color.GREEN | exprs.kt:184:1:187:1 | enums | VarAccess |
| exprs.kt:192:5:192:14 | ...=... | exprs.kt:191:1:199:1 | Class1 | KtInitializerAssignExpr |
@@ -1609,16 +1609,16 @@
| exprs.kt:215:13:215:14 | d0 | exprs.kt:206:5:217:5 | x | LocalVariableDeclExpr |
| exprs.kt:215:18:215:44 | Color | exprs.kt:206:5:217:5 | x | TypeAccess |
| exprs.kt:215:18:215:44 | valueOf(...) | exprs.kt:206:5:217:5 | x | MethodCall |
| exprs.kt:215:38:215:42 | "GREEN" | exprs.kt:206:5:217:5 | x | StringLiteral |
| exprs.kt:215:37:215:43 | "GREEN" | exprs.kt:206:5:217:5 | x | StringLiteral |
| exprs.kt:216:13:216:14 | d1 | exprs.kt:206:5:217:5 | x | LocalVariableDeclExpr |
| exprs.kt:216:24:216:39 | Color | exprs.kt:206:5:217:5 | x | TypeAccess |
| exprs.kt:216:24:216:39 | valueOf(...) | exprs.kt:206:5:217:5 | x | MethodCall |
| exprs.kt:216:33:216:37 | "GREEN" | exprs.kt:206:5:217:5 | x | StringLiteral |
| exprs.kt:216:32:216:38 | "GREEN" | exprs.kt:206:5:217:5 | x | StringLiteral |
| exprs.kt:220:1:222:1 | Unit | file://:0:0:0:0 | <none> | TypeAccess |
| exprs.kt:221:5:221:10 | StandardKt | exprs.kt:220:1:222:1 | todo | TypeAccess |
| exprs.kt:221:5:221:10 | TODO(...) | exprs.kt:220:1:222:1 | todo | MethodCall |
| exprs.kt:225:1:227:1 | Unit | file://:0:0:0:0 | <none> | TypeAccess |
| exprs.kt:226:9:226:9 | x | exprs.kt:225:1:227:1 | fnClassRef | LocalVariableDeclExpr |
| exprs.kt:226:5:226:29 | x | exprs.kt:225:1:227:1 | fnClassRef | LocalVariableDeclExpr |
| exprs.kt:226:13:226:29 | SomeClass1 | exprs.kt:225:1:227:1 | fnClassRef | TypeAccess |
| exprs.kt:226:13:226:29 | SomeClass1.class | exprs.kt:225:1:227:1 | fnClassRef | TypeLiteral |
| exprs.kt:229:1:250:1 | Unit | file://:0:0:0:0 | <none> | TypeAccess |
@@ -1719,23 +1719,23 @@
| exprs.kt:256:30:256:39 | double | file://:0:0:0:0 | <none> | TypeAccess |
| exprs.kt:257:18:257:26 | float | file://:0:0:0:0 | <none> | TypeAccess |
| exprs.kt:257:29:257:37 | float | file://:0:0:0:0 | <none> | TypeAccess |
| exprs.kt:259:7:259:7 | i | exprs.kt:252:1:265:1 | mulOperators | LocalVariableDeclExpr |
| exprs.kt:259:3:259:15 | i | exprs.kt:252:1:265:1 | mulOperators | LocalVariableDeclExpr |
| exprs.kt:259:11:259:11 | x | exprs.kt:252:1:265:1 | mulOperators | VarAccess |
| exprs.kt:259:11:259:15 | ... * ... | exprs.kt:252:1:265:1 | mulOperators | MulExpr |
| exprs.kt:259:15:259:15 | y | exprs.kt:252:1:265:1 | mulOperators | VarAccess |
| exprs.kt:260:7:260:7 | b | exprs.kt:252:1:265:1 | mulOperators | LocalVariableDeclExpr |
| exprs.kt:260:3:260:19 | b | exprs.kt:252:1:265:1 | mulOperators | LocalVariableDeclExpr |
| exprs.kt:260:11:260:13 | byx | exprs.kt:252:1:265:1 | mulOperators | VarAccess |
| exprs.kt:260:11:260:19 | ... * ... | exprs.kt:252:1:265:1 | mulOperators | MulExpr |
| exprs.kt:260:17:260:19 | byy | exprs.kt:252:1:265:1 | mulOperators | VarAccess |
| exprs.kt:261:7:261:7 | l | exprs.kt:252:1:265:1 | mulOperators | LocalVariableDeclExpr |
| exprs.kt:261:3:261:17 | l | exprs.kt:252:1:265:1 | mulOperators | LocalVariableDeclExpr |
| exprs.kt:261:11:261:12 | lx | exprs.kt:252:1:265:1 | mulOperators | VarAccess |
| exprs.kt:261:11:261:17 | ... * ... | exprs.kt:252:1:265:1 | mulOperators | MulExpr |
| exprs.kt:261:16:261:17 | ly | exprs.kt:252:1:265:1 | mulOperators | VarAccess |
| exprs.kt:262:7:262:7 | d | exprs.kt:252:1:265:1 | mulOperators | LocalVariableDeclExpr |
| exprs.kt:262:3:262:17 | d | exprs.kt:252:1:265:1 | mulOperators | LocalVariableDeclExpr |
| exprs.kt:262:11:262:12 | dx | exprs.kt:252:1:265:1 | mulOperators | VarAccess |
| exprs.kt:262:11:262:17 | ... * ... | exprs.kt:252:1:265:1 | mulOperators | MulExpr |
| exprs.kt:262:16:262:17 | dy | exprs.kt:252:1:265:1 | mulOperators | VarAccess |
| exprs.kt:263:7:263:7 | f | exprs.kt:252:1:265:1 | mulOperators | LocalVariableDeclExpr |
| exprs.kt:263:3:263:17 | f | exprs.kt:252:1:265:1 | mulOperators | LocalVariableDeclExpr |
| exprs.kt:263:11:263:12 | fx | exprs.kt:252:1:265:1 | mulOperators | VarAccess |
| exprs.kt:263:11:263:17 | ... * ... | exprs.kt:252:1:265:1 | mulOperators | MulExpr |
| exprs.kt:263:16:263:17 | fy | exprs.kt:252:1:265:1 | mulOperators | VarAccess |
@@ -1757,9 +1757,9 @@
| exprs.kt:274:3:274:9 | updated | exprs.kt:267:1:276:1 | inPlaceOperators | VarAccess |
| exprs.kt:274:3:274:14 | ...%=... | exprs.kt:267:1:276:1 | inPlaceOperators | AssignRemExpr |
| exprs.kt:274:14:274:14 | 1 | exprs.kt:267:1:276:1 | inPlaceOperators | IntegerLiteral |
| exprs.kt:278:8:278:66 | T | file://:0:0:0:0 | <none> | TypeAccess |
| exprs.kt:278:8:278:66 | T[] | file://:0:0:0:0 | <none> | TypeAccess |
| exprs.kt:278:52:278:66 | <error expr> | exprs.kt:278:8:278:66 | getEnumValues | ErrorExpr |
| exprs.kt:278:1:278:66 | T | file://:0:0:0:0 | <none> | TypeAccess |
| exprs.kt:278:1:278:66 | T[] | file://:0:0:0:0 | <none> | TypeAccess |
| exprs.kt:278:52:278:66 | <error expr> | exprs.kt:278:1:278:66 | getEnumValues | ErrorExpr |
| exprs.kt:280:1:283:1 | Unit | file://:0:0:0:0 | <none> | TypeAccess |
| exprs.kt:281:5:281:23 | <implicit coercion to unit> | exprs.kt:280:1:283:1 | callToEnumValues | ImplicitCoercionToUnitExpr |
| exprs.kt:281:5:281:23 | Color | exprs.kt:280:1:283:1 | callToEnumValues | TypeAccess |
@@ -1793,43 +1793,43 @@
| exprs.kt:289:5:289:6 | <implicit coercion to unit> | exprs.kt:285:1:346:1 | unaryExprs | ImplicitCoercionToUnitExpr |
| exprs.kt:289:5:289:6 | Unit | exprs.kt:285:1:346:1 | unaryExprs | TypeAccess |
| exprs.kt:289:6:289:6 | d | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:290:9:290:10 | i0 | exprs.kt:285:1:346:1 | unaryExprs | LocalVariableDeclExpr |
| exprs.kt:290:5:290:14 | i0 | exprs.kt:285:1:346:1 | unaryExprs | LocalVariableDeclExpr |
| exprs.kt:290:14:290:14 | 1 | exprs.kt:285:1:346:1 | unaryExprs | IntegerLiteral |
| exprs.kt:291:9:291:10 | i1 | exprs.kt:285:1:346:1 | unaryExprs | LocalVariableDeclExpr |
| exprs.kt:291:5:291:14 | i1 | exprs.kt:285:1:346:1 | unaryExprs | LocalVariableDeclExpr |
| exprs.kt:291:14:291:14 | 1 | exprs.kt:285:1:346:1 | unaryExprs | IntegerLiteral |
| exprs.kt:292:5:292:6 | i0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:292:5:292:6 | i0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:292:5:292:8 | ...=... | exprs.kt:285:1:346:1 | unaryExprs | AssignExpr |
| exprs.kt:292:5:292:8 | <Stmt> | exprs.kt:285:1:346:1 | unaryExprs | StmtExpr |
| exprs.kt:292:5:292:8 | <implicit coercion to unit> | exprs.kt:285:1:346:1 | unaryExprs | ImplicitCoercionToUnitExpr |
| exprs.kt:292:5:292:8 | <unary> | exprs.kt:285:1:346:1 | unaryExprs | LocalVariableDeclExpr |
| exprs.kt:292:5:292:8 | <unary> | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:292:5:292:8 | <unary> | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:292:5:292:8 | Unit | exprs.kt:285:1:346:1 | unaryExprs | TypeAccess |
| exprs.kt:292:5:292:8 | i0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:292:5:292:8 | inc(...) | exprs.kt:285:1:346:1 | unaryExprs | MethodCall |
| exprs.kt:292:5:292:8 | tmp0 | exprs.kt:285:1:346:1 | unaryExprs | LocalVariableDeclExpr |
| exprs.kt:292:5:292:8 | tmp0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:292:5:292:8 | tmp0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:293:5:293:6 | inc(...) | exprs.kt:285:1:346:1 | unaryExprs | MethodCall |
| exprs.kt:293:5:293:8 | <Stmt> | exprs.kt:285:1:346:1 | unaryExprs | StmtExpr |
| exprs.kt:293:5:293:8 | <implicit coercion to unit> | exprs.kt:285:1:346:1 | unaryExprs | ImplicitCoercionToUnitExpr |
| exprs.kt:293:5:293:8 | Unit | exprs.kt:285:1:346:1 | unaryExprs | TypeAccess |
| exprs.kt:293:5:293:8 | inc(...) | exprs.kt:285:1:346:1 | unaryExprs | MethodCall |
| exprs.kt:293:7:293:8 | ...=... | exprs.kt:285:1:346:1 | unaryExprs | AssignExpr |
| exprs.kt:293:7:293:7 | ...=... | exprs.kt:285:1:346:1 | unaryExprs | AssignExpr |
| exprs.kt:293:7:293:8 | i0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:293:7:293:8 | i0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:293:7:293:8 | i0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:294:5:294:6 | i0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:294:5:294:6 | i0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:294:5:294:8 | ...=... | exprs.kt:285:1:346:1 | unaryExprs | AssignExpr |
| exprs.kt:294:5:294:8 | <Stmt> | exprs.kt:285:1:346:1 | unaryExprs | StmtExpr |
| exprs.kt:294:5:294:8 | <implicit coercion to unit> | exprs.kt:285:1:346:1 | unaryExprs | ImplicitCoercionToUnitExpr |
| exprs.kt:294:5:294:8 | <unary> | exprs.kt:285:1:346:1 | unaryExprs | LocalVariableDeclExpr |
| exprs.kt:294:5:294:8 | <unary> | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:294:5:294:8 | <unary> | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:294:5:294:8 | Unit | exprs.kt:285:1:346:1 | unaryExprs | TypeAccess |
| exprs.kt:294:5:294:8 | dec(...) | exprs.kt:285:1:346:1 | unaryExprs | MethodCall |
| exprs.kt:294:5:294:8 | tmp1 | exprs.kt:285:1:346:1 | unaryExprs | LocalVariableDeclExpr |
| exprs.kt:294:5:294:8 | tmp1 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:294:5:294:8 | tmp1 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:294:5:294:8 | i0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:295:5:295:6 | dec(...) | exprs.kt:285:1:346:1 | unaryExprs | MethodCall |
| exprs.kt:295:5:295:8 | <Stmt> | exprs.kt:285:1:346:1 | unaryExprs | StmtExpr |
| exprs.kt:295:5:295:8 | <implicit coercion to unit> | exprs.kt:285:1:346:1 | unaryExprs | ImplicitCoercionToUnitExpr |
| exprs.kt:295:5:295:8 | Unit | exprs.kt:285:1:346:1 | unaryExprs | TypeAccess |
| exprs.kt:295:5:295:8 | dec(...) | exprs.kt:285:1:346:1 | unaryExprs | MethodCall |
| exprs.kt:295:7:295:8 | ...=... | exprs.kt:285:1:346:1 | unaryExprs | AssignExpr |
| exprs.kt:295:7:295:7 | ...=... | exprs.kt:285:1:346:1 | unaryExprs | AssignExpr |
| exprs.kt:295:7:295:8 | i0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:295:7:295:8 | i0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:295:7:295:8 | i0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
@@ -1861,43 +1861,43 @@
| exprs.kt:303:5:303:6 | <implicit coercion to unit> | exprs.kt:285:1:346:1 | unaryExprs | ImplicitCoercionToUnitExpr |
| exprs.kt:303:5:303:6 | Unit | exprs.kt:285:1:346:1 | unaryExprs | TypeAccess |
| exprs.kt:303:6:303:6 | b | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:304:9:304:10 | b0 | exprs.kt:285:1:346:1 | unaryExprs | LocalVariableDeclExpr |
| exprs.kt:304:5:304:20 | b0 | exprs.kt:285:1:346:1 | unaryExprs | LocalVariableDeclExpr |
| exprs.kt:304:20:304:20 | 1 | exprs.kt:285:1:346:1 | unaryExprs | IntegerLiteral |
| exprs.kt:305:9:305:10 | b1 | exprs.kt:285:1:346:1 | unaryExprs | LocalVariableDeclExpr |
| exprs.kt:305:5:305:20 | b1 | exprs.kt:285:1:346:1 | unaryExprs | LocalVariableDeclExpr |
| exprs.kt:305:20:305:20 | 1 | exprs.kt:285:1:346:1 | unaryExprs | IntegerLiteral |
| exprs.kt:306:5:306:6 | b0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:306:5:306:6 | b0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:306:5:306:8 | ...=... | exprs.kt:285:1:346:1 | unaryExprs | AssignExpr |
| exprs.kt:306:5:306:8 | <Stmt> | exprs.kt:285:1:346:1 | unaryExprs | StmtExpr |
| exprs.kt:306:5:306:8 | <implicit coercion to unit> | exprs.kt:285:1:346:1 | unaryExprs | ImplicitCoercionToUnitExpr |
| exprs.kt:306:5:306:8 | <unary> | exprs.kt:285:1:346:1 | unaryExprs | LocalVariableDeclExpr |
| exprs.kt:306:5:306:8 | <unary> | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:306:5:306:8 | <unary> | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:306:5:306:8 | Unit | exprs.kt:285:1:346:1 | unaryExprs | TypeAccess |
| exprs.kt:306:5:306:8 | b0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:306:5:306:8 | inc(...) | exprs.kt:285:1:346:1 | unaryExprs | MethodCall |
| exprs.kt:306:5:306:8 | tmp2 | exprs.kt:285:1:346:1 | unaryExprs | LocalVariableDeclExpr |
| exprs.kt:306:5:306:8 | tmp2 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:306:5:306:8 | tmp2 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:307:5:307:6 | inc(...) | exprs.kt:285:1:346:1 | unaryExprs | MethodCall |
| exprs.kt:307:5:307:8 | <Stmt> | exprs.kt:285:1:346:1 | unaryExprs | StmtExpr |
| exprs.kt:307:5:307:8 | <implicit coercion to unit> | exprs.kt:285:1:346:1 | unaryExprs | ImplicitCoercionToUnitExpr |
| exprs.kt:307:5:307:8 | Unit | exprs.kt:285:1:346:1 | unaryExprs | TypeAccess |
| exprs.kt:307:5:307:8 | inc(...) | exprs.kt:285:1:346:1 | unaryExprs | MethodCall |
| exprs.kt:307:7:307:8 | ...=... | exprs.kt:285:1:346:1 | unaryExprs | AssignExpr |
| exprs.kt:307:7:307:7 | ...=... | exprs.kt:285:1:346:1 | unaryExprs | AssignExpr |
| exprs.kt:307:7:307:8 | b0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:307:7:307:8 | b0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:307:7:307:8 | b0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:308:5:308:6 | b0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:308:5:308:6 | b0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:308:5:308:8 | ...=... | exprs.kt:285:1:346:1 | unaryExprs | AssignExpr |
| exprs.kt:308:5:308:8 | <Stmt> | exprs.kt:285:1:346:1 | unaryExprs | StmtExpr |
| exprs.kt:308:5:308:8 | <implicit coercion to unit> | exprs.kt:285:1:346:1 | unaryExprs | ImplicitCoercionToUnitExpr |
| exprs.kt:308:5:308:8 | <unary> | exprs.kt:285:1:346:1 | unaryExprs | LocalVariableDeclExpr |
| exprs.kt:308:5:308:8 | <unary> | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:308:5:308:8 | <unary> | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:308:5:308:8 | Unit | exprs.kt:285:1:346:1 | unaryExprs | TypeAccess |
| exprs.kt:308:5:308:8 | b0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:308:5:308:8 | dec(...) | exprs.kt:285:1:346:1 | unaryExprs | MethodCall |
| exprs.kt:308:5:308:8 | tmp3 | exprs.kt:285:1:346:1 | unaryExprs | LocalVariableDeclExpr |
| exprs.kt:308:5:308:8 | tmp3 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:308:5:308:8 | tmp3 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:309:5:309:6 | dec(...) | exprs.kt:285:1:346:1 | unaryExprs | MethodCall |
| exprs.kt:309:5:309:8 | <Stmt> | exprs.kt:285:1:346:1 | unaryExprs | StmtExpr |
| exprs.kt:309:5:309:8 | <implicit coercion to unit> | exprs.kt:285:1:346:1 | unaryExprs | ImplicitCoercionToUnitExpr |
| exprs.kt:309:5:309:8 | Unit | exprs.kt:285:1:346:1 | unaryExprs | TypeAccess |
| exprs.kt:309:5:309:8 | dec(...) | exprs.kt:285:1:346:1 | unaryExprs | MethodCall |
| exprs.kt:309:7:309:8 | ...=... | exprs.kt:285:1:346:1 | unaryExprs | AssignExpr |
| exprs.kt:309:7:309:7 | ...=... | exprs.kt:285:1:346:1 | unaryExprs | AssignExpr |
| exprs.kt:309:7:309:8 | b0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:309:7:309:8 | b0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:309:7:309:8 | b0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
@@ -1929,43 +1929,43 @@
| exprs.kt:317:5:317:6 | <implicit coercion to unit> | exprs.kt:285:1:346:1 | unaryExprs | ImplicitCoercionToUnitExpr |
| exprs.kt:317:5:317:6 | Unit | exprs.kt:285:1:346:1 | unaryExprs | TypeAccess |
| exprs.kt:317:6:317:6 | s | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:318:9:318:10 | s0 | exprs.kt:285:1:346:1 | unaryExprs | LocalVariableDeclExpr |
| exprs.kt:318:5:318:21 | s0 | exprs.kt:285:1:346:1 | unaryExprs | LocalVariableDeclExpr |
| exprs.kt:318:21:318:21 | 1 | exprs.kt:285:1:346:1 | unaryExprs | IntegerLiteral |
| exprs.kt:319:9:319:10 | s1 | exprs.kt:285:1:346:1 | unaryExprs | LocalVariableDeclExpr |
| exprs.kt:319:5:319:21 | s1 | exprs.kt:285:1:346:1 | unaryExprs | LocalVariableDeclExpr |
| exprs.kt:319:21:319:21 | 1 | exprs.kt:285:1:346:1 | unaryExprs | IntegerLiteral |
| exprs.kt:320:5:320:6 | s0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:320:5:320:6 | s0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:320:5:320:8 | ...=... | exprs.kt:285:1:346:1 | unaryExprs | AssignExpr |
| exprs.kt:320:5:320:8 | <Stmt> | exprs.kt:285:1:346:1 | unaryExprs | StmtExpr |
| exprs.kt:320:5:320:8 | <implicit coercion to unit> | exprs.kt:285:1:346:1 | unaryExprs | ImplicitCoercionToUnitExpr |
| exprs.kt:320:5:320:8 | <unary> | exprs.kt:285:1:346:1 | unaryExprs | LocalVariableDeclExpr |
| exprs.kt:320:5:320:8 | <unary> | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:320:5:320:8 | <unary> | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:320:5:320:8 | Unit | exprs.kt:285:1:346:1 | unaryExprs | TypeAccess |
| exprs.kt:320:5:320:8 | inc(...) | exprs.kt:285:1:346:1 | unaryExprs | MethodCall |
| exprs.kt:320:5:320:8 | tmp4 | exprs.kt:285:1:346:1 | unaryExprs | LocalVariableDeclExpr |
| exprs.kt:320:5:320:8 | tmp4 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:320:5:320:8 | tmp4 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:320:5:320:8 | s0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:321:5:321:6 | inc(...) | exprs.kt:285:1:346:1 | unaryExprs | MethodCall |
| exprs.kt:321:5:321:8 | <Stmt> | exprs.kt:285:1:346:1 | unaryExprs | StmtExpr |
| exprs.kt:321:5:321:8 | <implicit coercion to unit> | exprs.kt:285:1:346:1 | unaryExprs | ImplicitCoercionToUnitExpr |
| exprs.kt:321:5:321:8 | Unit | exprs.kt:285:1:346:1 | unaryExprs | TypeAccess |
| exprs.kt:321:5:321:8 | inc(...) | exprs.kt:285:1:346:1 | unaryExprs | MethodCall |
| exprs.kt:321:7:321:8 | ...=... | exprs.kt:285:1:346:1 | unaryExprs | AssignExpr |
| exprs.kt:321:7:321:7 | ...=... | exprs.kt:285:1:346:1 | unaryExprs | AssignExpr |
| exprs.kt:321:7:321:8 | s0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:321:7:321:8 | s0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:321:7:321:8 | s0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:322:5:322:6 | s0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:322:5:322:6 | s0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:322:5:322:8 | ...=... | exprs.kt:285:1:346:1 | unaryExprs | AssignExpr |
| exprs.kt:322:5:322:8 | <Stmt> | exprs.kt:285:1:346:1 | unaryExprs | StmtExpr |
| exprs.kt:322:5:322:8 | <implicit coercion to unit> | exprs.kt:285:1:346:1 | unaryExprs | ImplicitCoercionToUnitExpr |
| exprs.kt:322:5:322:8 | <unary> | exprs.kt:285:1:346:1 | unaryExprs | LocalVariableDeclExpr |
| exprs.kt:322:5:322:8 | <unary> | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:322:5:322:8 | <unary> | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:322:5:322:8 | Unit | exprs.kt:285:1:346:1 | unaryExprs | TypeAccess |
| exprs.kt:322:5:322:8 | dec(...) | exprs.kt:285:1:346:1 | unaryExprs | MethodCall |
| exprs.kt:322:5:322:8 | tmp5 | exprs.kt:285:1:346:1 | unaryExprs | LocalVariableDeclExpr |
| exprs.kt:322:5:322:8 | tmp5 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:322:5:322:8 | tmp5 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:322:5:322:8 | s0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:323:5:323:6 | dec(...) | exprs.kt:285:1:346:1 | unaryExprs | MethodCall |
| exprs.kt:323:5:323:8 | <Stmt> | exprs.kt:285:1:346:1 | unaryExprs | StmtExpr |
| exprs.kt:323:5:323:8 | <implicit coercion to unit> | exprs.kt:285:1:346:1 | unaryExprs | ImplicitCoercionToUnitExpr |
| exprs.kt:323:5:323:8 | Unit | exprs.kt:285:1:346:1 | unaryExprs | TypeAccess |
| exprs.kt:323:5:323:8 | dec(...) | exprs.kt:285:1:346:1 | unaryExprs | MethodCall |
| exprs.kt:323:7:323:8 | ...=... | exprs.kt:285:1:346:1 | unaryExprs | AssignExpr |
| exprs.kt:323:7:323:7 | ...=... | exprs.kt:285:1:346:1 | unaryExprs | AssignExpr |
| exprs.kt:323:7:323:8 | s0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:323:7:323:8 | s0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:323:7:323:8 | s0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
@@ -1997,43 +1997,43 @@
| exprs.kt:331:5:331:6 | <implicit coercion to unit> | exprs.kt:285:1:346:1 | unaryExprs | ImplicitCoercionToUnitExpr |
| exprs.kt:331:5:331:6 | Unit | exprs.kt:285:1:346:1 | unaryExprs | TypeAccess |
| exprs.kt:331:6:331:6 | l | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:332:9:332:10 | l0 | exprs.kt:285:1:346:1 | unaryExprs | LocalVariableDeclExpr |
| exprs.kt:332:5:332:20 | l0 | exprs.kt:285:1:346:1 | unaryExprs | LocalVariableDeclExpr |
| exprs.kt:332:20:332:20 | 1 | exprs.kt:285:1:346:1 | unaryExprs | LongLiteral |
| exprs.kt:333:9:333:10 | l1 | exprs.kt:285:1:346:1 | unaryExprs | LocalVariableDeclExpr |
| exprs.kt:333:5:333:20 | l1 | exprs.kt:285:1:346:1 | unaryExprs | LocalVariableDeclExpr |
| exprs.kt:333:20:333:20 | 1 | exprs.kt:285:1:346:1 | unaryExprs | LongLiteral |
| exprs.kt:334:5:334:6 | l0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:334:5:334:6 | l0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:334:5:334:8 | ...=... | exprs.kt:285:1:346:1 | unaryExprs | AssignExpr |
| exprs.kt:334:5:334:8 | <Stmt> | exprs.kt:285:1:346:1 | unaryExprs | StmtExpr |
| exprs.kt:334:5:334:8 | <implicit coercion to unit> | exprs.kt:285:1:346:1 | unaryExprs | ImplicitCoercionToUnitExpr |
| exprs.kt:334:5:334:8 | <unary> | exprs.kt:285:1:346:1 | unaryExprs | LocalVariableDeclExpr |
| exprs.kt:334:5:334:8 | <unary> | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:334:5:334:8 | <unary> | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:334:5:334:8 | Unit | exprs.kt:285:1:346:1 | unaryExprs | TypeAccess |
| exprs.kt:334:5:334:8 | inc(...) | exprs.kt:285:1:346:1 | unaryExprs | MethodCall |
| exprs.kt:334:5:334:8 | tmp6 | exprs.kt:285:1:346:1 | unaryExprs | LocalVariableDeclExpr |
| exprs.kt:334:5:334:8 | tmp6 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:334:5:334:8 | tmp6 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:334:5:334:8 | l0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:335:5:335:6 | inc(...) | exprs.kt:285:1:346:1 | unaryExprs | MethodCall |
| exprs.kt:335:5:335:8 | <Stmt> | exprs.kt:285:1:346:1 | unaryExprs | StmtExpr |
| exprs.kt:335:5:335:8 | <implicit coercion to unit> | exprs.kt:285:1:346:1 | unaryExprs | ImplicitCoercionToUnitExpr |
| exprs.kt:335:5:335:8 | Unit | exprs.kt:285:1:346:1 | unaryExprs | TypeAccess |
| exprs.kt:335:5:335:8 | inc(...) | exprs.kt:285:1:346:1 | unaryExprs | MethodCall |
| exprs.kt:335:7:335:8 | ...=... | exprs.kt:285:1:346:1 | unaryExprs | AssignExpr |
| exprs.kt:335:7:335:7 | ...=... | exprs.kt:285:1:346:1 | unaryExprs | AssignExpr |
| exprs.kt:335:7:335:8 | l0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:335:7:335:8 | l0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:335:7:335:8 | l0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:336:5:336:6 | l0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:336:5:336:6 | l0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:336:5:336:8 | ...=... | exprs.kt:285:1:346:1 | unaryExprs | AssignExpr |
| exprs.kt:336:5:336:8 | <Stmt> | exprs.kt:285:1:346:1 | unaryExprs | StmtExpr |
| exprs.kt:336:5:336:8 | <implicit coercion to unit> | exprs.kt:285:1:346:1 | unaryExprs | ImplicitCoercionToUnitExpr |
| exprs.kt:336:5:336:8 | <unary> | exprs.kt:285:1:346:1 | unaryExprs | LocalVariableDeclExpr |
| exprs.kt:336:5:336:8 | <unary> | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:336:5:336:8 | <unary> | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:336:5:336:8 | Unit | exprs.kt:285:1:346:1 | unaryExprs | TypeAccess |
| exprs.kt:336:5:336:8 | dec(...) | exprs.kt:285:1:346:1 | unaryExprs | MethodCall |
| exprs.kt:336:5:336:8 | tmp7 | exprs.kt:285:1:346:1 | unaryExprs | LocalVariableDeclExpr |
| exprs.kt:336:5:336:8 | tmp7 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:336:5:336:8 | tmp7 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:336:5:336:8 | l0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:337:5:337:6 | dec(...) | exprs.kt:285:1:346:1 | unaryExprs | MethodCall |
| exprs.kt:337:5:337:8 | <Stmt> | exprs.kt:285:1:346:1 | unaryExprs | StmtExpr |
| exprs.kt:337:5:337:8 | <implicit coercion to unit> | exprs.kt:285:1:346:1 | unaryExprs | ImplicitCoercionToUnitExpr |
| exprs.kt:337:5:337:8 | Unit | exprs.kt:285:1:346:1 | unaryExprs | TypeAccess |
| exprs.kt:337:5:337:8 | dec(...) | exprs.kt:285:1:346:1 | unaryExprs | MethodCall |
| exprs.kt:337:7:337:8 | ...=... | exprs.kt:285:1:346:1 | unaryExprs | AssignExpr |
| exprs.kt:337:7:337:7 | ...=... | exprs.kt:285:1:346:1 | unaryExprs | AssignExpr |
| exprs.kt:337:7:337:8 | l0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:337:7:337:8 | l0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |
| exprs.kt:337:7:337:8 | l0 | exprs.kt:285:1:346:1 | unaryExprs | VarAccess |

View File

@@ -0,0 +1,19 @@
import java
import TestUtilities.InlineExpectationsTest
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.security.AndroidLocalAuthQuery
module InsecureKeysTest implements TestSig {
string getARelevantTag() { result = "insecure-key" }
predicate hasActualResult(Location location, string element, string tag, string value) {
tag = "insecure-key" and
exists(InsecureBiometricKeyParamCall call | usesLocalAuth() |
call.getLocation() = location and
element = call.toString() and
value = ""
)
}
}
import MakeTest<InsecureKeysTest>

View File

@@ -0,0 +1,39 @@
import android.security.keystore.KeyGenParameterSpec;
import android.hardware.biometrics.BiometricPrompt;
import android.security.keystore.KeyProperties;
import javax.crypto.KeyGenerator;
class Test {
void test() {
KeyGenParameterSpec.Builder builder = new KeyGenParameterSpec.Builder("MySecretKey", KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT);
builder.setUserAuthenticationRequired(false); // $insecure-key
builder.setInvalidatedByBiometricEnrollment(false); // $insecure-key
builder.setUserAuthenticationValidityDurationSeconds(30); // $insecure-key
}
private void generateSecretKey() throws Exception {
KeyGenParameterSpec keyGenParameterSpec = new KeyGenParameterSpec.Builder(
"MySecretKey",
KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_CBC)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
// GOOD: Secure parameters are used to generate a key for biometric authentication.
.setUserAuthenticationRequired(true)
.setInvalidatedByBiometricEnrollment(true)
.setUserAuthenticationParameters(0, KeyProperties.AUTH_BIOMETRIC_STRONG)
.build();
KeyGenerator keyGenerator = KeyGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
keyGenerator.init(keyGenParameterSpec);
keyGenerator.generateKey();
}
}
class Callback extends BiometricPrompt.AuthenticationCallback {
public static void useKey(BiometricPrompt.CryptoObject key) {}
@Override
public void onAuthenticationSucceeded(BiometricPrompt.AuthenticationResult result) {
useKey(result.getCryptoObject());
}
}

View File

@@ -0,0 +1 @@
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../../stubs/google-android-9.0.0

View File

@@ -0,0 +1,2 @@
testFailures
failures

View File

@@ -0,0 +1,19 @@
import java
import TestUtilities.InlineExpectationsTest
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.security.AndroidLocalAuthQuery
module InsecureKeysTest implements TestSig {
string getARelevantTag() { result = "insecure-key" }
predicate hasActualResult(Location location, string element, string tag, string value) {
tag = "insecure-key" and
exists(InsecureBiometricKeyParamCall call | usesLocalAuth() |
call.getLocation() = location and
element = call.toString() and
value = ""
)
}
}
import MakeTest<InsecureKeysTest>

View File

@@ -0,0 +1,13 @@
import android.security.keystore.KeyGenParameterSpec;
import android.hardware.biometrics.BiometricPrompt;
import android.security.keystore.KeyProperties;
class Test {
void test() {
KeyGenParameterSpec.Builder builder = new KeyGenParameterSpec.Builder("MySecretKey", KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT);
// No alert as there is no use of biometric authentication in this application.
builder.setUserAuthenticationRequired(false);
builder.setInvalidatedByBiometricEnrollment(false);
builder.setUserAuthenticationValidityDurationSeconds(30);
}
}

View File

@@ -0,0 +1 @@
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../../stubs/google-android-9.0.0

View File

@@ -0,0 +1,2 @@
testFailures
failures

View File

@@ -1 +1 @@
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/google-android-9.0.0
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/google-android-9.0.0

View File

@@ -0,0 +1,76 @@
// Generated automatically from android.security.keystore.KeyGenParameterSpec for testing purposes
package android.security.keystore;
import java.math.BigInteger;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Date;
import javax.security.auth.x500.X500Principal;
public class KeyGenParameterSpec implements AlgorithmParameterSpec
{
public AlgorithmParameterSpec getAlgorithmParameterSpec(){ return null; }
public BigInteger getCertificateSerialNumber(){ return null; }
public Date getCertificateNotAfter(){ return null; }
public Date getCertificateNotBefore(){ return null; }
public Date getKeyValidityForConsumptionEnd(){ return null; }
public Date getKeyValidityForOriginationEnd(){ return null; }
public Date getKeyValidityStart(){ return null; }
public String getAttestKeyAlias(){ return null; }
public String getKeystoreAlias(){ return null; }
public String[] getBlockModes(){ return null; }
public String[] getDigests(){ return null; }
public String[] getEncryptionPaddings(){ return null; }
public String[] getSignaturePaddings(){ return null; }
public X500Principal getCertificateSubject(){ return null; }
public boolean isDevicePropertiesAttestationIncluded(){ return false; }
public boolean isDigestsSpecified(){ return false; }
public boolean isInvalidatedByBiometricEnrollment(){ return false; }
public boolean isRandomizedEncryptionRequired(){ return false; }
public boolean isStrongBoxBacked(){ return false; }
public boolean isUnlockedDeviceRequired(){ return false; }
public boolean isUserAuthenticationRequired(){ return false; }
public boolean isUserAuthenticationValidWhileOnBody(){ return false; }
public boolean isUserConfirmationRequired(){ return false; }
public boolean isUserPresenceRequired(){ return false; }
public byte[] getAttestationChallenge(){ return null; }
public int getKeySize(){ return 0; }
public int getMaxUsageCount(){ return 0; }
public int getPurposes(){ return 0; }
public int getUserAuthenticationType(){ return 0; }
public int getUserAuthenticationValidityDurationSeconds(){ return 0; }
static public class Builder
{
protected Builder() {}
public Builder(String p0, int p1){}
public KeyGenParameterSpec build(){ return null; }
public KeyGenParameterSpec.Builder setAlgorithmParameterSpec(AlgorithmParameterSpec p0){ return null; }
public KeyGenParameterSpec.Builder setAttestKeyAlias(String p0){ return null; }
public KeyGenParameterSpec.Builder setAttestationChallenge(byte[] p0){ return null; }
public KeyGenParameterSpec.Builder setBlockModes(String... p0){ return null; }
public KeyGenParameterSpec.Builder setCertificateNotAfter(Date p0){ return null; }
public KeyGenParameterSpec.Builder setCertificateNotBefore(Date p0){ return null; }
public KeyGenParameterSpec.Builder setCertificateSerialNumber(BigInteger p0){ return null; }
public KeyGenParameterSpec.Builder setCertificateSubject(X500Principal p0){ return null; }
public KeyGenParameterSpec.Builder setDevicePropertiesAttestationIncluded(boolean p0){ return null; }
public KeyGenParameterSpec.Builder setDigests(String... p0){ return null; }
public KeyGenParameterSpec.Builder setEncryptionPaddings(String... p0){ return null; }
public KeyGenParameterSpec.Builder setInvalidatedByBiometricEnrollment(boolean p0){ return null; }
public KeyGenParameterSpec.Builder setIsStrongBoxBacked(boolean p0){ return null; }
public KeyGenParameterSpec.Builder setKeySize(int p0){ return null; }
public KeyGenParameterSpec.Builder setKeyValidityEnd(Date p0){ return null; }
public KeyGenParameterSpec.Builder setKeyValidityForConsumptionEnd(Date p0){ return null; }
public KeyGenParameterSpec.Builder setKeyValidityForOriginationEnd(Date p0){ return null; }
public KeyGenParameterSpec.Builder setKeyValidityStart(Date p0){ return null; }
public KeyGenParameterSpec.Builder setMaxUsageCount(int p0){ return null; }
public KeyGenParameterSpec.Builder setRandomizedEncryptionRequired(boolean p0){ return null; }
public KeyGenParameterSpec.Builder setSignaturePaddings(String... p0){ return null; }
public KeyGenParameterSpec.Builder setUnlockedDeviceRequired(boolean p0){ return null; }
public KeyGenParameterSpec.Builder setUserAuthenticationParameters(int p0, int p1){ return null; }
public KeyGenParameterSpec.Builder setUserAuthenticationRequired(boolean p0){ return null; }
public KeyGenParameterSpec.Builder setUserAuthenticationValidWhileOnBody(boolean p0){ return null; }
public KeyGenParameterSpec.Builder setUserAuthenticationValidityDurationSeconds(int p0){ return null; }
public KeyGenParameterSpec.Builder setUserConfirmationRequired(boolean p0){ return null; }
public KeyGenParameterSpec.Builder setUserPresenceRequired(boolean p0){ return null; }
}
}

View File

@@ -0,0 +1,54 @@
// Generated automatically from android.security.keystore.KeyProperties for testing purposes
package android.security.keystore;
abstract public class KeyProperties
{
protected KeyProperties() {}
public static String BLOCK_MODE_CBC = null;
public static String BLOCK_MODE_CTR = null;
public static String BLOCK_MODE_ECB = null;
public static String BLOCK_MODE_GCM = null;
public static String DIGEST_MD5 = null;
public static String DIGEST_NONE = null;
public static String DIGEST_SHA1 = null;
public static String DIGEST_SHA224 = null;
public static String DIGEST_SHA256 = null;
public static String DIGEST_SHA384 = null;
public static String DIGEST_SHA512 = null;
public static String ENCRYPTION_PADDING_NONE = null;
public static String ENCRYPTION_PADDING_PKCS7 = null;
public static String ENCRYPTION_PADDING_RSA_OAEP = null;
public static String ENCRYPTION_PADDING_RSA_PKCS1 = null;
public static String KEY_ALGORITHM_3DES = null;
public static String KEY_ALGORITHM_AES = null;
public static String KEY_ALGORITHM_EC = null;
public static String KEY_ALGORITHM_HMAC_SHA1 = null;
public static String KEY_ALGORITHM_HMAC_SHA224 = null;
public static String KEY_ALGORITHM_HMAC_SHA256 = null;
public static String KEY_ALGORITHM_HMAC_SHA384 = null;
public static String KEY_ALGORITHM_HMAC_SHA512 = null;
public static String KEY_ALGORITHM_RSA = null;
public static String SIGNATURE_PADDING_RSA_PKCS1 = null;
public static String SIGNATURE_PADDING_RSA_PSS = null;
public static int AUTH_BIOMETRIC_STRONG = 0;
public static int AUTH_DEVICE_CREDENTIAL = 0;
public static int ORIGIN_GENERATED = 0;
public static int ORIGIN_IMPORTED = 0;
public static int ORIGIN_SECURELY_IMPORTED = 0;
public static int ORIGIN_UNKNOWN = 0;
public static int PURPOSE_AGREE_KEY = 0;
public static int PURPOSE_ATTEST_KEY = 0;
public static int PURPOSE_DECRYPT = 0;
public static int PURPOSE_ENCRYPT = 0;
public static int PURPOSE_SIGN = 0;
public static int PURPOSE_VERIFY = 0;
public static int PURPOSE_WRAP_KEY = 0;
public static int SECURITY_LEVEL_SOFTWARE = 0;
public static int SECURITY_LEVEL_STRONGBOX = 0;
public static int SECURITY_LEVEL_TRUSTED_ENVIRONMENT = 0;
public static int SECURITY_LEVEL_UNKNOWN = 0;
public static int SECURITY_LEVEL_UNKNOWN_SECURE = 0;
public static int UNRESTRICTED_USAGE_COUNT = 0;
}

View File

@@ -1,6 +1,6 @@
load("@//:dist.bzl", "dist")
load("@semmle_code//:dist.bzl", "dist")
load("@rules_pkg//pkg:mappings.bzl", "pkg_files")
load("@//buildutils-internal:zipmerge.bzl", "zipmerge")
load("@semmle_code//buildutils-internal:zipmerge.bzl", "zipmerge")
package(default_visibility = ["//visibility:public"])
@@ -30,7 +30,7 @@ dist(
"//javascript/downgrades",
"//javascript/externs",
"//javascript/extractor:tools-extractor",
"@//language-packs/javascript:resources",
"@semmle_code//language-packs/javascript:resources",
],
prefix = "javascript",
)

View File

@@ -1,4 +1,4 @@
load("@//:dist.bzl", "pack_zip")
load("@semmle_code//:dist.bzl", "pack_zip")
pack_zip(
name = "downgrades",

View File

@@ -1,4 +1,4 @@
load("@//:dist.bzl", "pack_zip")
load("@semmle_code//:dist.bzl", "pack_zip")
pack_zip(
name = "externs",

View File

@@ -1,21 +1,21 @@
load("@//:common.bzl", "codeql_fat_jar", "codeql_java_project")
load("@semmle_code//:common.bzl", "codeql_fat_jar", "codeql_java_project")
load("@rules_pkg//pkg:mappings.bzl", "pkg_files")
java_library(
name = "deps",
visibility = [":__subpackages__"],
exports = [
"@//extractor:html",
"@//extractor:yaml",
"@//resources/lib/java:commons-compress",
"@//resources/lib/java:gson",
"@//resources/lib/java:jericho-html",
"@//resources/lib/java:slf4j-api",
"@//resources/lib/java:snakeyaml",
"@//third_party:jackson",
"@//third_party:logback",
"@//util-java7",
"@//util-java8",
"@semmle_code//extractor:html",
"@semmle_code//extractor:yaml",
"@semmle_code//resources/lib/java:commons-compress",
"@semmle_code//resources/lib/java:gson",
"@semmle_code//resources/lib/java:jericho-html",
"@semmle_code//resources/lib/java:slf4j-api",
"@semmle_code//resources/lib/java:snakeyaml",
"@semmle_code//third_party:jackson",
"@semmle_code//third_party:logback",
"@semmle_code//util-java7",
"@semmle_code//util-java8",
],
)
@@ -36,18 +36,18 @@ codeql_fat_jar(
name = "extractor-javascript",
srcs = [
":extractor",
"@//extractor:html",
"@//extractor:xml-trap-writer",
"@//extractor:yaml",
"@//resources/lib/java:commons-compress",
"@//resources/lib/java:gson",
"@//resources/lib/java:jericho-html",
"@//resources/lib/java:slf4j-api",
"@//resources/lib/java:snakeyaml",
"@//third_party:jackson",
"@//third_party:logback",
"@//util-java7",
"@//util-java8",
"@semmle_code//extractor:html",
"@semmle_code//extractor:xml-trap-writer",
"@semmle_code//extractor:yaml",
"@semmle_code//resources/lib/java:commons-compress",
"@semmle_code//resources/lib/java:gson",
"@semmle_code//resources/lib/java:jericho-html",
"@semmle_code//resources/lib/java:slf4j-api",
"@semmle_code//resources/lib/java:snakeyaml",
"@semmle_code//third_party:jackson",
"@semmle_code//third_party:logback",
"@semmle_code//util-java7",
"@semmle_code//util-java8",
],
files = [":javascript-extractor-resources"],
main_class = "com.semmle.js.extractor.Main",

View File

@@ -1,4 +1,4 @@
load("@//:common.bzl", "on_windows")
load("@semmle_code//:common.bzl", "on_windows")
# Builds a zip file of the compiled typscript-parser-wrapper and its dependencies.
genrule(

View File

@@ -7,15 +7,15 @@ java_test(
"//javascript/extractor/tests",
"@nodejs//:node_bin",
],
test_class = "com.semmle.js.extractor.test.AllTests",
deps = [
"//javascript/extractor",
"//javascript/extractor:deps",
"@//resources/lib/java/DO_NOT_DISTRIBUTE:junit",
"@bazel_tools//tools/java/runfiles",
],
env = {
"NODE_BIN": "$(rlocationpath @nodejs//:node_bin)",
"TS_WRAPPER_ZIP": "$(rlocationpath //javascript/extractor/lib/typescript)",
},
test_class = "com.semmle.js.extractor.test.AllTests",
deps = [
"//javascript/extractor",
"//javascript/extractor:deps",
"@bazel_tools//tools/java/runfiles",
"@semmle_code//resources/lib/java/DO_NOT_DISTRIBUTE:junit",
],
)

View File

@@ -1 +1 @@
**/ql/javascript/extractor/tests/*/input//
**/*ql*/javascript/extractor/tests/*/input//

View File

@@ -22,7 +22,9 @@ CmakeInfo = provider(
)
def _cmake_name(label):
ret = ("%s_%s_%s" % (label.workspace_name, label.package, label.name)).replace("/", "_")
# strip away the bzlmod module version for now
workspace_name, _, _ = label.workspace_name.partition("~")
ret = ("%s_%s_%s" % (workspace_name, label.package, label.name)).replace("/", "_")
internal_transition_suffix = "_INTERNAL_TRANSITION"
if ret.endswith(internal_transition_suffix):
ret = ret[:-len(internal_transition_suffix)]
@@ -120,7 +122,6 @@ def _cmake_aspect_impl(target, ctx):
prefix, # source
"${BAZEL_EXEC_ROOT}/%s/%s" % (ctx.var["BINDIR"], prefix), # generated
]
deps = [dep[CmakeInfo] for dep in deps if CmakeInfo in dep]
# by the book this should be done with depsets, but so far the performance implication is negligible

View File

@@ -19,8 +19,7 @@ endmacro()
bazel(info workspace OUTPUT_VARIABLE BAZEL_WORKSPACE)
bazel(info output_base OUTPUT_VARIABLE BAZEL_OUTPUT_BASE)
string(REPLACE "-" "_" BAZEL_EXEC_ROOT ${PROJECT_NAME})
set(BAZEL_EXEC_ROOT ${BAZEL_OUTPUT_BASE}/execroot/${BAZEL_EXEC_ROOT})
set(BAZEL_EXEC_ROOT ${BAZEL_OUTPUT_BASE}/execroot/_main)
macro(include_generated BAZEL_TARGET)
bazel(build ${BAZEL_TARGET})

View File

@@ -0,0 +1,4 @@
module(
name = "semmle_code",
version = "0.0",
)

View File

@@ -3,7 +3,7 @@ load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe")
load("//swift/third_party:load.bzl", load_swift_dependencies = "load_dependencies")
def codeql_workspace(repository_name = "codeql"):
load_swift_dependencies(repository_name)
load_swift_dependencies(repository_name = repository_name)
maybe(
repo_rule = http_archive,
name = "rules_pkg",

View File

@@ -5,7 +5,7 @@ load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace")
def codeql_workspace_deps(repository_name = "codeql"):
pip_install(
name = "codegen_deps",
requirements = "@%s//misc/codegen:requirements.txt" % repository_name,
requirements = "@%s//misc/codegen:requirements_lock.txt" % repository_name,
)
bazel_skylib_workspace()
rules_pkg_dependencies()

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